finshed handControllerGrab refactoring

This commit is contained in:
Dante Ruiz 2017-09-01 17:07:26 -07:00
parent 9bd368c0a9
commit 3b357ad61e
13 changed files with 302 additions and 150 deletions

View file

@ -5,11 +5,12 @@
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
/*jslint bitwise: true */ /* jslint bitwise: true */
/* global Script, Entities, Overlays, Controller, Vec3, Quat, getControllerWorldLocation, RayPick, /* global Script, Entities, Overlays, Controller, Vec3, Quat, getControllerWorldLocation, RayPick,
controllerDispatcherPlugins, controllerDispatcherPluginsNeedSort, entityIsGrabbable, controllerDispatcherPlugins:true, controllerDispatcherPluginsNeedSort:true, entityIsGrabbable:true,
LEFT_HAND, RIGHT_HAND, NEAR_GRAB_PICK_RADIUS, DEFAULT_SEARCH_SPHERE_DISTANCE, DISPATCHER_PROPERTIES LEFT_HAND, RIGHT_HAND, NEAR_GRAB_PICK_RADIUS, DEFAULT_SEARCH_SPHERE_DISTANCE, DISPATCHER_PROPERTIES,
getGrabPointSphereOffset
*/ */
controllerDispatcherPlugins = {}; controllerDispatcherPlugins = {};
@ -21,18 +22,16 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
(function() { (function() {
var _this = this; var _this = this;
var NEAR_MIN_RADIUS = 0.1;
var NEAR_MAX_RADIUS = 1.0; var NEAR_MAX_RADIUS = 1.0;
var TARGET_UPDATE_HZ = 60; // 50hz good enough, but we're using update var TARGET_UPDATE_HZ = 60; // 50hz good enough, but we're using update
var BASIC_TIMER_INTERVAL_MS = 1000 / TARGET_UPDATE_HZ; var BASIC_TIMER_INTERVAL_MS = 1000 / TARGET_UPDATE_HZ;
var lastInterval = Date.now(); this.lastInterval = Date.now();
var intervalCount = 0; this.intervalCount = 0;
var totalDelta = 0; this.totalDelta = 0;
var totalVariance = 0; this.totalVariance = 0;
var highVarianceCount = 0; this.highVarianceCount = 0;
var veryhighVarianceCount = 0; this.veryhighVarianceCount = 0;
this.tabletID = null; this.tabletID = null;
this.blacklist = []; this.blacklist = [];
@ -63,7 +62,7 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
this.unmarkSlotsForPluginName = function (runningPluginName) { this.unmarkSlotsForPluginName = function (runningPluginName) {
// this is used to free activity-slots when a plugin is deactivated while it's running. // this is used to free activity-slots when a plugin is deactivated while it's running.
for (var activitySlot in _this.activitySlots) { for (var activitySlot in _this.activitySlots) {
if (activitySlot.hasOwnProperty(activitySlot) && _this.activitySlots[activitySlot] == runningPluginName) { if (activitySlot.hasOwnProperty(activitySlot) && _this.activitySlots[activitySlot] === runningPluginName) {
_this.activitySlots[activitySlot] = false; _this.activitySlots[activitySlot] = false;
} }
} }
@ -106,23 +105,23 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
}; };
this.updateTimings = function () { this.updateTimings = function () {
intervalCount++; _this.intervalCount++;
var thisInterval = Date.now(); var thisInterval = Date.now();
var deltaTimeMsec = thisInterval - lastInterval; var deltaTimeMsec = thisInterval - _this.lastInterval;
var deltaTime = deltaTimeMsec / 1000; var deltaTime = deltaTimeMsec / 1000;
lastInterval = thisInterval; _this.lastInterval = thisInterval;
totalDelta += deltaTimeMsec; _this.totalDelta += deltaTimeMsec;
var variance = Math.abs(deltaTimeMsec - BASIC_TIMER_INTERVAL_MS); var variance = Math.abs(deltaTimeMsec - BASIC_TIMER_INTERVAL_MS);
totalVariance += variance; _this.totalVariance += variance;
if (variance > 1) { if (variance > 1) {
highVarianceCount++; _this.highVarianceCount++;
} }
if (variance > 5) { if (variance > 5) {
veryhighVarianceCount++; _this.veryhighVarianceCount++;
} }
return deltaTime; return deltaTime;
@ -132,13 +131,12 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
if (HMD.tabletID !== _this.tabletID) { if (HMD.tabletID !== _this.tabletID) {
RayPick.setIgnoreOverlays(_this.leftControllerRayPick, [HMD.tabletID]); RayPick.setIgnoreOverlays(_this.leftControllerRayPick, [HMD.tabletID]);
RayPick.setIgnoreOverlays(_this.rightControllerRayPick, [HMD.tabletID]); RayPick.setIgnoreOverlays(_this.rightControllerRayPick, [HMD.tabletID]);
tabletIgnored = true
} }
} };
this.update = function () { this.update = function () {
var deltaTime = this.updateTimings(); var deltaTime = this.updateTimings();
this.setIgnoreTablet() this.setIgnoreTablet();
if (controllerDispatcherPluginsNeedSort) { if (controllerDispatcherPluginsNeedSort) {
this.orderedPluginNames = []; this.orderedPluginNames = [];
@ -167,8 +165,10 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
controllerDispatcherPluginsNeedSort = false; controllerDispatcherPluginsNeedSort = false;
} }
var controllerLocations = [_this.dataGatherers.leftControllerLocation(), var controllerLocations = [
_this.dataGatherers.rightControllerLocation()]; _this.dataGatherers.leftControllerLocation(),
_this.dataGatherers.rightControllerLocation()
];
// find 3d overlays near each hand // find 3d overlays near each hand
var nearbyOverlayIDs = []; var nearbyOverlayIDs = [];
@ -221,7 +221,7 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
length: 1000 length: 1000
}; };
if (rayPicks[h].type == RayPick.INTERSECTED_ENTITY) { if (rayPicks[h].type === RayPick.INTERSECTED_ENTITY) {
// XXX check to make sure this one isn't already in nearbyEntityProperties? // XXX check to make sure this one isn't already in nearbyEntityProperties?
if (rayPicks[h].distance < NEAR_GRAB_PICK_RADIUS) { if (rayPicks[h].distance < NEAR_GRAB_PICK_RADIUS) {
var nearEntityID = rayPicks[h].objectID; var nearEntityID = rayPicks[h].objectID;
@ -259,7 +259,6 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
var candidatePlugin = controllerDispatcherPlugins[orderedPluginName]; var candidatePlugin = controllerDispatcherPlugins[orderedPluginName];
if (_this.slotsAreAvailableForPlugin(candidatePlugin)) { if (_this.slotsAreAvailableForPlugin(candidatePlugin)) {
//print(orderedPluginName);
var readiness = candidatePlugin.isReady(controllerData, deltaTime); var readiness = candidatePlugin.isReady(controllerData, deltaTime);
if (readiness.active) { if (readiness.active) {
// this plugin will start. add it to the list of running plugins and mark the // this plugin will start. add it to the list of running plugins and mark the
@ -297,7 +296,7 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
this.setBlacklist = function() { this.setBlacklist = function() {
RayPick.setIgnoreEntities(_this.leftControllerRayPick, this.blacklist); RayPick.setIgnoreEntities(_this.leftControllerRayPick, this.blacklist);
RayPick.setIgnoreEntities(_this.rightControllerRayPick, this.blacklist); RayPick.setIgnoreEntities(_this.rightControllerRayPick, this.blacklist);
}; };
var MAPPING_NAME = "com.highfidelity.controllerDispatcher"; var MAPPING_NAME = "com.highfidelity.controllerDispatcher";
@ -314,19 +313,6 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
Controller.enableMapping(MAPPING_NAME); Controller.enableMapping(MAPPING_NAME);
this.mouseRayPick = RayPick.createRayPick({
joint: "Mouse",
filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS,
enabled: true
});
this.mouseHudRayPick = RayPick.createRayPick({
joint: "Mouse",
filter: RayPick.PICK_HUD,
enabled: true
});
this.leftControllerRayPick = RayPick.createRayPick({ this.leftControllerRayPick = RayPick.createRayPick({
joint: "_CONTROLLER_LEFTHAND", joint: "_CONTROLLER_LEFTHAND",
filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS,
@ -357,7 +343,7 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
}); });
this.handleHandMessage = function(channel, message, sender) { this.handleHandMessage = function(channel, message, sender) {
var data var data;
if (sender === MyAvatar.sessionUUID) { if (sender === MyAvatar.sessionUUID) {
try { try {
if (channel === 'Hifi-Hand-RayPick-Blacklist') { if (channel === 'Hifi-Hand-RayPick-Blacklist') {
@ -365,33 +351,29 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
var action = data.action; var action = data.action;
var id = data.id; var id = data.id;
var index = this.blacklis.indexOf(id); var index = this.blacklis.indexOf(id);
if (action === 'add' && index === -1) { if (action === 'add' && index === -1) {
this.blacklist.push(id); this.blacklist.push(id);
//this.setBlacklist(); this.setBlacklist();
} }
if (action === 'remove') { if (action === 'remove') {
if (index > -1) { if (index > -1) {
blacklist.splice(index, 1); this.blacklist.splice(index, 1);
//this.setBlacklist(); this.setBlacklist();
} }
} }
} }
} catch (e) { } catch (e) {
print("WARNING: handControllerGrab.js -- error parsing Hifi-Hand-RayPick-Blacklist message: " + message); print("WARNING: handControllerGrab.js -- error parsing Hifi-Hand-RayPick-Blacklist message: " + message);
} }
} }
}; };
this.cleanup = function () { this.cleanup = function () {
Script.update.disconnect(_this.update); Script.update.disconnect(_this.update);
Controller.disableMapping(MAPPING_NAME); Controller.disableMapping(MAPPING_NAME);
// RayPick.removeRayPick(_this.mouseRayPick);
RayPick.removeRayPick(_this.leftControllerRayPick); RayPick.removeRayPick(_this.leftControllerRayPick);
RayPick.removeRayPick(_this.rightControllerRayPick); RayPick.removeRayPick(_this.rightControllerRayPick);
RayPick.removeRayPick(_this.rightControllerHudRayPick); RayPick.removeRayPick(_this.rightControllerHudRayPick);

View file

@ -6,37 +6,37 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
/* global Camera, HMD, MyAvatar, controllerDispatcherPlugins, Quat, Vec3, Overlays, /* global Camera, HMD, MyAvatar, controllerDispatcherPlugins:true, Quat, Vec3, Overlays,
MSECS_PER_SEC, LEFT_HAND, RIGHT_HAND, NULL_UUID, AVATAR_SELF_ID, FORBIDDEN_GRAB_TYPES, MSECS_PER_SEC:true , LEFT_HAND:true, RIGHT_HAND:true, NULL_UUID:true, AVATAR_SELF_ID:true, FORBIDDEN_GRAB_TYPES:true,
HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, ZERO_VEC, ONE_VEC, DEFAULT_REGISTRATION_POINT, INCHES_TO_METERS, HAPTIC_PULSE_STRENGTH:true, HAPTIC_PULSE_DURATION:true, ZERO_VEC:true, ONE_VEC:true, DEFAULT_REGISTRATION_POINT:true, INCHES_TO_METERS:true,
TRIGGER_OFF_VALUE, TRIGGER_OFF_VALUE:true,
TRIGGER_ON_VALUE, TRIGGER_ON_VALUE:true,
PICK_MAX_DISTANCE, PICK_MAX_DISTANCE:true,
DEFAULT_SEARCH_SPHERE_DISTANCE, DEFAULT_SEARCH_SPHERE_DISTANCE:true,
NEAR_GRAB_PICK_RADIUS, NEAR_GRAB_PICK_RADIUS:true,
COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE:true,
COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE:true,
COLORS_GRAB_DISTANCE_HOLD, COLORS_GRAB_DISTANCE_HOLD:true,
NEAR_GRAB_RADIUS, NEAR_GRAB_RADIUS:true,
DISPATCHER_PROPERTIES, DISPATCHER_PROPERTIES:true,
Entities, Entities,
makeDispatcherModuleParameters, makeDispatcherModuleParameters:true,
makeRunningValues, makeRunningValues:true,
enableDispatcherModule, enableDispatcherModule:true,
disableDispatcherModule, disableDispatcherModule:true,
getEnabledModuleByName, getEnabledModuleByName:true,
getGrabbableData, getGrabbableData:true,
entityIsGrabbable, entityIsGrabbable:true,
entityIsDistanceGrabbable, entityIsDistanceGrabbable:true,
getControllerJointIndex, getControllerJointIndex:true,
propsArePhysical, propsArePhysical:true,
controllerDispatcherPluginsNeedSort, controllerDispatcherPluginsNeedSort:true,
projectOntoXYPlane, projectOntoXYPlane:true,
projectOntoEntityXYPlane, projectOntoEntityXYPlane:true,
projectOntoOverlayXYPlane, projectOntoOverlayXYPlane:true,
entityHasActions, entityHasActions:true,
ensureDynamic, ensureDynamic:true,
findGroupParent findGroupParent:true
*/ */
MSECS_PER_SEC = 1000.0; MSECS_PER_SEC = 1000.0;
@ -69,11 +69,8 @@ COLORS_GRAB_SEARCHING_HALF_SQUEEZE = { red: 10, green: 10, blue: 255 };
COLORS_GRAB_SEARCHING_FULL_SQUEEZE = { red: 250, green: 10, blue: 10 }; COLORS_GRAB_SEARCHING_FULL_SQUEEZE = { red: 250, green: 10, blue: 10 };
COLORS_GRAB_DISTANCE_HOLD = { red: 238, green: 75, blue: 214 }; COLORS_GRAB_DISTANCE_HOLD = { red: 238, green: 75, blue: 214 };
NEAR_GRAB_RADIUS = 0.1; NEAR_GRAB_RADIUS = 0.1;
DISPATCHER_PROPERTIES = [ DISPATCHER_PROPERTIES = [
"position", "position",
"registrationPoint", "registrationPoint",
@ -92,9 +89,6 @@ DISPATCHER_PROPERTIES = [
"userData" "userData"
]; ];
// priority -- a lower priority means the module will be asked sooner than one with a higher priority in a given update step // 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 // 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 // requiredDataForReady -- which "situation" parts this module looks at to decide if it will start
@ -211,12 +205,12 @@ getControllerJointIndex = function (hand) {
var controllerJointIndex = -1; var controllerJointIndex = -1;
if (Camera.mode === "first person") { if (Camera.mode === "first person") {
controllerJointIndex = MyAvatar.getJointIndex(hand === RIGHT_HAND ? controllerJointIndex = MyAvatar.getJointIndex(hand === RIGHT_HAND ?
"_CONTROLLER_RIGHTHAND" : "_CONTROLLER_RIGHTHAND" :
"_CONTROLLER_LEFTHAND"); "_CONTROLLER_LEFTHAND");
} else if (Camera.mode === "third person") { } else if (Camera.mode === "third person") {
controllerJointIndex = MyAvatar.getJointIndex(hand === RIGHT_HAND ? controllerJointIndex = MyAvatar.getJointIndex(hand === RIGHT_HAND ?
"_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" :
"_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"); "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND");
} }
return controllerJointIndex; return controllerJointIndex;
@ -229,19 +223,24 @@ propsArePhysical = function (props) {
if (!props.dynamic) { if (!props.dynamic) {
return false; return false;
} }
var isPhysical = (props.shapeType && props.shapeType != 'none'); var isPhysical = (props.shapeType && props.shapeType !== 'none');
return isPhysical; return isPhysical;
}; };
projectOntoXYPlane = function (worldPos, position, rotation, dimensions, registrationPoint) { projectOntoXYPlane = function (worldPos, position, rotation, dimensions, registrationPoint) {
var invRot = Quat.inverse(rotation); var invRot = Quat.inverse(rotation);
var localPos = Vec3.multiplyQbyV(invRot, Vec3.subtract(worldPos, position)); var localPos = Vec3.multiplyQbyV(invRot, Vec3.subtract(worldPos, position));
var invDimensions = { x: 1 / dimensions.x, var invDimensions = {
y: 1 / dimensions.y, x: 1 / dimensions.x,
z: 1 / dimensions.z }; y: 1 / dimensions.y,
z: 1 / dimensions.z
};
var normalizedPos = Vec3.sum(Vec3.multiplyVbyV(localPos, invDimensions), registrationPoint); var normalizedPos = Vec3.sum(Vec3.multiplyVbyV(localPos, invDimensions), registrationPoint);
return { x: normalizedPos.x * dimensions.x, return {
y: (1 - normalizedPos.y) * dimensions.y }; // flip y-axis x: normalizedPos.x * dimensions.x,
y: (1 - normalizedPos.y) * dimensions.y // flip y-axis
};
}; };
projectOntoEntityXYPlane = function (entityID, worldPos, props) { projectOntoEntityXYPlane = function (entityID, worldPos, props) {
@ -257,14 +256,14 @@ projectOntoOverlayXYPlane = function projectOntoOverlayXYPlane(overlayID, worldP
if (dpi) { if (dpi) {
// Calculate physical dimensions for web3d overlay from resolution and dpi; "dimensions" property is used as a scale. // Calculate physical dimensions for web3d overlay from resolution and dpi; "dimensions" property is used as a scale.
var resolution = Overlays.getProperty(overlayID, "resolution"); var resolution = Overlays.getProperty(overlayID, "resolution");
resolution.z = 1; // Circumvent divide-by-zero. resolution.z = 1; // Circumvent divide-by-zero.
var scale = Overlays.getProperty(overlayID, "dimensions"); var scale = Overlays.getProperty(overlayID, "dimensions");
scale.z = 0.01; // overlay dimensions are 2D, not 3D. scale.z = 0.01; // overlay dimensions are 2D, not 3D.
dimensions = Vec3.multiplyVbyV(Vec3.multiply(resolution, INCHES_TO_METERS / dpi), scale); dimensions = Vec3.multiplyVbyV(Vec3.multiply(resolution, INCHES_TO_METERS / dpi), scale);
} else { } else {
dimensions = Overlays.getProperty(overlayID, "dimensions"); dimensions = Overlays.getProperty(overlayID, "dimensions");
if (dimensions.z) { if (dimensions.z) {
dimensions.z = 0.01; // overlay dimensions are 2D, not 3D. dimensions.z = 0.01; // overlay dimensions are 2D, not 3D.
} }
} }
@ -279,7 +278,7 @@ ensureDynamic = function (entityID) {
// if we distance hold something and keep it very still before releasing it, it ends up // if we distance hold something and keep it very still before releasing it, it ends up
// non-dynamic in bullet. If it's too still, give it a little bounce so it will fall. // non-dynamic in bullet. If it's too still, give it a little bounce so it will fall.
var props = Entities.getEntityProperties(entityID, ["velocity", "dynamic", "parentID"]); var props = Entities.getEntityProperties(entityID, ["velocity", "dynamic", "parentID"]);
if (props.dynamic && props.parentID == NULL_UUID) { if (props.dynamic && props.parentID === NULL_UUID) {
var velocity = props.velocity; var velocity = props.velocity;
if (Vec3.length(velocity) < 0.05) { // see EntityMotionState.cpp DYNAMIC_LINEAR_VELOCITY_THRESHOLD if (Vec3.length(velocity) < 0.05) { // see EntityMotionState.cpp DYNAMIC_LINEAR_VELOCITY_THRESHOLD
velocity = { x: 0.0, y: 0.2, z: 0.0 }; velocity = { x: 0.0, y: 0.2, z: 0.0 };
@ -289,7 +288,7 @@ ensureDynamic = function (entityID) {
}; };
findGroupParent = function (controllerData, targetProps) { findGroupParent = function (controllerData, targetProps) {
while (targetProps.parentID && targetProps.parentID != NULL_UUID) { while (targetProps.parentID && targetProps.parentID !== NULL_UUID) {
// XXX use controllerData.nearbyEntityPropertiesByID ? // XXX use controllerData.nearbyEntityPropertiesByID ?
var parentProps = Entities.getEntityProperties(targetProps.parentID, DISPATCHER_PROPERTIES); var parentProps = Entities.getEntityProperties(targetProps.parentID, DISPATCHER_PROPERTIES);
if (!parentProps) { if (!parentProps) {

View file

@ -0,0 +1,85 @@
"use strict";
// nearTrigger.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, getGrabbableData, Vec3,
TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS,
getEnabledModuleByName
*/
Script.include("/~/system/controllers/controllerDispatcherUtils.js");
(function() {
function DisableModules(hand) {
this.hand = hand;
this.disableModules = false;
this.parameters = makeDispatcherModuleParameters(
90,
this.hand === RIGHT_HAND ? ["rightHand", "rightHandEquip", "rightHandTrigger"] : ["leftHand", "leftHandEquip", "leftHandTrigger"],
100);
this.isReady = function(controllerData) {
if (this.disableModules) {
return makeRunningValues(true, [], []);
}
return false;
};
this.run = function(controllerData) {
var teleportModuleName = this.hand === RIGHT_HAND ? "RightTeleporter" : "LeftTeleporter";
var teleportModule = getEnabledModuleByName(teleportModuleName);
if (teleportModule) {
var ready = teleportModule.isReady(controllerData);
if (ready) {
return makeRunningValues(false, [], []);
}
}
if (!this.disablemodules) {
return makeRunningValues(false, [], []);
}
return makeRunningValues(true, [], []);
};
}
var leftDisableModules = new DisableModules(LEFT_HAND);
var rightDisableModules = new DisableModules(RIGHT_HAND);
enableDispatcherModule("LeftDisableModules", leftDisableModules);
enableDispatcherModule("RightDisableModules", rightDisableModules);
this.handleMessage = function(channel, message, sender) {
if (sender === MyAvatar.sessionUUID) {
if (channel === 'Hifi-Hand-Disabler') {
if (message === 'left') {
leftDisableModules.disableModules = true;
}
if (message === 'right') {
rightDisableModules.disableModules = true;
}
if (message === 'both' || message === 'none') {
if (message === 'both') {
leftDisableModules.disableModules = true;
rightDisableModules.disableModules = true;
} else if (message === 'none') {
leftDisableModules.disableModules = false;
rightDisableModules.disableModules = false;
}
}
}
}
};
Messages.subscribe('Hifi-Hand-Disabler');
this.cleanup = function() {
disableDispatcherModule("LeftDisableModules");
disableDispatcherModule("RightDisableModules");
};
Messages.messageReceived.connect(this.handleMessage);
Script.scriptEnding.connect(this.cleanup);
}());

View file

@ -187,6 +187,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
wearable = props.userDataParsed.wearable ? props.userDataParsed.wearable : {}; wearable = props.userDataParsed.wearable ? props.userDataParsed.wearable : {};
} catch (err) { } catch (err) {
// don't want to spam the logs
} }
return wearable; return wearable;
} }
@ -199,6 +200,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
equipHotspots = props.userDataParsed.equipHotspots ? props.userDataParsed.equipHotspots : []; equipHotspots = props.userDataParsed.equipHotspots ? props.userDataParsed.equipHotspots : [];
} catch (err) { } catch (err) {
// don't want to spam the logs
} }
return equipHotspots; return equipHotspots;
} }
@ -255,7 +257,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
this.parameters = makeDispatcherModuleParameters( this.parameters = makeDispatcherModuleParameters(
300, 300,
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], this.hand === RIGHT_HAND ? ["rightHand", "rightHandEquip"] : ["leftHand", "rightHandEquip"],
[], [],
100); 100);
@ -556,8 +558,8 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
var controllerLocation = getControllerWorldLocation(this.handToController(), true); var controllerLocation = getControllerWorldLocation(this.handToController(), true);
var worldHandPosition = controllerLocation.position; var worldHandPosition = controllerLocation.position;
var candidateEntityProps = controllerData.nearbyEntityProperties[this.hand]; var candidateEntityProps = controllerData.nearbyEntityProperties[this.hand];
var potentialEquipHotspot = null; var potentialEquipHotspot = null;
if (this.messageGrabEntity) { if (this.messageGrabEntity) {
var hotspots = this.collectEquipHotspots(this.grabEntityProps); var hotspots = this.collectEquipHotspots(this.grabEntityProps);
@ -567,7 +569,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
} else { } else {
potentialEquipHotspot = this.chooseBestEquipHotspot(candidateEntityProps, controllerData); potentialEquipHotspot = this.chooseBestEquipHotspot(candidateEntityProps, controllerData);
} }
if (!this.waitForTriggerRelease) { if (!this.waitForTriggerRelease) {
this.updateEquipHaptics(potentialEquipHotspot, worldHandPosition); this.updateEquipHaptics(potentialEquipHotspot, worldHandPosition);
} }
@ -675,7 +677,6 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
var handleMessage = function(channel, message, sender) { var handleMessage = function(channel, message, sender) {
var data; var data;
print(channel);
if (sender === MyAvatar.sessionUUID) { if (sender === MyAvatar.sessionUUID) {
if (channel === 'Hifi-Hand-Grab') { if (channel === 'Hifi-Hand-Grab') {
try { try {

View file

@ -527,6 +527,19 @@ Script.include("/~/system/libraries/controllers.js");
this.distanceRotate(otherFarGrabModule); this.distanceRotate(otherFarGrabModule);
} }
} }
return this.exitIfDisabled();
};
this.exitIfDisabled = function() {
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, [], []); return makeRunningValues(true, [], []);
}; };

View file

@ -93,7 +93,7 @@ Script.include("/~/system/libraries/utils.js");
this.parameters = makeDispatcherModuleParameters( this.parameters = makeDispatcherModuleParameters(
160, 160,
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], this.hand === RIGHT_HAND ? ["rightHand", "rightHandEquip", "rightHandTrigger"] : ["leftHand", "leftHandEquip", "leftHandTrigger"],
100); 100);
this.nearTablet = function(overlays) { this.nearTablet = function(overlays) {

View file

@ -9,11 +9,12 @@
getControllerJointIndex, getGrabbableData, NULL_UUID, enableDispatcherModule, disableDispatcherModule, getControllerJointIndex, getGrabbableData, NULL_UUID, enableDispatcherModule, disableDispatcherModule,
propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, entityIsGrabbable, propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, entityIsGrabbable,
Quat, Vec3, MSECS_PER_SEC, getControllerWorldLocation, makeDispatcherModuleParameters, makeRunningValues, Quat, Vec3, MSECS_PER_SEC, getControllerWorldLocation, makeDispatcherModuleParameters, makeRunningValues,
TRIGGER_OFF_VALUE, NEAR_GRAB_RADIUS, findGroupParent TRIGGER_OFF_VALUE, NEAR_GRAB_RADIUS, findGroupParent, entityIsCloneable, propsAreCloneDynamic, cloneEntity
*/ */
Script.include("/~/system/controllers/controllerDispatcherUtils.js"); Script.include("/~/system/controllers/controllerDispatcherUtils.js");
Script.include("/~/system/libraries/controllers.js"); Script.include("/~/system/libraries/controllers.js");
Script.include("/~/system/libraries/cloneEntityUtils.js");
(function() { (function() {
@ -172,7 +173,7 @@ Script.include("/~/system/libraries/controllers.js");
var targetProps = this.getTargetProps(controllerData); var targetProps = this.getTargetProps(controllerData);
if (targetProps) { if (targetProps) {
if (!propsArePhysical(targetProps)) { if (!propsArePhysical(targetProps) && !propsAreCloneDynamic) {
return makeRunningValues(false, [], []); // let nearParentGrabEntity handle it return makeRunningValues(false, [], []); // let nearParentGrabEntity handle it
} else { } else {
this.targetEntityID = targetProps.id; this.targetEntityID = targetProps.id;
@ -185,13 +186,12 @@ Script.include("/~/system/libraries/controllers.js");
this.run = function (controllerData) { this.run = function (controllerData) {
if (this.actionID) { if (this.actionID) {
if (controllerData.triggerClicks[this.hand] == 0) { if (controllerData.triggerClicks[this.hand] === 0) {
this.endNearGrabAction(); this.endNearGrabAction();
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
} }
this.refreshNearGrabAction(controllerData); this.refreshNearGrabAction(controllerData);
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
Entities.callEntityMethod(this.targetEntityID, "continueNearGrab", args); Entities.callEntityMethod(this.targetEntityID, "continueNearGrab", args);
} else { } else {
@ -204,9 +204,18 @@ Script.include("/~/system/libraries/controllers.js");
var targetProps = this.getTargetProps(controllerData); var targetProps = this.getTargetProps(controllerData);
if (targetProps) { if (targetProps) {
if (controllerData.triggerClicks[this.hand] == 1) { if (controllerData.triggerClicks[this.hand] === 1) {
// switch to grabbing // switch to grabbing
this.startNearGrabAction(controllerData, targetProps); var targetCloneable = entityIsCloneable(targetProps);
if (targetCloneable) {
var worldEntityProps = controllerData.nearbyEntityProperties[this.hand];
var cloneID = cloneEntity(targetProps, worldEntityProps);
var cloneProps = Entities.getEntityProperties(cloneID);
this.targetEntityID = cloneID;
this.startNearGrabAction(controllerData, cloneProps);
} else {
this.startNearGrabAction(controllerData, targetProps);
}
} }
} }
} }

View file

@ -10,7 +10,7 @@
getControllerJointIndex, NULL_UUID, enableDispatcherModule, disableDispatcherModule, getControllerJointIndex, NULL_UUID, enableDispatcherModule, disableDispatcherModule,
propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, TRIGGER_OFF_VALUE, propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, TRIGGER_OFF_VALUE,
makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS, makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS,
findGroupParent, Vec3, cloneEntity, entityIsCloneable findGroupParent, Vec3, cloneEntity, entityIsCloneable, propsAreCloneDynamic
*/ */
Script.include("/~/system/controllers/controllerDispatcherUtils.js"); Script.include("/~/system/controllers/controllerDispatcherUtils.js");
@ -40,6 +40,14 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
this.handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"); this.handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
this.controllerJointIndex = getControllerJointIndex(this.hand); this.controllerJointIndex = getControllerJointIndex(this.hand);
this.getOtherModule = function() {
return (this.hand === RIGHT_HAND) ? leftNearParentingGrabEntity : rightNearParentingGrabEntity;
};
this.otherHandIsParent = function(props) {
return this.getOtherModule().thisHandIsParent(props);
};
this.thisHandIsParent = function(props) { this.thisHandIsParent = function(props) {
if (props.parentID !== MyAvatar.sessionUUID && props.parentID !== AVATAR_SELF_ID) { if (props.parentID !== MyAvatar.sessionUUID && props.parentID !== AVATAR_SELF_ID) {
return false; return false;
@ -67,7 +75,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
}; };
this.startNearParentingGrabEntity = function (controllerData, targetProps) { this.startNearParentingGrabEntity = function (controllerData, targetProps) {
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
var handJointIndex; var handJointIndex;
@ -92,10 +99,18 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
// this should never happen, but if it does, don't set previous parent to be this hand. // this should never happen, but if it does, don't set previous parent to be this hand.
// this.previousParentID[targetProps.id] = NULL; // this.previousParentID[targetProps.id] = NULL;
// this.previousParentJointIndex[targetProps.id] = -1; // this.previousParentJointIndex[targetProps.id] = -1;
} else if (this.otherHandIsParent(targetProps)) {
// the other hand is parent. Steal the object and information
var otherModule = this.getOtherModule();
this.previousParentID[targetProps.id] = otherModule.previousParentID[targetProps.id];
this.previousParentJointIndex[targetProps.id] = otherModule.previousParentJointIndex[targetProps.id];
otherModule.endNearParentingGrabEntity();
} else { } else {
this.previousParentID[targetProps.id] = targetProps.parentID; this.previousParentID[targetProps.id] = targetProps.parentID;
this.previousParentJointIndex[targetProps.id] = targetProps.parentJointIndex; this.previousParentJointIndex[targetProps.id] = targetProps.parentJointIndex;
} }
this.targetEntityID = targetProps.id;
Entities.editEntity(targetProps.id, reparentProps); Entities.editEntity(targetProps.id, reparentProps);
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
@ -103,10 +118,11 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
grabbedEntity: targetProps.id, grabbedEntity: targetProps.id,
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand" joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
})); }));
this.grabbing = true;
}; };
this.endNearParentingGrabEntity = function () { this.endNearParentingGrabEntity = function () {
if (this.previousParentID[this.targetEntityID] === NULL_UUID) { if (this.previousParentID[this.targetEntityID] === NULL_UUID || this.previousParentID === undefined) {
Entities.editEntity(this.targetEntityID, { Entities.editEntity(this.targetEntityID, {
parentID: this.previousParentID[this.targetEntityID], parentID: this.previousParentID[this.targetEntityID],
parentJointIndex: this.previousParentJointIndex[this.targetEntityID] parentJointIndex: this.previousParentJointIndex[this.targetEntityID]
@ -123,7 +139,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
Entities.callEntityMethod(this.targetEntityID, "releaseGrab", args); Entities.callEntityMethod(this.targetEntityID, "releaseGrab", args);
this.grabbing = false; this.grabbing = false;
this.targetEntityID = null; this.targetEntityID = null;
}; };
@ -160,7 +175,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
var targetProps = this.getTargetProps(controllerData); var targetProps = this.getTargetProps(controllerData);
if (targetProps) { if (targetProps) {
if (propsArePhysical(targetProps)) { if (propsArePhysical(targetProps) || propsAreCloneDynamic(targetProps)) {
return makeRunningValues(false, [], []); // let nearActionGrabEntity handle it return makeRunningValues(false, [], []); // let nearActionGrabEntity handle it
} else { } else {
this.targetEntityID = targetProps.id; this.targetEntityID = targetProps.id;
@ -178,6 +193,13 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
} }
var props = Entities.getEntityProperties(this.targetEntityID);
if (!this.thisHandIsParent(props)) {
this.grabbing = false;
this.targetEntityID = null;
return makeRunningValues(false, [], []);
}
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
Entities.callEntityMethod(this.targetEntityID, "continueNearGrab", args); Entities.callEntityMethod(this.targetEntityID, "continueNearGrab", args);
} else { } else {

View file

@ -38,31 +38,52 @@ var GRAB_RADIUS = 0.35;
this.handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"); this.handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
this.controllerJointIndex = getControllerJointIndex(this.hand); this.controllerJointIndex = getControllerJointIndex(this.hand);
this.getOtherModule = function() {
return (this.hand === RIGHT_HAND) ? leftNearParentingGrabOverlay : rightNearParentingGrabOverlay;
};
this.otherHandIsParent = function(props) {
return this.getOtherModule().thisHandIsParent(props);
};
this.thisHandIsParent = function(props) { this.thisHandIsParent = function(props) {
if (props.parentID !== MyAvatar.sessionUUID && props.parentID !== AVATAR_SELF_ID) { if (props.parentID !== MyAvatar.sessionUUID && props.parentID !== AVATAR_SELF_ID) {
return false; return false;
} }
var handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"); var handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
if (props.parentJointIndex == handJointIndex) { if (props.parentJointIndex === handJointIndex) {
return true; return true;
} }
var controllerJointIndex = this.controllerJointIndex; var controllerJointIndex = this.controllerJointIndex;
if (props.parentJointIndex == controllerJointIndex) { if (props.parentJointIndex === controllerJointIndex) {
return true; return true;
} }
var controllerCRJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? var controllerCRJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ?
"_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" :
"_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"); "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND");
if (props.parentJointIndex == controllerCRJointIndex) {
if (props.parentJointIndex === controllerCRJointIndex) {
return true; return true;
} }
return false; return false;
}; };
this.getGrabbedProperties = function() {
return {
position: Overlays.getProperty(this.grabbedThingID, "position"),
rotation: Overlays.getProperty(this.grabbedThingID, "rotation"),
parentID: Overlays.getProperty(this.grabbedThingID, "parentID"),
parentJointIndex: Overlays.getProperty(this.grabbedThingID, "parentJointIndex"),
dynamic: false,
shapeType: "none"
};
};
this.startNearParentingGrabOverlay = function (controllerData) { this.startNearParentingGrabOverlay = function (controllerData) {
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
@ -74,15 +95,8 @@ var GRAB_RADIUS = 0.35;
// } // }
handJointIndex = this.controllerJointIndex; handJointIndex = this.controllerJointIndex;
var grabbedProperties = { var grabbedProperties = this.getGrabbedProperties();
position: Overlays.getProperty(this.grabbedThingID, "position"),
rotation: Overlays.getProperty(this.grabbedThingID, "rotation"),
parentID: Overlays.getProperty(this.grabbedThingID, "parentID"),
parentJointIndex: Overlays.getProperty(this.grabbedThingID, "parentJointIndex"),
dynamic: false,
shapeType: "none"
};
var reparentProps = { var reparentProps = {
parentID: AVATAR_SELF_ID, parentID: AVATAR_SELF_ID,
parentJointIndex: handJointIndex, parentJointIndex: handJointIndex,
@ -94,6 +108,12 @@ var GRAB_RADIUS = 0.35;
// this should never happen, but if it does, don't set previous parent to be this hand. // this should never happen, but if it does, don't set previous parent to be this hand.
// this.previousParentID[this.grabbedThingID] = NULL; // this.previousParentID[this.grabbedThingID] = NULL;
// this.previousParentJointIndex[this.grabbedThingID] = -1; // this.previousParentJointIndex[this.grabbedThingID] = -1;
} else if (this.otherHandIsParent(grabbedProperties)) {
// the other hand is parent. Steal the object and information
var otherModule = this.getOtherModule();
this.previousParentID[this.grabbedThingID] = otherModule.previousParentID[this.garbbedThingID];
this.previousParentJointIndex[this.grabbedThingID] = otherModule.previousParentJointIndex[this.grabbedThingID];
} else { } else {
this.previousParentID[this.grabbedThingID] = grabbedProperties.parentID; this.previousParentID[this.grabbedThingID] = grabbedProperties.parentID;
this.previousParentJointIndex[this.grabbedThingID] = grabbedProperties.parentJointIndex; this.previousParentJointIndex[this.grabbedThingID] = grabbedProperties.parentJointIndex;
@ -117,7 +137,7 @@ var GRAB_RADIUS = 0.35;
// before we grabbed it, overlay was a child of something; put it back. // before we grabbed it, overlay was a child of something; put it back.
Overlays.editOverlay(this.grabbedThingID, { Overlays.editOverlay(this.grabbedThingID, {
parentID: this.previousParentID[this.grabbedThingID], parentID: this.previousParentID[this.grabbedThingID],
parentJointIndex: this.previousParentJointIndex[this.grabbedThingID], parentJointIndex: this.previousParentJointIndex[this.grabbedThingID]
}); });
} }
@ -135,10 +155,10 @@ var GRAB_RADIUS = 0.35;
} }
return null; return null;
}; };
this.isReady = function (controllerData) { this.isReady = function (controllerData) {
if (controllerData.triggerClicks[this.hand] == 0) { if (controllerData.triggerClicks[this.hand] === 0) {
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
} }
@ -160,10 +180,16 @@ var GRAB_RADIUS = 0.35;
}; };
this.run = function (controllerData) { this.run = function (controllerData) {
if (controllerData.triggerClicks[this.hand] == 0) { if (controllerData.triggerClicks[this.hand] === 0) {
this.endNearParentingGrabOverlay(); this.endNearParentingGrabOverlay();
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
} else { } else {
// check if someone stole the target from us
var grabbedProperties = this.getGrabbedProperties();
if (!this.thisHandIsParent(grabbedProperties)) {
return makeRunningValues(false, [], []);
}
return makeRunningValues(true, [this.grabbedThingID], []); return makeRunningValues(true, [this.grabbedThingID], []);
} }
}; };

View file

@ -30,7 +30,7 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
this.parameters = makeDispatcherModuleParameters( this.parameters = makeDispatcherModuleParameters(
520, 520,
this.hand === RIGHT_HAND ? ["rightHandTrigger"] : ["leftHandTrigger"], this.hand === RIGHT_HAND ? ["rightHandTrigger", "rightHand"] : ["leftHandTrigger", "leftHand"],
[], [],
100); 100);

View file

@ -26,6 +26,7 @@ var CONTOLLER_SCRIPTS = [
"controllerModules/overlayLaserInput.js", "controllerModules/overlayLaserInput.js",
"controllerModules/webEntityLaserInput.js", "controllerModules/webEntityLaserInput.js",
"controllerModules/inEditMode.js", "controllerModules/inEditMode.js",
"controllerModules/disableOtherModule.js",
"teleport.js" "teleport.js"
]; ];

View file

@ -14,6 +14,7 @@
Messages, makeDispatcherModuleParameters, makeRunningValues, Settings, entityHasActions, Messages, makeDispatcherModuleParameters, makeRunningValues, Settings, entityHasActions,
Vec3, Overlays, flatten, Xform, getControllerWorldLocation, ensureDynamic Vec3, Overlays, flatten, Xform, getControllerWorldLocation, ensureDynamic
*/ */
/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */
Script.include("/~/system/libraries/Xform.js"); Script.include("/~/system/libraries/Xform.js");
Script.include("/~/system/controllers/controllerDispatcherUtils.js"); Script.include("/~/system/controllers/controllerDispatcherUtils.js");
@ -225,7 +226,7 @@ function Teleporter(hand) {
} }
this.parameters = makeDispatcherModuleParameters( this.parameters = makeDispatcherModuleParameters(
300, 80,
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
[], [],
100); 100);
@ -338,12 +339,12 @@ function Teleporter(hand) {
} }
}; };
} }
// related to repositioning the avatar after you teleport // related to repositioning the avatar after you teleport
var FOOT_JOINT_NAMES = ["RightToe_End", "RightToeBase", "RightFoot"]; var FOOT_JOINT_NAMES = ["RightToe_End", "RightToeBase", "RightFoot"];
var DEFAULT_ROOT_TO_FOOT_OFFSET = 0.5; var DEFAULT_ROOT_TO_FOOT_OFFSET = 0.5;
function getAvatarFootOffset() { function getAvatarFootOffset() {
// find a valid foot jointIndex // find a valid foot jointIndex
var footJointIndex = -1; var footJointIndex = -1;
var i, l = FOOT_JOINT_NAMES.length; var i, l = FOOT_JOINT_NAMES.length;

View file

@ -5,11 +5,13 @@
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
/* global entityIsCloneable:true, getGrabbableData:true, cloneEntity:true propsAreCloneDynamic:true */
Script.include("/~/system/controllers/controllerDispatcherUtils.js"); Script.include("/~/system/controllers/controllerDispatcherUtils.js");
// Object assign polyfill // Object assign polyfill
if (typeof Object.assign != 'function') { if (typeof Object.assign !== 'function') {
Object.assign = function(target, varArgs) { Object.assign = function(target, varArgs) {
if (target === null) { if (target === null) {
throw new TypeError('Cannot convert undefined or null to object'); throw new TypeError('Cannot convert undefined or null to object');
@ -36,7 +38,18 @@ entityIsCloneable = function(props) {
} }
return false; return false;
} };
propsAreCloneDynamic = function(props) {
var cloneable = entityIsCloneable(props);
if (cloneable) {
var grabInfo = getGrabbableData(props);
if (grabInfo.cloneDynamic) {
return true;
}
}
return false;
};
cloneEntity = function(props, worldEntityProps) { cloneEntity = function(props, worldEntityProps) {
@ -49,26 +62,26 @@ cloneEntity = function(props, worldEntityProps) {
count++; count++;
} }
}); });
var grabInfo = getGrabbableData(cloneableProps); var grabInfo = getGrabbableData(cloneableProps);
var limit = grabInfo.cloneLimit ? grabInfo.cloneLimit : 0; var limit = grabInfo.cloneLimit ? grabInfo.cloneLimit : 0;
if (count >= limit && limit !== 0) { if (count >= limit && limit !== 0) {
return null; return null;
} }
cloneableProps.name = cloneableProps.name + '-clone-' + cloneableProps.id; cloneableProps.name = cloneableProps.name + '-clone-' + cloneableProps.id;
var lifetime = grabInfo.cloneLifetime ? grabInfo.cloneLifetime : 300; var lifetime = grabInfo.cloneLifetime ? grabInfo.cloneLifetime : 300;
var dynamic = grabInfo.cloneDynamic ? grabInfo.cloneDynamic : false; var dynamic = grabInfo.cloneDynamic ? grabInfo.cloneDynamic : false;
var cUserData = Object.assign({}, JSON.parse(cloneableProps.userData)); var cUserData = Object.assign({}, JSON.parse(cloneableProps.userData));
var cProperties = Object.assign({}, cloneableProps); var cProperties = Object.assign({}, cloneableProps);
delete cUserData.grabbableKey.cloneLifetime; delete cUserData.grabbableKey.cloneLifetime;
delete cUserData.grabbableKey.cloneable; delete cUserData.grabbableKey.cloneable;
delete cUserData.grabbableKey.cloneDynamic; delete cUserData.grabbableKey.cloneDynamic;
delete cUserData.grabbableKey.cloneLimit; delete cUserData.grabbableKey.cloneLimit;
delete cProperties.id; delete cProperties.id;
cProperties.dynamic = dynamic; cProperties.dynamic = dynamic;
cProperties.locked = false; cProperties.locked = false;
@ -76,7 +89,7 @@ cloneEntity = function(props, worldEntityProps) {
cUserData.grabbableKey.grabbable = true; cUserData.grabbableKey.grabbable = true;
cProperties.lifetime = lifetime; cProperties.lifetime = lifetime;
cProperties.userData = JSON.stringify(cUserData); cProperties.userData = JSON.stringify(cUserData);
var cloneID = Entities.addEntity(cProperties); var cloneID = Entities.addEntity(cProperties);
return cloneID; return cloneID;
} };