From b0422106373e13dcf22ca181fde8853c0a5edf3e Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 24 Jun 2016 15:08:55 -0700 Subject: [PATCH 01/10] Addition of equipHotspots --- .../system/controllers/handControllerGrab.js | 103 ++++++++++++++---- 1 file changed, 81 insertions(+), 22 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index f86ff158f6..e971450aff 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -324,6 +324,14 @@ EntityPropertiesCache.prototype.getWearableProps = function(entityID) { return undefined; } }; +EntityPropertiesCache.prototype.getEquipHotspotsProps = function(entityID) { + var props = this.cache[entityID]; + if (props) { + return props.userData.equipHotspots ? props.userData.equipHotspots : {}; + } else { + return undefined; + } +}; function MyController(hand) { this.hand = hand; @@ -1083,8 +1091,8 @@ function MyController(hand) { }; this.entityIsEquippableWithDistanceCheck = function (entityID, handPosition) { + var distance, handJointName; var props = this.entityPropertyCache.getProps(entityID); - var distance = Vec3.distance(props.position, handPosition); var grabProps = this.entityPropertyCache.getGrabProps(entityID); var debug = (WANT_DEBUG_SEARCH_NAME && props.name === WANT_DEBUG_SEARCH_NAME); @@ -1096,30 +1104,81 @@ function MyController(hand) { return false; } - if (distance > EQUIP_RADIUS) { - if (debug) { - print("equip is skipping '" + props.name + "': too far away, " + distance + " meters"); - } - return false; - } + var equipHotspotsProps = this.entityPropertyCache.getEquipHotspotsProps(entityID); + if (equipHotspotsProps && equipHotspotsProps.length > 0) { + var i, length = equipHotspotsProps.length; + for (i = 0; i < length; i++) { + var hotspot = equipHotspotsProps[i]; + if (!hotspot.position) { + if (debug) { + print("equip is skipping '" + props.name + "': equip hotspot[" + i + "] is missing a position"); + } + continue; + } - var wearableProps = this.entityPropertyCache.getWearableProps(entityID); - if (!wearableProps || !wearableProps.joints) { - if (debug) { - print("equip is skipping '" + props.name + "': no wearable attach-point"); - } - return false; - } + if (!hotspot.radius) { + if (debug) { + print("equip is skipping '" + props.name + "': equip hotspot[" + i + "] is missing a radius"); + } + continue; + } - var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"; - if (!wearableProps.joints[handJointName]) { - if (debug) { - print("equip is skipping '" + props.name + "': no wearable joint for " + handJointName); - } - return false; - } + distance = Vec3.distance(hotspot.position, handPosition); + if (distance > hotspot.radius) { + if (debug) { + print("equip is skipping '" + props.name + "': equip hotspot[" + i + "] is too far away, " + distance + " meters"); + } + continue; + } - return true; + if (!hotspot.joints) { + if (debug) { + print("equip is skipping '" + props.name + "': equip hotspot[" + i + "] is missing joints"); + } + continue; + } + + handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"; + if (!hotspot.joints[handJointName]) { + if (debug) { + print("equip is skipping '" + props.name + "': equip hotspot[" + i + "] is missing joint." + handJointName); + } + continue; + } + + return true; + } + + return false; + + } else { + + distance = Vec3.distance(props.position, handPosition); + if (distance > EQUIP_RADIUS) { + if (debug) { + print("equip is skipping '" + props.name + "': too far away, " + distance + " meters"); + } + return false; + } + + var wearableProps = this.entityPropertyCache.getWearableProps(entityID); + if (!wearableProps || !wearableProps.joints) { + if (debug) { + print("equip is skipping '" + props.name + "': no wearable attach-point"); + } + return false; + } + + handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"; + if (!wearableProps.joints[handJointName]) { + if (debug) { + print("equip is skipping '" + props.name + "': no wearable joint for " + handJointName); + } + return false; + } + + return true; + } }; this.entityIsGrabbable = function (entityID) { From 1b98c7347324c78aa069004c6dc47105e282ea0b Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 24 Jun 2016 18:08:25 -0700 Subject: [PATCH 02/10] WIP, equip-points work but they don't use the proper attach point. --- .../system/controllers/handControllerGrab.js | 177 ++++++++---------- scripts/system/libraries/Xform.js | 8 + 2 files changed, 82 insertions(+), 103 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index e971450aff..c814b4396f 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -10,9 +10,10 @@ // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, Reticle, Messages, setEntityCustomData, getEntityCustomData, vec3toStr */ +/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, Reticle, Messages, setEntityCustomData, getEntityCustomData, vec3toStr, Xform */ Script.include("/~/system/libraries/utils.js"); +Script.include("../libraries/Xform.js"); // // add lines where the hand ray picking is happening @@ -931,7 +932,8 @@ function MyController(hand) { this.hotspotOverlays.push({ entityID: undefined, overlay: overlay, - type: "hand" + type: "hand", + localPosition: {x: 0, y: 0, z: 0} }); } @@ -941,35 +943,38 @@ function MyController(hand) { var _this = this; this.entityPropertyCache.getEntities().forEach(function (entityID) { + var props = _this.entityPropertyCache.getProps(entityID); if (_this.entityIsEquippableWithoutDistanceCheck(entityID)) { - props = _this.entityPropertyCache.getProps(entityID); + var equipHotspots = _this.collectEquipHotspots(entityID); + var entityXform = new Xform(props.rotation, props.position); + var i, length = equipHotspots.length; + for (i = 0; i < length; i++) { + var hotspot = equipHotspots[i]; + overlay = Overlays.addOverlay("sphere", { + position: entityXform.xformPoint(hotspot.position), + size: hotspot.radius * 2, + color: EQUIP_SPHERE_COLOR, + alpha: EQUIP_SPHERE_ALPHA, + solid: true, + visible: true, + ignoreRayIntersection: true, + drawInFront: false + }); - overlay = Overlays.addOverlay("sphere", { - rotation: props.rotation, - position: props.position, - size: EQUIP_RADIUS * 2, - color: EQUIP_SPHERE_COLOR, - alpha: EQUIP_SPHERE_ALPHA, - solid: true, - visible: true, - ignoreRayIntersection: true, - drawInFront: false - }); - - _this.hotspotOverlays.push({ - entityID: entityID, - overlay: overlay, - type: "equip" - }); + _this.hotspotOverlays.push({ + entityID: entityID, + overlay: overlay, + type: "equip", + localPosition: hotspot.position + }); + } } if (DRAW_GRAB_BOXES && _this.entityIsGrabbable(entityID)) { - props = _this.entityPropertyCache.getProps(entityID); - overlay = Overlays.addOverlay("cube", { rotation: props.rotation, position: props.position, - size: props.dimensions, //{x: props.dimensions.x, y: props.dimensions.y, z: props.dimensions.z}, + size: props.dimensions, color: GRAB_BOX_COLOR, alpha: GRAB_BOX_ALPHA, solid: true, @@ -981,7 +986,8 @@ function MyController(hand) { _this.hotspotOverlays.push({ entityID: entityID, overlay: overlay, - type: "near" + type: "near", + localPosition: {x: 0, y: 0, z: 0} }); } }); @@ -996,7 +1002,8 @@ function MyController(hand) { } else if (overlayInfo.type === "equip") { _this.entityPropertyCache.updateEntity(overlayInfo.entityID); props = _this.entityPropertyCache.getProps(overlayInfo.entityID); - Overlays.editOverlay(overlayInfo.overlay, { position: props.position, rotation: props.rotation }); + 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); @@ -1084,17 +1091,41 @@ function MyController(hand) { return grabbableProps && grabbableProps.wantsTrigger; }; - this.entityIsEquippableWithoutDistanceCheck = function (entityID) { - var props = this.entityPropertyCache.getProps(entityID); - var handPosition = props.position; - return this.entityIsEquippableWithDistanceCheck(entityID, handPosition); + this.collectEquipHotspots = function (entityID) { + var result = []; + var equipHotspotsProps = this.entityPropertyCache.getEquipHotspotsProps(entityID); + if (equipHotspotsProps && equipHotspotsProps.length > 0) { + var i, length = equipHotspotsProps.length; + for (i = 0; i < length; i++) { + var hotspot = equipHotspotsProps[i]; + if (hotspot.position && hotspot.radius && hotspot.joints) { + result.push({ + position: hotspot.position, + radius: hotspot.radius, + joints: hotspot.joints + }); + } + } + } else { + var wearableProps = this.entityPropertyCache.getWearableProps(entityID); + if (wearableProps && wearableProps.joints) { + result.push({ + position: {x: 0, y: 0, z: 0}, + radius: EQUIP_RADIUS, + joints: wearableProps.joints + }); + } + } + return result; }; - this.entityIsEquippableWithDistanceCheck = function (entityID, handPosition) { - var distance, handJointName; + this.entityIsEquippableWithDistanceCheck = function (entityID, handPosition, skipDistanceCheck) { + var distance; + var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"; var props = this.entityPropertyCache.getProps(entityID); var grabProps = this.entityPropertyCache.getGrabProps(entityID); var debug = (WANT_DEBUG_SEARCH_NAME && props.name === WANT_DEBUG_SEARCH_NAME); + var entityXform = new Xform(props.rotation, props.position); var refCount = ("refCount" in grabProps) ? grabProps.refCount : 0; if (refCount > 0) { @@ -1104,81 +1135,21 @@ function MyController(hand) { return false; } - var equipHotspotsProps = this.entityPropertyCache.getEquipHotspotsProps(entityID); - if (equipHotspotsProps && equipHotspotsProps.length > 0) { - var i, length = equipHotspotsProps.length; - for (i = 0; i < length; i++) { - var hotspot = equipHotspotsProps[i]; - if (!hotspot.position) { - if (debug) { - print("equip is skipping '" + props.name + "': equip hotspot[" + i + "] is missing a position"); - } - continue; - } - - if (!hotspot.radius) { - if (debug) { - print("equip is skipping '" + props.name + "': equip hotspot[" + i + "] is missing a radius"); - } - continue; - } - - distance = Vec3.distance(hotspot.position, handPosition); - if (distance > hotspot.radius) { - if (debug) { - print("equip is skipping '" + props.name + "': equip hotspot[" + i + "] is too far away, " + distance + " meters"); - } - continue; - } - - if (!hotspot.joints) { - if (debug) { - print("equip is skipping '" + props.name + "': equip hotspot[" + i + "] is missing joints"); - } - continue; - } - - handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"; - if (!hotspot.joints[handJointName]) { - if (debug) { - print("equip is skipping '" + props.name + "': equip hotspot[" + i + "] is missing joint." + handJointName); - } - continue; - } - + var equipHotspots = this.collectEquipHotspots(entityID); + var i, length = equipHotspots.length; + for (i = 0; i < length; i++) { + var hotspot = equipHotspots[i]; + distance = Vec3.distance(entityXform.xformPoint(hotspot.position), handPosition); + if ((skipDistanceCheck || distance < hotspot.radius) && hotspot.joints[handJointName]) { return true; } - - return false; - - } else { - - distance = Vec3.distance(props.position, handPosition); - if (distance > EQUIP_RADIUS) { - if (debug) { - print("equip is skipping '" + props.name + "': too far away, " + distance + " meters"); - } - return false; - } - - var wearableProps = this.entityPropertyCache.getWearableProps(entityID); - if (!wearableProps || !wearableProps.joints) { - if (debug) { - print("equip is skipping '" + props.name + "': no wearable attach-point"); - } - return false; - } - - handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"; - if (!wearableProps.joints[handJointName]) { - if (debug) { - print("equip is skipping '" + props.name + "': no wearable joint for " + handJointName); - } - return false; - } - - return true; } + return false; + }; + + this.entityIsEquippableWithoutDistanceCheck = function (entityID) { + var handPosition = this.getHandPosition(); + return this.entityIsEquippableWithDistanceCheck(entityID, handPosition, true); }; this.entityIsGrabbable = function (entityID) { diff --git a/scripts/system/libraries/Xform.js b/scripts/system/libraries/Xform.js index 75051c4983..1aa43cf30b 100644 --- a/scripts/system/libraries/Xform.js +++ b/scripts/system/libraries/Xform.js @@ -33,6 +33,14 @@ Xform.prototype.mirrorX = function() { {x: -this.pos.x, y: this.pos.y, z: this.pos.z}); }; +Xform.prototype.xformVector = function (vector) { + return Vec3.multiplyQbyV(this.rot, vector); +} + +Xform.prototype.xformPoint = function (point) { + return Vec3.sum(Vec3.multiplyQbyV(this.rot, point), this.pos); +} + Xform.prototype.toString = function() { var rot = this.rot; var pos = this.pos; From 43d4dba4c0323d40bed0186269a6456995607ad9 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 27 Jun 2016 18:05:45 -0700 Subject: [PATCH 03/10] iterate over hotspots not entities. This makes it possible to render multiple hotspots per entity. Also, it will use the same logic to decide how to deal with overlapping entity equip hotspots. --- .../system/controllers/handControllerGrab.js | 145 +++++++++--------- scripts/system/libraries/utils.js | 8 +- 2 files changed, 78 insertions(+), 75 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index c814b4396f..fe95dda596 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -10,7 +10,7 @@ // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, Reticle, Messages, setEntityCustomData, getEntityCustomData, vec3toStr, Xform */ +/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, Reticle, Messages, setEntityCustomData, getEntityCustomData, vec3toStr, flatten, Xform */ Script.include("/~/system/libraries/utils.js"); Script.include("../libraries/Xform.js"); @@ -879,7 +879,7 @@ function MyController(hand) { }; this.createHotspots = function () { - var props, overlay; + var _this = this; var HAND_EQUIP_SPHERE_COLOR = { red: 90, green: 255, blue: 90 }; var HAND_EQUIP_SPHERE_ALPHA = 0.7; @@ -897,6 +897,7 @@ function MyController(hand) { this.hotspotOverlays = []; + var overlay; if (DRAW_HAND_SPHERES) { // add tiny green sphere around the palm. var handPosition = this.getHandPosition(); @@ -910,7 +911,6 @@ function MyController(hand) { ignoreRayIntersection: true, drawInFront: false }); - this.hotspotOverlays.push({ entityID: undefined, overlay: overlay, @@ -928,7 +928,6 @@ function MyController(hand) { ignoreRayIntersection: true, drawInFront: false }); - this.hotspotOverlays.push({ entityID: undefined, overlay: overlay, @@ -941,55 +940,54 @@ function MyController(hand) { this.entityPropertyCache.clear(); this.entityPropertyCache.findEntities(MyAvatar.position, HOTSPOT_DRAW_DISTANCE); - var _this = this; - this.entityPropertyCache.getEntities().forEach(function (entityID) { - var props = _this.entityPropertyCache.getProps(entityID); - if (_this.entityIsEquippableWithoutDistanceCheck(entityID)) { - var equipHotspots = _this.collectEquipHotspots(entityID); - var entityXform = new Xform(props.rotation, props.position); - var i, length = equipHotspots.length; - for (i = 0; i < length; i++) { - var hotspot = equipHotspots[i]; - overlay = Overlays.addOverlay("sphere", { - position: entityXform.xformPoint(hotspot.position), - size: hotspot.radius * 2, - color: EQUIP_SPHERE_COLOR, - alpha: EQUIP_SPHERE_ALPHA, + if (DRAW_GRAB_BOXES) { + // 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: "equip", - localPosition: hotspot.position + type: "near", + localPosition: {x: 0, y: 0, z: 0} }); } - } + }); + } - if (DRAW_GRAB_BOXES && _this.entityIsGrabbable(entityID)) { - 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} - }); - } + // add green spheres for each equippable hotspot. + flatten(this.entityPropertyCache.getEntities().map(function (entityID) { + return _this.collectEquipHotspots(entityID); + })).filter(function (hotspot) { + return _this.hotspotIsEquippable(hotspot); + }).forEach(function (hotspot) { + var overlay = Overlays.addOverlay("sphere", { + position: hotspot.worldPosition, + size: hotspot.radius * 2, + color: EQUIP_SPHERE_COLOR, + alpha: EQUIP_SPHERE_ALPHA, + solid: true, + visible: true, + ignoreRayIntersection: true, + drawInFront: false + }); + _this.hotspotOverlays.push({ + entityID: hotspot.entityID, + overlay: overlay, + type: "equip", + localPosition: hotspot.localPosition + }); }); }; @@ -1091,8 +1089,18 @@ function MyController(hand) { return grabbableProps && grabbableProps.wantsTrigger; }; + /// @param {UUID} entityID + // @returns {Object[]} array of objects with the following fields. + // * entityID {UUID} + // * localPosition {Vec3} position of the hotspot in object space. + // * worldPosition {vec3} position of the hotspot in world space. + // * radius {number} radius of equip hotspot + // * joints {Object} keys are joint names values are arrays of two elements: + // offset position {Vec3} and offset rotation {Quat}, both are in the coordinate system of the joint. this.collectEquipHotspots = function (entityID) { var result = []; + var props = this.entityPropertyCache.getProps(entityID); + var entityXform = new Xform(props.rotation, props.position); var equipHotspotsProps = this.entityPropertyCache.getEquipHotspotsProps(entityID); if (equipHotspotsProps && equipHotspotsProps.length > 0) { var i, length = equipHotspotsProps.length; @@ -1100,7 +1108,9 @@ function MyController(hand) { var hotspot = equipHotspotsProps[i]; if (hotspot.position && hotspot.radius && hotspot.joints) { result.push({ - position: hotspot.position, + entityID: entityID, + localPosition: hotspot.position, + worldPosition: entityXform.xformPoint(hotspot.position), radius: hotspot.radius, joints: hotspot.joints }); @@ -1110,7 +1120,9 @@ function MyController(hand) { var wearableProps = this.entityPropertyCache.getWearableProps(entityID); if (wearableProps && wearableProps.joints) { result.push({ - position: {x: 0, y: 0, z: 0}, + entityID: entityID, + localPosition: {x: 0, y: 0, z: 0}, + worldPosition: entityXform.pos, radius: EQUIP_RADIUS, joints: wearableProps.joints }); @@ -1119,13 +1131,10 @@ function MyController(hand) { return result; }; - this.entityIsEquippableWithDistanceCheck = function (entityID, handPosition, skipDistanceCheck) { - var distance; - var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"; - var props = this.entityPropertyCache.getProps(entityID); - var grabProps = this.entityPropertyCache.getGrabProps(entityID); + this.hotspotIsEquippable = function (hotspot) { + var props = this.entityPropertyCache.getProps(hotspot.entityID); + var grabProps = this.entityPropertyCache.getGrabProps(hotspot.entityID); var debug = (WANT_DEBUG_SEARCH_NAME && props.name === WANT_DEBUG_SEARCH_NAME); - var entityXform = new Xform(props.rotation, props.position); var refCount = ("refCount" in grabProps) ? grabProps.refCount : 0; if (refCount > 0) { @@ -1135,21 +1144,7 @@ function MyController(hand) { return false; } - var equipHotspots = this.collectEquipHotspots(entityID); - var i, length = equipHotspots.length; - for (i = 0; i < length; i++) { - var hotspot = equipHotspots[i]; - distance = Vec3.distance(entityXform.xformPoint(hotspot.position), handPosition); - if ((skipDistanceCheck || distance < hotspot.radius) && hotspot.joints[handJointName]) { - return true; - } - } - return false; - }; - - this.entityIsEquippableWithoutDistanceCheck = function (entityID) { - var handPosition = this.getHandPosition(); - return this.entityIsEquippableWithDistanceCheck(entityID, handPosition, true); + return true; }; this.entityIsGrabbable = function (entityID) { @@ -1285,22 +1280,24 @@ function MyController(hand) { this.entityPropertyCache.findEntities(handPosition, NEAR_GRAB_RADIUS); var candidateEntities = this.entityPropertyCache.getEntities(); - var equippableEntities = candidateEntities.filter(function (entity) { - return _this.entityIsEquippableWithDistanceCheck(entity, handPosition); + var equippableHotspots = flatten(candidateEntities.map(function (entityID) { + return _this.collectEquipHotspots(entityID); + })).filter(function (hotspot) { + return _this.hotspotIsEquippable(hotspot) && Vec3.distance(hotspot.worldPosition, handPosition) < hotspot.radius; }); var entity; - if (equippableEntities.length > 0) { + if (equippableHotspots.length > 0) { // sort by distance - equippableEntities.sort(function (a, b) { - var aDistance = Vec3.distance(_this.entityPropertyCache.getProps(a).position, handPosition); - var bDistance = Vec3.distance(_this.entityPropertyCache.getProps(b).position, handPosition); + equippableHotspots.sort(function (a, b) { + var aDistance = Vec3.distance(a.worldPosition, handPosition); + var bDistance = Vec3.distance(b.worldPosition, handPosition); return aDistance - bDistance; }); - entity = equippableEntities[0]; if (this.triggerSmoothedGrab()) { - this.grabbedEntity = entity; - this.setState(STATE_HOLD, "eqipping '" + this.entityPropertyCache.getProps(entity).name + "'"); + this.grabbedHotspot = equippableHotspots[0]; + this.grabbedEntity = equippableHotspots[0].entityID; + this.setState(STATE_HOLD, "eqipping '" + this.entityPropertyCache.getProps(this.grabbedEntity).name + "'"); return; } else { // TODO: highlight the equippable object? diff --git a/scripts/system/libraries/utils.js b/scripts/system/libraries/utils.js index f39f4d7913..b7de9b012c 100644 --- a/scripts/system/libraries/utils.js +++ b/scripts/system/libraries/utils.js @@ -309,5 +309,11 @@ calculateHandSizeRatio = function() { clamp = function(val, min, max){ return Math.max(min, Math.min(max, val)) - } +} +// flattens an array of arrays into a single array +// example: flatten([[1], [3, 4], []) => [1, 3, 4] +// NOTE: only does one level of flattening, it is not recursive. +flatten = function(array) { + return [].concat.apply([], array); +} From 6072487c9c388374e707a17fdb69b7d629e7f37b Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 29 Jun 2016 17:28:53 -0700 Subject: [PATCH 04/10] Equip-points attachments work Also made handControllerGrab.js eslint clean. --- .../system/controllers/handControllerGrab.js | 197 ++++++++---------- 1 file changed, 82 insertions(+), 115 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index fe95dda596..d37602f8e6 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -10,7 +10,7 @@ // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, Reticle, Messages, setEntityCustomData, getEntityCustomData, vec3toStr, flatten, Xform */ +/* global setEntityCustomData, getEntityCustomData, vec3toStr, flatten, Xform */ Script.include("/~/system/libraries/utils.js"); Script.include("../libraries/Xform.js"); @@ -139,7 +139,7 @@ var DEFAULT_GRABBABLE_DATA = { var USE_BLACKLIST = true; var blacklist = []; -//we've created various ways of visualizing looking for and moving distant objects +// we've created various ways of visualizing looking for and moving distant objects var USE_ENTITY_LINES_FOR_SEARCHING = false; var USE_OVERLAY_LINES_FOR_SEARCHING = true; @@ -255,7 +255,8 @@ function isIn2DMode() { // In this version, we make our own determination of whether we're aimed a HUD element, // because other scripts (such as handControllerPointer) might be using some other visualization // instead of setting Reticle.visible. - return EXTERNALLY_MANAGED_2D_MINOR_MODE && (Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(Reticle.position)); + return (EXTERNALLY_MANAGED_2D_MINOR_MODE && + (Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(Reticle.position))); } function restore2DMode() { if (!EXTERNALLY_MANAGED_2D_MINOR_MODE) { @@ -274,7 +275,7 @@ EntityPropertiesCache.prototype.clear = function() { EntityPropertiesCache.prototype.findEntities = function(position, radius) { var entities = Entities.findEntities(position, radius); var _this = this; - entities.forEach(function (x) { + entities.forEach(function(x) { _this.updateEntity(x); }); }; @@ -286,7 +287,7 @@ EntityPropertiesCache.prototype.updateEntity = function(entityID) { if (props.userData) { try { userData = JSON.parse(props.userData); - } catch(err) { + } catch (err) { print("WARNING: malformed userData on " + entityID + ", name = " + props.name + ", error = " + err); } } @@ -296,9 +297,9 @@ EntityPropertiesCache.prototype.updateEntity = function(entityID) { }; EntityPropertiesCache.prototype.getEntities = function() { return Object.keys(this.cache); -} +}; EntityPropertiesCache.prototype.getProps = function(entityID) { - var obj = this.cache[entityID] + var obj = this.cache[entityID]; return obj ? obj : undefined; }; EntityPropertiesCache.prototype.getGrabbableProps = function(entityID) { @@ -346,7 +347,7 @@ function MyController(hand) { this.getHandRotation = function() { var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; return Quat.multiply(MyAvatar.orientation, Controller.getPoseValue(controllerHandInput).rotation); - } + }; this.actionID = null; // action this script created... this.grabbedEntity = null; // on this entity. @@ -359,11 +360,11 @@ function MyController(hand) { this.rawSecondaryValue = 0; this.rawThumbValue = 0; - //for visualizations + // for visualizations this.overlayLine = null; this.particleBeamObject = null; - //for lights + // for lights this.spotlight = null; this.pointlight = null; this.overlayLine = null; @@ -388,7 +389,7 @@ function MyController(hand) { var _this = this; var suppressedIn2D = [STATE_OFF, STATE_SEARCHING]; - this.ignoreInput = function () { + this.ignoreInput = function() { // We've made the decision to use 'this' for new code, even though it is fragile, // in order to keep/ the code uniform without making any no-op line changes. return (-1 !== suppressedIn2D.indexOf(this.state)) && isIn2DMode(); @@ -419,7 +420,7 @@ function MyController(hand) { this.callEntityMethodOnGrabbed = function(entityMethodName) { var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(this.grabbedEntity, entityMethodName, args); - } + }; this.setState = function(newState, reason) { @@ -517,7 +518,7 @@ function MyController(hand) { ignoreRayIntersection: true, drawInFront: true, // Even when burried inside of something, show it. visible: true - } + }; this.searchSphere = Overlays.addOverlay("sphere", sphereProperties); } else { Overlays.editOverlay(this.searchSphere, { @@ -527,7 +528,7 @@ function MyController(hand) { visible: true }); } - } + }; this.overlayLineOn = function(closePoint, farPoint, color) { if (this.overlayLine === null) { @@ -576,7 +577,7 @@ function MyController(hand) { this.overlayLineOn(handPosition, searchSphereLocation, (this.triggerSmoothedGrab() || this.secondarySqueezed()) ? INTERSECT_COLOR : NO_INTERSECT_COLOR); } - } + }; this.handleDistantParticleBeam = function(handPosition, objectPosition, color) { @@ -643,7 +644,7 @@ function MyController(hand) { "alphaFinish": 1, "additiveBlending": 0, "textures": "https://hifi-content.s3.amazonaws.com/alan/dev/textures/grabsprite-3.png" - } + }; this.particleBeamObject = Entities.addEntity(particleBeamPropertiesObject); }; @@ -657,7 +658,7 @@ function MyController(hand) { emitSpeed: speed, speedSpread: spread, lifespan: lifespan - }) + }); }; this.evalLightWorldTransform = function(modelPos, modelRot) { @@ -711,9 +712,9 @@ function MyController(hand) { this.spotlight = Entities.addEntity(lightProperties); } else { Entities.editEntity(this.spotlight, { - //without this, this light would maintain rotation with its parent + // without this, this light would maintain rotation with its parent rotation: Quat.fromPitchYawRollDegrees(-90, 0, 0) - }) + }); } }; @@ -777,7 +778,7 @@ function MyController(hand) { Entities.deleteEntity(this.particleBeamObject); this.particleBeamObject = null; } - } + }; this.turnLightsOff = function() { if (this.spotlight !== null) { @@ -853,7 +854,7 @@ function MyController(hand) { this.thumbPress = function(value) { _this.rawThumbValue = value; - } + }; this.thumbPressed = function() { return _this.rawThumbValue > THUMB_ON_VALUE; @@ -878,7 +879,7 @@ function MyController(hand) { } }; - this.createHotspots = function () { + this.createHotspots = function() { var _this = this; var HAND_EQUIP_SPHERE_COLOR = { red: 90, green: 255, blue: 90 }; @@ -942,7 +943,7 @@ function MyController(hand) { if (DRAW_GRAB_BOXES) { // add blue box overlays for grabbable entities. - this.entityPropertyCache.getEntities().forEach(function (entityID) { + this.entityPropertyCache.getEntities().forEach(function(entityID) { var props = _this.entityPropertyCache.getProps(entityID); if (_this.entityIsGrabbable(entityID)) { var overlay = Overlays.addOverlay("cube", { @@ -967,11 +968,11 @@ function MyController(hand) { } // add green spheres for each equippable hotspot. - flatten(this.entityPropertyCache.getEntities().map(function (entityID) { + flatten(this.entityPropertyCache.getEntities().map(function(entityID) { return _this.collectEquipHotspots(entityID); - })).filter(function (hotspot) { + })).filter(function(hotspot) { return _this.hotspotIsEquippable(hotspot); - }).forEach(function (hotspot) { + }).forEach(function(hotspot) { var overlay = Overlays.addOverlay("sphere", { position: hotspot.worldPosition, size: hotspot.radius * 2, @@ -994,14 +995,17 @@ function MyController(hand) { this.updateHotspots = function() { var _this = this; var props; - this.hotspotOverlays.forEach(function (overlayInfo) { + 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 }); + 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); @@ -1011,7 +1015,7 @@ function MyController(hand) { }; this.destroyHotspots = function() { - this.hotspotOverlays.forEach(function (overlayInfo) { + this.hotspotOverlays.forEach(function(overlayInfo) { Overlays.deleteOverlay(overlayInfo.overlay); }); this.hotspotOverlays = []; @@ -1025,14 +1029,14 @@ function MyController(hand) { this.destroyHotspots(); }; - /// // 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 // this.calcRayPickInfo = function(hand) { - var pose = Controller.getPoseValue((hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand); + var standardControllerValue = (hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; + var pose = Controller.getPoseValue(standardControllerValue); var worldHandPosition = Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation, pose.translation), MyAvatar.position); var worldHandRotation = Quat.multiply(MyAvatar.orientation, pose.rotation); @@ -1071,33 +1075,37 @@ function MyController(hand) { } var overlayIntersection = Overlays.findRayIntersection(pickRayBacked); - if (!intersection.intersects || (overlayIntersection.intersects && (intersection.distance > overlayIntersection.distance))) { + if (!intersection.intersects || + (overlayIntersection.intersects && (intersection.distance > overlayIntersection.distance))) { intersection = overlayIntersection; } if (intersection.intersects) { - return { entityID: intersection.entityID, - searchRay: pickRay, - distance: Vec3.distance(pickRay.origin, intersection.intersection) } + return { + entityID: intersection.entityID, + searchRay: pickRay, + distance: Vec3.distance(pickRay.origin, intersection.intersection) + }; } else { return result; } }; - this.entityWantsTrigger = function (entityID) { + this.entityWantsTrigger = function(entityID) { var grabbableProps = this.entityPropertyCache.getGrabbableProps(entityID); return grabbableProps && grabbableProps.wantsTrigger; }; - /// @param {UUID} entityID - // @returns {Object[]} array of objects with the following fields. + // returns a list of all equip-hotspots assosiated with this entity. + // @param {UUID} entityID + // @returns {Object[]} array of objects with the following fields. // * entityID {UUID} // * localPosition {Vec3} position of the hotspot in object space. // * worldPosition {vec3} position of the hotspot in world space. // * radius {number} radius of equip hotspot // * joints {Object} keys are joint names values are arrays of two elements: // offset position {Vec3} and offset rotation {Quat}, both are in the coordinate system of the joint. - this.collectEquipHotspots = function (entityID) { + this.collectEquipHotspots = function(entityID) { var result = []; var props = this.entityPropertyCache.getProps(entityID); var entityXform = new Xform(props.rotation, props.position); @@ -1131,7 +1139,7 @@ function MyController(hand) { return result; }; - this.hotspotIsEquippable = function (hotspot) { + this.hotspotIsEquippable = function(hotspot) { var props = this.entityPropertyCache.getProps(hotspot.entityID); var grabProps = this.entityPropertyCache.getGrabProps(hotspot.entityID); var debug = (WANT_DEBUG_SEARCH_NAME && props.name === WANT_DEBUG_SEARCH_NAME); @@ -1147,7 +1155,7 @@ function MyController(hand) { return true; }; - this.entityIsGrabbable = function (entityID) { + this.entityIsGrabbable = function(entityID) { var grabbableProps = this.entityPropertyCache.getGrabbableProps(entityID); var grabProps = this.entityPropertyCache.getGrabProps(entityID); var props = this.entityPropertyCache.getProps(entityID); @@ -1280,16 +1288,16 @@ function MyController(hand) { this.entityPropertyCache.findEntities(handPosition, NEAR_GRAB_RADIUS); var candidateEntities = this.entityPropertyCache.getEntities(); - var equippableHotspots = flatten(candidateEntities.map(function (entityID) { + var equippableHotspots = flatten(candidateEntities.map(function(entityID) { return _this.collectEquipHotspots(entityID); - })).filter(function (hotspot) { + })).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) { + equippableHotspots.sort(function(a, b) { var aDistance = Vec3.distance(a.worldPosition, handPosition); var bDistance = Vec3.distance(b.worldPosition, handPosition); return aDistance - bDistance; @@ -1304,7 +1312,7 @@ function MyController(hand) { } } - var grabbableEntities = candidateEntities.filter(function (entity) { + var grabbableEntities = candidateEntities.filter(function(entity) { return _this.entityIsNearGrabbable(entity, handPosition, NEAR_GRAB_MAX_DISTANCE); }); @@ -1321,7 +1329,7 @@ function MyController(hand) { if (grabbableEntities.length > 0) { // sort by distance - grabbableEntities.sort(function (a, b) { + grabbableEntities.sort(function(a, b) { var aDistance = Vec3.distance(_this.entityPropertyCache.getProps(a).position, handPosition); var bDistance = Vec3.distance(_this.entityPropertyCache.getProps(b).position, handPosition); return aDistance - bDistance; @@ -1381,9 +1389,11 @@ function MyController(hand) { } } - //search line visualizations + // search line visualizations if (USE_ENTITY_LINES_FOR_SEARCHING === true) { - this.lineOn(rayPickInfo.searchRay.origin, Vec3.multiply(rayPickInfo.searchRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + this.lineOn(rayPickInfo.searchRay.origin, + Vec3.multiply(rayPickInfo.searchRay.direction, LINE_LENGTH), + NO_INTERSECT_COLOR); } this.searchIndicatorOn(rayPickInfo.searchRay); @@ -1398,11 +1408,11 @@ function MyController(hand) { timeScale = DISTANCE_HOLDING_ACTION_TIMEFRAME; } return timeScale; - } + }; this.getMass = function(dimensions, density) { return (dimensions.x * dimensions.y * dimensions.z) * density; - } + }; this.distanceHoldingEnter = function() { @@ -1529,7 +1539,8 @@ function MyController(hand) { var RADIAL_GRAB_AMPLIFIER = 10.0; if (Math.abs(this.grabRadialVelocity) > 0.0) { - this.grabRadius = this.grabRadius + (this.grabRadialVelocity * deltaObjectTime * this.grabRadius * RADIAL_GRAB_AMPLIFIER); + this.grabRadius = this.grabRadius + (this.grabRadialVelocity * deltaObjectTime * + this.grabRadius * RADIAL_GRAB_AMPLIFIER); } var newTargetPosition = Vec3.multiply(this.grabRadius, Quat.getUp(controllerRotation)); @@ -1557,30 +1568,9 @@ function MyController(hand) { } } - // var defaultConstraintData = { - // axisStart: false, - // axisEnd: false - // } - // - // var constraintData = getEntityCustomData('lightModifierKey', this.grabbedEntity, defaultConstraintData); - // var clampedVector; - // var targetPosition; - // if (constraintData.axisStart !== false) { - // clampedVector = this.projectVectorAlongAxis(this.currentObjectPosition, - // constraintData.axisStart, - // constraintData.axisEnd); - // targetPosition = clampedVector; - // } else { - // targetPosition = { - // x: this.currentObjectPosition.x, - // y: this.currentObjectPosition.y, - // z: this.currentObjectPosition.z - // } - // } - var handPosition = this.getHandPosition(); - //visualizations + // visualizations if (USE_ENTITY_LINES_FOR_MOVING === true) { this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR); } @@ -1588,7 +1578,7 @@ function MyController(hand) { this.overlayLineOn(handPosition, grabbedProperties.position, INTERSECT_COLOR); } if (USE_PARTICLE_BEAM_FOR_MOVING === true) { - this.handleDistantParticleBeam(handPosition, grabbedProperties.position, INTERSECT_COLOR) + this.handleDistantParticleBeam(handPosition, grabbedProperties.position, INTERSECT_COLOR); } if (USE_POINTLIGHT === true) { this.handlePointLight(this.grabbedEntity); @@ -1648,46 +1638,17 @@ function MyController(hand) { scalar = 1; } var projection = Vec3.sum(axisStart, Vec3.multiply(scalar, Vec3.normalize(bPrime))); - return projection + return projection; }; - this.hasPresetOffsets = function() { - var wearableData = getEntityCustomData('wearable', this.grabbedEntity, {joints: {}}); - if ("joints" in wearableData) { - var allowedJoints = wearableData.joints; - var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"; - if (handJointName in allowedJoints) { - return true; - } - } - return false; - } - - this.getPresetPosition = function() { - var wearableData = getEntityCustomData('wearable', this.grabbedEntity, {joints: {}}); - var allowedJoints = wearableData.joints; - var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"; - if (handJointName in allowedJoints) { - return allowedJoints[handJointName][0]; - } - } - - this.getPresetRotation = function() { - var wearableData = getEntityCustomData('wearable', this.grabbedEntity, {joints: {}}); - var allowedJoints = wearableData.joints; - var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"; - if (handJointName in allowedJoints) { - return allowedJoints[handJointName][1]; - } - } - this.dropGestureReset = function() { this.fastHandMoveDetected = false; this.fastHandMoveTimer = 0; }; this.dropGestureProcess = function(deltaTime) { - var pose = Controller.getPoseValue((this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand); + var standardControllerValue = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; + var pose = Controller.getPoseValue(standardControllerValue); var worldHandVelocity = Vec3.multiplyQbyV(MyAvatar.orientation, pose.velocity); var worldHandRotation = Quat.multiply(MyAvatar.orientation, pose.rotation); @@ -1745,13 +1706,17 @@ function MyController(hand) { var handPosition = this.getHandPosition(); var hasPresetPosition = false; - if (this.state == STATE_HOLD && this.hasPresetOffsets()) { + if (this.state == STATE_HOLD && this.grabbedHotspot) { var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA); // if an object is "equipped" and has a predefined offset, use it. this.ignoreIK = grabbableData.ignoreIK ? grabbableData.ignoreIK : false; - this.offsetPosition = this.getPresetPosition(); - this.offsetRotation = this.getPresetRotation(); - hasPresetPosition = true; + + var handJointName = this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"; + if (this.grabbedHotspot.joints[handJointName]) { + this.offsetPosition = this.grabbedHotspot.joints[handJointName][0]; + this.offsetRotation = this.grabbedHotspot.joints[handJointName][1]; + hasPresetPosition = true; + } } else { this.ignoreIK = false; @@ -1784,7 +1749,7 @@ function MyController(hand) { var reparentProps = { parentID: MyAvatar.sessionUUID, parentJointIndex: handJointIndex - } + }; if (hasPresetPosition) { reparentProps["localPosition"] = this.offsetPosition; reparentProps["localRotation"] = this.offsetRotation; @@ -2022,6 +1987,7 @@ function MyController(hand) { })); this.grabbedEntity = null; + this.grabbedHotspot = null; if (this.triggerSmoothedGrab()) { this.waitForTriggerRelease = true; @@ -2124,7 +2090,7 @@ function MyController(hand) { print("disconnecting stray child of hand: (" + _this.hand + ") " + childID); Entities.editEntity(childID, {parentID: NULL_UUID}); }); - } + }; this.deactivateEntity = function(entityID, noVelocity) { var deactiveProps; @@ -2149,7 +2115,7 @@ function MyController(hand) { // things that are held by parenting and dropped with no velocity will end up as "static" in bullet. If // it looks like the dropped thing should fall, give it a little velocity. - var props = Entities.getEntityProperties(entityID, ["parentID", "velocity", "dynamic", "shapeType"]) + var props = Entities.getEntityProperties(entityID, ["parentID", "velocity", "dynamic", "shapeType"]); var parentID = props.parentID; var doSetVelocity = false; @@ -2231,7 +2197,8 @@ mapping.from([Controller.Standard.RightPrimaryThumb]).peek().to(rightController. Controller.enableMapping(MAPPING_NAME); -//the section below allows the grab script to listen for messages that disable either one or both hands. useful for two handed items +// the section below allows the grab script to listen for messages +// that disable either one or both hands. useful for two handed items var handToDisable = 'none'; function update(deltaTime) { @@ -2294,7 +2261,7 @@ var handleHandMessages = function(channel, message, sender) { } } } -} +}; Messages.messageReceived.connect(handleHandMessages); From 759b3065fc8693bca06b89134b7a91a87cdccec4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 30 Jun 2016 20:48:19 +1200 Subject: [PATCH 05/10] Distinguish between file name and directory as prompt in file chooser --- interface/resources/qml/dialogs/FileDialog.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/dialogs/FileDialog.qml b/interface/resources/qml/dialogs/FileDialog.qml index 5372028da5..fa5be18cd3 100644 --- a/interface/resources/qml/dialogs/FileDialog.qml +++ b/interface/resources/qml/dialogs/FileDialog.qml @@ -603,7 +603,7 @@ ModalWindow { TextField { id: currentSelection - label: "Path:" + label: selectDirectory ? "Directory:" : "File name:" anchors { left: parent.left right: selectionType.visible ? selectionType.left: parent.right From 82b1cba81dcba949e1eaf3095c110a72ad90176e Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 30 Jun 2016 13:58:44 -0700 Subject: [PATCH 06/10] equip improvements Allow the user to equip an object while near or far grabbing it from the other hand. --- scripts/system/controllers/handControllerGrab.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index d37602f8e6..7a0bfc85cf 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -1144,10 +1144,11 @@ function MyController(hand) { var grabProps = this.entityPropertyCache.getGrabProps(hotspot.entityID); var debug = (WANT_DEBUG_SEARCH_NAME && props.name === WANT_DEBUG_SEARCH_NAME); + // Controller.Standard.LeftHand var refCount = ("refCount" in grabProps) ? grabProps.refCount : 0; - if (refCount > 0) { + if (refCount > 0 && this.getOtherHandController().grabbedEntity != hotspot.entityID) { if (debug) { - print("equip is skipping '" + props.name + "': it is already grabbed"); + print("equip is skipping '" + props.name + "': grabbed by someone else"); } return false; } @@ -1698,6 +1699,12 @@ function MyController(hand) { this.grabbedEntity = saveGrabbedID; } + var otherHandController = this.getOtherHandController(); + if (otherHandController.grabbedEntity == this.grabbedEntity && + (otherHandController.state == STATE_NEAR_GRABBING || otherHandController.state == STATE_DISTANCE_HOLDING)) { + otherHandController.setState(STATE_OFF, "other hand grabbed this entity"); + } + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); this.activateEntity(this.grabbedEntity, grabbedProperties, false); @@ -1818,7 +1825,6 @@ function MyController(hand) { return; } - var now = Date.now(); if (now - this.lastUnequipCheckTime > MSECS_PER_SEC * CHECK_TOO_FAR_UNEQUIP_TIME) { this.lastUnequipCheckTime = now; @@ -2176,6 +2182,10 @@ function MyController(hand) { } setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); }; + + this.getOtherHandController = function() { + return (this.hand === RIGHT_HAND) ? leftController : rightController; + }; } var rightController = new MyController(RIGHT_HAND); From 5b343c9b82e322f6452c4e3f48244fe55272457e Mon Sep 17 00:00:00 2001 From: Zander Otavka Date: Thu, 30 Jun 2016 14:18:07 -0700 Subject: [PATCH 07/10] Fix eslint descrepencies Prohibit trailing commas, and fix function spacing rule to be more in line with the coding standard. Also prohibit leading decimal points, also specified in coding standard. --- .eslintrc.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index e866713b11..a7f4291257 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -52,13 +52,14 @@ module.exports = { }, "rules": { "brace-style": ["error", "1tbs", { "allowSingleLine": false }], - "comma-dangle": ["error", "only-multiline"], + "comma-dangle": ["error", "never"], "camelcase": ["error"], "curly": ["error", "all"], "indent": ["error", 4, { "SwitchCase": 1 }], "keyword-spacing": ["error", { "before": true, "after": true }], "max-len": ["error", 128, 4], "new-cap": ["error"], + "no-floating-decimal": ["error"], //"no-magic-numbers": ["error", { "ignore": [0, 1], "ignoreArrayIndexes": true }], "no-multiple-empty-lines": ["error"], "no-multi-spaces": ["error"], @@ -67,6 +68,6 @@ module.exports = { "spaced-comment": ["error", "always", { "line": { "markers": ["/"] } }], - "space-before-function-paren": ["error", "never"] + "space-before-function-paren": ["error", {"anonymous": "always", "named": "never"}] } }; From d8e5e3cbe4b1c7af668193d738e6ef0f941de7fa Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 30 Jun 2016 16:00:18 -0700 Subject: [PATCH 08/10] equip bug fix you should not be able to equip an object that is already equipped, with your other hand. --- scripts/system/controllers/handControllerGrab.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 7a0bfc85cf..ecece8c4f7 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -1144,9 +1144,11 @@ function MyController(hand) { var grabProps = this.entityPropertyCache.getGrabProps(hotspot.entityID); var debug = (WANT_DEBUG_SEARCH_NAME && props.name === WANT_DEBUG_SEARCH_NAME); - // Controller.Standard.LeftHand var refCount = ("refCount" in grabProps) ? grabProps.refCount : 0; - if (refCount > 0 && this.getOtherHandController().grabbedEntity != hotspot.entityID) { + var okToEquipFromOtherHand = ((this.getOtherHandController().state == STATE_NEAR_GRABBING || + this.getOtherHandController().state == STATE_DISTANCE_HOLDING) && + this.getOtherHandController().grabbedEntity == hotspot.entityID); + if (refCount > 0 && !okToEquipFromOtherHand) { if (debug) { print("equip is skipping '" + props.name + "': grabbed by someone else"); } From b7926b8582829bc3ac444b401b5548f7872c21d8 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 30 Jun 2016 16:11:05 -0700 Subject: [PATCH 09/10] Don't render wire geometry with lighting effects --- interface/src/ui/overlays/Circle3DOverlay.cpp | 7 +++++-- interface/src/ui/overlays/Cube3DOverlay.cpp | 6 +++--- interface/src/ui/overlays/Grid3DOverlay.cpp | 5 +++-- interface/src/ui/overlays/Image3DOverlay.cpp | 8 +++++--- interface/src/ui/overlays/Line3DOverlay.cpp | 9 ++++++--- interface/src/ui/overlays/Rectangle3DOverlay.cpp | 8 +++++--- interface/src/ui/overlays/Sphere3DOverlay.cpp | 4 ++-- interface/src/ui/overlays/Web3DOverlay.cpp | 4 +++- libraries/render-utils/src/GeometryCache.cpp | 5 +++++ libraries/render-utils/src/GeometryCache.h | 8 +++++--- 10 files changed, 42 insertions(+), 22 deletions(-) diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index 8fb3a36919..1abcb0f5c0 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -97,7 +97,7 @@ void Circle3DOverlay::render(RenderArgs* args) { _lastColor = colorX; auto geometryCache = DependencyManager::get(); - + Q_ASSERT(args->_batch); auto& batch = *args->_batch; @@ -149,6 +149,7 @@ void Circle3DOverlay::render(RenderArgs* args) { geometryCache->updateVertices(_quadVerticesID, points, color); } + geometryCache->bindSimpleProgram(batch); geometryCache->renderVertices(batch, gpu::TRIANGLES, _quadVerticesID); } else { @@ -187,6 +188,8 @@ void Circle3DOverlay::render(RenderArgs* args) { geometryCache->updateVertices(_lineVerticesID, points, color); } + // Render unlit + geometryCache->bindSimpleProgram(batch, false, false, true); if (getIsDashedLine()) { geometryCache->renderVertices(batch, gpu::LINES, _lineVerticesID); } else { @@ -279,7 +282,7 @@ void Circle3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Circle3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace(); + auto builder = render::ShapeKey::Builder().withOwnPipeline(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 38650f9fda..17894aa091 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -48,7 +48,7 @@ void Cube3DOverlay::render(RenderArgs* args) { auto geometryCache = DependencyManager::get(); auto pipeline = args->_pipeline; if (!pipeline) { - pipeline = geometryCache->getShapePipeline(); + pipeline = _isSolid ? geometryCache->getShapePipeline() : geometryCache->getWireShapePipeline(); } if (_isSolid) { @@ -56,7 +56,7 @@ void Cube3DOverlay::render(RenderArgs* args) { batch->setModelTransform(transform); geometryCache->renderSolidCubeInstance(*batch, cubeColor, pipeline); } else { - + geometryCache->bindSimpleProgram(*batch, false, false, true, true); if (getIsDashedLine()) { transform.setScale(1.0f); batch->setModelTransform(transform); @@ -97,7 +97,7 @@ void Cube3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Cube3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder(); + auto builder = render::ShapeKey::Builder().withOwnPipeline(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Grid3DOverlay.cpp b/interface/src/ui/overlays/Grid3DOverlay.cpp index edc27e35f2..7d86395937 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.cpp +++ b/interface/src/ui/overlays/Grid3DOverlay.cpp @@ -75,10 +75,11 @@ void Grid3DOverlay::render(RenderArgs* args) { transform.setScale(glm::vec3(getDimensions(), 1.0f)); transform.setTranslation(position); batch->setModelTransform(transform); - + auto geometryCache = DependencyManager::get(); + geometryCache->bindSimpleProgram(*batch, false, false, true, true); const float MINOR_GRID_EDGE = 0.0025f; const float MAJOR_GRID_EDGE = 0.005f; - DependencyManager::get()->renderGrid(*batch, minCorner, maxCorner, + geometryCache->renderGrid(*batch, minCorner, maxCorner, _minorGridRowDivisions, _minorGridColDivisions, MINOR_GRID_EDGE, _majorGridRowDivisions, _majorGridColDivisions, MAJOR_GRID_EDGE, gridColor, _drawInFront); diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index fd0d2bcedf..72ae246859 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -92,8 +92,10 @@ void Image3DOverlay::render(RenderArgs* args) { batch->setModelTransform(transform); batch->setResourceTexture(0, _texture->getGPUTexture()); - - DependencyManager::get()->renderQuad( + + auto geometryCache = DependencyManager::get(); + geometryCache->bindSimpleProgram(*batch, true, false); + geometryCache->renderQuad( *batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha) ); @@ -102,7 +104,7 @@ void Image3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Image3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); + auto builder = render::ShapeKey::Builder().withOwnPipeline(); if (_emissive) { builder.withUnlit(); } diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index 3971e91211..d53b287f76 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -54,17 +54,20 @@ void Line3DOverlay::render(RenderArgs* args) { if (batch) { batch->setModelTransform(_transform); + auto geometryCache = DependencyManager::get(); + geometryCache->bindSimpleProgram(*batch, false, false, true, true); if (getIsDashedLine()) { // TODO: add support for color to renderDashedLine() - DependencyManager::get()->renderDashedLine(*batch, _start, _end, colorv4, _geometryCacheID); + geometryCache->renderDashedLine(*batch, _start, _end, colorv4, _geometryCacheID); } else { - DependencyManager::get()->renderLine(*batch, _start, _end, colorv4, _geometryCacheID); + + geometryCache->renderLine(*batch, _start, _end, colorv4, _geometryCacheID); } } } const render::ShapeKey Line3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace(); + auto builder = render::ShapeKey::Builder().withOwnPipeline(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.cpp b/interface/src/ui/overlays/Rectangle3DOverlay.cpp index 5a541fd58a..75d7ec565c 100644 --- a/interface/src/ui/overlays/Rectangle3DOverlay.cpp +++ b/interface/src/ui/overlays/Rectangle3DOverlay.cpp @@ -53,13 +53,15 @@ void Rectangle3DOverlay::render(RenderArgs* args) { transform.setRotation(rotation); batch->setModelTransform(transform); + auto geometryCache = DependencyManager::get(); if (getIsSolid()) { glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, 0.0f); glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, 0.0f); - DependencyManager::get()->renderQuad(*batch, topLeft, bottomRight, rectangleColor); + geometryCache->bindSimpleProgram(*batch); + geometryCache->renderQuad(*batch, topLeft, bottomRight, rectangleColor); } else { - auto geometryCache = DependencyManager::get(); + geometryCache->bindSimpleProgram(*batch, false, false, true, true); if (getIsDashedLine()) { glm::vec3 point1(-halfDimensions.x, -halfDimensions.y, 0.0f); glm::vec3 point2(halfDimensions.x, -halfDimensions.y, 0.0f); @@ -89,7 +91,7 @@ void Rectangle3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Rectangle3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder(); + auto builder = render::ShapeKey::Builder().withOwnPipeline(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index d50f2f7285..1dd61611f2 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -46,7 +46,7 @@ void Sphere3DOverlay::render(RenderArgs* args) { auto geometryCache = DependencyManager::get(); auto pipeline = args->_pipeline; if (!pipeline) { - pipeline = geometryCache->getShapePipeline(); + pipeline = _isSolid ? geometryCache->getShapePipeline() : geometryCache->getWireShapePipeline(); } if (_isSolid) { @@ -58,7 +58,7 @@ void Sphere3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Sphere3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder(); + auto builder = render::ShapeKey::Builder().withOwnPipeline(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index f5baecd96a..c9c24d3ab6 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -100,7 +100,9 @@ void Web3DOverlay::render(RenderArgs* args) { } batch.setModelTransform(transform); - DependencyManager::get()->renderQuad(batch, halfSize * -1.0f, halfSize, vec2(0), vec2(1), color); + auto geometryCache = DependencyManager::get(); + geometryCache->bindSimpleProgram(batch, true, false, true, false); + geometryCache->renderQuad(batch, halfSize * -1.0f, halfSize, vec2(0), vec2(1), color); batch.setResourceTexture(0, args->_whiteTexture); // restore default white color after me } diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 1154f27ee0..9ea4bd9905 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -309,6 +309,7 @@ gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() { } render::ShapePipelinePointer GeometryCache::_simplePipeline; +render::ShapePipelinePointer GeometryCache::_simpleWirePipeline; GeometryCache::GeometryCache() : _nextID(0) @@ -324,6 +325,10 @@ GeometryCache::GeometryCache() : DependencyManager::get()->getNormalFittingTexture()); } ); + GeometryCache::_simpleWirePipeline = + std::make_shared(getSimplePipeline(false, false, true, true), nullptr, + [](const render::ShapePipeline&, gpu::Batch& batch) { } + ); } GeometryCache::~GeometryCache() { diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index c46a9bb084..9f18f1644c 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -157,7 +157,8 @@ public: gpu::PipelinePointer getSimplePipeline(bool textured = false, bool culled = true, bool unlit = false, bool depthBias = false); render::ShapePipelinePointer getShapePipeline() { return GeometryCache::_simplePipeline; } - + render::ShapePipelinePointer getWireShapePipeline() { return GeometryCache::_simpleWirePipeline; } + // Static (instanced) geometry void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer); void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer); @@ -179,7 +180,7 @@ public: void renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline = _simplePipeline); void renderWireSphereInstance(gpu::Batch& batch, const glm::vec3& color, - const render::ShapePipelinePointer& pipeline = _simplePipeline) { + const render::ShapePipelinePointer& pipeline = _simpleWirePipeline) { renderWireSphereInstance(batch, glm::vec4(color, 1.0f), pipeline); } @@ -193,7 +194,7 @@ public: void renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline = _simplePipeline); void renderWireCubeInstance(gpu::Batch& batch, const glm::vec3& color, - const render::ShapePipelinePointer& pipeline = _simplePipeline) { + const render::ShapePipelinePointer& pipeline = _simpleWirePipeline) { renderWireCubeInstance(batch, glm::vec4(color, 1.0f), pipeline); } @@ -401,6 +402,7 @@ private: gpu::ShaderPointer _simpleShader; gpu::ShaderPointer _unlitShader; static render::ShapePipelinePointer _simplePipeline; + static render::ShapePipelinePointer _simpleWirePipeline; QHash _simplePrograms; }; From 5288d983763ea57e4e1d33f37cc21384a82c5ba5 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 30 Jun 2016 20:52:41 -0700 Subject: [PATCH 10/10] Using pipelines properly where appropriate --- interface/src/ui/overlays/Circle3DOverlay.cpp | 8 ++++---- interface/src/ui/overlays/Cube3DOverlay.cpp | 6 ++++-- interface/src/ui/overlays/Grid3DOverlay.cpp | 6 ++---- interface/src/ui/overlays/Image3DOverlay.cpp | 6 ++---- interface/src/ui/overlays/Sphere3DOverlay.cpp | 3 +++ 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index 1abcb0f5c0..2896ce711e 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -149,7 +149,6 @@ void Circle3DOverlay::render(RenderArgs* args) { geometryCache->updateVertices(_quadVerticesID, points, color); } - geometryCache->bindSimpleProgram(batch); geometryCache->renderVertices(batch, gpu::TRIANGLES, _quadVerticesID); } else { @@ -188,8 +187,6 @@ void Circle3DOverlay::render(RenderArgs* args) { geometryCache->updateVertices(_lineVerticesID, points, color); } - // Render unlit - geometryCache->bindSimpleProgram(batch, false, false, true); if (getIsDashedLine()) { geometryCache->renderVertices(batch, gpu::LINES, _lineVerticesID); } else { @@ -282,10 +279,13 @@ void Circle3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Circle3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withOwnPipeline(); + auto builder = render::ShapeKey::Builder().withoutCullFace(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } + if (!getIsSolid()) { + builder.withUnlit().withDepthBias(); + } return builder.build(); } diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 17894aa091..f72fb8d920 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -44,7 +44,6 @@ void Cube3DOverlay::render(RenderArgs* args) { Transform transform; transform.setTranslation(position); transform.setRotation(rotation); - auto geometryCache = DependencyManager::get(); auto pipeline = args->_pipeline; if (!pipeline) { @@ -97,10 +96,13 @@ void Cube3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Cube3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withOwnPipeline(); + auto builder = render::ShapeKey::Builder(); if (getAlpha() != 1.0f) { builder.withTranslucent(); } + if (!getIsSolid()) { + builder.withUnlit().withDepthBias(); + } return builder.build(); } diff --git a/interface/src/ui/overlays/Grid3DOverlay.cpp b/interface/src/ui/overlays/Grid3DOverlay.cpp index 7d86395937..e9bbcddf59 100644 --- a/interface/src/ui/overlays/Grid3DOverlay.cpp +++ b/interface/src/ui/overlays/Grid3DOverlay.cpp @@ -75,11 +75,9 @@ void Grid3DOverlay::render(RenderArgs* args) { transform.setScale(glm::vec3(getDimensions(), 1.0f)); transform.setTranslation(position); batch->setModelTransform(transform); - auto geometryCache = DependencyManager::get(); - geometryCache->bindSimpleProgram(*batch, false, false, true, true); const float MINOR_GRID_EDGE = 0.0025f; const float MAJOR_GRID_EDGE = 0.005f; - geometryCache->renderGrid(*batch, minCorner, maxCorner, + DependencyManager::get()->renderGrid(*batch, minCorner, maxCorner, _minorGridRowDivisions, _minorGridColDivisions, MINOR_GRID_EDGE, _majorGridRowDivisions, _majorGridColDivisions, MAJOR_GRID_EDGE, gridColor, _drawInFront); @@ -87,7 +85,7 @@ void Grid3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Grid3DOverlay::getShapeKey() { - return render::ShapeKey::Builder().withOwnPipeline(); + return render::ShapeKey::Builder().withOwnPipeline().withUnlit().withDepthBias(); } void Grid3DOverlay::setProperties(const QVariantMap& properties) { diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index 72ae246859..d59e552779 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -93,9 +93,7 @@ void Image3DOverlay::render(RenderArgs* args) { batch->setModelTransform(transform); batch->setResourceTexture(0, _texture->getGPUTexture()); - auto geometryCache = DependencyManager::get(); - geometryCache->bindSimpleProgram(*batch, true, false); - geometryCache->renderQuad( + DependencyManager::get()->renderQuad( *batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, glm::vec4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha) ); @@ -104,7 +102,7 @@ void Image3DOverlay::render(RenderArgs* args) { } const render::ShapeKey Image3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withOwnPipeline(); + auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); if (_emissive) { builder.withUnlit(); } diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 1dd61611f2..85530d1376 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -62,6 +62,9 @@ const render::ShapeKey Sphere3DOverlay::getShapeKey() { if (getAlpha() != 1.0f) { builder.withTranslucent(); } + if (!getIsSolid()) { + builder.withUnlit().withDepthBias(); + } return builder.build(); }