mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 16:30:16 +02:00
plugins occupy activity-slots and more than one plugin may run at a time, as long as their slots aren't in conflict
This commit is contained in:
parent
2dc76f6e42
commit
b4a54b017a
4 changed files with 105 additions and 30 deletions
|
@ -20,7 +20,6 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
var NEAR_MIN_RADIUS = 0.1;
|
var NEAR_MIN_RADIUS = 0.1;
|
||||||
var NEAR_MAX_RADIUS = 1.0;
|
var NEAR_MAX_RADIUS = 1.0;
|
||||||
|
|
||||||
|
|
||||||
var DISPATCHER_PROPERTIES = [
|
var DISPATCHER_PROPERTIES = [
|
||||||
"position",
|
"position",
|
||||||
"registrationPoint",
|
"registrationPoint",
|
||||||
|
@ -39,7 +38,39 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
"userData"
|
"userData"
|
||||||
];
|
];
|
||||||
|
|
||||||
this.runningPluginName = null;
|
// a module can occupy one or more 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
|
||||||
|
};
|
||||||
|
|
||||||
|
this.slotsAreAvailable = 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.leftTriggerValue = 0;
|
||||||
this.leftTriggerClicked = 0;
|
this.leftTriggerClicked = 0;
|
||||||
this.rightTriggerValue = 0;
|
this.rightTriggerValue = 0;
|
||||||
|
@ -68,7 +99,7 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
getControllerWorldLocation(Controller.Standard.RightHand, true)];
|
getControllerWorldLocation(Controller.Standard.RightHand, true)];
|
||||||
|
|
||||||
var nearbyEntityProperties = [[], []];
|
var nearbyEntityProperties = [[], []];
|
||||||
for (var h = LEFT_HAND; h <= RIGHT_HAND; h ++) {
|
for (var h = LEFT_HAND; h <= RIGHT_HAND; h++) {
|
||||||
// todo: check controllerLocations[h].valid
|
// todo: check controllerLocations[h].valid
|
||||||
var controllerPosition = controllerLocations[h].position;
|
var controllerPosition = controllerLocations[h].position;
|
||||||
var nearbyEntityIDs = Entities.findEntities(controllerPosition, NEAR_MIN_RADIUS);
|
var nearbyEntityIDs = Entities.findEntities(controllerPosition, NEAR_MIN_RADIUS);
|
||||||
|
@ -82,11 +113,12 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// sort by distance from each hand
|
// sort by distance from each hand
|
||||||
nearbyEntityProperties[h].sort(function (a, b) {
|
var sorter = function (a, b) {
|
||||||
var aDistance = Vec3.distance(a.position, controllerLocations[h]);
|
var aDistance = Vec3.distance(a.position, controllerLocations[h]);
|
||||||
var bDistance = Vec3.distance(b.position, controllerLocations[h]);
|
var bDistance = Vec3.distance(b.position, controllerLocations[h]);
|
||||||
return aDistance - bDistance;
|
return aDistance - bDistance;
|
||||||
});
|
};
|
||||||
|
nearbyEntityProperties[h].sort(sorter);
|
||||||
}
|
}
|
||||||
|
|
||||||
var controllerData = {
|
var controllerData = {
|
||||||
|
@ -96,20 +128,35 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
nearbyEntityProperties: nearbyEntityProperties,
|
nearbyEntityProperties: nearbyEntityProperties,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (_this.runningPluginName) {
|
|
||||||
var plugin = controllerDispatcherPlugins[_this.runningPluginName];
|
// check for plugins that would like to start
|
||||||
if (!plugin || !plugin.run(controllerData)) {
|
for (var pluginName in controllerDispatcherPlugins) {
|
||||||
_this.runningPluginName = null;
|
// TODO sort names by plugin.priority
|
||||||
|
if (controllerDispatcherPlugins.hasOwnProperty(pluginName)) {
|
||||||
|
var candidatePlugin = controllerDispatcherPlugins[pluginName];
|
||||||
|
if (_this.slotsAreAvailable(candidatePlugin) && candidatePlugin.isReady(controllerData)) {
|
||||||
|
// 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[pluginName] = true;
|
||||||
|
_this.markSlots(candidatePlugin, pluginName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (controllerDispatcherPlugins) {
|
}
|
||||||
for (var pluginName in controllerDispatcherPlugins) {
|
|
||||||
// TODO sort names by plugin.priority
|
// give time to running plugins
|
||||||
if (controllerDispatcherPlugins.hasOwnProperty(pluginName)) {
|
for (var runningPluginName in _this.runningPluginNames) {
|
||||||
var candidatePlugin = controllerDispatcherPlugins[pluginName];
|
if (_this.runningPluginNames.hasOwnProperty(runningPluginName)) {
|
||||||
if (candidatePlugin.isReady(controllerData)) {
|
var plugin = controllerDispatcherPlugins[runningPluginName];
|
||||||
_this.runningPluginName = pluginName;
|
if (!plugin) {
|
||||||
break;
|
// plugin was deactivated while running. find the activity-slots it was using and make
|
||||||
}
|
// them available.
|
||||||
|
delete _this.runningPluginNames[runningPluginName];
|
||||||
|
_this.unmarkSlotsForPluginName(runningPluginName);
|
||||||
|
} else if (!plugin.run(controllerData)) {
|
||||||
|
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,14 +164,14 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
|
|
||||||
var MAPPING_NAME = "com.highfidelity.controllerDispatcher";
|
var MAPPING_NAME = "com.highfidelity.controllerDispatcher";
|
||||||
var mapping = Controller.newMapping(MAPPING_NAME);
|
var mapping = Controller.newMapping(MAPPING_NAME);
|
||||||
mapping.from([Controller.Standard.RT]).peek().to(this.rightTriggerPress);
|
mapping.from([Controller.Standard.RT]).peek().to(_this.rightTriggerPress);
|
||||||
mapping.from([Controller.Standard.RTClick]).peek().to(this.rightTriggerClick);
|
mapping.from([Controller.Standard.RTClick]).peek().to(_this.rightTriggerClick);
|
||||||
mapping.from([Controller.Standard.LT]).peek().to(this.leftTriggerPress);
|
mapping.from([Controller.Standard.LT]).peek().to(_this.leftTriggerPress);
|
||||||
mapping.from([Controller.Standard.LTClick]).peek().to(this.leftTriggerClick);
|
mapping.from([Controller.Standard.LTClick]).peek().to(_this.leftTriggerClick);
|
||||||
Controller.enableMapping(MAPPING_NAME);
|
Controller.enableMapping(MAPPING_NAME);
|
||||||
|
|
||||||
this.cleanup = function () {
|
this.cleanup = function () {
|
||||||
Script.update.disconnect(this.update);
|
Script.update.disconnect(_this.update);
|
||||||
Controller.disableMapping(MAPPING_NAME);
|
Controller.disableMapping(MAPPING_NAME);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
/* global Camera, HMD, MyAvatar, controllerDispatcherPlugins,
|
/* global Camera, HMD, MyAvatar, controllerDispatcherPlugins,
|
||||||
MSECS_PER_SEC, LEFT_HAND, RIGHT_HAND, NULL_UUID, AVATAR_SELF_ID, FORBIDDEN_GRAB_TYPES,
|
MSECS_PER_SEC, LEFT_HAND, RIGHT_HAND, NULL_UUID, AVATAR_SELF_ID, FORBIDDEN_GRAB_TYPES,
|
||||||
HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION,
|
HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION,
|
||||||
|
makeDispatcherModuleParameters,
|
||||||
enableDispatcherModule,
|
enableDispatcherModule,
|
||||||
disableDispatcherModule,
|
disableDispatcherModule,
|
||||||
getGrabbableData,
|
getGrabbableData,
|
||||||
|
@ -31,6 +32,20 @@ HAPTIC_PULSE_STRENGTH = 1.0;
|
||||||
HAPTIC_PULSE_DURATION = 13.0;
|
HAPTIC_PULSE_DURATION = 13.0;
|
||||||
|
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// requiredDataForStart -- 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, requiredDataForStart, sleepMSBetweenRuns) {
|
||||||
|
return {
|
||||||
|
priority: priority,
|
||||||
|
activitySlots: activitySlots,
|
||||||
|
requiredDataForStart: requiredDataForStart,
|
||||||
|
sleepMSBetweenRuns: sleepMSBetweenRuns
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
enableDispatcherModule = function (moduleName, module, priority) {
|
enableDispatcherModule = function (moduleName, module, priority) {
|
||||||
if (!controllerDispatcherPlugins) {
|
if (!controllerDispatcherPlugins) {
|
||||||
controllerDispatcherPlugins = {};
|
controllerDispatcherPlugins = {};
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND,
|
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND,
|
||||||
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
|
Quat, Vec3, MSECS_PER_SEC, getControllerWorldLocation, makeDispatcherModuleParameters
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
|
@ -21,6 +21,12 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
this.grabbedThingID = null;
|
this.grabbedThingID = null;
|
||||||
this.actionID = null; // action this script created...
|
this.actionID = null; // action this script created...
|
||||||
|
|
||||||
|
this.parameters = makeDispatcherModuleParameters(
|
||||||
|
500,
|
||||||
|
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||||
|
[],
|
||||||
|
100);
|
||||||
|
|
||||||
var NEAR_GRABBING_ACTION_TIMEFRAME = 0.05; // how quickly objects move to their new position
|
var NEAR_GRABBING_ACTION_TIMEFRAME = 0.05; // how quickly objects move to their new position
|
||||||
var ACTION_TTL = 15; // seconds
|
var ACTION_TTL = 15; // seconds
|
||||||
var ACTION_TTL_REFRESH = 5;
|
var ACTION_TTL_REFRESH = 5;
|
||||||
|
@ -192,8 +198,8 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
enableDispatcherModule("LeftNearActionGrabEntity", new NearActionGrabEntity(LEFT_HAND), 500);
|
enableDispatcherModule("LeftNearActionGrabEntity", new NearActionGrabEntity(LEFT_HAND));
|
||||||
enableDispatcherModule("RightNearActionGrabEntity", new NearActionGrabEntity(RIGHT_HAND), 500);
|
enableDispatcherModule("RightNearActionGrabEntity", new NearActionGrabEntity(RIGHT_HAND));
|
||||||
|
|
||||||
this.cleanup = function () {
|
this.cleanup = function () {
|
||||||
disableDispatcherModule("LeftNearActionGrabEntity");
|
disableDispatcherModule("LeftNearActionGrabEntity");
|
||||||
|
|
|
@ -7,8 +7,9 @@
|
||||||
|
|
||||||
|
|
||||||
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, AVATAR_SELF_ID,
|
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, AVATAR_SELF_ID,
|
||||||
getControllerJointIndex, getGrabbableData, NULL_UUID, enableDispatcherModule, disableDispatcherModule,
|
getControllerJointIndex, NULL_UUID, enableDispatcherModule, disableDispatcherModule,
|
||||||
FORBIDDEN_GRAB_TYPES, propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION
|
propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION,
|
||||||
|
makeDispatcherModuleParameters, entityIsGrabbable
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
|
@ -25,6 +26,12 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
this.previousParentJointIndex = {};
|
this.previousParentJointIndex = {};
|
||||||
this.previouslyUnhooked = {};
|
this.previouslyUnhooked = {};
|
||||||
|
|
||||||
|
this.parameters = makeDispatcherModuleParameters(
|
||||||
|
500,
|
||||||
|
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||||
|
[],
|
||||||
|
100);
|
||||||
|
|
||||||
|
|
||||||
// XXX does handJointIndex change if the avatar changes?
|
// XXX does handJointIndex change if the avatar changes?
|
||||||
this.handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
|
this.handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
|
||||||
|
@ -156,8 +163,8 @@ Script.include("/~/system/controllers/controllerDispatcherUtils.js");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
enableDispatcherModule("LeftNearParentingGrabEntity", new NearParentingGrabEntity(LEFT_HAND), 500);
|
enableDispatcherModule("LeftNearParentingGrabEntity", new NearParentingGrabEntity(LEFT_HAND));
|
||||||
enableDispatcherModule("RightNearParentingGrabEntity", new NearParentingGrabEntity(RIGHT_HAND), 500);
|
enableDispatcherModule("RightNearParentingGrabEntity", new NearParentingGrabEntity(RIGHT_HAND));
|
||||||
|
|
||||||
this.cleanup = function () {
|
this.cleanup = function () {
|
||||||
disableDispatcherModule("LeftNearParentingGrabEntity");
|
disableDispatcherModule("LeftNearParentingGrabEntity");
|
||||||
|
|
Loading…
Reference in a new issue