mirror of
https://github.com/overte-org/overte.git
synced 2025-07-23 23:04:03 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into fix-throwing
This commit is contained in:
commit
c034879b74
2 changed files with 260 additions and 264 deletions
|
@ -43,7 +43,6 @@ ModelOverlay::ModelOverlay(const ModelOverlay* modelOverlay) :
|
||||||
void ModelOverlay::update(float deltatime) {
|
void ModelOverlay::update(float deltatime) {
|
||||||
if (_updateModel) {
|
if (_updateModel) {
|
||||||
_updateModel = false;
|
_updateModel = false;
|
||||||
|
|
||||||
_model->setSnapModelToCenter(true);
|
_model->setSnapModelToCenter(true);
|
||||||
_model->setScaleToFit(true, getDimensions());
|
_model->setScaleToFit(true, getDimensions());
|
||||||
_model->setRotation(getRotation());
|
_model->setRotation(getRotation());
|
||||||
|
@ -87,7 +86,6 @@ void ModelOverlay::render(RenderArgs* args) {
|
||||||
void ModelOverlay::setProperties(const QVariantMap& properties) {
|
void ModelOverlay::setProperties(const QVariantMap& properties) {
|
||||||
auto position = getPosition();
|
auto position = getPosition();
|
||||||
auto rotation = getRotation();
|
auto rotation = getRotation();
|
||||||
auto scale = getDimensions();
|
|
||||||
|
|
||||||
Volume3DOverlay::setProperties(properties);
|
Volume3DOverlay::setProperties(properties);
|
||||||
|
|
||||||
|
@ -95,14 +93,7 @@ void ModelOverlay::setProperties(const QVariantMap& properties) {
|
||||||
_updateModel = true;
|
_updateModel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scale != getDimensions()) {
|
|
||||||
auto newScale = getDimensions();
|
|
||||||
if (newScale.x <= 0 || newScale.y <= 0 || newScale.z <= 0) {
|
|
||||||
setDimensions(scale);
|
|
||||||
} else {
|
|
||||||
_updateModel = true;
|
_updateModel = true;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto urlValue = properties["url"];
|
auto urlValue = properties["url"];
|
||||||
if (urlValue.isValid() && urlValue.canConvert<QString>()) {
|
if (urlValue.isValid() && urlValue.canConvert<QString>()) {
|
||||||
|
|
|
@ -26,9 +26,11 @@ var WANT_DEBUG_SEARCH_NAME = null;
|
||||||
// these tune time-averaging and "on" value for analog trigger
|
// these tune time-averaging and "on" value for analog trigger
|
||||||
//
|
//
|
||||||
|
|
||||||
|
var SPARK_MODEL_SCALE_FACTOR = 0.75;
|
||||||
|
|
||||||
var TRIGGER_SMOOTH_RATIO = 0.1; // Time averaging of trigger - 0.0 disables smoothing
|
var TRIGGER_SMOOTH_RATIO = 0.1; // Time averaging of trigger - 0.0 disables smoothing
|
||||||
var TRIGGER_ON_VALUE = 0.4; // Squeezed just enough to activate search or near grab
|
var TRIGGER_ON_VALUE = 0.4; // Squeezed just enough to activate search or near grab
|
||||||
var TRIGGER_GRAB_VALUE = 0.75; // Squeezed far enough to complete distant grab
|
var TRIGGER_GRAB_VALUE = 0.85; // Squeezed far enough to complete distant grab
|
||||||
var TRIGGER_OFF_VALUE = 0.15;
|
var TRIGGER_OFF_VALUE = 0.15;
|
||||||
|
|
||||||
var BUMPER_ON_VALUE = 0.5;
|
var BUMPER_ON_VALUE = 0.5;
|
||||||
|
@ -43,6 +45,10 @@ var DRAW_GRAB_BOXES = false;
|
||||||
var DRAW_HAND_SPHERES = false;
|
var DRAW_HAND_SPHERES = false;
|
||||||
var DROP_WITHOUT_SHAKE = false;
|
var DROP_WITHOUT_SHAKE = false;
|
||||||
|
|
||||||
|
var EQUIP_SPHERE_COLOR = { red: 179, green: 120, blue: 211 };
|
||||||
|
var EQUIP_SPHERE_ALPHA = 0.15;
|
||||||
|
var EQUIP_SPHERE_SCALE_FACTOR = 0.65;
|
||||||
|
|
||||||
//
|
//
|
||||||
// distant manipulation
|
// distant manipulation
|
||||||
//
|
//
|
||||||
|
@ -72,11 +78,14 @@ var LINE_ENTITY_DIMENSIONS = {
|
||||||
var LINE_LENGTH = 500;
|
var LINE_LENGTH = 500;
|
||||||
var PICK_MAX_DISTANCE = 500; // max length of pick-ray
|
var PICK_MAX_DISTANCE = 500; // max length of pick-ray
|
||||||
|
|
||||||
|
var EQUIP_RADIUS_EMBIGGEN_FACTOR = 1.1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// near grabbing
|
// near grabbing
|
||||||
//
|
//
|
||||||
|
|
||||||
var EQUIP_RADIUS = 0.1; // radius used for palm vs equip-hotspot for equipping.
|
var EQUIP_RADIUS = 0.1; // radius used for palm vs equip-hotspot for equipping.
|
||||||
|
var EQUIP_HOTSPOT_RENDER_RADIUS = 0.3; // radius used for palm vs equip-hotspot for rendering hot-spots
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
@ -179,9 +188,7 @@ CONTROLLER_STATE_MACHINE[STATE_OFF] = {
|
||||||
};
|
};
|
||||||
CONTROLLER_STATE_MACHINE[STATE_SEARCHING] = {
|
CONTROLLER_STATE_MACHINE[STATE_SEARCHING] = {
|
||||||
name: "searching",
|
name: "searching",
|
||||||
updateMethod: "search",
|
updateMethod: "search"
|
||||||
enterMethod: "searchEnter",
|
|
||||||
exitMethod: "searchExit"
|
|
||||||
};
|
};
|
||||||
CONTROLLER_STATE_MACHINE[STATE_DISTANCE_HOLDING] = {
|
CONTROLLER_STATE_MACHINE[STATE_DISTANCE_HOLDING] = {
|
||||||
name: "distance_holding",
|
name: "distance_holding",
|
||||||
|
@ -261,7 +268,8 @@ function propsArePhysical(props) {
|
||||||
var EXTERNALLY_MANAGED_2D_MINOR_MODE = true;
|
var EXTERNALLY_MANAGED_2D_MINOR_MODE = true;
|
||||||
var EDIT_SETTING = "io.highfidelity.isEditting";
|
var EDIT_SETTING = "io.highfidelity.isEditting";
|
||||||
function isEditing() {
|
function isEditing() {
|
||||||
return EXTERNALLY_MANAGED_2D_MINOR_MODE && Settings.getValue(EDIT_SETTING);
|
var actualSettingValue = Settings.getValue(EDIT_SETTING) === "false" ? false : !!Settings.getValue(EDIT_SETTING);
|
||||||
|
return EXTERNALLY_MANAGED_2D_MINOR_MODE && actualSettingValue;
|
||||||
}
|
}
|
||||||
function isIn2DMode() {
|
function isIn2DMode() {
|
||||||
// In this version, we make our own determination of whether we're aimed a HUD element,
|
// In this version, we make our own determination of whether we're aimed a HUD element,
|
||||||
|
@ -398,6 +406,8 @@ function MyController(hand) {
|
||||||
|
|
||||||
this.entityPropertyCache = new EntityPropertiesCache();
|
this.entityPropertyCache = new EntityPropertiesCache();
|
||||||
|
|
||||||
|
this.equipOverlayInfoSetMap = {};
|
||||||
|
|
||||||
var _this = this;
|
var _this = this;
|
||||||
|
|
||||||
var suppressedIn2D = [STATE_OFF, STATE_SEARCHING];
|
var suppressedIn2D = [STATE_OFF, STATE_SEARCHING];
|
||||||
|
@ -545,7 +555,7 @@ function MyController(hand) {
|
||||||
this.overlayLineOn = function (closePoint, farPoint, color) {
|
this.overlayLineOn = function (closePoint, farPoint, color) {
|
||||||
if (this.overlayLine === null) {
|
if (this.overlayLine === null) {
|
||||||
var lineProperties = {
|
var lineProperties = {
|
||||||
lineWidth: 5,
|
glow: 1.0,
|
||||||
start: closePoint,
|
start: closePoint,
|
||||||
end: farPoint,
|
end: farPoint,
|
||||||
color: color,
|
color: color,
|
||||||
|
@ -877,7 +887,6 @@ function MyController(hand) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.off = function () {
|
this.off = function () {
|
||||||
|
|
||||||
if (this.triggerSmoothedReleased()) {
|
if (this.triggerSmoothedReleased()) {
|
||||||
this.waitForTriggerRelease = false;
|
this.waitForTriggerRelease = false;
|
||||||
}
|
}
|
||||||
|
@ -887,158 +896,122 @@ function MyController(hand) {
|
||||||
this.startingHandRotation = Controller.getPoseValue(controllerHandInput).rotation;
|
this.startingHandRotation = Controller.getPoseValue(controllerHandInput).rotation;
|
||||||
if (this.triggerSmoothedSqueezed()) {
|
if (this.triggerSmoothedSqueezed()) {
|
||||||
this.setState(STATE_SEARCHING, "trigger squeeze detected");
|
this.setState(STATE_SEARCHING, "trigger squeeze detected");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.entityPropertyCache.clear();
|
||||||
|
this.entityPropertyCache.findEntities(this.getHandPosition(), EQUIP_HOTSPOT_RENDER_RADIUS);
|
||||||
|
var candidateEntities = this.entityPropertyCache.getEntities();
|
||||||
|
|
||||||
|
var potentialEquipHotspot = this.chooseBestEquipHotspot(candidateEntities);
|
||||||
|
if (!this.waitForTriggerRelease) {
|
||||||
|
this.updateEquipHaptics(potentialEquipHotspot);
|
||||||
|
}
|
||||||
|
|
||||||
|
var nearEquipHotspots = this.chooseNearEquipHotspots(candidateEntities, EQUIP_HOTSPOT_RENDER_RADIUS);
|
||||||
|
this.updateEquipHotspotRendering(nearEquipHotspots, potentialEquipHotspot);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.createHotspots = function() {
|
this.clearEquipHaptics = function () {
|
||||||
var _this = this;
|
this.prevPotentialEquipHotspot = null;
|
||||||
|
};
|
||||||
|
|
||||||
var HAND_EQUIP_SPHERE_COLOR = { red: 90, green: 255, blue: 90 };
|
this.updateEquipHaptics = function (potentialEquipHotspot) {
|
||||||
var HAND_EQUIP_SPHERE_ALPHA = 0.7;
|
if (potentialEquipHotspot && !this.prevPotentialEquipHotspot ||
|
||||||
var HAND_EQUIP_SPHERE_RADIUS = 0.01;
|
!potentialEquipHotspot && this.prevPotentialEquipHotspot) {
|
||||||
|
Controller.triggerShortHapticPulse(0.5, this.hand);
|
||||||
var HAND_GRAB_SPHERE_COLOR = { red: 90, green: 90, blue: 255 };
|
|
||||||
var HAND_GRAB_SPHERE_ALPHA = 0.3;
|
|
||||||
var HAND_GRAB_SPHERE_RADIUS = NEAR_GRAB_RADIUS;
|
|
||||||
|
|
||||||
var EQUIP_SPHERE_COLOR = { red: 90, green: 255, blue: 90 };
|
|
||||||
var EQUIP_SPHERE_ALPHA = 0.3;
|
|
||||||
|
|
||||||
var GRAB_BOX_COLOR = { red: 90, green: 90, blue: 255 };
|
|
||||||
var GRAB_BOX_ALPHA = 0.1;
|
|
||||||
|
|
||||||
this.hotspotOverlays = [];
|
|
||||||
|
|
||||||
var overlay;
|
|
||||||
if (DRAW_HAND_SPHERES) {
|
|
||||||
// add tiny green sphere around the palm.
|
|
||||||
var handPosition = this.getHandPosition();
|
|
||||||
overlay = Overlays.addOverlay("sphere", {
|
|
||||||
position: handPosition,
|
|
||||||
size: HAND_EQUIP_SPHERE_RADIUS * 2,
|
|
||||||
color: HAND_EQUIP_SPHERE_COLOR,
|
|
||||||
alpha: HAND_EQUIP_SPHERE_ALPHA,
|
|
||||||
solid: true,
|
|
||||||
visible: true,
|
|
||||||
ignoreRayIntersection: true,
|
|
||||||
drawInFront: false
|
|
||||||
});
|
|
||||||
this.hotspotOverlays.push({
|
|
||||||
entityID: undefined,
|
|
||||||
overlay: overlay,
|
|
||||||
type: "hand"
|
|
||||||
});
|
|
||||||
|
|
||||||
// add larger blue sphere around the palm.
|
|
||||||
overlay = Overlays.addOverlay("sphere", {
|
|
||||||
position: handPosition,
|
|
||||||
size: HAND_GRAB_SPHERE_RADIUS * 2,
|
|
||||||
color: HAND_GRAB_SPHERE_COLOR,
|
|
||||||
alpha: HAND_GRAB_SPHERE_ALPHA,
|
|
||||||
solid: true,
|
|
||||||
visible: true,
|
|
||||||
ignoreRayIntersection: true,
|
|
||||||
drawInFront: false
|
|
||||||
});
|
|
||||||
this.hotspotOverlays.push({
|
|
||||||
entityID: undefined,
|
|
||||||
overlay: overlay,
|
|
||||||
type: "hand",
|
|
||||||
localPosition: {x: 0, y: 0, z: 0}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
this.prevPotentialEquipHotspot = potentialEquipHotspot;
|
||||||
|
};
|
||||||
|
|
||||||
// find entities near the avatar that might be equipable.
|
this.clearEquipHotspotRendering = function () {
|
||||||
this.entityPropertyCache.clear();
|
var keys = Object.keys(this.equipOverlayInfoSetMap);
|
||||||
this.entityPropertyCache.findEntities(MyAvatar.position, HOTSPOT_DRAW_DISTANCE);
|
for (var i = 0; i < keys.length; i++) {
|
||||||
|
var overlayInfoSet = this.equipOverlayInfoSetMap[keys[i]];
|
||||||
if (DRAW_GRAB_BOXES) {
|
this.deleteOverlayInfoSet(overlayInfoSet);
|
||||||
// add blue box overlays for grabbable entities.
|
|
||||||
this.entityPropertyCache.getEntities().forEach(function(entityID) {
|
|
||||||
var props = _this.entityPropertyCache.getProps(entityID);
|
|
||||||
if (_this.entityIsGrabbable(entityID)) {
|
|
||||||
var overlay = Overlays.addOverlay("cube", {
|
|
||||||
rotation: props.rotation,
|
|
||||||
position: props.position,
|
|
||||||
size: props.dimensions,
|
|
||||||
color: GRAB_BOX_COLOR,
|
|
||||||
alpha: GRAB_BOX_ALPHA,
|
|
||||||
solid: true,
|
|
||||||
visible: true,
|
|
||||||
ignoreRayIntersection: true,
|
|
||||||
drawInFront: false
|
|
||||||
});
|
|
||||||
_this.hotspotOverlays.push({
|
|
||||||
entityID: entityID,
|
|
||||||
overlay: overlay,
|
|
||||||
type: "near",
|
|
||||||
localPosition: {x: 0, y: 0, z: 0}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
this.equipOverlayInfoSetMap = {};
|
||||||
|
};
|
||||||
|
|
||||||
// add green spheres for each equippable hotspot.
|
this.createOverlayInfoSet = function (hotspot, timestamp) {
|
||||||
flatten(this.entityPropertyCache.getEntities().map(function(entityID) {
|
var overlayInfoSet = {
|
||||||
return _this.collectEquipHotspots(entityID);
|
timestamp: timestamp,
|
||||||
})).filter(function(hotspot) {
|
entityID: hotspot.entityID,
|
||||||
return _this.hotspotIsEquippable(hotspot);
|
localPosition: hotspot.localPosition,
|
||||||
}).forEach(function(hotspot) {
|
hotspot: hotspot,
|
||||||
var overlay = Overlays.addOverlay("sphere", {
|
overlays: []
|
||||||
|
};
|
||||||
|
|
||||||
|
var diameter = hotspot.radius * 2;
|
||||||
|
|
||||||
|
overlayInfoSet.overlays.push(Overlays.addOverlay("sphere", {
|
||||||
position: hotspot.worldPosition,
|
position: hotspot.worldPosition,
|
||||||
size: hotspot.radius * 2,
|
rotation: {x: 0, y: 0, z: 0, w: 1},
|
||||||
|
dimensions: diameter * EQUIP_SPHERE_SCALE_FACTOR,
|
||||||
color: EQUIP_SPHERE_COLOR,
|
color: EQUIP_SPHERE_COLOR,
|
||||||
alpha: EQUIP_SPHERE_ALPHA,
|
alpha: EQUIP_SPHERE_ALPHA,
|
||||||
solid: true,
|
solid: true,
|
||||||
visible: true,
|
visible: true,
|
||||||
ignoreRayIntersection: true,
|
ignoreRayIntersection: true,
|
||||||
drawInFront: false
|
drawInFront: false
|
||||||
});
|
}));
|
||||||
_this.hotspotOverlays.push({
|
|
||||||
entityID: hotspot.entityID,
|
return overlayInfoSet;
|
||||||
overlay: overlay,
|
};
|
||||||
type: "equip",
|
|
||||||
localPosition: hotspot.localPosition
|
this.updateOverlayInfoSet = function (overlayInfoSet, timestamp, potentialEquipHotspot) {
|
||||||
|
overlayInfoSet.timestamp = timestamp;
|
||||||
|
|
||||||
|
var diameter = overlayInfoSet.hotspot.radius * 2;
|
||||||
|
|
||||||
|
// embiggen the overlays if it maches the potentialEquipHotspot
|
||||||
|
if (potentialEquipHotspot && overlayInfoSet.entityID == potentialEquipHotspot.entityID &&
|
||||||
|
Vec3.equal(overlayInfoSet.localPosition, potentialEquipHotspot.localPosition)) {
|
||||||
|
diameter = diameter * EQUIP_RADIUS_EMBIGGEN_FACTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
var props = _this.entityPropertyCache.getProps(overlayInfoSet.entityID);
|
||||||
|
var entityXform = new Xform(props.rotation, props.position);
|
||||||
|
var position = entityXform.xformPoint(overlayInfoSet.localPosition);
|
||||||
|
|
||||||
|
overlayInfoSet.overlays.forEach(function (overlay) {
|
||||||
|
Overlays.editOverlay(overlay, {
|
||||||
|
position: position,
|
||||||
|
rotation: props.rotation,
|
||||||
|
dimensions: diameter * EQUIP_SPHERE_SCALE_FACTOR
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.updateHotspots = function() {
|
this.deleteOverlayInfoSet = function (overlayInfoSet) {
|
||||||
var _this = this;
|
overlayInfoSet.overlays.forEach(function (overlay) {
|
||||||
var props;
|
Overlays.deleteOverlay(overlay);
|
||||||
this.hotspotOverlays.forEach(function(overlayInfo) {
|
|
||||||
if (overlayInfo.type === "hand") {
|
|
||||||
Overlays.editOverlay(overlayInfo.overlay, { position: _this.getHandPosition() });
|
|
||||||
} else if (overlayInfo.type === "equip") {
|
|
||||||
_this.entityPropertyCache.updateEntity(overlayInfo.entityID);
|
|
||||||
props = _this.entityPropertyCache.getProps(overlayInfo.entityID);
|
|
||||||
var entityXform = new Xform(props.rotation, props.position);
|
|
||||||
Overlays.editOverlay(overlayInfo.overlay, {
|
|
||||||
position: entityXform.xformPoint(overlayInfo.localPosition),
|
|
||||||
rotation: props.rotation
|
|
||||||
});
|
});
|
||||||
} else if (overlayInfo.type === "near") {
|
};
|
||||||
_this.entityPropertyCache.updateEntity(overlayInfo.entityID);
|
|
||||||
props = _this.entityPropertyCache.getProps(overlayInfo.entityID);
|
this.updateEquipHotspotRendering = function (hotspots, potentialEquipHotspot) {
|
||||||
Overlays.editOverlay(overlayInfo.overlay, { position: props.position, rotation: props.rotation });
|
var now = Date.now();
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
hotspots.forEach(function (hotspot) {
|
||||||
|
var overlayInfoSet = _this.equipOverlayInfoSetMap[hotspot.key];
|
||||||
|
if (overlayInfoSet) {
|
||||||
|
_this.updateOverlayInfoSet(overlayInfoSet, now, potentialEquipHotspot);
|
||||||
|
} else {
|
||||||
|
_this.equipOverlayInfoSetMap[hotspot.key] = _this.createOverlayInfoSet(hotspot, now);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
this.destroyHotspots = function() {
|
// delete sets with old timestamps.
|
||||||
this.hotspotOverlays.forEach(function(overlayInfo) {
|
var keys = Object.keys(this.equipOverlayInfoSetMap);
|
||||||
Overlays.deleteOverlay(overlayInfo.overlay);
|
for (var i = 0; i < keys.length; i++) {
|
||||||
});
|
var overlayInfoSet = this.equipOverlayInfoSetMap[keys[i]];
|
||||||
this.hotspotOverlays = [];
|
if (overlayInfoSet.timestamp !== now) {
|
||||||
};
|
this.deleteOverlayInfoSet(overlayInfoSet);
|
||||||
|
delete this.equipOverlayInfoSetMap[keys[i]];
|
||||||
this.searchEnter = function() {
|
}
|
||||||
this.createHotspots();
|
}
|
||||||
};
|
|
||||||
|
|
||||||
this.searchExit = function() {
|
|
||||||
this.destroyHotspots();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Performs ray pick test from the hand controller into the world
|
// Performs ray pick test from the hand controller into the world
|
||||||
|
@ -1106,6 +1079,7 @@ function MyController(hand) {
|
||||||
// returns a list of all equip-hotspots assosiated with this entity.
|
// returns a list of all equip-hotspots assosiated with this entity.
|
||||||
// @param {UUID} entityID
|
// @param {UUID} entityID
|
||||||
// @returns {Object[]} array of objects with the following fields.
|
// @returns {Object[]} array of objects with the following fields.
|
||||||
|
// * key {string} a string that can be used to uniquely identify this hotspot
|
||||||
// * entityID {UUID}
|
// * entityID {UUID}
|
||||||
// * localPosition {Vec3} position of the hotspot in object space.
|
// * localPosition {Vec3} position of the hotspot in object space.
|
||||||
// * worldPosition {vec3} position of the hotspot in world space.
|
// * worldPosition {vec3} position of the hotspot in world space.
|
||||||
|
@ -1123,6 +1097,7 @@ function MyController(hand) {
|
||||||
var hotspot = equipHotspotsProps[i];
|
var hotspot = equipHotspotsProps[i];
|
||||||
if (hotspot.position && hotspot.radius && hotspot.joints) {
|
if (hotspot.position && hotspot.radius && hotspot.joints) {
|
||||||
result.push({
|
result.push({
|
||||||
|
key: entityID.toString() + i.toString(),
|
||||||
entityID: entityID,
|
entityID: entityID,
|
||||||
localPosition: hotspot.position,
|
localPosition: hotspot.position,
|
||||||
worldPosition: entityXform.xformPoint(hotspot.position),
|
worldPosition: entityXform.xformPoint(hotspot.position),
|
||||||
|
@ -1135,6 +1110,7 @@ function MyController(hand) {
|
||||||
var wearableProps = this.entityPropertyCache.getWearableProps(entityID);
|
var wearableProps = this.entityPropertyCache.getWearableProps(entityID);
|
||||||
if (wearableProps && wearableProps.joints) {
|
if (wearableProps && wearableProps.joints) {
|
||||||
result.push({
|
result.push({
|
||||||
|
key: entityID.toString() + "0",
|
||||||
entityID: entityID,
|
entityID: entityID,
|
||||||
localPosition: {x: 0, y: 0, z: 0},
|
localPosition: {x: 0, y: 0, z: 0},
|
||||||
worldPosition: entityXform.pos,
|
worldPosition: entityXform.pos,
|
||||||
|
@ -1275,12 +1251,36 @@ function MyController(hand) {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.chooseNearEquipHotspots = function (candidateEntities, distance) {
|
||||||
|
var equippableHotspots = flatten(candidateEntities.map(function (entityID) {
|
||||||
|
return _this.collectEquipHotspots(entityID);
|
||||||
|
})).filter(function (hotspot) {
|
||||||
|
return (_this.hotspotIsEquippable(hotspot) &&
|
||||||
|
Vec3.distance(hotspot.worldPosition, _this.getHandPosition()) < hotspot.radius + distance);
|
||||||
|
});
|
||||||
|
return equippableHotspots;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.chooseBestEquipHotspot = function (candidateEntities) {
|
||||||
|
var DISTANCE = 0;
|
||||||
|
var equippableHotspots = this.chooseNearEquipHotspots(candidateEntities, DISTANCE);
|
||||||
|
if (equippableHotspots.length > 0) {
|
||||||
|
// sort by distance
|
||||||
|
equippableHotspots.sort(function (a, b) {
|
||||||
|
var aDistance = Vec3.distance(a.worldPosition, this.getHandPosition());
|
||||||
|
var bDistance = Vec3.distance(b.worldPosition, this.getHandPosition());
|
||||||
|
return aDistance - bDistance;
|
||||||
|
});
|
||||||
|
return equippableHotspots[0];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this.search = function () {
|
this.search = function () {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
var name;
|
var name;
|
||||||
|
|
||||||
this.updateHotspots();
|
|
||||||
|
|
||||||
this.grabbedEntity = null;
|
this.grabbedEntity = null;
|
||||||
this.isInitialGrab = false;
|
this.isInitialGrab = false;
|
||||||
this.shouldResetParentOnRelease = false;
|
this.shouldResetParentOnRelease = false;
|
||||||
|
@ -1298,27 +1298,13 @@ function MyController(hand) {
|
||||||
this.entityPropertyCache.findEntities(handPosition, NEAR_GRAB_RADIUS);
|
this.entityPropertyCache.findEntities(handPosition, NEAR_GRAB_RADIUS);
|
||||||
var candidateEntities = this.entityPropertyCache.getEntities();
|
var candidateEntities = this.entityPropertyCache.getEntities();
|
||||||
|
|
||||||
var equippableHotspots = flatten(candidateEntities.map(function(entityID) {
|
var potentialEquipHotspot = this.chooseBestEquipHotspot(candidateEntities);
|
||||||
return _this.collectEquipHotspots(entityID);
|
if (potentialEquipHotspot) {
|
||||||
})).filter(function(hotspot) {
|
|
||||||
return _this.hotspotIsEquippable(hotspot) && Vec3.distance(hotspot.worldPosition, handPosition) < hotspot.radius;
|
|
||||||
});
|
|
||||||
|
|
||||||
var entity;
|
|
||||||
if (equippableHotspots.length > 0) {
|
|
||||||
// sort by distance
|
|
||||||
equippableHotspots.sort(function(a, b) {
|
|
||||||
var aDistance = Vec3.distance(a.worldPosition, handPosition);
|
|
||||||
var bDistance = Vec3.distance(b.worldPosition, handPosition);
|
|
||||||
return aDistance - bDistance;
|
|
||||||
});
|
|
||||||
if (this.triggerSmoothedGrab()) {
|
if (this.triggerSmoothedGrab()) {
|
||||||
this.grabbedHotspot = equippableHotspots[0];
|
this.grabbedHotspot = potentialEquipHotspot;
|
||||||
this.grabbedEntity = equippableHotspots[0].entityID;
|
this.grabbedEntity = potentialEquipHotspot.entityID;
|
||||||
this.setState(STATE_HOLD, "eqipping '" + this.entityPropertyCache.getProps(this.grabbedEntity).name + "'");
|
this.setState(STATE_HOLD, "eqipping '" + this.entityPropertyCache.getProps(this.grabbedEntity).name + "'");
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
// TODO: highlight the equippable object?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1339,6 +1325,7 @@ function MyController(hand) {
|
||||||
this.intersectionDistance = 0;
|
this.intersectionDistance = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var entity;
|
||||||
if (grabbableEntities.length > 0) {
|
if (grabbableEntities.length > 0) {
|
||||||
// sort by distance
|
// sort by distance
|
||||||
grabbableEntities.sort(function (a, b) {
|
grabbableEntities.sort(function (a, b) {
|
||||||
|
@ -1354,11 +1341,10 @@ function MyController(hand) {
|
||||||
this.setState(STATE_NEAR_TRIGGER, "near trigger '" + name + "'");
|
this.setState(STATE_NEAR_TRIGGER, "near trigger '" + name + "'");
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// TODO: highlight the near-triggerable object?
|
// potentialNearTriggerEntity = entity;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.triggerSmoothedGrab()) {
|
if (this.triggerSmoothedGrab()) {
|
||||||
|
|
||||||
var props = this.entityPropertyCache.getProps(entity);
|
var props = this.entityPropertyCache.getProps(entity);
|
||||||
var grabProps = this.entityPropertyCache.getGrabProps(entity);
|
var grabProps = this.entityPropertyCache.getGrabProps(entity);
|
||||||
var refCount = grabProps.refCount ? grabProps.refCount : 0;
|
var refCount = grabProps.refCount ? grabProps.refCount : 0;
|
||||||
|
@ -1373,10 +1359,9 @@ function MyController(hand) {
|
||||||
this.setState(STATE_NEAR_GRABBING, "near grab '" + name + "'");
|
this.setState(STATE_NEAR_GRABBING, "near grab '" + name + "'");
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// TODO: highlight the grabbable object?
|
// potentialNearGrabEntity = entity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rayPickInfo.entityID) {
|
if (rayPickInfo.entityID) {
|
||||||
|
@ -1388,7 +1373,7 @@ function MyController(hand) {
|
||||||
this.setState(STATE_FAR_TRIGGER, "far trigger '" + name + "'");
|
this.setState(STATE_FAR_TRIGGER, "far trigger '" + name + "'");
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// TODO: highlight the far-triggerable object?
|
// potentialFarTriggerEntity = entity;
|
||||||
}
|
}
|
||||||
} else if (this.entityIsDistanceGrabbable(rayPickInfo.entityID, handPosition)) {
|
} else if (this.entityIsDistanceGrabbable(rayPickInfo.entityID, handPosition)) {
|
||||||
if (this.triggerSmoothedGrab() && !isEditing()) {
|
if (this.triggerSmoothedGrab() && !isEditing()) {
|
||||||
|
@ -1396,11 +1381,16 @@ function MyController(hand) {
|
||||||
this.setState(STATE_DISTANCE_HOLDING, "distance hold '" + name + "'");
|
this.setState(STATE_DISTANCE_HOLDING, "distance hold '" + name + "'");
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// TODO: highlight the far-grabbable object?
|
// potentialFarGrabEntity = entity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.updateEquipHaptics(potentialEquipHotspot);
|
||||||
|
|
||||||
|
var nearEquipHotspots = this.chooseNearEquipHotspots(candidateEntities, EQUIP_HOTSPOT_RENDER_RADIUS);
|
||||||
|
this.updateEquipHotspotRendering(nearEquipHotspots, potentialEquipHotspot);
|
||||||
|
|
||||||
// search line visualizations
|
// search line visualizations
|
||||||
if (USE_ENTITY_LINES_FOR_SEARCHING === true) {
|
if (USE_ENTITY_LINES_FOR_SEARCHING === true) {
|
||||||
this.lineOn(rayPickInfo.searchRay.origin,
|
this.lineOn(rayPickInfo.searchRay.origin,
|
||||||
|
@ -1428,6 +1418,9 @@ function MyController(hand) {
|
||||||
|
|
||||||
this.distanceHoldingEnter = function () {
|
this.distanceHoldingEnter = function () {
|
||||||
|
|
||||||
|
this.clearEquipHotspotRendering();
|
||||||
|
this.clearEquipHaptics();
|
||||||
|
|
||||||
// controller pose is in avatar frame
|
// controller pose is in avatar frame
|
||||||
var avatarControllerPose =
|
var avatarControllerPose =
|
||||||
Controller.getPoseValue((this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand);
|
Controller.getPoseValue((this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand);
|
||||||
|
@ -1703,6 +1696,10 @@ function MyController(hand) {
|
||||||
this.overlayLineOff();
|
this.overlayLineOff();
|
||||||
|
|
||||||
this.dropGestureReset();
|
this.dropGestureReset();
|
||||||
|
this.clearEquipHaptics();
|
||||||
|
this.clearEquipHotspotRendering();
|
||||||
|
|
||||||
|
Controller.triggerShortHapticPulse(1.0, this.hand);
|
||||||
|
|
||||||
if (this.entityActivated) {
|
if (this.entityActivated) {
|
||||||
var saveGrabbedID = this.grabbedEntity;
|
var saveGrabbedID = this.grabbedEntity;
|
||||||
|
@ -1920,10 +1917,18 @@ function MyController(hand) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.nearTriggerEnter = function () {
|
this.nearTriggerEnter = function () {
|
||||||
|
|
||||||
|
this.clearEquipHotspotRendering();
|
||||||
|
this.clearEquipHaptics();
|
||||||
|
|
||||||
|
Controller.triggerShortHapticPulse(1.0, this.hand);
|
||||||
this.callEntityMethodOnGrabbed("startNearTrigger");
|
this.callEntityMethodOnGrabbed("startNearTrigger");
|
||||||
};
|
};
|
||||||
|
|
||||||
this.farTriggerEnter = function () {
|
this.farTriggerEnter = function () {
|
||||||
|
this.clearEquipHotspotRendering();
|
||||||
|
this.clearEquipHaptics();
|
||||||
|
|
||||||
this.callEntityMethodOnGrabbed("startFarTrigger");
|
this.callEntityMethodOnGrabbed("startFarTrigger");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue