mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-30 23:34:33 +02:00
Merge pull request #11722 from druiz17/ui
Update controllerDispatcher scripts to use the new Pointers API(WIP)
This commit is contained in:
commit
d1747060f5
24 changed files with 790 additions and 1617 deletions
scripts
defaultScripts.js
system
controllers
controllerDispatcher.js
controllerModules
disableOtherModule.jsequipEntity.jsfarActionGrabEntity.jsfarTrigger.jshudOverlayPointer.jsinEditMode.jsnearActionGrabEntity.jsnearParentGrabEntity.jsnearParentGrabOverlay.jsnearTrigger.jsoverlayLaserInput.jsscaleAvatar.jsscaleEntity.jsstylusInput.jstabletStylusInput.jsteleport.jswebEntityLaserInput.jswebSurfaceLaserInput.js
controllerScripts.jsgrab.jslibraries
|
@ -32,8 +32,8 @@ var DEFAULT_SCRIPTS_COMBINED = [
|
|||
"system/tablet-ui/tabletUI.js"
|
||||
];
|
||||
var DEFAULT_SCRIPTS_SEPARATE = [
|
||||
//"system/controllers/controllerScripts.js"
|
||||
// "system/chat.js"
|
||||
"system/controllers/controllerScripts.js"
|
||||
//"system/chat.js"
|
||||
];
|
||||
|
||||
// add a menu item for debugging
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
/* global Script, Entities, Overlays, Controller, Vec3, Quat, getControllerWorldLocation, RayPick,
|
||||
controllerDispatcherPlugins:true, controllerDispatcherPluginsNeedSort:true,
|
||||
LEFT_HAND, RIGHT_HAND, NEAR_GRAB_PICK_RADIUS, DEFAULT_SEARCH_SPHERE_DISTANCE, DISPATCHER_PROPERTIES,
|
||||
getGrabPointSphereOffset, HMD, MyAvatar, Messages, findHandChildEntities
|
||||
getGrabPointSphereOffset, HMD, MyAvatar, Messages, findHandChildEntities, Pointers, PickType, COLORS_GRAB_SEARCHING_HALF_SQUEEZE
|
||||
COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, Picks, TRIGGER_ON_VALUE, PointerManager
|
||||
*/
|
||||
|
||||
controllerDispatcherPlugins = {};
|
||||
|
@ -21,6 +22,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
||||
(function() {
|
||||
Script.include("/~/system/libraries/pointersUtils.js");
|
||||
var NEAR_MAX_RADIUS = 0.1;
|
||||
|
||||
var TARGET_UPDATE_HZ = 60; // 50hz good enough, but we're using update
|
||||
|
@ -43,6 +45,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
this.veryhighVarianceCount = 0;
|
||||
this.tabletID = null;
|
||||
this.blacklist = [];
|
||||
this.pointerManager = new PointerManager();
|
||||
|
||||
// a module can occupy one or more "activity" slots while it's running. If all the required slots for a module are
|
||||
// not set to false (not in use), a module cannot start. When a module is using a slot, that module's name
|
||||
|
@ -57,6 +60,9 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
mouse: false
|
||||
};
|
||||
|
||||
this.laserVisibleStatus = [false, false, false, false];
|
||||
this.laserLockStatus = [false, false, false, false];
|
||||
|
||||
this.slotsAreAvailableForPlugin = function (plugin) {
|
||||
for (var i = 0; i < plugin.parameters.activitySlots.length; i++) {
|
||||
if (_this.activitySlots[plugin.parameters.activitySlots[i]]) {
|
||||
|
@ -108,7 +114,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
_this.rightSecondaryValue = value;
|
||||
};
|
||||
|
||||
|
||||
this.dataGatherers = {};
|
||||
this.dataGatherers.leftControllerLocation = function () {
|
||||
return getControllerWorldLocation(Controller.Standard.LeftHand, true);
|
||||
|
@ -143,8 +148,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
this.setIgnoreTablet = function() {
|
||||
if (HMD.tabletID !== this.tabletID) {
|
||||
this.tabletID = HMD.tabletID;
|
||||
RayPick.setIgnoreItems(_this.leftControllerRayPick, _this.blacklist.concat([HMD.tabletID]));
|
||||
RayPick.setIgnoreItems(_this.rightControllerRayPick, _this.blacklist.concat([HMD.tabletID]));
|
||||
Pointers.setIgnoreItems(_this.leftPointer, _this.blacklist.concat([HMD.tabletID]));
|
||||
Pointers.setIgnoreItems(_this.rightPointer, _this.blacklist.concat([HMD.tabletID]));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -234,14 +239,14 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
|
||||
// raypick for each controller
|
||||
var rayPicks = [
|
||||
RayPick.getPrevRayPickResult(_this.leftControllerRayPick),
|
||||
RayPick.getPrevRayPickResult(_this.rightControllerRayPick)
|
||||
Pointers.getPrevPickResult(_this.leftPointer),
|
||||
Pointers.getPrevPickResult(_this.rightPointer)
|
||||
];
|
||||
var hudRayPicks = [
|
||||
RayPick.getPrevRayPickResult(_this.leftControllerHudRayPick),
|
||||
RayPick.getPrevRayPickResult(_this.rightControllerHudRayPick)
|
||||
Pointers.getPrevPickResult(_this.leftHudPointer),
|
||||
Pointers.getPrevPickResult(_this.rightHudPointer)
|
||||
];
|
||||
var mouseRayPick = RayPick.getPrevRayPickResult(_this.mouseRayPick);
|
||||
var mouseRayPick = Pointers.getPrevPickResult(_this.mouseRayPick);
|
||||
// if the pickray hit something very nearby, put it into the nearby entities list
|
||||
for (h = LEFT_HAND; h <= RIGHT_HAND; h++) {
|
||||
|
||||
|
@ -319,6 +324,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
// activity-slots which this plugin consumes as "in use"
|
||||
_this.runningPluginNames[orderedPluginName] = true;
|
||||
_this.markSlots(candidatePlugin, orderedPluginName);
|
||||
_this.pointerManager.makePointerVisible(candidatePlugin.parameters.handLaser);
|
||||
if (DEBUG) {
|
||||
print("controllerDispatcher running " + orderedPluginName);
|
||||
}
|
||||
|
@ -354,16 +360,19 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
// of running plugins and mark its activity-slots as "not in use"
|
||||
delete _this.runningPluginNames[runningPluginName];
|
||||
_this.markSlots(plugin, false);
|
||||
_this.pointerManager.makePointerInvisible(plugin.parameters.handLaser);
|
||||
if (DEBUG) {
|
||||
print("controllerDispatcher stopping " + runningPluginName);
|
||||
}
|
||||
}
|
||||
_this.pointerManager.lockPointerEnd(plugin.parameters.handLaser, runningness.laserLockInfo);
|
||||
if (PROFILE) {
|
||||
Script.endProfileRange("dispatch.run." + runningPluginName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_this.pointerManager.updatePointersRenderState(controllerData.triggerClicks, controllerData.triggerValues);
|
||||
if (PROFILE) {
|
||||
Script.endProfileRange("dispatch.run");
|
||||
}
|
||||
|
@ -388,40 +397,49 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
|
||||
Controller.enableMapping(MAPPING_NAME);
|
||||
|
||||
this.leftControllerRayPick = RayPick.createRayPick({
|
||||
this.leftPointer = this.pointerManager.createPointer(false, PickType.Ray, {
|
||||
joint: "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND",
|
||||
filter: Picks.PICK_ENTITIES | Picks.PICK_OVERLAYS,
|
||||
enabled: true,
|
||||
maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE,
|
||||
posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand, true)
|
||||
filter: Picks.PICK_OVERLAYS | Picks.PICK_ENTITIES,
|
||||
triggers: [{action: Controller.Standard.LTClick, button: "Focus"}, {action: Controller.Standard.LTClick, button: "Primary"}],
|
||||
posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand, true),
|
||||
hover: true,
|
||||
distanceScaleEnd: true,
|
||||
hand: LEFT_HAND
|
||||
});
|
||||
this.leftControllerHudRayPick = RayPick.createRayPick({
|
||||
joint: "_CONTROLLER_LEFTHAND",
|
||||
filter: Picks.PICK_HUD,
|
||||
enabled: true,
|
||||
maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE,
|
||||
posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand, true)
|
||||
});
|
||||
this.rightControllerRayPick = RayPick.createRayPick({
|
||||
this.rightPointer = this.pointerManager.createPointer(false, PickType.Ray, {
|
||||
joint: "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND",
|
||||
filter: Picks.PICK_ENTITIES | Picks.PICK_OVERLAYS,
|
||||
enabled: true,
|
||||
maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE,
|
||||
posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand, true)
|
||||
filter: Picks.PICK_OVERLAYS | Picks.PICK_ENTITIES,
|
||||
triggers: [{action: Controller.Standard.RTClick, button: "Focus"}, {action: Controller.Standard.RTClick, button: "Primary"}],
|
||||
posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand, true),
|
||||
hover: true,
|
||||
distanceScaleEnd: true,
|
||||
hand: RIGHT_HAND
|
||||
});
|
||||
this.rightControllerHudRayPick = RayPick.createRayPick({
|
||||
joint: "_CONTROLLER_RIGHTHAND",
|
||||
this.leftHudPointer = this.pointerManager.createPointer(true, PickType.Ray, {
|
||||
joint: "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND",
|
||||
filter: Picks.PICK_HUD,
|
||||
enabled: true,
|
||||
maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE,
|
||||
posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand, true)
|
||||
posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand, true),
|
||||
triggers: [{action: Controller.Standard.LTClick, button: "Focus"}, {action: Controller.Standard.LTClick, button: "Primary"}],
|
||||
hover: true,
|
||||
distanceScaleEnd: true,
|
||||
hand: LEFT_HAND
|
||||
});
|
||||
this.mouseRayPick = RayPick.createRayPick({
|
||||
this.rightHudPointer = this.pointerManager.createPointer(true, PickType.Ray, {
|
||||
joint: "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND",
|
||||
filter: Picks.PICK_HUD,
|
||||
maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE,
|
||||
posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand, true),
|
||||
triggers: [{action: Controller.Standard.RTClick, button: "Focus"}, {action: Controller.Standard.RTClick, button: "Primary"}],
|
||||
hover: true,
|
||||
distanceScaleEnd: true,
|
||||
hand: RIGHT_HAND
|
||||
});
|
||||
this.mouseRayPick = Pointers.createPointer(PickType.Ray, {
|
||||
joint: "Mouse",
|
||||
filter: Picks.PICK_ENTITIES | Picks.PICK_OVERLAYS,
|
||||
enabled: true
|
||||
});
|
||||
|
||||
this.handleHandMessage = function(channel, message, sender) {
|
||||
var data;
|
||||
if (sender === MyAvatar.sessionUUID) {
|
||||
|
@ -454,13 +472,31 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
this.cleanup = function () {
|
||||
Script.update.disconnect(_this.update);
|
||||
Controller.disableMapping(MAPPING_NAME);
|
||||
RayPick.removeRayPick(_this.leftControllerRayPick);
|
||||
RayPick.removeRayPick(_this.rightControllerRayPick);
|
||||
RayPick.removeRayPick(_this.rightControllerHudRayPick);
|
||||
RayPick.removeRayPick(_this.leftControllerHudRayPick);
|
||||
_this.pointerManager.removePointers();
|
||||
Pointers.removePointer(this.mouseRayPick);
|
||||
};
|
||||
}
|
||||
function mouseReleaseOnOverlay(overlayID, event) {
|
||||
if (overlayID === HMD.homeButtonID && event.button === "Primary") {
|
||||
Messages.sendLocalMessage("home", overlayID);
|
||||
}
|
||||
}
|
||||
|
||||
var HAPTIC_STYLUS_STRENGTH = 1.0;
|
||||
var HAPTIC_STYLUS_DURATION = 20.0;
|
||||
function mousePress(id, event) {
|
||||
if (HMD.active) {
|
||||
var runningPlugins = controllerDispatcher.runningPluginNames;
|
||||
if (event.id === controllerDispatcher.leftPointer && event.button === "Primary" && runningPlugins.LeftWebSurfaceLaserInput) {
|
||||
Controller.triggerHapticPulse(HAPTIC_STYLUS_STRENGTH, HAPTIC_STYLUS_DURATION, LEFT_HAND);
|
||||
} else if (event.id === controllerDispatcher.rightPointer && event.button === "Primary" && runningPlugins.RightWebSurfaceLaserInput) {
|
||||
Controller.triggerHapticPulse(HAPTIC_STYLUS_STRENGTH, HAPTIC_STYLUS_DURATION, RIGHT_HAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
Overlays.mouseReleaseOnOverlay.connect(mouseReleaseOnOverlay);
|
||||
Overlays.mousePressOnOverlay.connect(mousePress);
|
||||
Entities.mousePressOnEntity.connect(mousePress);
|
||||
var controllerDispatcher = new ControllerDispatcher();
|
||||
Messages.subscribe('Hifi-Hand-RayPick-Blacklist');
|
||||
Messages.messageReceived.connect(controllerDispatcher.handleHandMessage);
|
||||
|
|
|
@ -53,7 +53,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
|
||||
enableDispatcherModule("LeftDisableModules", leftDisableModules);
|
||||
enableDispatcherModule("RightDisableModules", rightDisableModules);
|
||||
this.handleMessage = function(channel, message, sender) {
|
||||
function handleMessage(channel, message, sender) {
|
||||
if (sender === MyAvatar.sessionUUID) {
|
||||
if (channel === 'Hifi-Hand-Disabler') {
|
||||
if (message === 'left') {
|
||||
|
@ -73,13 +73,13 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Messages.subscribe('Hifi-Hand-Disabler');
|
||||
this.cleanup = function() {
|
||||
function cleanup() {
|
||||
disableDispatcherModule("LeftDisableModules");
|
||||
disableDispatcherModule("RightDisableModules");
|
||||
};
|
||||
Messages.messageReceived.connect(this.handleMessage);
|
||||
Script.scriptEnding.connect(this.cleanup);
|
||||
}
|
||||
Messages.messageReceived.connect(handleMessage);
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}());
|
||||
|
|
|
@ -773,6 +773,6 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
|||
disableDispatcherModule("LeftEquipEntity");
|
||||
disableDispatcherModule("RightEquipEntity");
|
||||
clearAttachPoints();
|
||||
};
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}());
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
makeDispatcherModuleParameters, MSECS_PER_SEC, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION,
|
||||
PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD,
|
||||
DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, ensureDynamic,
|
||||
getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays, isPointingAtUI, Xform, getEntityParents
|
||||
|
||||
getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays, isPointingAtUI
|
||||
Picks, makeLaserLockInfo Xform
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
@ -22,76 +22,6 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
Script.include("/~/system/libraries/Xform.js");
|
||||
|
||||
(function() {
|
||||
var PICK_WITH_HAND_RAY = true;
|
||||
|
||||
var SEARCH_SPHERE_SIZE = 0.0132;
|
||||
var dim = {x: SEARCH_SPHERE_SIZE, y: SEARCH_SPHERE_SIZE, z: SEARCH_SPHERE_SIZE};
|
||||
var halfPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
var halfEnd = {
|
||||
type: "sphere",
|
||||
dimensions: dim,
|
||||
solid: true,
|
||||
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
alpha: 0.9,
|
||||
ignoreRayIntersection: true,
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
visible: true
|
||||
};
|
||||
var fullPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
var fullEnd = {
|
||||
type: "sphere",
|
||||
dimensions: dim,
|
||||
solid: true,
|
||||
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
|
||||
alpha: 0.9,
|
||||
ignoreRayIntersection: true,
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
visible: true
|
||||
};
|
||||
var holdPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_DISTANCE_HOLD,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
|
||||
var renderStates = [
|
||||
{name: "half", path: halfPath, end: halfEnd},
|
||||
{name: "full", path: fullPath, end: fullEnd},
|
||||
{name: "hold", path: holdPath}
|
||||
];
|
||||
|
||||
var defaultRenderStates = [
|
||||
{name: "half", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: halfPath},
|
||||
{name: "full", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: fullPath},
|
||||
{name: "hold", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: holdPath}
|
||||
];
|
||||
|
||||
var GRABBABLE_PROPERTIES = [
|
||||
"position",
|
||||
"registrationPoint",
|
||||
|
@ -188,53 +118,8 @@ Script.include("/~/system/libraries/Xform.js");
|
|||
550,
|
||||
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||
[],
|
||||
100);
|
||||
|
||||
this.updateLaserPointer = function(controllerData) {
|
||||
var mode = "hold";
|
||||
if (!this.distanceHolding && !this.distanceRotating) {
|
||||
if (controllerData.triggerClicks[this.hand]) {
|
||||
mode = "full";
|
||||
} else {
|
||||
mode = "half";
|
||||
}
|
||||
}
|
||||
|
||||
var laserPointerID = PICK_WITH_HAND_RAY ? this.laserPointer : this.headLaserPointer;
|
||||
if (mode === "full") {
|
||||
this.contextOverlayTimer = false;
|
||||
this.destroyContextOverlay();
|
||||
}
|
||||
|
||||
LaserPointers.enableLaserPointer(laserPointerID);
|
||||
LaserPointers.setRenderState(laserPointerID, mode);
|
||||
if (this.distanceHolding || this.distanceRotating) {
|
||||
if (!this.locked) {
|
||||
// calculate offset
|
||||
var targetProps = Entities.getEntityProperties(this.targetObject.entityID, [
|
||||
"position",
|
||||
"rotation"
|
||||
]);
|
||||
var zeroVector = { x: 0, y: 0, z:0, w: 0 };
|
||||
var intersection = controllerData.rayPicks[this.hand].intersection;
|
||||
var intersectionMat = new Xform(zeroVector, intersection);
|
||||
var modelMat = new Xform(targetProps.rotation, targetProps.position);
|
||||
var modelMatInv = modelMat.inv();
|
||||
var xformMat = Xform.mul(modelMatInv, intersectionMat);
|
||||
var offsetMat = Mat4.createFromRotAndTrans(xformMat.rot, xformMat.pos);
|
||||
LaserPointers.setLockEndUUID(laserPointerID, this.targetObject.entityID, this.grabbedIsOverlay, offsetMat);
|
||||
this.locked = true;
|
||||
}
|
||||
} else {
|
||||
LaserPointers.setLockEndUUID(laserPointerID, null, false);
|
||||
this.locked = false;
|
||||
}
|
||||
};
|
||||
|
||||
this.laserPointerOff = function() {
|
||||
LaserPointers.disableLaserPointer(this.laserPointer);
|
||||
LaserPointers.disableLaserPointer(this.headLaserPointer);
|
||||
};
|
||||
100,
|
||||
this.hand);
|
||||
|
||||
|
||||
this.handToController = function() {
|
||||
|
@ -374,9 +259,6 @@ Script.include("/~/system/libraries/Xform.js");
|
|||
// XXX
|
||||
// this.maybeScale(grabbedProperties);
|
||||
|
||||
// visualizations
|
||||
this.updateLaserPointer(controllerData);
|
||||
|
||||
var distanceToObject = Vec3.length(Vec3.subtract(MyAvatar.position, this.currentObjectPosition));
|
||||
|
||||
this.linearTimeScale = (this.linearTimeScale / 2);
|
||||
|
@ -506,11 +388,9 @@ Script.include("/~/system/libraries/Xform.js");
|
|||
if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE ||
|
||||
this.notPointingAtEntity(controllerData)) {
|
||||
this.endNearGrabAction();
|
||||
this.laserPointerOff();
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
this.intersectionDistance = controllerData.rayPicks[this.hand].distance;
|
||||
this.updateLaserPointer(controllerData);
|
||||
|
||||
var otherModuleName =this.hand === RIGHT_HAND ? "LeftFarActionGrabEntity" : "RightFarActionGrabEntity";
|
||||
var otherFarGrabModule = getEnabledModuleByName(otherModuleName);
|
||||
|
@ -536,7 +416,6 @@ Script.include("/~/system/libraries/Xform.js");
|
|||
// stop the far-grab so the near-grab or equip can take over.
|
||||
for (var k = 0; k < nearGrabReadiness.length; k++) {
|
||||
if (nearGrabReadiness[k].active && nearGrabReadiness[k].targets[0] === this.grabbedThingID) {
|
||||
this.laserPointerOff();
|
||||
this.endNearGrabAction();
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
|
@ -548,7 +427,6 @@ Script.include("/~/system/libraries/Xform.js");
|
|||
// where it could near-grab something, stop searching.
|
||||
for (var j = 0; j < nearGrabReadiness.length; j++) {
|
||||
if (nearGrabReadiness[j].active) {
|
||||
this.laserPointerOff();
|
||||
this.endNearGrabAction();
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
|
@ -617,38 +495,41 @@ Script.include("/~/system/libraries/Xform.js");
|
|||
this.distanceRotate(otherFarGrabModule);
|
||||
}
|
||||
}
|
||||
return this.exitIfDisabled();
|
||||
return this.exitIfDisabled(controllerData);
|
||||
};
|
||||
|
||||
this.exitIfDisabled = function() {
|
||||
this.exitIfDisabled = function(controllerData) {
|
||||
var moduleName = this.hand === RIGHT_HAND ? "RightDisableModules" : "LeftDisableModules";
|
||||
var disableModule = getEnabledModuleByName(moduleName);
|
||||
if (disableModule) {
|
||||
if (disableModule.disableModules) {
|
||||
this.laserPointerOff();
|
||||
this.endNearGrabAction();
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
}
|
||||
return makeRunningValues(true, [], []);
|
||||
var grabbedThing = (this.distanceHolding || this.distanceRotating) ? this.targetObject.entityID : null;
|
||||
var offset = this.calculateOffset(controllerData);
|
||||
var laserLockInfo = makeLaserLockInfo(grabbedThing, false, this.hand, offset);
|
||||
return makeRunningValues(true, [], [], laserLockInfo);
|
||||
};
|
||||
|
||||
this.cleanup = function () {
|
||||
LaserPointers.disableLaserPointer(this.laserPointer);
|
||||
LaserPointers.removeLaserPointer(this.laserPointer);
|
||||
this.calculateOffset = function(controllerData) {
|
||||
if (this.distanceHolding || this.distanceRotating) {
|
||||
var targetProps = Entities.getEntityProperties(this.targetObject.entityID, [
|
||||
"position",
|
||||
"rotation"
|
||||
]);
|
||||
var zeroVector = { x: 0, y: 0, z:0, w: 0 };
|
||||
var intersection = controllerData.rayPicks[this.hand].intersection;
|
||||
var intersectionMat = new Xform(zeroVector, intersection);
|
||||
var modelMat = new Xform(targetProps.rotation, targetProps.position);
|
||||
var modelMatInv = modelMat.inv();
|
||||
var xformMat = Xform.mul(modelMatInv, intersectionMat);
|
||||
var offsetMat = Mat4.createFromRotAndTrans(xformMat.rot, xformMat.pos);
|
||||
return offsetMat;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
this.laserPointer = LaserPointers.createLaserPointer({
|
||||
joint: (this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND",
|
||||
filter: Picks.PICK_ENTITIES | Picks.PICK_OVERLAYS,
|
||||
maxDistance: PICK_MAX_DISTANCE,
|
||||
posOffset: getGrabPointSphereOffset(this.handToController(), true),
|
||||
renderStates: renderStates,
|
||||
faceAvatar: true,
|
||||
distanceScaleEnd: true,
|
||||
scaleWithAvatar: true,
|
||||
defaultRenderStates: defaultRenderStates
|
||||
});
|
||||
}
|
||||
|
||||
var leftFarActionGrabEntity = new FarActionGrabEntity(LEFT_HAND);
|
||||
|
@ -657,11 +538,9 @@ Script.include("/~/system/libraries/Xform.js");
|
|||
enableDispatcherModule("LeftFarActionGrabEntity", leftFarActionGrabEntity);
|
||||
enableDispatcherModule("RightFarActionGrabEntity", rightFarActionGrabEntity);
|
||||
|
||||
this.cleanup = function () {
|
||||
leftFarActionGrabEntity.cleanup();
|
||||
rightFarActionGrabEntity.cleanup();
|
||||
function cleanup() {
|
||||
disableDispatcherModule("LeftFarActionGrabEntity");
|
||||
disableDispatcherModule("RightFarActionGrabEntity");
|
||||
};
|
||||
Script.scriptEnding.connect(this.cleanup);
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}());
|
||||
|
|
|
@ -16,74 +16,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
Script.include("/~/system/libraries/controllers.js");
|
||||
|
||||
(function() {
|
||||
var SEARCH_SPHERE_SIZE = 0.0132;
|
||||
var dim = {x: SEARCH_SPHERE_SIZE, y: SEARCH_SPHERE_SIZE, z: SEARCH_SPHERE_SIZE};
|
||||
var halfPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
var halfEnd = {
|
||||
type: "sphere",
|
||||
dimensions: dim,
|
||||
solid: true,
|
||||
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
alpha: 0.9,
|
||||
ignoreRayIntersection: true,
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
visible: true
|
||||
};
|
||||
var fullPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
var fullEnd = {
|
||||
type: "sphere",
|
||||
dimensions: dim,
|
||||
solid: true,
|
||||
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
|
||||
alpha: 0.9,
|
||||
ignoreRayIntersection: true,
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
visible: true
|
||||
};
|
||||
var holdPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_DISTANCE_HOLD,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
|
||||
var renderStates = [
|
||||
{name: "half", path: halfPath, end: halfEnd},
|
||||
{name: "full", path: fullPath, end: fullEnd},
|
||||
{name: "hold", path: holdPath}
|
||||
];
|
||||
|
||||
var defaultRenderStates = [
|
||||
{name: "half", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: halfPath},
|
||||
{name: "full", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: fullPath},
|
||||
{name: "hold", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: holdPath}
|
||||
];
|
||||
|
||||
function entityWantsNearTrigger(props) {
|
||||
var grabbableData = getGrabbableData(props);
|
||||
return grabbableData.triggerable || grabbableData.wantsTrigger;
|
||||
|
@ -101,27 +33,8 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
520,
|
||||
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||
[],
|
||||
100);
|
||||
|
||||
this.handToController = function() {
|
||||
return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
|
||||
};
|
||||
|
||||
this.updateLaserPointer = function(controllerData) {
|
||||
var mode = "none";
|
||||
if (controllerData.triggerClicks[this.hand]) {
|
||||
mode = "full";
|
||||
} else {
|
||||
mode = "half";
|
||||
}
|
||||
|
||||
LaserPointers.enableLaserPointer(this.laserPointer);
|
||||
LaserPointers.setRenderState(this.laserPointer, mode);
|
||||
};
|
||||
|
||||
this.laserPointerOff = function() {
|
||||
LaserPointers.disableLaserPointer(this.laserPointer);
|
||||
};
|
||||
100,
|
||||
this.hand);
|
||||
|
||||
this.getTargetProps = function (controllerData) {
|
||||
// nearbyEntityProperties is already sorted by length from controller
|
||||
|
@ -148,7 +61,6 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
this.endFarTrigger = function (controllerData) {
|
||||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||
Entities.callEntityMethod(this.targetEntityID, "stopFarTrigger", args);
|
||||
this.laserPointerOff();
|
||||
};
|
||||
|
||||
this.isReady = function (controllerData) {
|
||||
|
@ -173,32 +85,9 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
this.endFarTrigger(controllerData);
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
|
||||
this.updateLaserPointer(controllerData);
|
||||
this.continueFarTrigger(controllerData);
|
||||
return makeRunningValues(true, [this.targetEntityID], []);
|
||||
};
|
||||
|
||||
this.laserPointer = LaserPointers.createLaserPointer({
|
||||
joint: (this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND",
|
||||
filter: Picks.PICK_ENTITIES | Picks.PICK_OVERLAYS,
|
||||
maxDistance: PICK_MAX_DISTANCE,
|
||||
posOffset: getGrabPointSphereOffset(this.handToController(), true),
|
||||
renderStates: renderStates,
|
||||
faceAvatar: true,
|
||||
distanceScaleEnd: true,
|
||||
scaleWithAvatar: true,
|
||||
defaultRenderStates: defaultRenderStates
|
||||
});
|
||||
|
||||
this.cleanup = function () {
|
||||
if (this.targetEntityID) {
|
||||
this.endFarTrigger();
|
||||
}
|
||||
|
||||
LaserPointers.disableLaserPointer(this.laserPointer);
|
||||
LaserPointers.removeLaserPointer(this.laserPointer);
|
||||
};
|
||||
}
|
||||
|
||||
var leftFarTriggerEntity = new FarTriggerEntity(LEFT_HAND);
|
||||
|
@ -207,11 +96,9 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
enableDispatcherModule("LeftFarTriggerEntity", leftFarTriggerEntity);
|
||||
enableDispatcherModule("RightFarTriggerEntity", rightFarTriggerEntity);
|
||||
|
||||
this.cleanup = function () {
|
||||
leftFarTriggerEntity.cleanup();
|
||||
rightFarTriggerEntity.cleanup();
|
||||
function cleanup() {
|
||||
disableDispatcherModule("LeftFarTriggerEntity");
|
||||
disableDispatcherModule("RightFarTriggerEntity");
|
||||
};
|
||||
Script.scriptEnding.connect(this.cleanup);
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}());
|
||||
|
|
|
@ -22,100 +22,26 @@
|
|||
(function() {
|
||||
Script.include("/~/system/libraries/controllers.js");
|
||||
var ControllerDispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
var END_RADIUS = 0.005;
|
||||
var dim = { x: END_RADIUS, y: END_RADIUS, z: END_RADIUS };
|
||||
var halfPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawHUDLayer: true,
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
var halfEnd = {
|
||||
type: "sphere",
|
||||
dimensions: dim,
|
||||
solid: true,
|
||||
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
alpha: 0.9,
|
||||
ignoreRayIntersection: true,
|
||||
drawHUDLayer: true,
|
||||
visible: true
|
||||
};
|
||||
var fullPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawHUDLayer: true,
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
var fullEnd = {
|
||||
type: "sphere",
|
||||
dimensions: dim,
|
||||
solid: true,
|
||||
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
|
||||
alpha: 0.9,
|
||||
ignoreRayIntersection: true,
|
||||
drawHUDLayer: true,
|
||||
visible: true
|
||||
};
|
||||
var holdPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_DISTANCE_HOLD,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawHUDLayer: true,
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
|
||||
var renderStates = [
|
||||
{name: "half", path: halfPath, end: halfEnd},
|
||||
{name: "full", path: fullPath, end: fullEnd},
|
||||
{name: "hold", path: holdPath}
|
||||
];
|
||||
|
||||
var defaultRenderStates = [
|
||||
{name: "half", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: halfPath},
|
||||
{name: "full", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: fullPath},
|
||||
{name: "hold", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: holdPath}
|
||||
];
|
||||
|
||||
var MARGIN = 25;
|
||||
|
||||
var HUD_LASER_OFFSET = 2;
|
||||
function HudOverlayPointer(hand) {
|
||||
var _this = this;
|
||||
this.hand = hand;
|
||||
this.running = false;
|
||||
this.reticleMinX = MARGIN;
|
||||
this.reticleMaxX;
|
||||
this.reticleMinY = MARGIN;
|
||||
this.reticleMaxY;
|
||||
this.clicked = false;
|
||||
this.triggerClicked = 0;
|
||||
this.movedAway = false;
|
||||
this.parameters = ControllerDispatcherUtils.makeDispatcherModuleParameters(
|
||||
540,
|
||||
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||
[],
|
||||
100);
|
||||
100,
|
||||
(this.hand + HUD_LASER_OFFSET));
|
||||
|
||||
this.getOtherHandController = function() {
|
||||
return (this.hand === RIGHT_HAND) ? Controller.Standard.LeftHand : Controller.Standard.RightHand;
|
||||
};
|
||||
|
||||
_this.isClicked = function() {
|
||||
return _this.triggerClicked;
|
||||
};
|
||||
|
||||
this.handToController = function() {
|
||||
return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
|
||||
};
|
||||
|
@ -126,22 +52,6 @@
|
|||
this.reticleMaxY = dims.y - MARGIN;
|
||||
};
|
||||
|
||||
this.updateLaserPointer = function(controllerData) {
|
||||
LaserPointers.enableLaserPointer(this.laserPointer);
|
||||
LaserPointers.setRenderState(this.laserPointer, this.mode);
|
||||
};
|
||||
|
||||
this.processControllerTriggers = function(controllerData) {
|
||||
if (controllerData.triggerClicks[this.hand]) {
|
||||
this.mode = "full";
|
||||
} else if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) {
|
||||
this.clicked = false;
|
||||
this.mode = "half";
|
||||
} else {
|
||||
this.mode = "none";
|
||||
}
|
||||
};
|
||||
|
||||
this.calculateNewReticlePosition = function(intersection) {
|
||||
this.updateRecommendedArea();
|
||||
var point2d = HMD.overlayFromWorldPoint(intersection);
|
||||
|
@ -150,78 +60,55 @@
|
|||
return point2d;
|
||||
};
|
||||
|
||||
this.setReticlePosition = function(point2d) {
|
||||
Reticle.setPosition(point2d);
|
||||
};
|
||||
|
||||
this.pointingAtTablet = function(controllerData) {
|
||||
var rayPick = controllerData.rayPicks[this.hand];
|
||||
return (rayPick.objectID === HMD.tabletScreenID || rayPick.objectID === HMD.homeButtonID);
|
||||
};
|
||||
|
||||
this.getOtherModule = function() {
|
||||
return this.hand === RIGHT_HAND ? leftHudOverlayPointer : rightHudOverlayPointer;
|
||||
};
|
||||
|
||||
this.processLaser = function(controllerData) {
|
||||
var controllerLocation = controllerData.controllerLocations[this.hand];
|
||||
var otherModuleRunning = this.getOtherModule().running;
|
||||
if ((controllerData.triggerValues[this.hand] < ControllerDispatcherUtils.TRIGGER_ON_VALUE || !controllerLocation.valid) ||
|
||||
this.pointingAtTablet(controllerData)) {
|
||||
this.exitModule();
|
||||
return false;
|
||||
}
|
||||
var hudRayPick = controllerData.hudRayPicks[this.hand];
|
||||
var point2d = this.calculateNewReticlePosition(hudRayPick.intersection);
|
||||
if (!Window.isPointOnDesktopWindow(point2d) && !this.triggerClicked) {
|
||||
this.exitModule();
|
||||
return false;
|
||||
}
|
||||
this.setReticlePosition(point2d);
|
||||
Reticle.visible = false;
|
||||
this.movedAway = false;
|
||||
|
||||
this.triggerClicked = controllerData.triggerClicks[this.hand];
|
||||
this.processControllerTriggers(controllerData);
|
||||
this.updateLaserPointer(controllerData);
|
||||
return true;
|
||||
};
|
||||
|
||||
this.exitModule = function() {
|
||||
LaserPointers.disableLaserPointer(this.laserPointer);
|
||||
};
|
||||
|
||||
this.isReady = function (controllerData) {
|
||||
if (this.processLaser(controllerData)) {
|
||||
return ControllerDispatcherUtils.makeRunningValues(true, [], []);
|
||||
} else {
|
||||
return ControllerDispatcherUtils.makeRunningValues(false, [], []);
|
||||
var otherModuleRunning = this.getOtherModule().running;
|
||||
if (!otherModuleRunning) {
|
||||
if (this.processLaser(controllerData)) {
|
||||
this.running = true;
|
||||
return ControllerDispatcherUtils.makeRunningValues(true, [], []);
|
||||
} else {
|
||||
this.running = false;
|
||||
return ControllerDispatcherUtils.makeRunningValues(false, [], []);
|
||||
}
|
||||
}
|
||||
return ControllerDispatcherUtils.makeRunningValues(false, [], []);
|
||||
};
|
||||
|
||||
this.run = function (controllerData, deltaTime) {
|
||||
return this.isReady(controllerData);
|
||||
};
|
||||
|
||||
this.cleanup = function () {
|
||||
LaserPointers.disableLaserPointer(this.laserPointer);
|
||||
LaserPointers.removeLaserPointer(this.laserPointer);
|
||||
};
|
||||
|
||||
this.laserPointer = LaserPointers.createLaserPointer({
|
||||
joint: (this.hand === RIGHT_HAND) ? "_CONTROLLER_RIGHTHAND" : "_CONTROLLER_LEFTHAND",
|
||||
filter: Picks.PICK_HUD,
|
||||
maxDistance: PICK_MAX_DISTANCE,
|
||||
posOffset: getGrabPointSphereOffset(this.handToController(), true),
|
||||
renderStates: renderStates,
|
||||
enabled: true,
|
||||
defaultRenderStates: defaultRenderStates
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var leftHudOverlayPointer = new HudOverlayPointer(LEFT_HAND);
|
||||
var rightHudOverlayPointer = new HudOverlayPointer(RIGHT_HAND);
|
||||
|
||||
var clickMapping = Controller.newMapping('HudOverlayPointer-click');
|
||||
clickMapping.from(rightHudOverlayPointer.isClicked).to(Controller.Actions.ReticleClick);
|
||||
clickMapping.from(leftHudOverlayPointer.isClicked).to(Controller.Actions.ReticleClick);
|
||||
clickMapping.enable();
|
||||
|
||||
ControllerDispatcherUtils.enableDispatcherModule("LeftHudOverlayPointer", leftHudOverlayPointer);
|
||||
ControllerDispatcherUtils.enableDispatcherModule("RightHudOverlayPointer", rightHudOverlayPointer);
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
/* global Script, Controller, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule, makeRunningValues,
|
||||
Messages, makeDispatcherModuleParameters, HMD, getGrabPointSphereOffset, COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_ON_VALUE,
|
||||
getEnabledModuleByName, PICK_MAX_DISTANCE, isInEditMode, LaserPointers, RayPick
|
||||
getEnabledModuleByName, PICK_MAX_DISTANCE, isInEditMode, LaserPointers, RayPick, Picks
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
@ -18,84 +18,17 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
Script.include("/~/system/libraries/utils.js");
|
||||
|
||||
(function () {
|
||||
var END_RADIUS = 0.005;
|
||||
var dim = { x: END_RADIUS, y: END_RADIUS, z: END_RADIUS };
|
||||
var halfPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
var halfEnd = {
|
||||
type: "sphere",
|
||||
dimensions: dim,
|
||||
solid: true,
|
||||
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
alpha: 0.9,
|
||||
ignoreRayIntersection: true,
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
visible: true
|
||||
};
|
||||
var fullPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
var fullEnd = {
|
||||
type: "sphere",
|
||||
dimensions: dim,
|
||||
solid: true,
|
||||
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
|
||||
alpha: 0.9,
|
||||
ignoreRayIntersection: true,
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
visible: true
|
||||
};
|
||||
var holdPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_DISTANCE_HOLD,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
|
||||
var renderStates = [
|
||||
{name: "half", path: halfPath, end: halfEnd},
|
||||
{name: "full", path: fullPath, end: fullEnd},
|
||||
{name: "hold", path: holdPath}
|
||||
];
|
||||
|
||||
var defaultRenderStates = [
|
||||
{name: "half", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: halfPath},
|
||||
{name: "full", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: fullPath},
|
||||
{name: "hold", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: holdPath}
|
||||
];
|
||||
|
||||
function InEditMode(hand) {
|
||||
this.hand = hand;
|
||||
this.triggerClicked = false;
|
||||
this.mode = "none";
|
||||
this.selectedTarget = null;
|
||||
|
||||
this.parameters = makeDispatcherModuleParameters(
|
||||
160,
|
||||
this.hand === RIGHT_HAND ? ["rightHand", "rightHandEquip", "rightHandTrigger"] : ["leftHand", "leftHandEquip", "leftHandTrigger"],
|
||||
[],
|
||||
100);
|
||||
100,
|
||||
this.hand);
|
||||
|
||||
this.nearTablet = function(overlays) {
|
||||
for (var i = 0; i < overlays.length; i++) {
|
||||
|
@ -110,29 +43,6 @@ Script.include("/~/system/libraries/utils.js");
|
|||
return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
|
||||
};
|
||||
|
||||
|
||||
this.processControllerTriggers = function(controllerData) {
|
||||
if (controllerData.triggerClicks[this.hand]) {
|
||||
this.mode = "full";
|
||||
} else if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) {
|
||||
this.mode = "half";
|
||||
} else {
|
||||
this.mode = "none";
|
||||
}
|
||||
};
|
||||
|
||||
this.updateLaserPointer = function(controllerData) {
|
||||
LaserPointers.enableLaserPointer(this.laserPointer);
|
||||
LaserPointers.setRenderState(this.laserPointer, this.mode);
|
||||
|
||||
if (HMD.tabletID !== this.tabletID || HMD.homeButtonID !== this.homeButtonID || HMD.tabletScreenID !== this.tabletScreenID) {
|
||||
this.tabletID = HMD.tabletID;
|
||||
this.homeButtonID = HMD.homeButtonID;
|
||||
this.tabletScreenID = HMD.tabletScreenID;
|
||||
LaserPointers.setIgnoreItems(this.laserPointer, [HMD.tabletID, HMD.homeButtonID, HMD.tabletScreenID]);
|
||||
}
|
||||
};
|
||||
|
||||
this.pointingAtTablet = function(objectID) {
|
||||
if (objectID === HMD.tabletScreenID || objectID === HMD.homeButtonID) {
|
||||
return true;
|
||||
|
@ -141,41 +51,39 @@ Script.include("/~/system/libraries/utils.js");
|
|||
};
|
||||
|
||||
this.sendPickData = function(controllerData) {
|
||||
if (controllerData.triggerClicks[this.hand] && !this.triggerClicked) {
|
||||
var intersection = controllerData.rayPicks[this.hand];
|
||||
if (intersection.type === Picks.INTERSECTED_ENTITY) {
|
||||
if (controllerData.triggerClicks[this.hand]) {
|
||||
if (!this.triggerClicked) {
|
||||
this.selectedTarget = controllerData.rayPicks[this.hand];
|
||||
}
|
||||
if (this.selectedTarget.type === Picks.INTERSECTED_ENTITY) {
|
||||
Messages.sendLocalMessage("entityToolUpdates", JSON.stringify({
|
||||
method: "selectEntity",
|
||||
entityID: intersection.objectID
|
||||
entityID: this.selectedTarget.objectID
|
||||
}));
|
||||
} else if (intersection.type === Picks.INTERSECTED_OVERLAY) {
|
||||
} else if (this.selectedTarget.type === Picks.INTERSECTED_OVERLAY) {
|
||||
Messages.sendLocalMessage("entityToolUpdates", JSON.stringify({
|
||||
method: "selectOverlay",
|
||||
overlayID: intersection.objectID
|
||||
overlayID: this.selectedTarget.objectID
|
||||
}));
|
||||
}
|
||||
|
||||
this.triggerClicked = true;
|
||||
} else {
|
||||
this.triggerClicked = false;
|
||||
}
|
||||
};
|
||||
|
||||
this.exitModule = function() {
|
||||
this.disableLasers();
|
||||
return makeRunningValues(false, [], []);
|
||||
};
|
||||
|
||||
this.disableLasers = function() {
|
||||
LaserPointers.disableLaserPointer(this.laserPointer);
|
||||
};
|
||||
|
||||
this.isReady = function(controllerData) {
|
||||
if (isInEditMode()) {
|
||||
this.triggerClicked = false;
|
||||
if (controllerData.triggerValues[this.hand] < TRIGGER_ON_VALUE) {
|
||||
this.triggerClicked = false;
|
||||
}
|
||||
return makeRunningValues(true, [], []);
|
||||
}
|
||||
return this.exitModule();
|
||||
this.triggerClicked = false;
|
||||
return makeRunningValues(false, [], []);
|
||||
};
|
||||
|
||||
this.run = function(controllerData) {
|
||||
|
@ -188,7 +96,7 @@ Script.include("/~/system/libraries/utils.js");
|
|||
}
|
||||
}
|
||||
|
||||
var overlayLaser = getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightOverlayLaserInput" : "LeftOverlayLaserInput");
|
||||
var overlayLaser = getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightWebSurfaceLaserInput" : "LeftWebSurfaceLaserInput");
|
||||
if (overlayLaser) {
|
||||
var overlayLaserReady = overlayLaser.isReady(controllerData);
|
||||
|
||||
|
@ -213,32 +121,9 @@ Script.include("/~/system/libraries/utils.js");
|
|||
return this.exitModule();
|
||||
}
|
||||
}
|
||||
|
||||
this.processControllerTriggers(controllerData);
|
||||
this.updateLaserPointer(controllerData);
|
||||
this.sendPickData(controllerData);
|
||||
|
||||
|
||||
return this.isReady(controllerData);
|
||||
};
|
||||
|
||||
this.cleanup = function() {
|
||||
LaserPointers.disableLaserPointer(this.laserPointer);
|
||||
LaserPointers.removeLaserPointer(this.laserPointer);
|
||||
};
|
||||
|
||||
this.laserPointer = LaserPointers.createLaserPointer({
|
||||
joint: (this.hand === RIGHT_HAND) ? "_CONTROLLER_RIGHTHAND" : "_CONTROLLER_LEFTHAND",
|
||||
filter: Picks.PICK_ENTITIES | Picks.PICK_OVERLAYS,
|
||||
maxDistance: PICK_MAX_DISTANCE,
|
||||
posOffset: getGrabPointSphereOffset(this.handToController(), true),
|
||||
renderStates: renderStates,
|
||||
faceAvatar: true,
|
||||
scaleWithAvatar: true,
|
||||
defaultRenderStates: defaultRenderStates
|
||||
});
|
||||
|
||||
LaserPointers.setIgnoreItems(this.laserPointer, [HMD.tabletID, HMD.homeButtonID, HMD.tabletScreenID]);
|
||||
}
|
||||
|
||||
var leftHandInEditMode = new InEditMode(LEFT_HAND);
|
||||
|
@ -247,12 +132,10 @@ Script.include("/~/system/libraries/utils.js");
|
|||
enableDispatcherModule("LeftHandInEditMode", leftHandInEditMode);
|
||||
enableDispatcherModule("RightHandInEditMode", rightHandInEditMode);
|
||||
|
||||
this.cleanup = function() {
|
||||
leftHandInEditMode.cleanup();
|
||||
rightHandInEditMode.cleanup();
|
||||
function cleanup() {
|
||||
disableDispatcherModule("LeftHandInEditMode");
|
||||
disableDispatcherModule("RightHandInEditMode");
|
||||
};
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(this.cleanup);
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}());
|
||||
|
|
|
@ -256,11 +256,11 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
|||
enableDispatcherModule("LeftNearActionGrabEntity", leftNearActionGrabEntity);
|
||||
enableDispatcherModule("RightNearActionGrabEntity", rightNearActionGrabEntity);
|
||||
|
||||
this.cleanup = function () {
|
||||
function cleanup() {
|
||||
leftNearActionGrabEntity.cleanup();
|
||||
rightNearActionGrabEntity.cleanup();
|
||||
disableDispatcherModule("LeftNearActionGrabEntity");
|
||||
disableDispatcherModule("RightNearActionGrabEntity");
|
||||
};
|
||||
Script.scriptEnding.connect(this.cleanup);
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}());
|
||||
|
|
|
@ -338,11 +338,11 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
|||
enableDispatcherModule("LeftNearParentingGrabEntity", leftNearParentingGrabEntity);
|
||||
enableDispatcherModule("RightNearParentingGrabEntity", rightNearParentingGrabEntity);
|
||||
|
||||
this.cleanup = function () {
|
||||
function cleanup() {
|
||||
leftNearParentingGrabEntity.cleanup();
|
||||
rightNearParentingGrabEntity.cleanup();
|
||||
disableDispatcherModule("LeftNearParentingGrabEntity");
|
||||
disableDispatcherModule("RightNearParentingGrabEntity");
|
||||
};
|
||||
Script.scriptEnding.connect(this.cleanup);
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}());
|
||||
|
|
|
@ -224,11 +224,11 @@ Script.include("/~/system/libraries/utils.js");
|
|||
enableDispatcherModule("LeftNearParentingGrabOverlay", leftNearParentingGrabOverlay);
|
||||
enableDispatcherModule("RightNearParentingGrabOverlay", rightNearParentingGrabOverlay);
|
||||
|
||||
this.cleanup = function () {
|
||||
function cleanup() {
|
||||
leftNearParentingGrabOverlay.cleanup();
|
||||
rightNearParentingGrabOverlay.cleanup();
|
||||
disableDispatcherModule("LeftNearParentingGrabOverlay");
|
||||
disableDispatcherModule("RightNearParentingGrabOverlay");
|
||||
};
|
||||
Script.scriptEnding.connect(this.cleanup);
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}());
|
||||
|
|
|
@ -110,11 +110,11 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
enableDispatcherModule("LeftNearTriggerEntity", leftNearTriggerEntity);
|
||||
enableDispatcherModule("RightNearTriggerEntity", rightNearTriggerEntity);
|
||||
|
||||
this.cleanup = function () {
|
||||
function cleanup() {
|
||||
leftNearTriggerEntity.cleanup();
|
||||
rightNearTriggerEntity.cleanup();
|
||||
disableDispatcherModule("LeftNearTriggerEntity");
|
||||
disableDispatcherModule("RightNearTriggerEntity");
|
||||
};
|
||||
Script.scriptEnding.connect(this.cleanup);
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}());
|
||||
|
|
|
@ -1,391 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
// overlayLaserInput.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, Controller, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule,
|
||||
makeRunningValues, Messages, Quat, Vec3, makeDispatcherModuleParameters, Overlays, ZERO_VEC, HMD,
|
||||
INCHES_TO_METERS, DEFAULT_REGISTRATION_POINT, getGrabPointSphereOffset, COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_ON_VALUE,
|
||||
TRIGGER_OFF_VALUE, getEnabledModuleByName, PICK_MAX_DISTANCE, LaserPointers, RayPick, ContextOverlay
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
Script.include("/~/system/libraries/controllers.js");
|
||||
|
||||
(function() {
|
||||
var TouchEventUtils = Script.require("/~/system/libraries/touchEventUtils.js");
|
||||
var END_RADIUS = 0.005;
|
||||
var dim = { x: END_RADIUS, y: END_RADIUS, z: END_RADIUS };
|
||||
var halfPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
var halfEnd = {
|
||||
type: "sphere",
|
||||
dimensions: dim,
|
||||
solid: true,
|
||||
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
alpha: 0.9,
|
||||
ignoreRayIntersection: true,
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
visible: true
|
||||
};
|
||||
var fullPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
var fullEnd = {
|
||||
type: "sphere",
|
||||
dimensions: dim,
|
||||
solid: true,
|
||||
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
|
||||
alpha: 0.9,
|
||||
ignoreRayIntersection: true,
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
visible: true
|
||||
};
|
||||
var holdPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_DISTANCE_HOLD,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
|
||||
var renderStates = [
|
||||
{name: "half", path: halfPath, end: halfEnd},
|
||||
{name: "full", path: fullPath, end: fullEnd},
|
||||
{name: "hold", path: holdPath}
|
||||
];
|
||||
|
||||
var defaultRenderStates = [
|
||||
{name: "half", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: halfPath},
|
||||
{name: "full", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: fullPath},
|
||||
{name: "hold", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: holdPath}
|
||||
];
|
||||
|
||||
|
||||
// triggered when stylus presses a web overlay/entity
|
||||
var HAPTIC_STYLUS_STRENGTH = 1.0;
|
||||
var HAPTIC_STYLUS_DURATION = 20.0;
|
||||
|
||||
function distance2D(a, b) {
|
||||
var dx = (a.x - b.x);
|
||||
var dy = (a.y - b.y);
|
||||
return Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
function OverlayLaserInput(hand) {
|
||||
this.hand = hand;
|
||||
this.active = false;
|
||||
this.previousLaserClickedTarget = false;
|
||||
this.laserPressingTarget = false;
|
||||
this.mode = "none";
|
||||
this.laserTarget = null;
|
||||
this.pressEnterLaserTarget = null;
|
||||
|
||||
|
||||
this.parameters = makeDispatcherModuleParameters(
|
||||
120,
|
||||
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||
[],
|
||||
100);
|
||||
|
||||
this.getOtherHandController = function() {
|
||||
return (this.hand === RIGHT_HAND) ? Controller.Standard.LeftHand : Controller.Standard.RightHand;
|
||||
};
|
||||
|
||||
this.getOtherModule = function() {
|
||||
return (this.hand === RIGHT_HAND) ? leftOverlayLaserInput : rightOverlayLaserInput;
|
||||
};
|
||||
|
||||
this.handToController = function() {
|
||||
return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
|
||||
};
|
||||
|
||||
this.hasTouchFocus = function(laserTarget) {
|
||||
return (laserTarget.overlayID === this.hoverOverlay);
|
||||
};
|
||||
|
||||
this.requestTouchFocus = function(laserTarget) {
|
||||
if (laserTarget.overlayID &&
|
||||
laserTarget.overlayID !== this.hoverOverlay) {
|
||||
this.hoverOverlay = laserTarget.overlayID;
|
||||
TouchEventUtils.sendHoverEnterEventToTouchTarget(this.hand, laserTarget);
|
||||
}
|
||||
};
|
||||
|
||||
this.relinquishTouchFocus = function() {
|
||||
// send hover leave event.
|
||||
if (this.hoverOverlay) {
|
||||
var pointerEvent = { type: "Move", id: this.hand + 1 };
|
||||
Overlays.sendMouseMoveOnOverlay(this.hoverOverlay, pointerEvent);
|
||||
Overlays.sendHoverOverOverlay(this.hoverOverlay, pointerEvent);
|
||||
Overlays.sendHoverLeaveOverlay(this.hoverOverlay, pointerEvent);
|
||||
this.hoverOverlay = null;
|
||||
}
|
||||
};
|
||||
|
||||
this.relinquishStylusTargetTouchFocus = function(laserTarget) {
|
||||
var stylusModuleNames = ["LeftTabletStylusInput", "RightTabletStylusError"];
|
||||
for (var i = 0; i < stylusModuleNames.length; i++) {
|
||||
var stylusModule = getEnabledModuleByName(stylusModuleNames[i]);
|
||||
if (stylusModule) {
|
||||
if (stylusModule.hoverOverlay === laserTarget.overlayID) {
|
||||
stylusModule.relinquishTouchFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.stealTouchFocus = function(laserTarget) {
|
||||
if (laserTarget.overlayID === this.getOtherModule().hoverOverlay) {
|
||||
this.getOtherModule().relinquishTouchFocus();
|
||||
}
|
||||
|
||||
// If the focus target we want to request is the same of one of the stylus
|
||||
// tell the stylus to relinquish it focus on our target
|
||||
this.relinquishStylusTargetTouchFocus(laserTarget);
|
||||
|
||||
this.requestTouchFocus(laserTarget);
|
||||
};
|
||||
|
||||
this.updateLaserPointer = function(controllerData) {
|
||||
LaserPointers.enableLaserPointer(this.laserPointer);
|
||||
LaserPointers.setRenderState(this.laserPointer, this.mode);
|
||||
|
||||
if (HMD.tabletID !== this.tabletID) {
|
||||
this.tabletID = HMD.tabletID;
|
||||
LaserPointers.setIgnoreItems(this.laserPointer, [HMD.tabletID]);
|
||||
}
|
||||
};
|
||||
|
||||
this.processControllerTriggers = function(controllerData) {
|
||||
if (controllerData.triggerClicks[this.hand]) {
|
||||
this.mode = "full";
|
||||
} else if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) {
|
||||
this.mode = "half";
|
||||
} else {
|
||||
this.mode = "none";
|
||||
}
|
||||
};
|
||||
|
||||
this.laserPressEnter = function () {
|
||||
this.stealTouchFocus(this.laserTarget);
|
||||
TouchEventUtils.sendTouchStartEventToTouchTarget(this.hand, this.laserTarget);
|
||||
Controller.triggerHapticPulse(HAPTIC_STYLUS_STRENGTH, HAPTIC_STYLUS_DURATION, this.hand);
|
||||
|
||||
this.touchingEnterTimer = 0;
|
||||
this.pressEnterLaserTarget = this.laserTarget;
|
||||
this.deadspotExpired = false;
|
||||
|
||||
var LASER_PRESS_TO_MOVE_DEADSPOT = 0.094;
|
||||
this.deadspotRadius = Math.tan(LASER_PRESS_TO_MOVE_DEADSPOT) * this.laserTarget.distance;
|
||||
};
|
||||
|
||||
this.laserPressExit = function () {
|
||||
if (this.laserTarget === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// special case to handle home button.
|
||||
if (this.laserTarget.overlayID === HMD.homeButtonID) {
|
||||
Messages.sendLocalMessage("home", this.laserTarget.overlayID);
|
||||
}
|
||||
|
||||
// send press event
|
||||
if (this.deadspotExpired) {
|
||||
TouchEventUtils.sendTouchEndEventToTouchTarget(this.hand, this.laserTarget);
|
||||
} else {
|
||||
TouchEventUtils.sendTouchEndEventToTouchTarget(this.hand, this.pressEnterLaserTarget);
|
||||
}
|
||||
};
|
||||
|
||||
this.laserPressing = function (controllerData, dt) {
|
||||
this.touchingEnterTimer += dt;
|
||||
|
||||
if (this.laserTarget) {
|
||||
if (controllerData.triggerClicks[this.hand]) {
|
||||
var POINTER_PRESS_TO_MOVE_DELAY = 0.33; // seconds
|
||||
if (this.deadspotExpired || this.touchingEnterTimer > POINTER_PRESS_TO_MOVE_DELAY ||
|
||||
distance2D(this.laserTarget.position2D,
|
||||
this.pressEnterLaserTarget.position2D) > this.deadspotRadius) {
|
||||
TouchEventUtils.sendTouchMoveEventToTouchTarget(this.hand, this.laserTarget);
|
||||
this.deadspotExpired = true;
|
||||
}
|
||||
} else {
|
||||
this.laserPressingTarget = false;
|
||||
}
|
||||
} else {
|
||||
this.laserPressingTarget = false;
|
||||
}
|
||||
};
|
||||
|
||||
this.processLaser = function(controllerData) {
|
||||
if (this.shouldExit(controllerData) || this.getOtherModule().active) {
|
||||
this.exitModule();
|
||||
return false;
|
||||
}
|
||||
var intersection = controllerData.rayPicks[this.hand];
|
||||
var laserTarget = TouchEventUtils.composeTouchTargetFromIntersection(intersection);
|
||||
|
||||
if (controllerData.triggerClicks[this.hand]) {
|
||||
this.laserTarget = laserTarget;
|
||||
this.laserPressingTarget = true;
|
||||
} else {
|
||||
this.requestTouchFocus(laserTarget);
|
||||
|
||||
if (!TouchEventUtils.touchTargetHasKeyboardFocus(laserTarget)) {
|
||||
TouchEventUtils.setKeyboardFocusOnTouchTarget(laserTarget);
|
||||
}
|
||||
|
||||
if (this.hasTouchFocus(laserTarget) && !this.laserPressingTarget) {
|
||||
TouchEventUtils.sendHoverOverEventToTouchTarget(this.hand, laserTarget);
|
||||
}
|
||||
}
|
||||
|
||||
this.processControllerTriggers(controllerData);
|
||||
this.updateLaserPointer(controllerData);
|
||||
this.active = true;
|
||||
return true;
|
||||
};
|
||||
|
||||
this.grabModuleWantsNearbyOverlay = function(controllerData) {
|
||||
if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) {
|
||||
var nearGrabName = this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay";
|
||||
var nearGrabModule = getEnabledModuleByName(nearGrabName);
|
||||
if (nearGrabModule) {
|
||||
var candidateOverlays = controllerData.nearbyOverlayIDs[this.hand];
|
||||
var grabbableOverlays = candidateOverlays.filter(function(overlayID) {
|
||||
return Overlays.getProperty(overlayID, "grabbable");
|
||||
});
|
||||
var target = nearGrabModule.getTargetID(grabbableOverlays, controllerData);
|
||||
if (target) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.shouldExit = function(controllerData) {
|
||||
var intersection = controllerData.rayPicks[this.hand];
|
||||
var offOverlay = (intersection.type !== Picks.INTERSECTED_OVERLAY);
|
||||
var triggerOff = (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE);
|
||||
if (triggerOff) {
|
||||
this.deleteContextOverlay();
|
||||
}
|
||||
var grabbingOverlay = this.grabModuleWantsNearbyOverlay(controllerData);
|
||||
return offOverlay || grabbingOverlay || triggerOff;
|
||||
};
|
||||
|
||||
this.exitModule = function() {
|
||||
if (this.laserPressingTarget) {
|
||||
this.deadspotExpired = true;
|
||||
this.laserPressExit();
|
||||
this.laserPressingTarget = false;
|
||||
}
|
||||
this.relinquishTouchFocus();
|
||||
this.reset();
|
||||
this.updateLaserPointer();
|
||||
LaserPointers.disableLaserPointer(this.laserPointer);
|
||||
};
|
||||
|
||||
this.reset = function() {
|
||||
this.mode = "none";
|
||||
this.active = false;
|
||||
};
|
||||
|
||||
this.deleteContextOverlay = function() {
|
||||
var farGrabModule = getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightFarActionGrabEntity" : "LeftFarActionGrabEntity");
|
||||
if (farGrabModule) {
|
||||
var entityWithContextOverlay = farGrabModule.entityWithContextOverlay;
|
||||
|
||||
if (entityWithContextOverlay) {
|
||||
ContextOverlay.destroyContextOverlay(entityWithContextOverlay);
|
||||
farGrabModule.entityWithContextOverlay = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.isReady = function (controllerData) {
|
||||
if (this.processLaser(controllerData)) {
|
||||
return makeRunningValues(true, [], []);
|
||||
}
|
||||
return makeRunningValues(false, [], []);
|
||||
};
|
||||
|
||||
this.run = function (controllerData, deltaTime) {
|
||||
if (!this.previousLaserClickedTarget && this.laserPressingTarget) {
|
||||
this.laserPressEnter();
|
||||
}
|
||||
if (this.previousLaserClickedTarget && !this.laserPressingTarget) {
|
||||
this.laserPressExit();
|
||||
}
|
||||
this.previousLaserClickedTarget = this.laserPressingTarget;
|
||||
|
||||
if (this.laserPressingTarget) {
|
||||
this.laserPressing(controllerData, deltaTime);
|
||||
}
|
||||
|
||||
if (this.processLaser(controllerData)) {
|
||||
return makeRunningValues(true, [], []);
|
||||
} else {
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
};
|
||||
|
||||
this.cleanup = function () {
|
||||
LaserPointers.disableLaserPointer(this.laserPointer);
|
||||
LaserPointers.removeLaserPointer(this.laserPointer);
|
||||
};
|
||||
|
||||
this.laserPointer = LaserPointers.createLaserPointer({
|
||||
joint: (this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND",
|
||||
filter: Picks.PICK_OVERLAYS,
|
||||
maxDistance: PICK_MAX_DISTANCE,
|
||||
posOffset: getGrabPointSphereOffset(this.handToController(), true),
|
||||
renderStates: renderStates,
|
||||
faceAvatar: true,
|
||||
scaleWithAvatar: true,
|
||||
defaultRenderStates: defaultRenderStates
|
||||
});
|
||||
|
||||
LaserPointers.setIgnoreItems(this.laserPointer, [HMD.tabletID]);
|
||||
}
|
||||
|
||||
var leftOverlayLaserInput = new OverlayLaserInput(LEFT_HAND);
|
||||
var rightOverlayLaserInput = new OverlayLaserInput(RIGHT_HAND);
|
||||
|
||||
enableDispatcherModule("LeftOverlayLaserInput", leftOverlayLaserInput);
|
||||
enableDispatcherModule("RightOverlayLaserInput", rightOverlayLaserInput);
|
||||
|
||||
this.cleanup = function () {
|
||||
leftOverlayLaserInput.cleanup();
|
||||
rightOverlayLaserInput.cleanup();
|
||||
disableDispatcherModule("LeftOverlayLaserInput");
|
||||
disableDispatcherModule("RightOverlayLaserInput");
|
||||
};
|
||||
Script.scriptEnding.connect(this.cleanup);
|
||||
}());
|
|
@ -8,7 +8,6 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
/* global Script, Vec3, MyAvatar, RIGHT_HAND */
|
||||
/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */
|
||||
|
||||
(function () {
|
||||
var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
@ -59,7 +58,7 @@
|
|||
if (this.hand === dispatcherUtils.RIGHT_HAND) {
|
||||
var scalingCurrentDistance =
|
||||
Vec3.length(Vec3.subtract(controllerData.controllerLocations[this.hand].position,
|
||||
controllerData.controllerLocations[this.otherHand()].position));
|
||||
controllerData.controllerLocations[this.otherHand()].position));
|
||||
|
||||
var newAvatarScale = (scalingCurrentDistance / this.scalingStartDistance) * this.scalingStartAvatarScale;
|
||||
MyAvatar.scale = newAvatarScale;
|
||||
|
@ -79,6 +78,6 @@
|
|||
function cleanup() {
|
||||
dispatcherUtils.disableDispatcherModule("LeftScaleAvatar");
|
||||
dispatcherUtils.disableDispatcherModule("RightScaleAvatar");
|
||||
};
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
})();
|
||||
|
|
|
@ -8,11 +8,9 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
/* global Script, Vec3, MyAvatar, RIGHT_HAND */
|
||||
/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */
|
||||
|
||||
(function() {
|
||||
var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
||||
function ScaleEntity(hand) {
|
||||
this.hand = hand;
|
||||
this.grabbedThingID = false;
|
||||
|
@ -81,7 +79,7 @@
|
|||
if (this.hand === dispatcherUtils.RIGHT_HAND) {
|
||||
var scalingCurrentDistance =
|
||||
Vec3.length(Vec3.subtract(controllerData.controllerLocations[this.hand].position,
|
||||
controllerData.controllerLocations[this.otherHand()].position));
|
||||
controllerData.controllerLocations[this.otherHand()].position));
|
||||
var currentRescale = scalingCurrentDistance / this.scalingStartDistance;
|
||||
var newDimensions = Vec3.multiply(currentRescale, this.scalingStartDimensions);
|
||||
Entities.editEntity(this.grabbedThingID, { dimensions: newDimensions });
|
||||
|
@ -98,9 +96,9 @@
|
|||
dispatcherUtils.enableDispatcherModule("LeftScaleEntity", leftScaleEntity);
|
||||
dispatcherUtils.enableDispatcherModule("RightScaleEntity", rightScaleEntity);
|
||||
|
||||
this.cleanup = function() {
|
||||
function cleanup() {
|
||||
dispatcherUtils.disableDispatcherModule("LeftScaleEntity");
|
||||
dispatcherUtils.disableDispatcherModule("RightScaleEntity");
|
||||
};
|
||||
Script.scriptEnding.connect(this.cleanup);
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
})();
|
||||
|
|
205
scripts/system/controllers/controllerModules/stylusInput.js
Normal file
205
scripts/system/controllers/controllerModules/stylusInput.js
Normal file
|
@ -0,0 +1,205 @@
|
|||
"use strict";
|
||||
|
||||
// stylusInput.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,
|
||||
enableDispatcherModule, disableDispatcherModule, makeRunningValues,
|
||||
Messages, Quat, Vec3, getControllerWorldLocation, makeDispatcherModuleParameters, Overlays, ZERO_VEC,
|
||||
HMD, INCHES_TO_METERS, DEFAULT_REGISTRATION_POINT, Settings, getGrabPointSphereOffset,
|
||||
getEnabledModuleByName, Pointers, Picks, PickType
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
Script.include("/~/system/libraries/controllers.js");
|
||||
|
||||
(function() {
|
||||
function isNearStylusTarget(stylusTargets, maxNormalDistance) {
|
||||
var stylusTargetIDs = [];
|
||||
for (var index = 0; index < stylusTargets.length; index++) {
|
||||
var stylusTarget = stylusTargets[index];
|
||||
if (stylusTarget.distance <= maxNormalDistance && stylusTarget.id !== HMD.tabletID) {
|
||||
stylusTargetIDs.push(stylusTarget.id);
|
||||
}
|
||||
}
|
||||
return stylusTargetIDs;
|
||||
}
|
||||
|
||||
function getOverlayDistance(controllerPosition, overlayID) {
|
||||
var position = Overlays.getProperty(overlayID, "position");
|
||||
return {
|
||||
id: overlayID,
|
||||
distance: Vec3.distance(position, controllerPosition)
|
||||
};
|
||||
}
|
||||
|
||||
function getEntityDistance(controllerPosition, entityProps) {
|
||||
return {
|
||||
id: entityProps.id,
|
||||
distance: Vec3.distance(entityProps.position, controllerPosition)
|
||||
};
|
||||
}
|
||||
|
||||
function StylusInput(hand) {
|
||||
this.hand = hand;
|
||||
|
||||
this.parameters = makeDispatcherModuleParameters(
|
||||
100,
|
||||
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||
[],
|
||||
100);
|
||||
|
||||
this.pointer = Pointers.createPointer(PickType.Stylus, {
|
||||
hand: this.hand,
|
||||
filter: Picks.PICK_OVERLAYS,
|
||||
hover: true,
|
||||
enabled: true
|
||||
});
|
||||
|
||||
this.disable = false;
|
||||
|
||||
this.otherModuleNeedsToRun = function(controllerData) {
|
||||
var grabOverlayModuleName = this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay";
|
||||
var grabOverlayModule = getEnabledModuleByName(grabOverlayModuleName);
|
||||
var grabOverlayModuleReady = grabOverlayModule ? grabOverlayModule.isReady(controllerData) : makeRunningValues(false, [], []);
|
||||
var farGrabModuleName = this.hand === RIGHT_HAND ? "RightFarActionGrabEntity" : "LeftFarActionGrabEntity";
|
||||
var farGrabModule = getEnabledModuleByName(farGrabModuleName);
|
||||
var farGrabModuleReady = farGrabModule ? farGrabModule.isReady(controllerData) : makeRunningValues(false, [], []);
|
||||
return grabOverlayModuleReady.active || farGrabModuleReady.active;
|
||||
};
|
||||
|
||||
this.overlayLaserActive = function(controllerData) {
|
||||
var rightOverlayLaserModule = getEnabledModuleByName("RightWebSurfaceLaserInput");
|
||||
var leftOverlayLaserModule = getEnabledModuleByName("LeftWebSurfaceLaserInput");
|
||||
var rightModuleRunning = rightOverlayLaserModule ? rightOverlayLaserModule.isReady(controllerData).active : false;
|
||||
var leftModuleRunning = leftOverlayLaserModule ? leftOverlayLaserModule.isReady(controllerData).active : false;
|
||||
return leftModuleRunning || rightModuleRunning;
|
||||
};
|
||||
|
||||
this.processStylus = function(controllerData) {
|
||||
if (this.overlayLaserActive(controllerData) || this.otherModuleNeedsToRun(controllerData)) {
|
||||
Pointers.setRenderState(this.pointer, "disabled");
|
||||
return false;
|
||||
}
|
||||
|
||||
var sensorScaleFactor = MyAvatar.sensorToWorldScale;
|
||||
|
||||
// build list of stylus targets, near the stylusTip
|
||||
var stylusTargets = [];
|
||||
var candidateOverlays = controllerData.nearbyOverlayIDs;
|
||||
var controllerPosition = controllerData.controllerLocations[this.hand].position;
|
||||
var i, stylusTarget;
|
||||
|
||||
for (i = 0; i < candidateOverlays.length; i++) {
|
||||
if (candidateOverlays[i] !== HMD.tabletID &&
|
||||
Overlays.getProperty(candidateOverlays[i], "visible")) {
|
||||
stylusTarget = getOverlayDistance(controllerPosition, candidateOverlays[i]);
|
||||
if (stylusTarget) {
|
||||
stylusTargets.push(stylusTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add the tabletScreen, if it is valid
|
||||
if (HMD.tabletScreenID && HMD.tabletScreenID !== Uuid.NULL &&
|
||||
Overlays.getProperty(HMD.tabletScreenID, "visible")) {
|
||||
stylusTarget = getOverlayDistance(controllerPosition, HMD.tabletScreenID);
|
||||
if (stylusTarget) {
|
||||
stylusTargets.push(stylusTarget);
|
||||
}
|
||||
}
|
||||
|
||||
// add the tablet home button.
|
||||
if (HMD.homeButtonID && HMD.homeButtonID !== Uuid.NULL &&
|
||||
Overlays.getProperty(HMD.homeButtonID, "visible")) {
|
||||
stylusTarget = getOverlayDistance(controllerPosition, HMD.homeButtonID);
|
||||
if (stylusTarget) {
|
||||
stylusTargets.push(stylusTarget);
|
||||
}
|
||||
}
|
||||
|
||||
var WEB_DISPLAY_STYLUS_DISTANCE = 0.5;
|
||||
var nearStylusTarget = isNearStylusTarget(stylusTargets, WEB_DISPLAY_STYLUS_DISTANCE * sensorScaleFactor);
|
||||
|
||||
if (nearStylusTarget.length !== 0) {
|
||||
if (!this.disable) {
|
||||
Pointers.setRenderState(this.pointer,"events on");
|
||||
Pointers.setIncludeItems(this.pointer, nearStylusTarget);
|
||||
} else {
|
||||
Pointers.setRenderState(this.pointer,"events off");
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
Pointers.setRenderState(this.pointer, "disabled");
|
||||
Pointers.setIncludeItems(this.pointer, []);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
this.isReady = function (controllerData) {
|
||||
if (this.processStylus(controllerData)) {
|
||||
Pointers.enablePointer(this.pointer);
|
||||
return makeRunningValues(true, [], []);
|
||||
} else {
|
||||
Pointers.disablePointer(this.pointer);
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
};
|
||||
|
||||
this.run = function (controllerData, deltaTime) {
|
||||
return this.isReady(controllerData);
|
||||
};
|
||||
|
||||
this.cleanup = function () {
|
||||
Pointers.removePointer(this.pointer);
|
||||
};
|
||||
}
|
||||
|
||||
function mouseHoverEnter(overlayID, event) {
|
||||
if (event.id === leftTabletStylusInput.pointer && !rightTabletStylusInput.disable && !leftTabletStylusInput.disable) {
|
||||
rightTabletStylusInput.disable = true;
|
||||
} else if (event.id === rightTabletStylusInput.pointer && !leftTabletStylusInput.disable && !rightTabletStylusInput.disable) {
|
||||
leftTabletStylusInput.disable = true;
|
||||
}
|
||||
}
|
||||
|
||||
function mouseHoverLeave(overlayID, event) {
|
||||
if (event.id === leftTabletStylusInput.pointer) {
|
||||
rightTabletStylusInput.disable = false;
|
||||
} else if (event.id === rightTabletStylusInput.pointer) {
|
||||
leftTabletStylusInput.disable = false;
|
||||
}
|
||||
}
|
||||
|
||||
var HAPTIC_STYLUS_STRENGTH = 1.0;
|
||||
var HAPTIC_STYLUS_DURATION = 20.0;
|
||||
function mousePress(overlayID, event) {
|
||||
if (HMD.active) {
|
||||
if (event.id === leftTabletStylusInput.pointer && event.button === "Primary") {
|
||||
Controller.triggerHapticPulse(HAPTIC_STYLUS_STRENGTH, HAPTIC_STYLUS_DURATION, LEFT_HAND);
|
||||
} else if (event.id === rightTabletStylusInput.pointer && event.button === "Primary") {
|
||||
Controller.triggerHapticPulse(HAPTIC_STYLUS_STRENGTH, HAPTIC_STYLUS_DURATION, RIGHT_HAND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var leftTabletStylusInput = new StylusInput(LEFT_HAND);
|
||||
var rightTabletStylusInput = new StylusInput(RIGHT_HAND);
|
||||
|
||||
enableDispatcherModule("LeftTabletStylusInput", leftTabletStylusInput);
|
||||
enableDispatcherModule("RightTabletStylusInput", rightTabletStylusInput);
|
||||
|
||||
Overlays.hoverEnterOverlay.connect(mouseHoverEnter);
|
||||
Overlays.hoverLeaveOverlay.connect(mouseHoverLeave);
|
||||
Overlays.mousePressOnOverlay.connect(mousePress);
|
||||
|
||||
this.cleanup = function () {
|
||||
leftTabletStylusInput.cleanup();
|
||||
rightTabletStylusInput.cleanup();
|
||||
disableDispatcherModule("LeftTabletStylusInput");
|
||||
disableDispatcherModule("RightTabletStylusInput");
|
||||
};
|
||||
Script.scriptEnding.connect(this.cleanup);
|
||||
}());
|
|
@ -1,78 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
// tabletStylusInput.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,
|
||||
enableDispatcherModule, disableDispatcherModule, makeRunningValues,
|
||||
Messages, Quat, Vec3, getControllerWorldLocation, makeDispatcherModuleParameters, Overlays, ZERO_VEC,
|
||||
HMD, INCHES_TO_METERS, DEFAULT_REGISTRATION_POINT, Settings, getGrabPointSphereOffset,
|
||||
getEnabledModuleByName
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
Script.include("/~/system/libraries/controllers.js");
|
||||
|
||||
(function() {
|
||||
function TabletStylusInput(hand) {
|
||||
this.hand = hand;
|
||||
|
||||
this.parameters = makeDispatcherModuleParameters(
|
||||
100,
|
||||
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||
[],
|
||||
100);
|
||||
|
||||
this.pointer = Pointers.createPointer(PickType.Stylus, { hand: this.hand });
|
||||
|
||||
this.otherModuleNeedsToRun = function(controllerData) {
|
||||
var grabOverlayModuleName = this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay";
|
||||
var grabOverlayModule = getEnabledModuleByName(grabOverlayModuleName);
|
||||
var grabOverlayModuleReady = grabOverlayModule ? grabOverlayModule.isReady(controllerData) : makeRunningValues(false, [], []);
|
||||
var farGrabModuleName = this.hand === RIGHT_HAND ? "RightFarActionGrabEntity" : "LeftFarActionGrabEntity";
|
||||
var farGrabModule = getEnabledModuleByName(farGrabModuleName);
|
||||
var farGrabModuleReady = farGrabModule ? farGrabModule.isReady(controllerData) : makeRunningValues(false, [], []);
|
||||
return grabOverlayModuleReady.active || farGrabModuleReady.active;
|
||||
};
|
||||
|
||||
this.overlayLaserActive = function(controllerData) {
|
||||
var rightOverlayLaserModule = getEnabledModuleByName("RightOverlayLaserInput");
|
||||
var leftOverlayLaserModule = getEnabledModuleByName("LeftOverlayLaserInput");
|
||||
var rightModuleRunning = rightOverlayLaserModule ? !rightOverlayLaserModule.shouldExit(controllerData) : false;
|
||||
var leftModuleRunning = leftOverlayLaserModule ? !leftOverlayLaserModule.shouldExit(controllerData) : false;
|
||||
return leftModuleRunning || rightModuleRunning;
|
||||
};
|
||||
|
||||
this.isReady = function (controllerData) {
|
||||
if (!this.overlayLaserActive(controllerData) && !this.otherModuleNeedsToRun(controllerData)) {
|
||||
return makeRunningValues(true, [], []);
|
||||
} else {
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
};
|
||||
|
||||
this.run = function (controllerData, deltaTime) {
|
||||
return this.isReady(controllerData);
|
||||
};
|
||||
|
||||
this.cleanup = function () {
|
||||
Pointers.createPointer(this.pointer);
|
||||
};
|
||||
}
|
||||
|
||||
var leftTabletStylusInput = new TabletStylusInput(LEFT_HAND);
|
||||
var rightTabletStylusInput = new TabletStylusInput(RIGHT_HAND);
|
||||
|
||||
enableDispatcherModule("LeftTabletStylusInput", leftTabletStylusInput);
|
||||
enableDispatcherModule("RightTabletStylusInput", rightTabletStylusInput);
|
||||
|
||||
this.cleanup = function () {
|
||||
leftTabletStylusInput.cleanup();
|
||||
rightTabletStylusInput.cleanup();
|
||||
disableDispatcherModule("LeftTabletStylusInput");
|
||||
disableDispatcherModule("RightTabletStylusInput");
|
||||
};
|
||||
Script.scriptEnding.connect(this.cleanup);
|
||||
}());
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, getControllerJointIndex,
|
||||
enableDispatcherModule, disableDispatcherModule, Messages, makeDispatcherModuleParameters, makeRunningValues, Vec3,
|
||||
LaserPointers, RayPick, HMD, Uuid, AvatarList
|
||||
RayPick, HMD, Uuid, AvatarList, Picks, Pointers, PickType
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/Xform.js");
|
||||
|
@ -109,8 +109,8 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
|
||||
|
||||
var teleportRenderStates = [{name: "cancel", path: cancelPath, end: cancelEnd},
|
||||
{name: "teleport", path: teleportPath, end: teleportEnd},
|
||||
{name: "seat", path: seatPath, end: seatEnd}];
|
||||
{name: "teleport", path: teleportPath, end: teleportEnd},
|
||||
{name: "seat", path: seatPath, end: seatEnd}];
|
||||
|
||||
var DEFAULT_DISTANCE = 50;
|
||||
var teleportDefaultRenderStates = [{name: "cancel", distance: DEFAULT_DISTANCE, path: cancelPath}];
|
||||
|
@ -127,18 +127,18 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
};
|
||||
|
||||
var TARGET = {
|
||||
NONE: 'none', // Not currently targetting anything
|
||||
INVISIBLE: 'invisible', // The current target is an invvsible surface
|
||||
INVALID: 'invalid', // The current target is invalid (wall, ceiling, etc.)
|
||||
SURFACE: 'surface', // The current target is a valid surface
|
||||
SEAT: 'seat' // The current target is a seat
|
||||
NONE: 'none', // Not currently targetting anything
|
||||
INVISIBLE: 'invisible', // The current target is an invvsible surface
|
||||
INVALID: 'invalid', // The current target is invalid (wall, ceiling, etc.)
|
||||
SURFACE: 'surface', // The current target is a valid surface
|
||||
SEAT: 'seat' // The current target is a seat
|
||||
};
|
||||
|
||||
function Teleporter(hand) {
|
||||
var _this = this;
|
||||
this.hand = hand;
|
||||
this.buttonValue = 0;
|
||||
this.disabled = false; // used by the 'Hifi-Teleport-Disabler' message handler
|
||||
this.disabled = false; // used by the 'Hifi-Teleport-Disabler' message handler
|
||||
this.active = false;
|
||||
this.state = TELEPORTER_STATES.IDLE;
|
||||
this.currentTarget = TARGET.INVALID;
|
||||
|
@ -149,7 +149,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
return otherModule;
|
||||
};
|
||||
|
||||
this.teleportRayHandVisible = LaserPointers.createLaserPointer({
|
||||
this.teleportRayHandVisible = Pointers.createPointer(PickType.Ray, {
|
||||
joint: (_this.hand === RIGHT_HAND) ? "RightHand" : "LeftHand",
|
||||
filter: Picks.PICK_ENTITIES,
|
||||
faceAvatar: true,
|
||||
|
@ -158,7 +158,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
renderStates: teleportRenderStates,
|
||||
defaultRenderStates: teleportDefaultRenderStates
|
||||
});
|
||||
this.teleportRayHandInvisible = LaserPointers.createLaserPointer({
|
||||
this.teleportRayHandInvisible = Pointers.createPointer(PickType.Ray, {
|
||||
joint: (_this.hand === RIGHT_HAND) ? "RightHand" : "LeftHand",
|
||||
filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE,
|
||||
faceAvatar: true,
|
||||
|
@ -166,7 +166,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
centerEndY: false,
|
||||
renderStates: teleportRenderStates
|
||||
});
|
||||
this.teleportRayHeadVisible = LaserPointers.createLaserPointer({
|
||||
this.teleportRayHeadVisible = Pointers.createPointer(PickType.Ray, {
|
||||
joint: "Avatar",
|
||||
filter: Picks.PICK_ENTITIES,
|
||||
faceAvatar: true,
|
||||
|
@ -175,7 +175,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
renderStates: teleportRenderStates,
|
||||
defaultRenderStates: teleportDefaultRenderStates
|
||||
});
|
||||
this.teleportRayHeadInvisible = LaserPointers.createLaserPointer({
|
||||
this.teleportRayHeadInvisible = Pointers.createPointer(PickType.Ray, {
|
||||
joint: "Avatar",
|
||||
filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE,
|
||||
faceAvatar: true,
|
||||
|
@ -185,10 +185,10 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
});
|
||||
|
||||
this.cleanup = function() {
|
||||
LaserPointers.removeLaserPointer(this.teleportRayHandVisible);
|
||||
LaserPointers.removeLaserPointer(this.teleportRayHandInvisible);
|
||||
LaserPointers.removeLaserPointer(this.teleportRayHeadVisible);
|
||||
LaserPointers.removeLaserPointer(this.teleportRayHeadInvisible);
|
||||
Pointers.removePointer(this.teleportRayHandVisible);
|
||||
Pointers.removePointer(this.teleportRayHandInvisible);
|
||||
Pointers.removePointer(this.teleportRayHeadVisible);
|
||||
Pointers.removePointer(this.teleportRayHeadInvisible);
|
||||
};
|
||||
|
||||
this.buttonPress = function(value) {
|
||||
|
@ -222,23 +222,23 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
seatEnd.dimensions = AVATAR_PROPORTIONAL_TARGET_MODEL_DIMENSIONS;
|
||||
|
||||
teleportRenderStates = [{name: "cancel", path: cancelPath, end: cancelEnd},
|
||||
{name: "teleport", path: teleportPath, end: teleportEnd},
|
||||
{name: "seat", path: seatPath, end: seatEnd}];
|
||||
{name: "teleport", path: teleportPath, end: teleportEnd},
|
||||
{name: "seat", path: seatPath, end: seatEnd}];
|
||||
|
||||
LaserPointers.editRenderState(this.teleportRayHandVisible, "cancel", teleportRenderStates[0]);
|
||||
LaserPointers.editRenderState(this.teleportRayHandInvisible, "cancel", teleportRenderStates[0]);
|
||||
LaserPointers.editRenderState(this.teleportRayHeadVisible, "cancel", teleportRenderStates[0]);
|
||||
LaserPointers.editRenderState(this.teleportRayHeadInvisible, "cancel", teleportRenderStates[0]);
|
||||
Pointers.editRenderState(this.teleportRayHandVisible, "cancel", teleportRenderStates[0]);
|
||||
Pointers.editRenderState(this.teleportRayHandInvisible, "cancel", teleportRenderStates[0]);
|
||||
Pointers.editRenderState(this.teleportRayHeadVisible, "cancel", teleportRenderStates[0]);
|
||||
Pointers.editRenderState(this.teleportRayHeadInvisible, "cancel", teleportRenderStates[0]);
|
||||
|
||||
LaserPointers.editRenderState(this.teleportRayHandVisible, "teleport", teleportRenderStates[1]);
|
||||
LaserPointers.editRenderState(this.teleportRayHandInvisible, "teleport", teleportRenderStates[1]);
|
||||
LaserPointers.editRenderState(this.teleportRayHeadVisible, "teleport", teleportRenderStates[1]);
|
||||
LaserPointers.editRenderState(this.teleportRayHeadInvisible, "teleport", teleportRenderStates[1]);
|
||||
Pointers.editRenderState(this.teleportRayHandVisible, "teleport", teleportRenderStates[1]);
|
||||
Pointers.editRenderState(this.teleportRayHandInvisible, "teleport", teleportRenderStates[1]);
|
||||
Pointers.editRenderState(this.teleportRayHeadVisible, "teleport", teleportRenderStates[1]);
|
||||
Pointers.editRenderState(this.teleportRayHeadInvisible, "teleport", teleportRenderStates[1]);
|
||||
|
||||
LaserPointers.editRenderState(this.teleportRayHandVisible, "seat", teleportRenderStates[2]);
|
||||
LaserPointers.editRenderState(this.teleportRayHandInvisible, "seat", teleportRenderStates[2]);
|
||||
LaserPointers.editRenderState(this.teleportRayHeadVisible, "seat", teleportRenderStates[2]);
|
||||
LaserPointers.editRenderState(this.teleportRayHeadInvisible, "seat", teleportRenderStates[2]);
|
||||
Pointers.editRenderState(this.teleportRayHandVisible, "seat", teleportRenderStates[2]);
|
||||
Pointers.editRenderState(this.teleportRayHandInvisible, "seat", teleportRenderStates[2]);
|
||||
Pointers.editRenderState(this.teleportRayHeadVisible, "seat", teleportRenderStates[2]);
|
||||
Pointers.editRenderState(this.teleportRayHeadInvisible, "seat", teleportRenderStates[2]);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -258,15 +258,15 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
var pose = Controller.getPoseValue(handInfo[(_this.hand === RIGHT_HAND) ? 'right' : 'left'].controllerInput);
|
||||
var mode = pose.valid ? _this.hand : 'head';
|
||||
if (!pose.valid) {
|
||||
LaserPointers.disableLaserPointer(_this.teleportRayHandVisible);
|
||||
LaserPointers.disableLaserPointer(_this.teleportRayHandInvisible);
|
||||
LaserPointers.enableLaserPointer(_this.teleportRayHeadVisible);
|
||||
LaserPointers.enableLaserPointer(_this.teleportRayHeadInvisible);
|
||||
Pointers.disablePointer(_this.teleportRayHandVisible);
|
||||
Pointers.disablePointer(_this.teleportRayHandInvisible);
|
||||
Pointers.enablePointer(_this.teleportRayHeadVisible);
|
||||
Pointers.enablePointer(_this.teleportRayHeadInvisible);
|
||||
} else {
|
||||
LaserPointers.enableLaserPointer(_this.teleportRayHandVisible);
|
||||
LaserPointers.enableLaserPointer(_this.teleportRayHandInvisible);
|
||||
LaserPointers.disableLaserPointer(_this.teleportRayHeadVisible);
|
||||
LaserPointers.disableLaserPointer(_this.teleportRayHeadInvisible);
|
||||
Pointers.enablePointer(_this.teleportRayHandVisible);
|
||||
Pointers.enablePointer(_this.teleportRayHandInvisible);
|
||||
Pointers.disablePointer(_this.teleportRayHeadVisible);
|
||||
Pointers.disablePointer(_this.teleportRayHeadInvisible);
|
||||
}
|
||||
|
||||
// We do up to 2 ray picks to find a teleport location.
|
||||
|
@ -280,17 +280,17 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
//
|
||||
var result;
|
||||
if (mode === 'head') {
|
||||
result = LaserPointers.getPrevRayPickResult(_this.teleportRayHeadInvisible);
|
||||
result = Pointers.getPrevPickResult(_this.teleportRayHeadInvisible);
|
||||
} else {
|
||||
result = LaserPointers.getPrevRayPickResult(_this.teleportRayHandInvisible);
|
||||
result = Pointers.getPrevPickResult(_this.teleportRayHandInvisible);
|
||||
}
|
||||
|
||||
var teleportLocationType = getTeleportTargetType(result);
|
||||
if (teleportLocationType === TARGET.INVISIBLE) {
|
||||
if (mode === 'head') {
|
||||
result = LaserPointers.getPrevRayPickResult(_this.teleportRayHeadVisible);
|
||||
result = Pointers.getPrevPickResult(_this.teleportRayHeadVisible);
|
||||
} else {
|
||||
result = LaserPointers.getPrevRayPickResult(_this.teleportRayHandVisible);
|
||||
result = Pointers.getPrevPickResult(_this.teleportRayHandVisible);
|
||||
}
|
||||
teleportLocationType = getTeleportTargetType(result);
|
||||
}
|
||||
|
@ -336,27 +336,27 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
};
|
||||
|
||||
this.disableLasers = function() {
|
||||
LaserPointers.disableLaserPointer(_this.teleportRayHandVisible);
|
||||
LaserPointers.disableLaserPointer(_this.teleportRayHandInvisible);
|
||||
LaserPointers.disableLaserPointer(_this.teleportRayHeadVisible);
|
||||
LaserPointers.disableLaserPointer(_this.teleportRayHeadInvisible);
|
||||
Pointers.disablePointer(_this.teleportRayHandVisible);
|
||||
Pointers.disablePointer(_this.teleportRayHandInvisible);
|
||||
Pointers.disablePointer(_this.teleportRayHeadVisible);
|
||||
Pointers.disablePointer(_this.teleportRayHeadInvisible);
|
||||
};
|
||||
|
||||
this.setTeleportState = function(mode, visibleState, invisibleState) {
|
||||
if (mode === 'head') {
|
||||
LaserPointers.setRenderState(_this.teleportRayHeadVisible, visibleState);
|
||||
LaserPointers.setRenderState(_this.teleportRayHeadInvisible, invisibleState);
|
||||
Pointers.setRenderState(_this.teleportRayHeadVisible, visibleState);
|
||||
Pointers.setRenderState(_this.teleportRayHeadInvisible, invisibleState);
|
||||
} else {
|
||||
LaserPointers.setRenderState(_this.teleportRayHandVisible, visibleState);
|
||||
LaserPointers.setRenderState(_this.teleportRayHandInvisible, invisibleState);
|
||||
Pointers.setRenderState(_this.teleportRayHandVisible, visibleState);
|
||||
Pointers.setRenderState(_this.teleportRayHandInvisible, invisibleState);
|
||||
}
|
||||
};
|
||||
|
||||
this.setIgnoreEntities = function(entitiesToIgnore) {
|
||||
LaserPointers.setIgnoreItems(this.teleportRayHandVisible, entitiesToIgnore);
|
||||
LaserPointers.setIgnoreItems(this.teleportRayHandInvisible, entitiesToIgnore);
|
||||
LaserPointers.setIgnoreItems(this.teleportRayHeadVisible, entitiesToIgnore);
|
||||
LaserPointers.setIgnoreItems(this.teleportRayHeadInvisible, entitiesToIgnore);
|
||||
Pointers.setIgnoreItems(this.teleportRayHandVisible, entitiesToIgnore);
|
||||
Pointers.setIgnoreItems(this.teleportRayHandInvisible, entitiesToIgnore);
|
||||
Pointers.setIgnoreItems(this.teleportRayHeadVisible, entitiesToIgnore);
|
||||
Pointers.setIgnoreItems(this.teleportRayHeadInvisible, entitiesToIgnore);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -453,6 +453,8 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
|
||||
function cleanup() {
|
||||
teleportMapping.disable();
|
||||
leftTeleporter.cleanup();
|
||||
rightTeleporter.cleanup();
|
||||
disableDispatcherModule("LeftTeleporter");
|
||||
disableDispatcherModule("RightTeleporter");
|
||||
}
|
||||
|
|
|
@ -1,471 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
// webEntityLaserInput.js
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
/* jslint bitwise: true */
|
||||
|
||||
/* global Script, Controller, LaserPointers, RayPick, RIGHT_HAND, LEFT_HAND, Vec3, Quat, getGrabPointSphereOffset,
|
||||
makeRunningValues, Entities, enableDispatcherModule, disableDispatcherModule, makeDispatcherModuleParameters,
|
||||
PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD,
|
||||
DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_ON_VALUE, ZERO_VEC, Overlays
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
Script.include("/~/system/libraries/controllers.js");
|
||||
|
||||
(function() {
|
||||
var END_RADIUS = 0.005;
|
||||
var dim = { x: END_RADIUS, y: END_RADIUS, z: END_RADIUS };
|
||||
var halfPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
var halfEnd = {
|
||||
type: "sphere",
|
||||
dimensions: dim,
|
||||
solid: true,
|
||||
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
alpha: 0.9,
|
||||
ignoreRayIntersection: true,
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
visible: true
|
||||
};
|
||||
var fullPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
var fullEnd = {
|
||||
type: "sphere",
|
||||
dimensions: dim,
|
||||
solid: true,
|
||||
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
|
||||
alpha: 0.9,
|
||||
ignoreRayIntersection: true,
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
visible: true
|
||||
};
|
||||
var holdPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_DISTANCE_HOLD,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: true, // Even when burried inside of something, show it.
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
|
||||
var renderStates = [
|
||||
{name: "half", path: halfPath, end: halfEnd},
|
||||
{name: "full", path: fullPath, end: fullEnd},
|
||||
{name: "hold", path: holdPath}
|
||||
];
|
||||
|
||||
var defaultRenderStates = [
|
||||
{name: "half", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: halfPath},
|
||||
{name: "full", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: fullPath},
|
||||
{name: "hold", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: holdPath}
|
||||
];
|
||||
|
||||
// triggered when stylus presses a web overlay/entity
|
||||
var HAPTIC_STYLUS_STRENGTH = 1.0;
|
||||
var HAPTIC_STYLUS_DURATION = 20.0;
|
||||
|
||||
function laserTargetHasKeyboardFocus(laserTarget) {
|
||||
if (laserTarget && laserTarget !== Uuid.NULL) {
|
||||
return Entities.keyboardFocusOverlay === laserTarget;
|
||||
}
|
||||
}
|
||||
|
||||
function setKeyboardFocusOnLaserTarget(laserTarget) {
|
||||
if (laserTarget && laserTarget !== Uuid.NULL) {
|
||||
Entities.wantsHandControllerPointerEvents(laserTarget);
|
||||
Overlays.keyboardFocusOverlay = Uuid.NULL;
|
||||
Entities.keyboardFocusEntity = laserTarget;
|
||||
}
|
||||
}
|
||||
|
||||
function sendHoverEnterEventToLaserTarget(hand, laserTarget) {
|
||||
if (!laserTarget) {
|
||||
return;
|
||||
}
|
||||
var pointerEvent = {
|
||||
type: "Move",
|
||||
id: hand + 1, // 0 is reserved for hardware mouse
|
||||
pos2D: laserTarget.position2D,
|
||||
pos3D: laserTarget.position,
|
||||
normal: laserTarget.normal,
|
||||
direction: Vec3.subtract(ZERO_VEC, laserTarget.normal),
|
||||
button: "None"
|
||||
};
|
||||
|
||||
if (laserTarget.entityID && laserTarget.entityID !== Uuid.NULL) {
|
||||
Entities.sendHoverEnterEntity(laserTarget.entityID, pointerEvent);
|
||||
}
|
||||
}
|
||||
|
||||
function sendHoverOverEventToLaserTarget(hand, laserTarget) {
|
||||
|
||||
if (!laserTarget) {
|
||||
return;
|
||||
}
|
||||
var pointerEvent = {
|
||||
type: "Move",
|
||||
id: hand + 1, // 0 is reserved for hardware mouse
|
||||
pos2D: laserTarget.position2D,
|
||||
pos3D: laserTarget.position,
|
||||
normal: laserTarget.normal,
|
||||
direction: Vec3.subtract(ZERO_VEC, laserTarget.normal),
|
||||
button: "None"
|
||||
};
|
||||
|
||||
if (laserTarget.entityID && laserTarget.entityID !== Uuid.NULL) {
|
||||
Entities.sendMouseMoveOnEntity(laserTarget.entityID, pointerEvent);
|
||||
Entities.sendHoverOverEntity(laserTarget.entityID, pointerEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function sendTouchStartEventToLaserTarget(hand, laserTarget) {
|
||||
var pointerEvent = {
|
||||
type: "Press",
|
||||
id: hand + 1, // 0 is reserved for hardware mouse
|
||||
pos2D: laserTarget.position2D,
|
||||
pos3D: laserTarget.position,
|
||||
normal: laserTarget.normal,
|
||||
direction: Vec3.subtract(ZERO_VEC, laserTarget.normal),
|
||||
button: "Primary",
|
||||
isPrimaryHeld: true
|
||||
};
|
||||
|
||||
if (laserTarget.entityID && laserTarget.entityID !== Uuid.NULL) {
|
||||
Entities.sendMousePressOnEntity(laserTarget.entityID, pointerEvent);
|
||||
Entities.sendClickDownOnEntity(laserTarget.entityID, pointerEvent);
|
||||
}
|
||||
}
|
||||
|
||||
function sendTouchEndEventToLaserTarget(hand, laserTarget) {
|
||||
var pointerEvent = {
|
||||
type: "Release",
|
||||
id: hand + 1, // 0 is reserved for hardware mouse
|
||||
pos2D: laserTarget.position2D,
|
||||
pos3D: laserTarget.position,
|
||||
normal: laserTarget.normal,
|
||||
direction: Vec3.subtract(ZERO_VEC, laserTarget.normal),
|
||||
button: "Primary"
|
||||
};
|
||||
|
||||
if (laserTarget.entityID && laserTarget.entityID !== Uuid.NULL) {
|
||||
Entities.sendMouseReleaseOnEntity(laserTarget.entityID, pointerEvent);
|
||||
Entities.sendClickReleaseOnEntity(laserTarget.entityID, pointerEvent);
|
||||
Entities.sendHoverLeaveEntity(laserTarget.entityID, pointerEvent);
|
||||
}
|
||||
}
|
||||
|
||||
function sendTouchMoveEventToLaserTarget(hand, laserTarget) {
|
||||
var pointerEvent = {
|
||||
type: "Move",
|
||||
id: hand + 1, // 0 is reserved for hardware mouse
|
||||
pos2D: laserTarget.position2D,
|
||||
pos3D: laserTarget.position,
|
||||
normal: laserTarget.normal,
|
||||
direction: Vec3.subtract(ZERO_VEC, laserTarget.normal),
|
||||
button: "Primary",
|
||||
isPrimaryHeld: true
|
||||
};
|
||||
|
||||
if (laserTarget.entityID && laserTarget.entityID !== Uuid.NULL) {
|
||||
Entities.sendMouseMoveOnEntity(laserTarget.entityID, pointerEvent);
|
||||
Entities.sendHoldingClickOnEntity(laserTarget.entityID, pointerEvent);
|
||||
}
|
||||
}
|
||||
|
||||
function calculateTargetFromEntity(intersection, props) {
|
||||
if (props.rotation === undefined) {
|
||||
// if rotation is missing from props object, then this entity has probably been deleted.
|
||||
return null;
|
||||
}
|
||||
|
||||
// project stylus tip onto entity plane.
|
||||
var normal = Vec3.multiplyQbyV(props.rotation, {x: 0, y: 0, z: 1});
|
||||
Vec3.multiplyQbyV(props.rotation, {x: 0, y: 1, z: 0});
|
||||
var distance = Vec3.dot(Vec3.subtract(intersection, props.position), normal);
|
||||
var position = Vec3.subtract(intersection, Vec3.multiply(normal, distance));
|
||||
|
||||
// generate normalized coordinates
|
||||
var invRot = Quat.inverse(props.rotation);
|
||||
var localPos = Vec3.multiplyQbyV(invRot, Vec3.subtract(position, props.position));
|
||||
var invDimensions = { x: 1 / props.dimensions.x, y: 1 / props.dimensions.y, z: 1 / props.dimensions.z };
|
||||
var normalizedPosition = Vec3.sum(Vec3.multiplyVbyV(localPos, invDimensions), props.registrationPoint);
|
||||
|
||||
// 2D position on entity plane in meters, relative to the bounding box upper-left hand corner.
|
||||
var position2D = {
|
||||
x: normalizedPosition.x * props.dimensions.x,
|
||||
y: (1 - normalizedPosition.y) * props.dimensions.y // flip y-axis
|
||||
};
|
||||
|
||||
return {
|
||||
entityID: props.id,
|
||||
entityProps: props,
|
||||
overlayID: null,
|
||||
distance: distance,
|
||||
position: position,
|
||||
position2D: position2D,
|
||||
normal: normal,
|
||||
normalizedPosition: normalizedPosition,
|
||||
dimensions: props.dimensions,
|
||||
valid: true
|
||||
};
|
||||
}
|
||||
|
||||
function distance2D(a, b) {
|
||||
var dx = (a.x - b.x);
|
||||
var dy = (a.y - b.y);
|
||||
return Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
function WebEntityLaserInput(hand) {
|
||||
this.hand = hand;
|
||||
this.active = false;
|
||||
this.previousLaserClickedTarget = false;
|
||||
this.laserPressingTarget = false;
|
||||
this.hover = false;
|
||||
this.mode = "none";
|
||||
this.pressEnterLaserTarget = null;
|
||||
this.laserTarget = null;
|
||||
this.laserTargetID = null;
|
||||
this.lastValidTargetID = null;
|
||||
|
||||
this.handToController = function() {
|
||||
return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
|
||||
};
|
||||
|
||||
this.getOtherModule = function() {
|
||||
return (this.hand === RIGHT_HAND) ? leftWebEntityLaserInput : rightWebEntityLaserInput;
|
||||
};
|
||||
|
||||
this.parameters = makeDispatcherModuleParameters(
|
||||
550,
|
||||
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||
[],
|
||||
100);
|
||||
|
||||
this.requestTouchFocus = function(laserTarget) {
|
||||
if (laserTarget !== null || laserTarget !== undefined) {
|
||||
sendHoverEnterEventToLaserTarget(this.hand, this.laserTarget);
|
||||
this.lastValidTargetID = laserTarget;
|
||||
}
|
||||
};
|
||||
|
||||
this.relinquishTouchFocus = function() {
|
||||
// send hover leave event.
|
||||
var pointerEvent = { type: "Move", id: this.hand + 1 };
|
||||
Entities.sendMouseMoveOnEntity(this.lastValidTargetID, pointerEvent);
|
||||
Entities.sendHoverOverEntity(this.lastValidTargetID, pointerEvent);
|
||||
Entities.sendHoverLeaveEntity(this.lastValidID, pointerEvent);
|
||||
};
|
||||
|
||||
this.updateLaserTargets = function(controllerData) {
|
||||
var intersection = controllerData.rayPicks[this.hand];
|
||||
this.laserTargetID = intersection.objectID;
|
||||
var props = Entities.getEntityProperties(intersection.objectID);
|
||||
this.laserTarget = calculateTargetFromEntity(intersection.intersection, props);
|
||||
};
|
||||
|
||||
this.processControllerTriggers = function(controllerData) {
|
||||
if (controllerData.triggerClicks[this.hand]) {
|
||||
this.mode = "full";
|
||||
this.laserPressingTarget = true;
|
||||
this.hover = false;
|
||||
} else if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) {
|
||||
this.mode = "half";
|
||||
this.laserPressingTarget = false;
|
||||
this.hover = true;
|
||||
this.requestTouchFocus(this.laserTargetID);
|
||||
} else {
|
||||
this.mode = "none";
|
||||
this.laserPressingTarget = false;
|
||||
this.hover = false;
|
||||
this.relinquishTouchFocus();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
this.hovering = function() {
|
||||
if (!laserTargetHasKeyboardFocus(this.laserTagetID)) {
|
||||
setKeyboardFocusOnLaserTarget(this.laserTargetID);
|
||||
}
|
||||
sendHoverOverEventToLaserTarget(this.hand, this.laserTarget);
|
||||
};
|
||||
|
||||
this.laserPressEnter = function () {
|
||||
sendTouchStartEventToLaserTarget(this.hand, this.laserTarget);
|
||||
Controller.triggerHapticPulse(HAPTIC_STYLUS_STRENGTH, HAPTIC_STYLUS_DURATION, this.hand);
|
||||
|
||||
this.touchingEnterTimer = 0;
|
||||
this.pressEnterLaserTarget = this.laserTarget;
|
||||
this.deadspotExpired = false;
|
||||
|
||||
var LASER_PRESS_TO_MOVE_DEADSPOT = 0.026;
|
||||
this.deadspotRadius = Math.tan(LASER_PRESS_TO_MOVE_DEADSPOT) * this.laserTarget.distance;
|
||||
};
|
||||
|
||||
this.laserPressExit = function () {
|
||||
if (this.laserTarget === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// send press event
|
||||
if (this.deadspotExpired) {
|
||||
sendTouchEndEventToLaserTarget(this.hand, this.laserTarget);
|
||||
} else {
|
||||
sendTouchEndEventToLaserTarget(this.hand, this.pressEnterLaserTarget);
|
||||
}
|
||||
};
|
||||
|
||||
this.laserPressing = function (controllerData, dt) {
|
||||
this.touchingEnterTimer += dt;
|
||||
|
||||
if (this.laserTarget) {
|
||||
var POINTER_PRESS_TO_MOVE_DELAY = 0.33; // seconds
|
||||
if (this.deadspotExpired || this.touchingEnterTimer > POINTER_PRESS_TO_MOVE_DELAY ||
|
||||
distance2D(this.laserTarget.position2D,
|
||||
this.pressEnterLaserTarget.position2D) > this.deadspotRadius) {
|
||||
sendTouchMoveEventToLaserTarget(this.hand, this.laserTarget);
|
||||
this.deadspotExpired = true;
|
||||
}
|
||||
} else {
|
||||
this.laserPressingTarget = false;
|
||||
}
|
||||
};
|
||||
|
||||
this.releaseTouchEvent = function() {
|
||||
if (this.pressEnterLaserTarget === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
sendTouchEndEventToLaserTarget(this.hand, this.pressEnterLaserTarget);
|
||||
};
|
||||
|
||||
this.updateLaserPointer = function(controllerData) {
|
||||
LaserPointers.enableLaserPointer(this.laserPointer);
|
||||
LaserPointers.setRenderState(this.laserPointer, this.mode);
|
||||
};
|
||||
|
||||
this.isPointingAtWebEntity = function(controllerData) {
|
||||
var intersection = controllerData.rayPicks[this.hand];
|
||||
var entityProperty = Entities.getEntityProperties(intersection.objectID);
|
||||
var entityType = entityProperty.type;
|
||||
|
||||
if ((intersection.type === Picks.INTERSECTED_ENTITY && entityType === "Web")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.exitModule = function() {
|
||||
this.releaseTouchEvent();
|
||||
this.relinquishTouchFocus();
|
||||
this.reset();
|
||||
this.updateLaserPointer();
|
||||
LaserPointers.disableLaserPointer(this.laserPointer);
|
||||
};
|
||||
|
||||
this.reset = function() {
|
||||
this.pressEnterLaserTarget = null;
|
||||
this.laserTarget = null;
|
||||
this.laserTargetID = null;
|
||||
this.laserPressingTarget = false;
|
||||
this.previousLaserClickedTarget = null;
|
||||
this.mode = "none";
|
||||
this.active = false;
|
||||
};
|
||||
|
||||
this.isReady = function(controllerData) {
|
||||
var otherModule = this.getOtherModule();
|
||||
if (this.isPointingAtWebEntity(controllerData) && !otherModule.active) {
|
||||
return makeRunningValues(true, [], []);
|
||||
}
|
||||
|
||||
return makeRunningValues(false, [], []);
|
||||
};
|
||||
|
||||
this.run = function(controllerData, deltaTime) {
|
||||
if (!this.isPointingAtWebEntity(controllerData)) {
|
||||
this.exitModule();
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
|
||||
this.updateLaserTargets(controllerData);
|
||||
this.processControllerTriggers(controllerData);
|
||||
this.updateLaserPointer(controllerData);
|
||||
|
||||
if (!this.previousLaserClickedTarget && this.laserPressingTarget) {
|
||||
this.laserPressEnter();
|
||||
}
|
||||
if (this.previousLaserClickedTarget && !this.laserPressingTarget) {
|
||||
this.laserPressExit();
|
||||
}
|
||||
this.previousLaserClickedTarget = this.laserPressingTarget;
|
||||
|
||||
if (this.laserPressingTarget) {
|
||||
this.laserPressing(controllerData, deltaTime);
|
||||
}
|
||||
|
||||
if (this.hover) {
|
||||
this.hovering();
|
||||
}
|
||||
return makeRunningValues(true, [], []);
|
||||
};
|
||||
|
||||
this.cleanup = function() {
|
||||
LaserPointers.disableLaserPointer(this.laserPointer);
|
||||
LaserPointers.removeLaserPointer(this.laserPointer);
|
||||
};
|
||||
|
||||
this.laserPointer = LaserPointers.createLaserPointer({
|
||||
joint: (this.hand === RIGHT_HAND) ? "_CONTROLLER_RIGHTHAND" : "_CONTROLLER_LEFTHAND",
|
||||
filter: Picks.PICK_ENTITIES,
|
||||
maxDistance: PICK_MAX_DISTANCE,
|
||||
posOffset: getGrabPointSphereOffset(this.handToController(), true),
|
||||
renderStates: renderStates,
|
||||
faceAvatar: true,
|
||||
scaleWithAvatar: true,
|
||||
defaultRenderStates: defaultRenderStates
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var leftWebEntityLaserInput = new WebEntityLaserInput(LEFT_HAND);
|
||||
var rightWebEntityLaserInput = new WebEntityLaserInput(RIGHT_HAND);
|
||||
|
||||
enableDispatcherModule("LeftWebEntityLaserInput", leftWebEntityLaserInput);
|
||||
enableDispatcherModule("RightWebEntityLaserInput", rightWebEntityLaserInput);
|
||||
|
||||
this.cleanup = function() {
|
||||
leftWebEntityLaserInput.cleanup();
|
||||
rightWebEntityLaserInput.cleanup();
|
||||
disableDispatcherModule("LeftWebEntityLaserInput");
|
||||
disableDispatcherModule("RightWebEntityLaserInput");
|
||||
};
|
||||
Script.scriptEnding.connect(this.cleanup);
|
||||
|
||||
}());
|
|
@ -0,0 +1,113 @@
|
|||
"use strict";
|
||||
|
||||
// webSurfaceLaserInput.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, Controller, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule,
|
||||
makeRunningValues, Messages, Quat, Vec3, makeDispatcherModuleParameters, Overlays, ZERO_VEC, HMD,
|
||||
INCHES_TO_METERS, DEFAULT_REGISTRATION_POINT, getGrabPointSphereOffset, COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_ON_VALUE,
|
||||
TRIGGER_OFF_VALUE, getEnabledModuleByName, PICK_MAX_DISTANCE, LaserPointers, RayPick, ContextOverlay, Picks
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
Script.include("/~/system/libraries/controllers.js");
|
||||
|
||||
(function() {
|
||||
function WebSurfaceLaserInput(hand) {
|
||||
this.hand = hand;
|
||||
this.running = false;
|
||||
|
||||
this.parameters = makeDispatcherModuleParameters(
|
||||
120,
|
||||
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||
[],
|
||||
100,
|
||||
this.hand);
|
||||
|
||||
this.grabModuleWantsNearbyOverlay = function(controllerData) {
|
||||
if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) {
|
||||
var nearGrabName = this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay";
|
||||
var nearGrabModule = getEnabledModuleByName(nearGrabName);
|
||||
if (nearGrabModule) {
|
||||
var candidateOverlays = controllerData.nearbyOverlayIDs[this.hand];
|
||||
var grabbableOverlays = candidateOverlays.filter(function(overlayID) {
|
||||
return Overlays.getProperty(overlayID, "grabbable");
|
||||
});
|
||||
var target = nearGrabModule.getTargetID(grabbableOverlays, controllerData);
|
||||
if (target) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.getOtherModule = function() {
|
||||
return this.hand === RIGHT_HAND ? leftOverlayLaserInput : rightOverlayLaserInput;
|
||||
};
|
||||
|
||||
this.isPointingAtWebEntity = function(controllerData) {
|
||||
var intersection = controllerData.rayPicks[this.hand];
|
||||
var entityProperty = Entities.getEntityProperties(intersection.objectID);
|
||||
var entityType = entityProperty.type;
|
||||
if ((intersection.type === Picks.INTERSECTED_ENTITY && entityType === "Web")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.isPointingAtOverlay = function(controllerData) {
|
||||
var intersection = controllerData.rayPicks[this.hand];
|
||||
return intersection.type === Picks.INTERSECTED_OVERLAY;
|
||||
};
|
||||
|
||||
this.deleteContextOverlay = function() {
|
||||
var farGrabModule = getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightFarActionGrabEntity" : "LeftFarActionGrabEntity");
|
||||
if (farGrabModule) {
|
||||
var entityWithContextOverlay = farGrabModule.entityWithContextOverlay;
|
||||
|
||||
if (entityWithContextOverlay) {
|
||||
ContextOverlay.destroyContextOverlay(entityWithContextOverlay);
|
||||
farGrabModule.entityWithContextOverlay = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.isReady = function (controllerData) {
|
||||
var otherModuleRunning = this.getOtherModule().running;
|
||||
if ((this.isPointingAtOverlay(controllerData) || this.isPointingAtWebEntity(controllerData)) &&
|
||||
!otherModuleRunning) {
|
||||
if (controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE) {
|
||||
return makeRunningValues(true, [], []);
|
||||
}
|
||||
}
|
||||
return makeRunningValues(false, [], []);
|
||||
};
|
||||
|
||||
this.run = function (controllerData, deltaTime) {
|
||||
var grabModuleNeedsToRun = this.grabModuleWantsNearbyOverlay(controllerData);
|
||||
if (controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE && !grabModuleNeedsToRun) {
|
||||
this.running = true;
|
||||
return makeRunningValues(true, [], []);
|
||||
}
|
||||
this.deleteContextOverlay();
|
||||
this.running = false;
|
||||
return makeRunningValues(false, [], []);
|
||||
};
|
||||
}
|
||||
|
||||
var leftOverlayLaserInput = new WebSurfaceLaserInput(LEFT_HAND);
|
||||
var rightOverlayLaserInput = new WebSurfaceLaserInput(RIGHT_HAND);
|
||||
|
||||
enableDispatcherModule("LeftWebSurfaceLaserInput", leftOverlayLaserInput);
|
||||
enableDispatcherModule("RightWebSurfaceLaserInput", rightOverlayLaserInput);
|
||||
|
||||
function cleanup() {
|
||||
disableDispatcherModule("LeftWebSurfaceLaserInput");
|
||||
disableDispatcherModule("RightWebSurfaceLaserInput");
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}());
|
|
@ -19,11 +19,10 @@ var CONTOLLER_SCRIPTS = [
|
|||
"controllerModules/nearParentGrabOverlay.js",
|
||||
"controllerModules/nearActionGrabEntity.js",
|
||||
"controllerModules/farActionGrabEntity.js",
|
||||
"controllerModules/tabletStylusInput.js",
|
||||
"controllerModules/stylusInput.js",
|
||||
"controllerModules/equipEntity.js",
|
||||
"controllerModules/nearTrigger.js",
|
||||
"controllerModules/overlayLaserInput.js",
|
||||
"controllerModules/webEntityLaserInput.js",
|
||||
"controllerModules/webSurfaceLaserInput.js",
|
||||
"controllerModules/inEditMode.js",
|
||||
"controllerModules/inVREditMode.js",
|
||||
"controllerModules/disableOtherModule.js",
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
//
|
||||
|
||||
/* global MyAvatar, Entities, Script, Camera, Vec3, Reticle, Overlays, getEntityCustomData, Messages, Quat, Controller,
|
||||
isInEditMode, HMD entityIsGrabbable*/
|
||||
isInEditMode, HMD entityIsGrabbable, Pointers, PickType RayPick*/
|
||||
|
||||
|
||||
(function() { // BEGIN LOCAL_SCOPE
|
||||
|
@ -265,7 +265,7 @@ function Grabber() {
|
|||
});
|
||||
RayPick.setIncludeItems(this.mouseRayOverlays, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]);
|
||||
var renderStates = [{name: "grabbed", end: beacon}];
|
||||
this.mouseRayEntities = LaserPointers.createLaserPointer({
|
||||
this.mouseRayEntities = Pointers.createPointer(PickType.Ray, {
|
||||
joint: "Mouse",
|
||||
filter: Picks.PICK_ENTITIES,
|
||||
faceAvatar: true,
|
||||
|
@ -329,9 +329,9 @@ Grabber.prototype.pressEvent = function(event) {
|
|||
return;
|
||||
}
|
||||
|
||||
var pickResults = LaserPointers.getPrevRayPickResult(this.mouseRayEntities);
|
||||
var pickResults = Pointers.getPrevPickResult(this.mouseRayEntities);
|
||||
if (pickResults.type == Picks.INTERSECTED_NONE) {
|
||||
LaserPointers.setRenderState(this.mouseRayEntities, "");
|
||||
Pointers.setRenderState(this.mouseRayEntities, "");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -348,8 +348,8 @@ Grabber.prototype.pressEvent = function(event) {
|
|||
return;
|
||||
}
|
||||
|
||||
LaserPointers.setRenderState(this.mouseRayEntities, "grabbed");
|
||||
LaserPointers.setLockEndUUID(this.mouseRayEntities, pickResults.objectID, false);
|
||||
Pointers.setRenderState(this.mouseRayEntities, "grabbed");
|
||||
Pointers.setLockEndUUID(this.mouseRayEntities, pickResults.objectID, false);
|
||||
|
||||
mouse.startDrag(event);
|
||||
|
||||
|
@ -362,7 +362,7 @@ Grabber.prototype.pressEvent = function(event) {
|
|||
|
||||
var objectBoundingDiameter = Vec3.length(entityProperties.dimensions);
|
||||
beacon.dimensions.y = objectBoundingDiameter;
|
||||
LaserPointers.editRenderState(this.mouseRayEntities, "grabbed", {end: beacon});
|
||||
Pointers.editRenderState(this.mouseRayEntities, "grabbed", {end: beacon});
|
||||
this.maxDistance = objectBoundingDiameter / MAX_SOLID_ANGLE;
|
||||
if (Vec3.distance(this.startPosition, cameraPosition) > this.maxDistance) {
|
||||
// don't allow grabs of things far away
|
||||
|
@ -439,7 +439,7 @@ Grabber.prototype.releaseEvent = function(event) {
|
|||
|
||||
this.actionID = null;
|
||||
|
||||
LaserPointers.setRenderState(this.mouseRayEntities, "");
|
||||
Pointers.setRenderState(this.mouseRayEntities, "");
|
||||
|
||||
var args = "mouse";
|
||||
Entities.callEntityMethod(this.entityID, "releaseGrab", args);
|
||||
|
@ -594,7 +594,7 @@ Grabber.prototype.keyPressEvent = function(event) {
|
|||
};
|
||||
|
||||
Grabber.prototype.cleanup = function() {
|
||||
LaserPointers.removeLaserPointer(this.mouseRayEntities);
|
||||
Pointers.removePointer(this.mouseRayEntities);
|
||||
RayPick.removeRayPick(this.mouseRayOverlays);
|
||||
};
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
getChildrenProps:true,
|
||||
projectOntoEntityXYPlane:true,
|
||||
projectOntoOverlayXYPlane:true,
|
||||
makeLaserLockInfo:true,
|
||||
entityHasActions:true,
|
||||
ensureDynamic:true,
|
||||
findGroupParent:true,
|
||||
|
@ -102,27 +103,43 @@ DISPATCHER_PROPERTIES = [
|
|||
"parentJointIndex",
|
||||
"density",
|
||||
"dimensions",
|
||||
"userData"
|
||||
"userData",
|
||||
"type"
|
||||
];
|
||||
|
||||
// priority -- a lower priority means the module will be asked sooner than one with a higher priority in a given update step
|
||||
// activitySlots -- indicates which "slots" must not yet be in use for this module to start
|
||||
// requiredDataForReady -- which "situation" parts this module looks at to decide if it will start
|
||||
// sleepMSBetweenRuns -- how long to wait between calls to this module's "run" method
|
||||
makeDispatcherModuleParameters = function (priority, activitySlots, requiredDataForReady, sleepMSBetweenRuns) {
|
||||
makeDispatcherModuleParameters = function (priority, activitySlots, requiredDataForReady, sleepMSBetweenRuns, enableLaserForHand) {
|
||||
if (enableLaserForHand === undefined) {
|
||||
enableLaserForHand = -1;
|
||||
}
|
||||
|
||||
return {
|
||||
priority: priority,
|
||||
activitySlots: activitySlots,
|
||||
requiredDataForReady: requiredDataForReady,
|
||||
sleepMSBetweenRuns: sleepMSBetweenRuns
|
||||
sleepMSBetweenRuns: sleepMSBetweenRuns,
|
||||
handLaser: enableLaserForHand
|
||||
};
|
||||
};
|
||||
|
||||
makeRunningValues = function (active, targets, requiredDataForRun) {
|
||||
makeLaserLockInfo = function(targetID, isOverlay, hand, offset) {
|
||||
return {
|
||||
targetID: targetID,
|
||||
isOverlay: isOverlay,
|
||||
hand: hand,
|
||||
offset: offset
|
||||
};
|
||||
};
|
||||
|
||||
makeRunningValues = function (active, targets, requiredDataForRun, laserLockInfo) {
|
||||
return {
|
||||
active: active,
|
||||
targets: targets,
|
||||
requiredDataForRun: requiredDataForRun
|
||||
requiredDataForRun: requiredDataForRun,
|
||||
laserLockInfo: laserLockInfo
|
||||
};
|
||||
};
|
||||
|
||||
|
|
208
scripts/system/libraries/pointersUtils.js
Normal file
208
scripts/system/libraries/pointersUtils.js
Normal file
|
@ -0,0 +1,208 @@
|
|||
"use strict";
|
||||
|
||||
// pointerUtils.js
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
/* jslint bitwise: true */
|
||||
|
||||
/* global Script, Entities, Overlays, Controller, Vec3, Quat, getControllerWorldLocation, RayPick,
|
||||
controllerDispatcherPlugins:true, controllerDispatcherPluginsNeedSort:true,
|
||||
LEFT_HAND, RIGHT_HAND, NEAR_GRAB_PICK_RADIUS, DEFAULT_SEARCH_SPHERE_DISTANCE, DISPATCHER_PROPERTIES,
|
||||
getGrabPointSphereOffset, HMD, MyAvatar, Messages, findHandChildEntities, Pointers, PickType, COLORS_GRAB_SEARCHING_HALF_SQUEEZE
|
||||
COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, Picks, TRIGGER_ON_VALUE
|
||||
*/
|
||||
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
Pointer = function(hudLayer, pickType, pointerData) {
|
||||
var _this = this;
|
||||
this.SEARCH_SPHERE_SIZE = 0.0132;
|
||||
this.dim = {x: this.SEARCH_SPHERE_SIZE, y: this.SEARCH_SPHERE_SIZE, z: this.SEARCH_SPHERE_SIZE};
|
||||
this.halfPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
lineWidth: 5,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: !hudLayer, // Even when burried inside of something, show it.
|
||||
drawHUDLayer: hudLayer,
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
this.halfEnd = {
|
||||
type: "sphere",
|
||||
dimensions: this.dim,
|
||||
solid: true,
|
||||
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
alpha: 0.9,
|
||||
ignoreRayIntersection: true,
|
||||
drawInFront: !hudLayer, // Even when burried inside of something, show it.
|
||||
drawHUDLayer: hudLayer,
|
||||
visible: true
|
||||
};
|
||||
this.fullPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
lineWidth: 5,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: !hudLayer, // Even when burried inside of something, show it.
|
||||
drawHUDLayer: hudLayer,
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
this.fullEnd = {
|
||||
type: "sphere",
|
||||
dimensions: this.dim,
|
||||
solid: true,
|
||||
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
|
||||
alpha: 0.9,
|
||||
ignoreRayIntersection: true,
|
||||
drawInFront: !hudLayer, // Even when burried inside of something, show it.
|
||||
drawHUDLayer: hudLayer,
|
||||
visible: true
|
||||
};
|
||||
this.holdPath = {
|
||||
type: "line3d",
|
||||
color: COLORS_GRAB_DISTANCE_HOLD,
|
||||
visible: true,
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
glow: 1.0,
|
||||
lineWidth: 5,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawInFront: !hudLayer, // Even when burried inside of something, show it.
|
||||
drawHUDLayer: hudLayer,
|
||||
parentID: MyAvatar.SELF_ID
|
||||
};
|
||||
|
||||
this.renderStates = [
|
||||
{name: "half", path: this.halfPath, end: this.halfEnd},
|
||||
{name: "full", path: this.fullPath, end: this.fullEnd},
|
||||
{name: "hold", path: this.holdPath}
|
||||
];
|
||||
|
||||
this.defaultRenderStates = [
|
||||
{name: "half", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: this.halfPath},
|
||||
{name: "full", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: this.fullPath},
|
||||
{name: "hold", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: this.holdPath}
|
||||
];
|
||||
|
||||
|
||||
this.pointerID = null;
|
||||
this.visible = false;
|
||||
this.locked = false;
|
||||
this.hand = pointerData.hand;
|
||||
delete pointerData.hand;
|
||||
|
||||
function createPointer(pickType, pointerData) {
|
||||
var pointerID = Pointers.createPointer(pickType, pointerData);
|
||||
Pointers.setRenderState(pointerID, "");
|
||||
Pointers.enablePointer(pointerID);
|
||||
return pointerID;
|
||||
}
|
||||
|
||||
this.enable = function() {
|
||||
Pointers.enablePointer(this.pointerID);
|
||||
};
|
||||
|
||||
this.disable = function() {
|
||||
Pointers.disablePointer(this.pointerID);
|
||||
};
|
||||
|
||||
this.removePointer = function() {
|
||||
Pointers.removePointer(this.pointerID);
|
||||
};
|
||||
|
||||
this.makeVisible = function() {
|
||||
this.visible = true;
|
||||
};
|
||||
|
||||
this.makeInvisible = function() {
|
||||
this.visible = false;
|
||||
};
|
||||
|
||||
this.lockEnd = function(lockData) {
|
||||
if (lockData !== undefined) {
|
||||
if (this.visible && !this.locked && lockData.targetID !== null) {
|
||||
var targetID = lockData.targetID;
|
||||
var targetIsOverlay = lockData.isOverlay;
|
||||
if (lockData.offset === undefined) {
|
||||
Pointers.setLockEndUUID(this.pointerID, targetID, targetIsOverlay);
|
||||
} else {
|
||||
Pointers.setLockEndUUID(this.pointerID, targetID, targetIsOverlay, lockData.offset);
|
||||
}
|
||||
this.locked = targetID;
|
||||
}
|
||||
} else if (this.locked) {
|
||||
Pointers.setLockEndUUID(this.pointerID, null, false);
|
||||
this.locked = false;
|
||||
}
|
||||
};
|
||||
|
||||
this.updateRenderState = function(triggerClicks, triggerValues) {
|
||||
var mode = "";
|
||||
if (this.visible) {
|
||||
if (this.locked) {
|
||||
mode = "hold";
|
||||
} else if (triggerClicks[this.hand]) {
|
||||
mode = "full";
|
||||
} else if (triggerValues[this.hand] > TRIGGER_ON_VALUE) {
|
||||
mode = "half";
|
||||
}
|
||||
}
|
||||
|
||||
Pointers.setRenderState(this.pointerID, mode);
|
||||
};
|
||||
pointerData.renderStates = this.renderStates;
|
||||
pointerData.defaultRenderStates = this.defaultRenderStates;
|
||||
this.pointerID = createPointer(pickType, pointerData);
|
||||
};
|
||||
|
||||
|
||||
PointerManager = function() {
|
||||
this.pointers = [];
|
||||
|
||||
this.createPointer = function(hudLayer, pickType, pointerData) {
|
||||
var pointer = new Pointer(hudLayer, pickType, pointerData);
|
||||
this.pointers.push(pointer);
|
||||
return pointer.pointerID;
|
||||
};
|
||||
|
||||
this.makePointerVisible = function(index) {
|
||||
if (index < this.pointers.length && index >= 0) {
|
||||
this.pointers[index].makeVisible();
|
||||
}
|
||||
};
|
||||
|
||||
this.makePointerInvisible = function(index) {
|
||||
if (index < this.pointers.length && index >= 0) {
|
||||
this.pointers[index].makeInvisible();
|
||||
}
|
||||
};
|
||||
|
||||
this.lockPointerEnd = function(index, lockData) {
|
||||
if (index < this.pointers.length && index >= 0) {
|
||||
this.pointers[index].lockEnd(lockData);
|
||||
}
|
||||
};
|
||||
|
||||
this.updatePointersRenderState = function(triggerClicks, triggerValues) {
|
||||
for (var index = 0; index < this.pointers.length; index++) {
|
||||
this.pointers[index].updateRenderState(triggerClicks, triggerValues);
|
||||
}
|
||||
};
|
||||
|
||||
this.removePointers = function() {
|
||||
for (var index = 0; index < this.pointers.length; index++) {
|
||||
this.pointers[index].removePointer();
|
||||
}
|
||||
this.pointers = [];
|
||||
};
|
||||
};
|
Loading…
Reference in a new issue