From b062d23f612e780abee293bf5483d53a2b5ade33 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 17 Nov 2015 09:51:52 -0800 Subject: [PATCH] bumper is now an equip toggle --- examples/controllers/handControllerGrab.js | 103 ++++++++++++++++++--- examples/libraries/utils.js | 10 +- libraries/entities/src/EntityTree.cpp | 8 ++ 3 files changed, 105 insertions(+), 16 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index d308b3dc49..c50a1418bd 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -28,6 +28,8 @@ var TRIGGER_SMOOTH_RATIO = 0.1; // 0.0 disables smoothing of trigger value var TRIGGER_ON_VALUE = 0.4; var TRIGGER_OFF_VALUE = 0.15; +var BUMPER_ON_VALUE = 0.5; + // // distant manipulation // @@ -106,6 +108,11 @@ var STATE_CONTINUE_NEAR_TRIGGER = 7; var STATE_FAR_TRIGGER = 8; var STATE_CONTINUE_FAR_TRIGGER = 9; var STATE_RELEASE = 10; +var STATE_EQUIP_SEARCHING = 11; +var STATE_EQUIP = 12 +var STATE_CONTINUE_EQUIP_BD = 13; // equip while bumper is still held down +var STATE_CONTINUE_EQUIP = 14; +var STATE_WAITING_FOR_BUMPER_RELEASE = 15; function stateToName(state) { @@ -132,6 +139,16 @@ function stateToName(state) { return "continue_far_trigger"; case STATE_RELEASE: return "release"; + case STATE_EQUIP_SEARCHING: + return "equip_searching"; + case STATE_EQUIP: + return "equip"; + case STATE_CONTINUE_EQUIP_BD: + return "continue_equip_bd"; + case STATE_CONTINUE_EQUIP: + return "continue_equip"; + case STATE_WAITING_FOR_BUMPER_RELEASE: + return "waiting_for_bumper_release"; } return "unknown"; @@ -182,6 +199,7 @@ function MyController(hand) { this.pointer = null; // entity-id of line object this.triggerValue = 0; // rolling average of trigger value this.rawTriggerValue = 0; + this.rawBumperValue = 0; this.offsetPosition = { x: 0.0, y: 0.0, z: 0.0 }; this.offsetRotation = { x: 0.0, y: 0.0, z: 0.0, w: 1.0 }; @@ -200,6 +218,9 @@ function MyController(hand) { case STATE_SEARCHING: this.search(); break; + case STATE_EQUIP_SEARCHING: + this.search(); + break; case STATE_DISTANCE_HOLDING: this.distanceHolding(); break; @@ -209,7 +230,15 @@ function MyController(hand) { case STATE_NEAR_GRABBING: this.nearGrabbing(); break; + case STATE_EQUIP: + this.nearGrabbing(); + break; + case STATE_WAITING_FOR_BUMPER_RELEASE: + this.waitingForBumperRelease(); + break; case STATE_CONTINUE_NEAR_GRABBING: + case STATE_CONTINUE_EQUIP_BD: + case STATE_CONTINUE_EQUIP: this.continueNearGrabbing(); break; case STATE_NEAR_TRIGGER: @@ -281,10 +310,15 @@ function MyController(hand) { this.pointer = null; }; - this.eitherTrigger = function (value) { + this.triggerPress = function (value) { _this.rawTriggerValue = value; }; + this.bumperPress = function (value) { + _this.rawBumperValue = value; + }; + + this.updateSmoothedTrigger = function () { var triggerValue = this.rawTriggerValue; // smooth out trigger value @@ -305,23 +339,37 @@ function MyController(hand) { return triggerValue > TRIGGER_ON_VALUE; }; + this.bumperSqueezed = function() { + return _this.rawBumperValue > BUMPER_ON_VALUE; + } + + this.bumperReleased = function() { + return _this.rawBumperValue < BUMPER_ON_VALUE; + } + + this.off = function() { if (this.triggerSmoothedSqueezed()) { this.lastPickTime = 0; this.setState(STATE_SEARCHING); return; } + if (this.bumperSqueezed()) { + this.lastPickTime = 0; + this.setState(STATE_EQUIP_SEARCHING); + return; + } } this.search = function() { this.grabbedEntity = null; - //if this hand is the one that's disabled, we don't want to search for anything at all + // if this hand is the one that's disabled, we don't want to search for anything at all if (this.hand === disabledHand) { return; } - if (this.triggerSmoothedReleased()) { + if (this.state == STATE_SEARCHING ? this.triggerSmoothedReleased() : this.bumperReleased()) { this.setState(STATE_RELEASE); return; } @@ -398,7 +446,7 @@ function MyController(hand) { return; } else if (!intersection.properties.locked) { this.grabbedEntity = intersection.entityID; - this.setState(STATE_NEAR_GRABBING); + this.setState(this.state == STATE_SEARCHING ? STATE_NEAR_GRABBING : STATE_EQUIP) return; } } else if (! entityIsGrabbedByOther(intersection.entityID)) { @@ -407,8 +455,14 @@ function MyController(hand) { && !intersection.properties.locked) { // the hand is far from the intersected object. go into distance-holding mode this.grabbedEntity = intersection.entityID; - this.setState(STATE_DISTANCE_HOLDING); - return; + if (typeof grabbableData.spatialKey !== 'undefined' && this.state == STATE_EQUIP_SEARCHING) { + // if a distance pick in equip mode hits something with a spatialKey, equip it + this.setState(STATE_EQUIP); + return; + } else if (this.state == STATE_SEARCHING) { + this.setState(STATE_DISTANCE_HOLDING); + return; + } } else if (grabbableData.wantsTrigger) { this.grabbedEntity = intersection.entityID; this.setState(STATE_FAR_TRIGGER); @@ -434,6 +488,7 @@ function MyController(hand) { var nearbyEntities = Entities.findEntities(handPosition, GRAB_RADIUS); var minDistance = PICK_MAX_DISTANCE; var i, props, distance, grabbableData; + this.grabbedEntity = null; for (i = 0; i < nearbyEntities.length; i++) { var grabbableDataForCandidate = getEntityCustomData(GRABBABLE_DATA_KEY, nearbyEntities[i], DEFAULT_GRABBABLE_DATA); @@ -490,7 +545,7 @@ function MyController(hand) { this.setState(STATE_NEAR_TRIGGER); return; } else if (!props.locked && props.collisionsWillMove) { - this.setState(STATE_NEAR_GRABBING); + this.setState(this.state == STATE_SEARCHING ? STATE_NEAR_GRABBING : STATE_EQUIP) return; } }; @@ -634,13 +689,12 @@ function MyController(hand) { return; } - if (this.triggerSmoothedReleased()) { + if (this.state == STATE_NEAR_GRABBING && this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); return; } - this.lineOff(); var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES); @@ -686,7 +740,7 @@ function MyController(hand) { this.actionID = null; } else { this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC); - this.setState(STATE_CONTINUE_NEAR_GRABBING); + this.setState(this.state == STATE_NEAR_GRABBING ? STATE_CONTINUE_NEAR_GRABBING : STATE_CONTINUE_EQUIP_BD) if (this.hand === RIGHT_HAND) { Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); } else { @@ -696,17 +750,26 @@ function MyController(hand) { } - this.currentHandControllerTipPosition = (this.hand === RIGHT_HAND) ? MyAvatar.rightHandTipPosition : MyAvatar.leftHandTipPosition;; + this.currentHandControllerTipPosition = + (this.hand === RIGHT_HAND) ? MyAvatar.rightHandTipPosition : MyAvatar.leftHandTipPosition; this.currentObjectTime = Date.now(); }; this.continueNearGrabbing = function() { - if (this.triggerSmoothedReleased()) { + if (this.state == STATE_CONTINUE_NEAR_GRABBING && this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); return; } + if (this.state == STATE_CONTINUE_EQUIP_BD && this.bumperReleased()) { + this.setState(STATE_CONTINUE_EQUIP); + return; + } + if (this.state == STATE_CONTINUE_EQUIP && this.bumperSqueezed()) { + this.setState(STATE_WAITING_FOR_BUMPER_RELEASE); + return; + } // Keep track of the fingertip velocity to impart when we release the object. // Note that the idea of using a constant 'tip' velocity regardless of the @@ -740,6 +803,13 @@ function MyController(hand) { } }; + this.waitingForBumperRelease = function() { + if (this.bumperReleased()) { + this.setState(STATE_RELEASE); + Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); + } + } + this.nearTrigger = function() { if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); @@ -919,6 +989,7 @@ function MyController(hand) { } Entities.editEntity(entityID, whileHeldProperties); } + setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); return data; }; @@ -948,8 +1019,12 @@ var leftController = new MyController(LEFT_HAND); var MAPPING_NAME = "com.highfidelity.handControllerGrab"; var mapping = Controller.newMapping(MAPPING_NAME); -mapping.from([Controller.Standard.RB, Controller.Standard.RT]).peek().to(rightController.eitherTrigger); -mapping.from([Controller.Standard.LB, Controller.Standard.LT]).peek().to(leftController.eitherTrigger); +mapping.from([Controller.Standard.RT]).peek().to(rightController.triggerPress); +mapping.from([Controller.Standard.LT]).peek().to(leftController.triggerPress); + +mapping.from([Controller.Standard.RB]).peek().to(rightController.bumperPress); +mapping.from([Controller.Standard.LB]).peek().to(leftController.bumperPress); + Controller.enableMapping(MAPPING_NAME); diff --git a/examples/libraries/utils.js b/examples/libraries/utils.js index 25900471c1..5d14bfb7dd 100644 --- a/examples/libraries/utils.js +++ b/examples/libraries/utils.js @@ -11,6 +11,12 @@ vec3toStr = function(v, digits) { return "{ " + v.x.toFixed(digits) + ", " + v.y.toFixed(digits) + ", " + v.z.toFixed(digits)+ " }"; } +quatToStr = function(q, digits) { + if (!digits) { digits = 3; } + return "{ " + q.w.toFixed(digits) + ", " + q.x.toFixed(digits) + ", " + + q.y.toFixed(digits) + ", " + q.z.toFixed(digits)+ " }"; +} + vec3equal = function(v0, v1) { return (v0.x == v1.x) && (v0.y == v1.y) && (v0.z == v1.z); } @@ -51,7 +57,7 @@ addLine = function(origin, vector, color) { // FIXME fetch from a subkey of user data to support non-destructive modifications setEntityUserData = function(id, data) { var json = JSON.stringify(data) - Entities.editEntity(id, { userData: json }); + Entities.editEntity(id, { userData: json }); } // FIXME do non-destructive modification of the existing user data @@ -60,7 +66,7 @@ getEntityUserData = function(id) { var properties = Entities.getEntityProperties(id, "userData"); if (properties.userData) { try { - results = JSON.parse(properties.userData); + results = JSON.parse(properties.userData); } catch(err) { logDebug(err); logDebug(properties.userData); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 027972549a..dc7c19056a 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -704,6 +704,14 @@ void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList= 0) { + QString changeHint = properties.getUserData(); + changedProperties[index] = QString("userData:") + changeHint; + } + } } int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* editData, int maxLength,