mirror of
https://github.com/overte-org/overte.git
synced 2025-06-15 18:19:15 +02:00
Fix for double rendering of equip hotspots
This commit is contained in:
parent
848d5a8975
commit
0ce970408c
1 changed files with 117 additions and 105 deletions
|
@ -380,6 +380,106 @@ EntityPropertiesCache.prototype.getEquipHotspotsProps = function (entityID) {
|
||||||
// global cache
|
// global cache
|
||||||
var entityPropertiesCache = new EntityPropertiesCache();
|
var entityPropertiesCache = new EntityPropertiesCache();
|
||||||
|
|
||||||
|
// Each overlayInfoSet describes a single equip hotspot.
|
||||||
|
// It is an object with the following keys:
|
||||||
|
// timestamp - last time this object was updated, used to delete stale hotspot overlays.
|
||||||
|
// entityID - entity assosicated with this hotspot
|
||||||
|
// localPosition - position relative to the entity
|
||||||
|
// hotspot - hotspot object
|
||||||
|
// overlays - array of overlay objects created by Overlay.addOverlay()
|
||||||
|
function EquipHotspotBuddy() {
|
||||||
|
// holds map from {string} hotspot.key to {object} overlayInfoSet.
|
||||||
|
this.map = {};
|
||||||
|
|
||||||
|
// array of all hotspots that are highlighed.
|
||||||
|
this.highlightedHotspots = [];
|
||||||
|
}
|
||||||
|
EquipHotspotBuddy.prototype.clear = function () {
|
||||||
|
var keys = Object.keys(this.map);
|
||||||
|
for (var i = 0; i < keys.length; i++) {
|
||||||
|
var overlayInfoSet = this.map[keys[i]];
|
||||||
|
this.deleteOverlayInfoSet(overlayInfoSet);
|
||||||
|
}
|
||||||
|
this.map = {};
|
||||||
|
this.highlightedHotspots = [];
|
||||||
|
};
|
||||||
|
EquipHotspotBuddy.prototype.highlightHotspot = function (hotspot) {
|
||||||
|
this.highlightedHotspots.push(hotspot);
|
||||||
|
};
|
||||||
|
EquipHotspotBuddy.prototype.updateHotspot = function (hotspot, timestamp) {
|
||||||
|
var overlayInfoSet = this.map[hotspot.key];
|
||||||
|
if (!overlayInfoSet) {
|
||||||
|
// create a new overlayInfoSet
|
||||||
|
overlayInfoSet = {
|
||||||
|
timestamp: timestamp,
|
||||||
|
entityID: hotspot.entityID,
|
||||||
|
localPosition: hotspot.localPosition,
|
||||||
|
hotspot: hotspot,
|
||||||
|
overlays: []
|
||||||
|
};
|
||||||
|
|
||||||
|
var diameter = hotspot.radius * 2;
|
||||||
|
|
||||||
|
// TODO: check for custom hotspot model urls.
|
||||||
|
|
||||||
|
// default sphere
|
||||||
|
overlayInfoSet.overlays.push(Overlays.addOverlay("sphere", {
|
||||||
|
position: hotspot.worldPosition,
|
||||||
|
rotation: {x: 0, y: 0, z: 0, w: 1},
|
||||||
|
dimensions: diameter * EQUIP_SPHERE_SCALE_FACTOR,
|
||||||
|
color: EQUIP_SPHERE_COLOR,
|
||||||
|
alpha: EQUIP_SPHERE_ALPHA,
|
||||||
|
solid: true,
|
||||||
|
visible: true,
|
||||||
|
ignoreRayIntersection: true,
|
||||||
|
drawInFront: false
|
||||||
|
}));
|
||||||
|
|
||||||
|
this.map[hotspot.key] = overlayInfoSet;
|
||||||
|
} else {
|
||||||
|
overlayInfoSet.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
EquipHotspotBuddy.prototype.updateHotspots = function (hotspots, timestamp) {
|
||||||
|
var _this = this;
|
||||||
|
hotspots.forEach(function (hotspot) {
|
||||||
|
_this.updateHotspot(hotspot, timestamp);
|
||||||
|
});
|
||||||
|
this.highlightedHotspots = [];
|
||||||
|
};
|
||||||
|
EquipHotspotBuddy.prototype.update = function (deltaTime, timestamp) {
|
||||||
|
var keys = Object.keys(this.map);
|
||||||
|
for (var i = 0; i < keys.length; i++) {
|
||||||
|
var overlayInfoSet = this.map[keys[i]];
|
||||||
|
|
||||||
|
// TODO: figure out how to do animation.... fade in, fade out, highlight, un-highlight
|
||||||
|
|
||||||
|
if (overlayInfoSet.timestamp != timestamp) {
|
||||||
|
// this is an old stale overlay, delete it!
|
||||||
|
overlayInfoSet.overlays.forEach(function (overlay) {
|
||||||
|
Overlays.deleteOverlay(overlay);
|
||||||
|
});
|
||||||
|
delete this.map[keys[i]];
|
||||||
|
} else {
|
||||||
|
// update overlay position, rotation to follow the object it's attached to.
|
||||||
|
|
||||||
|
var props = entityPropertiesCache.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
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// global EquipHotspotBuddy instance
|
||||||
|
var equipHotspotBuddy = new EquipHotspotBuddy();
|
||||||
|
|
||||||
function MyController(hand) {
|
function MyController(hand) {
|
||||||
this.hand = hand;
|
this.hand = hand;
|
||||||
if (this.hand === RIGHT_HAND) {
|
if (this.hand === RIGHT_HAND) {
|
||||||
|
@ -440,7 +540,7 @@ function MyController(hand) {
|
||||||
return (-1 !== suppressedIn2D.indexOf(this.state)) && isIn2DMode();
|
return (-1 !== suppressedIn2D.indexOf(this.state)) && isIn2DMode();
|
||||||
};
|
};
|
||||||
|
|
||||||
this.update = function (deltaTime) {
|
this.update = function (deltaTime, timestamp) {
|
||||||
|
|
||||||
this.updateSmoothedTrigger();
|
this.updateSmoothedTrigger();
|
||||||
|
|
||||||
|
@ -453,7 +553,7 @@ function MyController(hand) {
|
||||||
var updateMethodName = CONTROLLER_STATE_MACHINE[this.state].updateMethod;
|
var updateMethodName = CONTROLLER_STATE_MACHINE[this.state].updateMethod;
|
||||||
var updateMethod = this[updateMethodName];
|
var updateMethod = this[updateMethodName];
|
||||||
if (updateMethod) {
|
if (updateMethod) {
|
||||||
updateMethod.call(this, deltaTime);
|
updateMethod.call(this, deltaTime, timestamp);
|
||||||
} else {
|
} else {
|
||||||
print("WARNING: could not find updateMethod for state " + stateToName(this.state));
|
print("WARNING: could not find updateMethod for state " + stateToName(this.state));
|
||||||
}
|
}
|
||||||
|
@ -909,7 +1009,7 @@ function MyController(hand) {
|
||||||
return _this.rawThumbValue < THUMB_ON_VALUE;
|
return _this.rawThumbValue < THUMB_ON_VALUE;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.off = function () {
|
this.off = function (deltaTime, timestamp) {
|
||||||
if (this.triggerSmoothedReleased()) {
|
if (this.triggerSmoothedReleased()) {
|
||||||
this.waitForTriggerRelease = false;
|
this.waitForTriggerRelease = false;
|
||||||
}
|
}
|
||||||
|
@ -931,7 +1031,8 @@ function MyController(hand) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var nearEquipHotspots = this.chooseNearEquipHotspots(candidateEntities, EQUIP_HOTSPOT_RENDER_RADIUS);
|
var nearEquipHotspots = this.chooseNearEquipHotspots(candidateEntities, EQUIP_HOTSPOT_RENDER_RADIUS);
|
||||||
this.updateEquipHotspotRendering(nearEquipHotspots, potentialEquipHotspot);
|
equipHotspotBuddy.updateHotspots(nearEquipHotspots, timestamp);
|
||||||
|
equipHotspotBuddy.highlightHotspot(potentialEquipHotspot);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.clearEquipHaptics = function () {
|
this.clearEquipHaptics = function () {
|
||||||
|
@ -946,95 +1047,6 @@ function MyController(hand) {
|
||||||
this.prevPotentialEquipHotspot = potentialEquipHotspot;
|
this.prevPotentialEquipHotspot = potentialEquipHotspot;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.clearEquipHotspotRendering = function () {
|
|
||||||
var keys = Object.keys(this.equipOverlayInfoSetMap);
|
|
||||||
for (var i = 0; i < keys.length; i++) {
|
|
||||||
var overlayInfoSet = this.equipOverlayInfoSetMap[keys[i]];
|
|
||||||
this.deleteOverlayInfoSet(overlayInfoSet);
|
|
||||||
}
|
|
||||||
this.equipOverlayInfoSetMap = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
this.createOverlayInfoSet = function (hotspot, timestamp) {
|
|
||||||
var overlayInfoSet = {
|
|
||||||
timestamp: timestamp,
|
|
||||||
entityID: hotspot.entityID,
|
|
||||||
localPosition: hotspot.localPosition,
|
|
||||||
hotspot: hotspot,
|
|
||||||
overlays: []
|
|
||||||
};
|
|
||||||
|
|
||||||
var diameter = hotspot.radius * 2;
|
|
||||||
|
|
||||||
overlayInfoSet.overlays.push(Overlays.addOverlay("sphere", {
|
|
||||||
position: hotspot.worldPosition,
|
|
||||||
rotation: {x: 0, y: 0, z: 0, w: 1},
|
|
||||||
dimensions: diameter * EQUIP_SPHERE_SCALE_FACTOR,
|
|
||||||
color: EQUIP_SPHERE_COLOR,
|
|
||||||
alpha: EQUIP_SPHERE_ALPHA,
|
|
||||||
solid: true,
|
|
||||||
visible: true,
|
|
||||||
ignoreRayIntersection: true,
|
|
||||||
drawInFront: false
|
|
||||||
}));
|
|
||||||
|
|
||||||
return overlayInfoSet;
|
|
||||||
};
|
|
||||||
|
|
||||||
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 = entityPropertiesCache.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.deleteOverlayInfoSet = function (overlayInfoSet) {
|
|
||||||
overlayInfoSet.overlays.forEach(function (overlay) {
|
|
||||||
Overlays.deleteOverlay(overlay);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.updateEquipHotspotRendering = function (hotspots, potentialEquipHotspot) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// delete sets with old timestamps.
|
|
||||||
var keys = Object.keys(this.equipOverlayInfoSetMap);
|
|
||||||
for (var i = 0; i < keys.length; i++) {
|
|
||||||
var overlayInfoSet = this.equipOverlayInfoSetMap[keys[i]];
|
|
||||||
if (overlayInfoSet.timestamp !== now) {
|
|
||||||
this.deleteOverlayInfoSet(overlayInfoSet);
|
|
||||||
delete this.equipOverlayInfoSetMap[keys[i]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Performs ray pick test from the hand controller into the world
|
// Performs ray pick test from the hand controller into the world
|
||||||
// @param {number} which hand to use, RIGHT_HAND or LEFT_HAND
|
// @param {number} which hand to use, RIGHT_HAND or LEFT_HAND
|
||||||
// @returns {object} returns object with two keys entityID and distance
|
// @returns {object} returns object with two keys entityID and distance
|
||||||
|
@ -1298,7 +1310,7 @@ function MyController(hand) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.search = function () {
|
this.search = function (deltaTime, timestamp) {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
var name;
|
var name;
|
||||||
|
|
||||||
|
@ -1409,7 +1421,8 @@ function MyController(hand) {
|
||||||
this.updateEquipHaptics(potentialEquipHotspot);
|
this.updateEquipHaptics(potentialEquipHotspot);
|
||||||
|
|
||||||
var nearEquipHotspots = this.chooseNearEquipHotspots(candidateEntities, EQUIP_HOTSPOT_RENDER_RADIUS);
|
var nearEquipHotspots = this.chooseNearEquipHotspots(candidateEntities, EQUIP_HOTSPOT_RENDER_RADIUS);
|
||||||
this.updateEquipHotspotRendering(nearEquipHotspots, potentialEquipHotspot);
|
equipHotspotBuddy.updateHotspots(nearEquipHotspots, timestamp);
|
||||||
|
equipHotspotBuddy.highlightHotspot(potentialEquipHotspot);
|
||||||
|
|
||||||
// search line visualizations
|
// search line visualizations
|
||||||
if (USE_ENTITY_LINES_FOR_SEARCHING === true) {
|
if (USE_ENTITY_LINES_FOR_SEARCHING === true) {
|
||||||
|
@ -1438,7 +1451,6 @@ function MyController(hand) {
|
||||||
|
|
||||||
this.distanceHoldingEnter = function () {
|
this.distanceHoldingEnter = function () {
|
||||||
|
|
||||||
this.clearEquipHotspotRendering();
|
|
||||||
this.clearEquipHaptics();
|
this.clearEquipHaptics();
|
||||||
|
|
||||||
// controller pose is in avatar frame
|
// controller pose is in avatar frame
|
||||||
|
@ -1498,7 +1510,7 @@ function MyController(hand) {
|
||||||
this.previousControllerRotation = controllerRotation;
|
this.previousControllerRotation = controllerRotation;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.distanceHolding = function () {
|
this.distanceHolding = function (deltaTime, timestamp) {
|
||||||
if (this.triggerSmoothedReleased()) {
|
if (this.triggerSmoothedReleased()) {
|
||||||
this.callEntityMethodOnGrabbed("releaseGrab");
|
this.callEntityMethodOnGrabbed("releaseGrab");
|
||||||
this.setState(STATE_OFF, "trigger released");
|
this.setState(STATE_OFF, "trigger released");
|
||||||
|
@ -1717,7 +1729,6 @@ function MyController(hand) {
|
||||||
|
|
||||||
this.dropGestureReset();
|
this.dropGestureReset();
|
||||||
this.clearEquipHaptics();
|
this.clearEquipHaptics();
|
||||||
this.clearEquipHotspotRendering();
|
|
||||||
|
|
||||||
Controller.triggerShortHapticPulse(1.0, this.hand);
|
Controller.triggerShortHapticPulse(1.0, this.hand);
|
||||||
|
|
||||||
|
@ -1819,7 +1830,7 @@ function MyController(hand) {
|
||||||
this.currentAngularVelocity = ZERO_VEC;
|
this.currentAngularVelocity = ZERO_VEC;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.nearGrabbing = function (deltaTime) {
|
this.nearGrabbing = function (deltaTime, timestamp) {
|
||||||
|
|
||||||
var dropDetected = this.dropGestureProcess(deltaTime);
|
var dropDetected = this.dropGestureProcess(deltaTime);
|
||||||
|
|
||||||
|
@ -1938,7 +1949,6 @@ function MyController(hand) {
|
||||||
|
|
||||||
this.nearTriggerEnter = function () {
|
this.nearTriggerEnter = function () {
|
||||||
|
|
||||||
this.clearEquipHotspotRendering();
|
|
||||||
this.clearEquipHaptics();
|
this.clearEquipHaptics();
|
||||||
|
|
||||||
Controller.triggerShortHapticPulse(1.0, this.hand);
|
Controller.triggerShortHapticPulse(1.0, this.hand);
|
||||||
|
@ -1946,13 +1956,12 @@ function MyController(hand) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.farTriggerEnter = function () {
|
this.farTriggerEnter = function () {
|
||||||
this.clearEquipHotspotRendering();
|
|
||||||
this.clearEquipHaptics();
|
this.clearEquipHaptics();
|
||||||
|
|
||||||
this.callEntityMethodOnGrabbed("startFarTrigger");
|
this.callEntityMethodOnGrabbed("startFarTrigger");
|
||||||
};
|
};
|
||||||
|
|
||||||
this.nearTrigger = function () {
|
this.nearTrigger = function (deltaTime, timestamp) {
|
||||||
if (this.triggerSmoothedReleased()) {
|
if (this.triggerSmoothedReleased()) {
|
||||||
this.callEntityMethodOnGrabbed("stopNearTrigger");
|
this.callEntityMethodOnGrabbed("stopNearTrigger");
|
||||||
this.setState(STATE_OFF, "trigger released");
|
this.setState(STATE_OFF, "trigger released");
|
||||||
|
@ -1961,7 +1970,7 @@ function MyController(hand) {
|
||||||
this.callEntityMethodOnGrabbed("continueNearTrigger");
|
this.callEntityMethodOnGrabbed("continueNearTrigger");
|
||||||
};
|
};
|
||||||
|
|
||||||
this.farTrigger = function () {
|
this.farTrigger = function (deltaTime, timestamp) {
|
||||||
if (this.triggerSmoothedReleased()) {
|
if (this.triggerSmoothedReleased()) {
|
||||||
this.callEntityMethodOnGrabbed("stopFarTrigger");
|
this.callEntityMethodOnGrabbed("stopFarTrigger");
|
||||||
this.setState(STATE_OFF, "trigger released");
|
this.setState(STATE_OFF, "trigger released");
|
||||||
|
@ -2262,12 +2271,15 @@ Controller.enableMapping(MAPPING_NAME);
|
||||||
var handToDisable = 'none';
|
var handToDisable = 'none';
|
||||||
|
|
||||||
function update(deltaTime) {
|
function update(deltaTime) {
|
||||||
|
var timestamp = Date.now();
|
||||||
|
|
||||||
if (handToDisable !== LEFT_HAND && handToDisable !== 'both') {
|
if (handToDisable !== LEFT_HAND && handToDisable !== 'both') {
|
||||||
leftController.update(deltaTime);
|
leftController.update(deltaTime, timestamp);
|
||||||
}
|
}
|
||||||
if (handToDisable !== RIGHT_HAND && handToDisable !== 'both') {
|
if (handToDisable !== RIGHT_HAND && handToDisable !== 'both') {
|
||||||
rightController.update(deltaTime);
|
rightController.update(deltaTime, timestamp);
|
||||||
}
|
}
|
||||||
|
equipHotspotBuddy.update(deltaTime, timestamp);
|
||||||
entityPropertiesCache.update();
|
entityPropertiesCache.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue