mirror of
https://github.com/lubosz/overte.git
synced 2025-04-24 07:13:57 +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
|
||||
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) {
|
||||
this.hand = hand;
|
||||
if (this.hand === RIGHT_HAND) {
|
||||
|
@ -440,7 +540,7 @@ function MyController(hand) {
|
|||
return (-1 !== suppressedIn2D.indexOf(this.state)) && isIn2DMode();
|
||||
};
|
||||
|
||||
this.update = function (deltaTime) {
|
||||
this.update = function (deltaTime, timestamp) {
|
||||
|
||||
this.updateSmoothedTrigger();
|
||||
|
||||
|
@ -453,7 +553,7 @@ function MyController(hand) {
|
|||
var updateMethodName = CONTROLLER_STATE_MACHINE[this.state].updateMethod;
|
||||
var updateMethod = this[updateMethodName];
|
||||
if (updateMethod) {
|
||||
updateMethod.call(this, deltaTime);
|
||||
updateMethod.call(this, deltaTime, timestamp);
|
||||
} else {
|
||||
print("WARNING: could not find updateMethod for state " + stateToName(this.state));
|
||||
}
|
||||
|
@ -909,7 +1009,7 @@ function MyController(hand) {
|
|||
return _this.rawThumbValue < THUMB_ON_VALUE;
|
||||
};
|
||||
|
||||
this.off = function () {
|
||||
this.off = function (deltaTime, timestamp) {
|
||||
if (this.triggerSmoothedReleased()) {
|
||||
this.waitForTriggerRelease = false;
|
||||
}
|
||||
|
@ -931,7 +1031,8 @@ function MyController(hand) {
|
|||
}
|
||||
|
||||
var nearEquipHotspots = this.chooseNearEquipHotspots(candidateEntities, EQUIP_HOTSPOT_RENDER_RADIUS);
|
||||
this.updateEquipHotspotRendering(nearEquipHotspots, potentialEquipHotspot);
|
||||
equipHotspotBuddy.updateHotspots(nearEquipHotspots, timestamp);
|
||||
equipHotspotBuddy.highlightHotspot(potentialEquipHotspot);
|
||||
};
|
||||
|
||||
this.clearEquipHaptics = function () {
|
||||
|
@ -946,95 +1047,6 @@ function MyController(hand) {
|
|||
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
|
||||
// @param {number} which hand to use, RIGHT_HAND or LEFT_HAND
|
||||
// @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 name;
|
||||
|
||||
|
@ -1409,7 +1421,8 @@ function MyController(hand) {
|
|||
this.updateEquipHaptics(potentialEquipHotspot);
|
||||
|
||||
var nearEquipHotspots = this.chooseNearEquipHotspots(candidateEntities, EQUIP_HOTSPOT_RENDER_RADIUS);
|
||||
this.updateEquipHotspotRendering(nearEquipHotspots, potentialEquipHotspot);
|
||||
equipHotspotBuddy.updateHotspots(nearEquipHotspots, timestamp);
|
||||
equipHotspotBuddy.highlightHotspot(potentialEquipHotspot);
|
||||
|
||||
// search line visualizations
|
||||
if (USE_ENTITY_LINES_FOR_SEARCHING === true) {
|
||||
|
@ -1438,7 +1451,6 @@ function MyController(hand) {
|
|||
|
||||
this.distanceHoldingEnter = function () {
|
||||
|
||||
this.clearEquipHotspotRendering();
|
||||
this.clearEquipHaptics();
|
||||
|
||||
// controller pose is in avatar frame
|
||||
|
@ -1498,7 +1510,7 @@ function MyController(hand) {
|
|||
this.previousControllerRotation = controllerRotation;
|
||||
};
|
||||
|
||||
this.distanceHolding = function () {
|
||||
this.distanceHolding = function (deltaTime, timestamp) {
|
||||
if (this.triggerSmoothedReleased()) {
|
||||
this.callEntityMethodOnGrabbed("releaseGrab");
|
||||
this.setState(STATE_OFF, "trigger released");
|
||||
|
@ -1717,7 +1729,6 @@ function MyController(hand) {
|
|||
|
||||
this.dropGestureReset();
|
||||
this.clearEquipHaptics();
|
||||
this.clearEquipHotspotRendering();
|
||||
|
||||
Controller.triggerShortHapticPulse(1.0, this.hand);
|
||||
|
||||
|
@ -1819,7 +1830,7 @@ function MyController(hand) {
|
|||
this.currentAngularVelocity = ZERO_VEC;
|
||||
};
|
||||
|
||||
this.nearGrabbing = function (deltaTime) {
|
||||
this.nearGrabbing = function (deltaTime, timestamp) {
|
||||
|
||||
var dropDetected = this.dropGestureProcess(deltaTime);
|
||||
|
||||
|
@ -1938,7 +1949,6 @@ function MyController(hand) {
|
|||
|
||||
this.nearTriggerEnter = function () {
|
||||
|
||||
this.clearEquipHotspotRendering();
|
||||
this.clearEquipHaptics();
|
||||
|
||||
Controller.triggerShortHapticPulse(1.0, this.hand);
|
||||
|
@ -1946,13 +1956,12 @@ function MyController(hand) {
|
|||
};
|
||||
|
||||
this.farTriggerEnter = function () {
|
||||
this.clearEquipHotspotRendering();
|
||||
this.clearEquipHaptics();
|
||||
|
||||
this.callEntityMethodOnGrabbed("startFarTrigger");
|
||||
};
|
||||
|
||||
this.nearTrigger = function () {
|
||||
this.nearTrigger = function (deltaTime, timestamp) {
|
||||
if (this.triggerSmoothedReleased()) {
|
||||
this.callEntityMethodOnGrabbed("stopNearTrigger");
|
||||
this.setState(STATE_OFF, "trigger released");
|
||||
|
@ -1961,7 +1970,7 @@ function MyController(hand) {
|
|||
this.callEntityMethodOnGrabbed("continueNearTrigger");
|
||||
};
|
||||
|
||||
this.farTrigger = function () {
|
||||
this.farTrigger = function (deltaTime, timestamp) {
|
||||
if (this.triggerSmoothedReleased()) {
|
||||
this.callEntityMethodOnGrabbed("stopFarTrigger");
|
||||
this.setState(STATE_OFF, "trigger released");
|
||||
|
@ -2262,12 +2271,15 @@ Controller.enableMapping(MAPPING_NAME);
|
|||
var handToDisable = 'none';
|
||||
|
||||
function update(deltaTime) {
|
||||
var timestamp = Date.now();
|
||||
|
||||
if (handToDisable !== LEFT_HAND && handToDisable !== 'both') {
|
||||
leftController.update(deltaTime);
|
||||
leftController.update(deltaTime, timestamp);
|
||||
}
|
||||
if (handToDisable !== RIGHT_HAND && handToDisable !== 'both') {
|
||||
rightController.update(deltaTime);
|
||||
rightController.update(deltaTime, timestamp);
|
||||
}
|
||||
equipHotspotBuddy.update(deltaTime, timestamp);
|
||||
entityPropertiesCache.update();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue