diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index 3826222666..43ad2ccf51 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -21,366 +21,378 @@ Script.include("/~/system/libraries/controllers.js"); Script.include("/~/system/controllers/controllerDispatcherUtils.js"); (function() { - var _this = this; var NEAR_MAX_RADIUS = 1.0; var TARGET_UPDATE_HZ = 60; // 50hz good enough, but we're using update var BASIC_TIMER_INTERVAL_MS = 1000 / TARGET_UPDATE_HZ; - this.lastInterval = Date.now(); - this.intervalCount = 0; - this.totalDelta = 0; - this.totalVariance = 0; - this.highVarianceCount = 0; - this.veryhighVarianceCount = 0; - this.tabletID = null; - this.blacklist = []; - // 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 - // is stored as the value, rather than false. - this.activitySlots = { - leftHand: false, - rightHand: false, - mouse: false - }; + function ControllerDispatcher() { + var _this = this + this.lastInterval = Date.now(); + this.intervalCount = 0; + this.totalDelta = 0; + this.totalVariance = 0; + this.highVarianceCount = 0; + this.veryhighVarianceCount = 0; + this.tabletID = null; + this.blacklist = []; - this.slotsAreAvailableForPlugin = function (plugin) { - for (var i = 0; i < plugin.parameters.activitySlots.length; i++) { - if (_this.activitySlots[plugin.parameters.activitySlots[i]]) { - return false; // something is already using a slot which _this plugin requires - } - } - return true; - }; - - this.markSlots = function (plugin, used) { - for (var i = 0; i < plugin.parameters.activitySlots.length; i++) { - _this.activitySlots[plugin.parameters.activitySlots[i]] = used; - } - }; - - this.unmarkSlotsForPluginName = function (runningPluginName) { - // this is used to free activity-slots when a plugin is deactivated while it's running. - for (var activitySlot in _this.activitySlots) { - if (activitySlot.hasOwnProperty(activitySlot) && _this.activitySlots[activitySlot] === runningPluginName) { - _this.activitySlots[activitySlot] = false; - } - } - }; - - this.runningPluginNames = {}; - this.leftTriggerValue = 0; - this.leftTriggerClicked = 0; - this.rightTriggerValue = 0; - this.rightTriggerClicked = 0; - this.leftSecondaryValue = 0; - this.rightSecondaryValue = 0; - - this.leftTriggerPress = function (value) { - _this.leftTriggerValue = value; - }; - this.leftTriggerClick = function (value) { - _this.leftTriggerClicked = value; - }; - this.rightTriggerPress = function (value) { - _this.rightTriggerValue = value; - }; - this.rightTriggerClick = function (value) { - _this.rightTriggerClicked = value; - }; - this.leftSecondaryPress = function (value) { - _this.leftSecondaryValue = value; - }; - this.rightSecondaryPress = function (value) { - _this.rightSecondaryValue = value; - }; - - - this.dataGatherers = {}; - this.dataGatherers.leftControllerLocation = function () { - return getControllerWorldLocation(Controller.Standard.LeftHand, true); - }; - this.dataGatherers.rightControllerLocation = function () { - return getControllerWorldLocation(Controller.Standard.RightHand, true); - }; - - this.updateTimings = function () { - _this.intervalCount++; - var thisInterval = Date.now(); - var deltaTimeMsec = thisInterval - _this.lastInterval; - var deltaTime = deltaTimeMsec / 1000; - _this.lastInterval = thisInterval; - - _this.totalDelta += deltaTimeMsec; - - var variance = Math.abs(deltaTimeMsec - BASIC_TIMER_INTERVAL_MS); - _this.totalVariance += variance; - - if (variance > 1) { - _this.highVarianceCount++; - } - - if (variance > 5) { - _this.veryhighVarianceCount++; - } - - return deltaTime; - }; - - this.setIgnoreTablet = function() { - if (HMD.tabletID !== _this.tabletID) { - RayPick.setIgnoreOverlays(_this.leftControllerRayPick, [HMD.tabletID]); - RayPick.setIgnoreOverlays(_this.rightControllerRayPick, [HMD.tabletID]); - } - }; - - this.update = function () { - var deltaTime = this.updateTimings(); - this.setIgnoreTablet(); - - if (controllerDispatcherPluginsNeedSort) { - this.orderedPluginNames = []; - for (var pluginName in controllerDispatcherPlugins) { - if (controllerDispatcherPlugins.hasOwnProperty(pluginName)) { - this.orderedPluginNames.push(pluginName); - } - } - this.orderedPluginNames.sort(function (a, b) { - return controllerDispatcherPlugins[a].parameters.priority - - controllerDispatcherPlugins[b].parameters.priority; - }); - - // print("controllerDispatcher -- new plugin order: " + JSON.stringify(this.orderedPluginNames)); - var output = "controllerDispatcher -- new plugin order: "; - for (var k = 0; k < this.orderedPluginNames.length; k++) { - var dbgPluginName = this.orderedPluginNames[k]; - var priority = controllerDispatcherPlugins[dbgPluginName].parameters.priority; - output += dbgPluginName + ":" + priority; - if (k + 1 < this.orderedPluginNames.length) { - output += ", "; - } - } - print(output); - - controllerDispatcherPluginsNeedSort = false; - } - - var controllerLocations = [ - _this.dataGatherers.leftControllerLocation(), - _this.dataGatherers.rightControllerLocation() - ]; - - // find 3d overlays near each hand - var nearbyOverlayIDs = []; - var h; - for (h = LEFT_HAND; h <= RIGHT_HAND; h++) { - // todo: check controllerLocations[h].valid - var nearbyOverlays = Overlays.findOverlays(controllerLocations[h].position, NEAR_MAX_RADIUS); - nearbyOverlays.sort(function (a, b) { - var aPosition = Overlays.getProperty(a, "position"); - var aDistance = Vec3.distance(aPosition, controllerLocations[h].position); - var bPosition = Overlays.getProperty(b, "position"); - var bDistance = Vec3.distance(bPosition, controllerLocations[h].position); - return aDistance - bDistance; - }); - nearbyOverlayIDs.push(nearbyOverlays); - } - - // find entities near each hand - var nearbyEntityProperties = [[], []]; - var nearbyEntityPropertiesByID = {}; - for (h = LEFT_HAND; h <= RIGHT_HAND; h++) { - // todo: check controllerLocations[h].valid - var controllerPosition = controllerLocations[h].position; - var nearbyEntityIDs = Entities.findEntities(controllerPosition, NEAR_MAX_RADIUS); - for (var j = 0; j < nearbyEntityIDs.length; j++) { - var entityID = nearbyEntityIDs[j]; - var props = Entities.getEntityProperties(entityID, DISPATCHER_PROPERTIES); - props.id = entityID; - nearbyEntityPropertiesByID[entityID] = props; - nearbyEntityProperties[h].push(props); - } - } - - // raypick for each controller - var rayPicks = [ - RayPick.getPrevRayPickResult(_this.leftControllerRayPick), - RayPick.getPrevRayPickResult(_this.rightControllerRayPick) - ]; - var hudRayPicks = [ - RayPick.getPrevRayPickResult(_this.leftControllerHudRayPick), - RayPick.getPrevRayPickResult(_this.rightControllerHudRayPick) - ]; - // if the pickray hit something very nearby, put it into the nearby entities list - for (h = LEFT_HAND; h <= RIGHT_HAND; h++) { - - // XXX find a way to extract searchRay from samuel's stuff - rayPicks[h].searchRay = { - origin: controllerLocations[h].position, - direction: Quat.getUp(controllerLocations[h].orientation), - length: 1000 - }; - - if (rayPicks[h].type === RayPick.INTERSECTED_ENTITY) { - // XXX check to make sure this one isn't already in nearbyEntityProperties? - if (rayPicks[h].distance < NEAR_GRAB_PICK_RADIUS) { - var nearEntityID = rayPicks[h].objectID; - var nearbyProps = Entities.getEntityProperties(nearEntityID, DISPATCHER_PROPERTIES); - nearbyProps.id = nearEntityID; - nearbyEntityPropertiesByID[nearEntityID] = nearbyProps; - nearbyEntityProperties[h].push(nearbyProps); - } - } - - // sort by distance from each hand - nearbyEntityProperties[h].sort(function (a, b) { - var aDistance = Vec3.distance(a.position, controllerLocations[h].position); - var bDistance = Vec3.distance(b.position, controllerLocations[h].position); - return aDistance - bDistance; - }); - } - - // bundle up all the data about the current situation - var controllerData = { - triggerValues: [_this.leftTriggerValue, _this.rightTriggerValue], - triggerClicks: [_this.leftTriggerClicked, _this.rightTriggerClicked], - secondaryValues: [_this.leftSecondaryValue, _this.rightSecondaryValue], - controllerLocations: controllerLocations, - nearbyEntityProperties: nearbyEntityProperties, - nearbyEntityPropertiesByID: nearbyEntityPropertiesByID, - nearbyOverlayIDs: nearbyOverlayIDs, - rayPicks: rayPicks, - hudRayPicks: hudRayPicks + // 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 + // is stored as the value, rather than false. + this.activitySlots = { + leftHand: false, + rightHand: false, + rightHandTrigger: false, + leftHandTrigger: false, + rightHandEquip: false, + leftHandEquip: false, + mouse: false }; - // check for plugins that would like to start. ask in order of increasing priority value - for (var pluginIndex = 0; pluginIndex < this.orderedPluginNames.length; pluginIndex++) { - var orderedPluginName = this.orderedPluginNames[pluginIndex]; - var candidatePlugin = controllerDispatcherPlugins[orderedPluginName]; - - if (_this.slotsAreAvailableForPlugin(candidatePlugin)) { - var readiness = candidatePlugin.isReady(controllerData, deltaTime); - if (readiness.active) { - // this plugin will start. add it to the list of running plugins and mark the - // activity-slots which this plugin consumes as "in use" - _this.runningPluginNames[orderedPluginName] = true; - _this.markSlots(candidatePlugin, orderedPluginName); + this.slotsAreAvailableForPlugin = function (plugin) { + for (var i = 0; i < plugin.parameters.activitySlots.length; i++) { + if (_this.activitySlots[plugin.parameters.activitySlots[i]]) { + return false; // something is already using a slot which _this plugin requires } } - } + return true; + }; - // print("QQQ running plugins: " + JSON.stringify(_this.runningPluginNames)); + this.markSlots = function (plugin, pluginName) { + for (var i = 0; i < plugin.parameters.activitySlots.length; i++) { + _this.activitySlots[plugin.parameters.activitySlots[i]] = pluginName; + } + }; - // give time to running plugins - for (var runningPluginName in _this.runningPluginNames) { - if (_this.runningPluginNames.hasOwnProperty(runningPluginName)) { - var plugin = controllerDispatcherPlugins[runningPluginName]; - if (!plugin) { - // plugin was deactivated while running. find the activity-slots it was using and make - // them available. - delete _this.runningPluginNames[runningPluginName]; - _this.unmarkSlotsForPluginName(runningPluginName); + this.unmarkSlotsForPluginName = function (runningPluginName) { + // this is used to free activity-slots when a plugin is deactivated while it's running. + for (var activitySlot in _this.activitySlots) { + if (activitySlot.hasOwnProperty(activitySlot) && _this.activitySlots[activitySlot] === runningPluginName) { + _this.activitySlots[activitySlot] = false; + } + } + }; + + this.runningPluginNames = {}; + this.leftTriggerValue = 0; + this.leftTriggerClicked = 0; + this.rightTriggerValue = 0; + this.rightTriggerClicked = 0; + this.leftSecondaryValue = 0; + this.rightSecondaryValue = 0; + + this.leftTriggerPress = function (value) { + _this.leftTriggerValue = value; + }; + this.leftTriggerClick = function (value) { + _this.leftTriggerClicked = value; + }; + this.rightTriggerPress = function (value) { + _this.rightTriggerValue = value; + }; + this.rightTriggerClick = function (value) { + _this.rightTriggerClicked = value; + }; + this.leftSecondaryPress = function (value) { + _this.leftSecondaryValue = value; + }; + this.rightSecondaryPress = function (value) { + _this.rightSecondaryValue = value; + }; + + + this.dataGatherers = {}; + this.dataGatherers.leftControllerLocation = function () { + return getControllerWorldLocation(Controller.Standard.LeftHand, true); + }; + this.dataGatherers.rightControllerLocation = function () { + return getControllerWorldLocation(Controller.Standard.RightHand, true); + }; + + this.updateTimings = function () { + _this.intervalCount++; + var thisInterval = Date.now(); + var deltaTimeMsec = thisInterval - _this.lastInterval; + var deltaTime = deltaTimeMsec / 1000; + _this.lastInterval = thisInterval; + + _this.totalDelta += deltaTimeMsec; + + var variance = Math.abs(deltaTimeMsec - BASIC_TIMER_INTERVAL_MS); + _this.totalVariance += variance; + + if (variance > 1) { + _this.highVarianceCount++; + } + + if (variance > 5) { + _this.veryhighVarianceCount++; + } + + return deltaTime; + }; + + this.setIgnoreTablet = function() { + if (HMD.tabletID !== _this.tabletID) { + RayPick.setIgnoreOverlays(_this.leftControllerRayPick, [HMD.tabletID]); + RayPick.setIgnoreOverlays(_this.rightControllerRayPick, [HMD.tabletID]); + } + }; + + this.update = function () { + var deltaTime = _this.updateTimings(); + _this.setIgnoreTablet(); + + if (controllerDispatcherPluginsNeedSort) { + _this.orderedPluginNames = []; + for (var pluginName in controllerDispatcherPlugins) { + if (controllerDispatcherPlugins.hasOwnProperty(pluginName)) { + _this.orderedPluginNames.push(pluginName); + } + } + _this.orderedPluginNames.sort(function (a, b) { + return controllerDispatcherPlugins[a].parameters.priority - + controllerDispatcherPlugins[b].parameters.priority; + }); + + // print("controllerDispatcher -- new plugin order: " + JSON.stringify(this.orderedPluginNames)); + var output = "controllerDispatcher -- new plugin order: "; + for (var k = 0; k < _this.orderedPluginNames.length; k++) { + var dbgPluginName = _this.orderedPluginNames[k]; + var priority = controllerDispatcherPlugins[dbgPluginName].parameters.priority; + output += dbgPluginName + ":" + priority; + if (k + 1 < _this.orderedPluginNames.length) { + output += ", "; + } + } + + controllerDispatcherPluginsNeedSort = false; + } + + var controllerLocations = [ + _this.dataGatherers.leftControllerLocation(), + _this.dataGatherers.rightControllerLocation() + ]; + + // find 3d overlays near each hand + var nearbyOverlayIDs = []; + var h; + for (h = LEFT_HAND; h <= RIGHT_HAND; h++) { + if (controllerLocations[h].valid) { + var nearbyOverlays = Overlays.findOverlays(controllerLocations[h].position, NEAR_MAX_RADIUS); + nearbyOverlays.sort(function (a, b) { + var aPosition = Overlays.getProperty(a, "position"); + var aDistance = Vec3.distance(aPosition, controllerLocations[h].position); + var bPosition = Overlays.getProperty(b, "position"); + var bDistance = Vec3.distance(bPosition, controllerLocations[h].position); + return aDistance - bDistance; + }); + nearbyOverlayIDs.push(nearbyOverlays); } else { - var runningness = plugin.run(controllerData, deltaTime); - if (!runningness.active) { - // plugin is finished running, for now. remove it from the list - // of running plugins and mark its activity-slots as "not in use" - delete _this.runningPluginNames[runningPluginName]; - _this.markSlots(plugin, false); + nearbyOverlayIDs.push([]); + } + } + + // find entities near each hand + var nearbyEntityProperties = [[], []]; + var nearbyEntityPropertiesByID = {}; + for (h = LEFT_HAND; h <= RIGHT_HAND; h++) { + if (controllerLocations[h].valid) { + var controllerPosition = controllerLocations[h].position; + var nearbyEntityIDs = Entities.findEntities(controllerPosition, NEAR_MAX_RADIUS); + for (var j = 0; j < nearbyEntityIDs.length; j++) { + var entityID = nearbyEntityIDs[j]; + var props = Entities.getEntityProperties(entityID, DISPATCHER_PROPERTIES); + props.id = entityID; + nearbyEntityPropertiesByID[entityID] = props; + nearbyEntityProperties[h].push(props); } } } - } - }; - this.setBlacklist = function() { - RayPick.setIgnoreEntities(_this.leftControllerRayPick, this.blacklist); - RayPick.setIgnoreEntities(_this.rightControllerRayPick, this.blacklist); + // raypick for each controller + var rayPicks = [ + RayPick.getPrevRayPickResult(_this.leftControllerRayPick), + RayPick.getPrevRayPickResult(_this.rightControllerRayPick) + ]; + var hudRayPicks = [ + RayPick.getPrevRayPickResult(_this.leftControllerHudRayPick), + RayPick.getPrevRayPickResult(_this.rightControllerHudRayPick) + ]; + // if the pickray hit something very nearby, put it into the nearby entities list + for (h = LEFT_HAND; h <= RIGHT_HAND; h++) { - }; + // XXX find a way to extract searchRay from samuel's stuff + rayPicks[h].searchRay = { + origin: controllerLocations[h].position, + direction: Quat.getUp(controllerLocations[h].orientation), + length: 1000 + }; - var MAPPING_NAME = "com.highfidelity.controllerDispatcher"; - var mapping = Controller.newMapping(MAPPING_NAME); - mapping.from([Controller.Standard.RT]).peek().to(_this.rightTriggerPress); - mapping.from([Controller.Standard.RTClick]).peek().to(_this.rightTriggerClick); - mapping.from([Controller.Standard.LT]).peek().to(_this.leftTriggerPress); - mapping.from([Controller.Standard.LTClick]).peek().to(_this.leftTriggerClick); - - mapping.from([Controller.Standard.RB]).peek().to(_this.rightSecondaryPress); - mapping.from([Controller.Standard.LB]).peek().to(_this.leftSecondaryPress); - mapping.from([Controller.Standard.LeftGrip]).peek().to(_this.leftSecondaryPress); - mapping.from([Controller.Standard.RightGrip]).peek().to(_this.rightSecondaryPress); - - Controller.enableMapping(MAPPING_NAME); - - this.leftControllerRayPick = RayPick.createRayPick({ - joint: "_CONTROLLER_LEFTHAND", - filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, - enabled: true, - maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, - posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand) - }); - this.leftControllerHudRayPick = RayPick.createRayPick({ - joint: "_CONTROLLER_LEFTHAND", - filter: RayPick.PICK_HUD, - enabled: true, - maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, - posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand) - }); - this.rightControllerRayPick = RayPick.createRayPick({ - joint: "_CONTROLLER_RIGHTHAND", - filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, - enabled: true, - maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, - posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand) - }); - this.rightControllerHudRayPick = RayPick.createRayPick({ - joint: "_CONTROLLER_RIGHTHAND", - filter: RayPick.PICK_HUD, - enabled: true, - maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, - posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand) - }); - - this.handleHandMessage = function(channel, message, sender) { - var data; - if (sender === MyAvatar.sessionUUID) { - try { - if (channel === 'Hifi-Hand-RayPick-Blacklist') { - data = JSON.parse(message); - var action = data.action; - var id = data.id; - var index = this.blacklis.indexOf(id); - - if (action === 'add' && index === -1) { - this.blacklist.push(id); - this.setBlacklist(); + if (rayPicks[h].type === RayPick.INTERSECTED_ENTITY) { + // XXX check to make sure this one isn't already in nearbyEntityProperties? + if (rayPicks[h].distance < NEAR_GRAB_PICK_RADIUS) { + var nearEntityID = rayPicks[h].objectID; + var nearbyProps = Entities.getEntityProperties(nearEntityID, DISPATCHER_PROPERTIES); + nearbyProps.id = nearEntityID; + nearbyEntityPropertiesByID[nearEntityID] = nearbyProps; + nearbyEntityProperties[h].push(nearbyProps); } + } - if (action === 'remove') { - if (index > -1) { - this.blacklist.splice(index, 1); - this.setBlacklist(); + // sort by distance from each hand + nearbyEntityProperties[h].sort(function (a, b) { + var aDistance = Vec3.distance(a.position, controllerLocations[h].position); + var bDistance = Vec3.distance(b.position, controllerLocations[h].position); + return aDistance - bDistance; + }); + } + + // bundle up all the data about the current situation + var controllerData = { + triggerValues: [_this.leftTriggerValue, _this.rightTriggerValue], + triggerClicks: [_this.leftTriggerClicked, _this.rightTriggerClicked], + secondaryValues: [_this.leftSecondaryValue, _this.rightSecondaryValue], + controllerLocations: controllerLocations, + nearbyEntityProperties: nearbyEntityProperties, + nearbyEntityPropertiesByID: nearbyEntityPropertiesByID, + nearbyOverlayIDs: nearbyOverlayIDs, + rayPicks: rayPicks, + hudRayPicks: hudRayPicks + }; + + // check for plugins that would like to start. ask in order of increasing priority value + for (var pluginIndex = 0; pluginIndex < _this.orderedPluginNames.length; pluginIndex++) { + var orderedPluginName = _this.orderedPluginNames[pluginIndex]; + var candidatePlugin = controllerDispatcherPlugins[orderedPluginName]; + + if (_this.slotsAreAvailableForPlugin(candidatePlugin)) { + var readiness = candidatePlugin.isReady(controllerData, deltaTime); + if (readiness.active) { + // this plugin will start. add it to the list of running plugins and mark the + // activity-slots which this plugin consumes as "in use" + _this.runningPluginNames[orderedPluginName] = true; + _this.markSlots(candidatePlugin, orderedPluginName); + } + } + } + + // print("QQQ running plugins: " + JSON.stringify(_this.runningPluginNames)); + + // give time to running plugins + for (var runningPluginName in _this.runningPluginNames) { + if (_this.runningPluginNames.hasOwnProperty(runningPluginName)) { + var plugin = controllerDispatcherPlugins[runningPluginName]; + if (!plugin) { + // plugin was deactivated while running. find the activity-slots it was using and make + // them available. + delete _this.runningPluginNames[runningPluginName]; + _this.unmarkSlotsForPluginName(runningPluginName); + } else { + var runningness = plugin.run(controllerData, deltaTime); + if (!runningness.active) { + // plugin is finished running, for now. remove it from the list + // of running plugins and mark its activity-slots as "not in use" + delete _this.runningPluginNames[runningPluginName]; + _this.markSlots(plugin, false); } } } - - } catch (e) { - print("WARNING: handControllerGrab.js -- error parsing Hifi-Hand-RayPick-Blacklist message: " + message); } - } - }; + }; - 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.setBlacklist = function() { + RayPick.setIgnoreEntities(_this.leftControllerRayPick, this.blacklist); + RayPick.setIgnoreEntities(_this.rightControllerRayPick, this.blacklist); + + }; + + var MAPPING_NAME = "com.highfidelity.controllerDispatcher"; + var mapping = Controller.newMapping(MAPPING_NAME); + mapping.from([Controller.Standard.RT]).peek().to(_this.rightTriggerPress); + mapping.from([Controller.Standard.RTClick]).peek().to(_this.rightTriggerClick); + mapping.from([Controller.Standard.LT]).peek().to(_this.leftTriggerPress); + mapping.from([Controller.Standard.LTClick]).peek().to(_this.leftTriggerClick); + + mapping.from([Controller.Standard.RB]).peek().to(_this.rightSecondaryPress); + mapping.from([Controller.Standard.LB]).peek().to(_this.leftSecondaryPress); + mapping.from([Controller.Standard.LeftGrip]).peek().to(_this.leftSecondaryPress); + mapping.from([Controller.Standard.RightGrip]).peek().to(_this.rightSecondaryPress); + + Controller.enableMapping(MAPPING_NAME); + + this.leftControllerRayPick = RayPick.createRayPick({ + joint: "_CONTROLLER_LEFTHAND", + filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, + enabled: true, + maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, + posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand) + }); + this.leftControllerHudRayPick = RayPick.createRayPick({ + joint: "_CONTROLLER_LEFTHAND", + filter: RayPick.PICK_HUD, + enabled: true, + maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, + posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand) + }); + this.rightControllerRayPick = RayPick.createRayPick({ + joint: "_CONTROLLER_RIGHTHAND", + filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, + enabled: true, + maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, + posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand) + }); + this.rightControllerHudRayPick = RayPick.createRayPick({ + joint: "_CONTROLLER_RIGHTHAND", + filter: RayPick.PICK_HUD, + enabled: true, + maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, + posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand) + }); + + this.handleHandMessage = function(channel, message, sender) { + var data; + if (sender === MyAvatar.sessionUUID) { + try { + if (channel === 'Hifi-Hand-RayPick-Blacklist') { + data = JSON.parse(message); + var action = data.action; + var id = data.id; + var index = _this.blacklis.indexOf(id); + + if (action === 'add' && index === -1) { + _this.blacklist.push(id); + _this.setBlacklist(); + } + + if (action === 'remove') { + if (index > -1) { + _this.blacklist.splice(index, 1); + _this.setBlacklist(); + } + } + } + + } catch (e) { + print("WARNING: handControllerGrab.js -- error parsing Hifi-Hand-RayPick-Blacklist message: " + message); + } + } + }; + + 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); + }; + } + + var controllerDispatcher = new ControllerDispatcher(); Messages.subscribe('Hifi-Hand-RayPick-Blacklist'); - Messages.messageReceived.connect(this.handleHandMessage); - Script.scriptEnding.connect(this.cleanup); - Script.update.connect(this.update); + Messages.messageReceived.connect(controllerDispatcher.handleHandMessage); + Script.scriptEnding.connect(controllerDispatcher.cleanup); + Script.update.connect(controllerDispatcher.update); }()); diff --git a/scripts/system/controllers/controllerModules/disableOtherModule.js b/scripts/system/controllers/controllerModules/disableOtherModule.js index 65732dd08d..d6079ffafb 100644 --- a/scripts/system/controllers/controllerModules/disableOtherModule.js +++ b/scripts/system/controllers/controllerModules/disableOtherModule.js @@ -12,7 +12,7 @@ getEnabledModuleByName */ -Script.include("/~/system/controllers/controllerDispatcherUtils.js"); +Script.include("/~/system/libraries/controllerDispatcherUtils.js"); (function() { function DisableModules(hand) { @@ -21,6 +21,7 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js"); this.parameters = makeDispatcherModuleParameters( 90, this.hand === RIGHT_HAND ? ["rightHand", "rightHandEquip", "rightHandTrigger"] : ["leftHand", "leftHandEquip", "leftHandTrigger"], + [], 100); this.isReady = function(controllerData) { diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 40e0e19cf3..fa1321b168 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -14,7 +14,7 @@ */ Script.include("/~/system/libraries/Xform.js"); -Script.include("/~/system/controllers/controllerDispatcherUtils.js"); +Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); Script.include("/~/system/libraries/cloneEntityUtils.js"); diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index 44360c2e39..56513ab766 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -17,7 +17,7 @@ */ -Script.include("/~/system/controllers/controllerDispatcherUtils.js"); +Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); (function() { diff --git a/scripts/system/controllers/controllerModules/farTrigger.js b/scripts/system/controllers/controllerModules/farTrigger.js index 671fc58c7d..38152aac91 100644 --- a/scripts/system/controllers/controllerModules/farTrigger.js +++ b/scripts/system/controllers/controllerModules/farTrigger.js @@ -16,7 +16,7 @@ */ -Script.include("/~/system/controllers/controllerDispatcherUtils.js"); +Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); (function() { diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js index c6ac0c01bc..cf82de1820 100644 --- a/scripts/system/controllers/controllerModules/inEditMode.js +++ b/scripts/system/controllers/controllerModules/inEditMode.js @@ -14,7 +14,7 @@ isInEditMode */ -Script.include("/~/system/controllers/controllerDispatcherUtils.js"); +Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); Script.include("/~/system/libraries/utils.js"); @@ -94,6 +94,7 @@ Script.include("/~/system/libraries/utils.js"); this.parameters = makeDispatcherModuleParameters( 160, this.hand === RIGHT_HAND ? ["rightHand", "rightHandEquip", "rightHandTrigger"] : ["leftHand", "leftHandEquip", "leftHandTrigger"], + [], 100); this.nearTablet = function(overlays) { diff --git a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js index 2b3a2405fb..7c856535ab 100644 --- a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js @@ -12,7 +12,7 @@ TRIGGER_OFF_VALUE, NEAR_GRAB_RADIUS, findGroupParent, entityIsCloneable, propsAreCloneDynamic, cloneEntity */ -Script.include("/~/system/controllers/controllerDispatcherUtils.js"); +Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); Script.include("/~/system/libraries/cloneEntityUtils.js"); diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index 4a59fd727f..47f80932bb 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -13,7 +13,7 @@ findGroupParent, Vec3, cloneEntity, entityIsCloneable, propsAreCloneDynamic */ -Script.include("/~/system/controllers/controllerDispatcherUtils.js"); +Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/cloneEntityUtils.js"); (function() { @@ -169,7 +169,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); this.targetEntityID = null; this.grabbing = false; - if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE) { + if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE && controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) { return makeRunningValues(false, [], []); } @@ -188,7 +188,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); this.run = function (controllerData, deltaTime) { if (this.grabbing) { - if (controllerData.triggerClicks[this.hand] === 0) { + if (controllerData.triggerClicks[this.hand] === 0 && controllerData.secondaryValues[this.hand] === 0) { this.endNearParentingGrabEntity(); return makeRunningValues(false, [], []); } @@ -208,7 +208,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); if (!readiness.active) { return readiness; } - if (controllerData.triggerClicks[this.hand] === 1) { + if (controllerData.triggerClicks[this.hand] === 1 || controllerData.secondaryValues[this.hand] === 1) { // switch to grab var targetProps = this.getTargetProps(controllerData); var targetCloneable = entityIsCloneable(targetProps); diff --git a/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js b/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js index 46ed8df271..9c8e6265ed 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js @@ -12,7 +12,7 @@ makeDispatcherModuleParameters, Overlays, makeRunningValues */ -Script.include("/~/system/controllers/controllerDispatcherUtils.js"); +Script.include("/~/system/libraries/controllerDispatcherUtils.js"); var GRAB_RADIUS = 0.35; (function() { @@ -158,7 +158,7 @@ var GRAB_RADIUS = 0.35; this.isReady = function (controllerData) { - if (controllerData.triggerClicks[this.hand] === 0) { + if (controllerData.triggerClicks[this.hand] === 0 && controllerData.secondaryValues[this.hand] === 0) { return makeRunningValues(false, [], []); } @@ -180,7 +180,7 @@ var GRAB_RADIUS = 0.35; }; this.run = function (controllerData) { - if (controllerData.triggerClicks[this.hand] === 0) { + if (controllerData.triggerClicks[this.hand] === 0 && controllerData.secondaryValues[this.hand] === 0) { this.endNearParentingGrabOverlay(); return makeRunningValues(false, [], []); } else { diff --git a/scripts/system/controllers/controllerModules/nearTrigger.js b/scripts/system/controllers/controllerModules/nearTrigger.js index 4d31a8a22b..03fc7f8f64 100644 --- a/scripts/system/controllers/controllerModules/nearTrigger.js +++ b/scripts/system/controllers/controllerModules/nearTrigger.js @@ -11,7 +11,7 @@ TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS */ -Script.include("/~/system/controllers/controllerDispatcherUtils.js"); +Script.include("/~/system/libraries/controllerDispatcherUtils.js"); (function() { diff --git a/scripts/system/controllers/controllerModules/overlayLaserInput.js b/scripts/system/controllers/controllerModules/overlayLaserInput.js index 86623dbc72..4b17f90524 100644 --- a/scripts/system/controllers/controllerModules/overlayLaserInput.js +++ b/scripts/system/controllers/controllerModules/overlayLaserInput.js @@ -14,7 +14,7 @@ DISPATCHER_PROPERTIES */ -Script.include("/~/system/controllers/controllerDispatcherUtils.js"); +Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); (function() { diff --git a/scripts/system/controllers/controllerModules/tabletStylusInput.js b/scripts/system/controllers/controllerModules/tabletStylusInput.js index 9720bc8022..9e6062e3c3 100644 --- a/scripts/system/controllers/controllerModules/tabletStylusInput.js +++ b/scripts/system/controllers/controllerModules/tabletStylusInput.js @@ -11,7 +11,7 @@ AVATAR_SELF_ID, HMD, INCHES_TO_METERS, DEFAULT_REGISTRATION_POINT, Settings, getGrabPointSphereOffset */ -Script.include("/~/system/controllers/controllerDispatcherUtils.js"); +Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); (function() { diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/controllerModules/teleport.js similarity index 98% rename from scripts/system/controllers/teleport.js rename to scripts/system/controllers/controllerModules/teleport.js index 17ac36d955..fcf5ea0ed2 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/controllerModules/teleport.js @@ -17,7 +17,7 @@ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ Script.include("/~/system/libraries/Xform.js"); -Script.include("/~/system/controllers/controllerDispatcherUtils.js"); +Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); (function() { // BEGIN LOCAL_SCOPE @@ -27,9 +27,9 @@ var inTeleportMode = false; var SMOOTH_ARRIVAL_SPACING = 33; var NUMBER_OF_STEPS = 6; -var TARGET_MODEL_URL = Script.resolvePath("../assets/models/teleport-destination.fbx"); -var TOO_CLOSE_MODEL_URL = Script.resolvePath("../assets/models/teleport-cancel.fbx"); -var SEAT_MODEL_URL = Script.resolvePath("../assets/models/teleport-seat.fbx"); +var TARGET_MODEL_URL = Script.resolvePath("../../assets/models/teleport-destination.fbx"); +var TOO_CLOSE_MODEL_URL = Script.resolvePath("../../assets/models/teleport-cancel.fbx"); +var SEAT_MODEL_URL = Script.resolvePath("../../assets/models/teleport-seat.fbx"); var TARGET_MODEL_DIMENSIONS = { x: 1.15, diff --git a/scripts/system/controllers/controllerModules/webEntityLaserInput.js b/scripts/system/controllers/controllerModules/webEntityLaserInput.js index 747e1bae44..1e954d5917 100644 --- a/scripts/system/controllers/controllerModules/webEntityLaserInput.js +++ b/scripts/system/controllers/controllerModules/webEntityLaserInput.js @@ -16,7 +16,7 @@ */ -Script.include("/~/system/controllers/controllerDispatcherUtils.js"); +Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); (function() { diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index 569fad4855..e3375a5a27 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -28,7 +28,7 @@ var CONTOLLER_SCRIPTS = [ "controllerModules/inEditMode.js", "controllerModules/disableOtherModule.js", "controllerModules/farTrigger.js", - "teleport.js" + "controllerModules/teleport.js" ]; var DEBUG_MENU_ITEM = "Debug defaultScripts.js"; diff --git a/scripts/system/controllers/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js similarity index 100% rename from scripts/system/controllers/controllerDispatcherUtils.js rename to scripts/system/libraries/controllerDispatcherUtils.js