diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index aaaa7c5962..ac903190c4 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -181,9 +181,9 @@ var COLLIDES_WITH_WHILE_MULTI_GRABBED = "dynamic"; var HEART_BEAT_INTERVAL = 5 * MSECS_PER_SEC; var HEART_BEAT_TIMEOUT = 15 * MSECS_PER_SEC; -var avCollideLater; -var setCollidesLaterTimeout; -var collideLaterID; +var delayedDeactivateFunc; +var delayedDeactivateTimeout; +var delayedDeactivateEntityID; var CONTROLLER_STATE_MACHINE = {}; @@ -2064,15 +2064,15 @@ function MyController(hand) { } this.entityActivated = true; - if (setCollidesLaterTimeout && collideLaterID == entityID) { + if (delayedDeactivateTimeout && delayedDeactivateEntityID == entityID) { // we have a timeout waiting to set collisions with myAvatar back on (so that when something // is thrown it doesn't collide with the avatar's capsule the moment it's released). We've // regrabbed the entity before the timeout fired, so cancel the timeout, run the function now // and adjust the grabbedProperties. This will make the saved set of properties (the ones that // get re-instated after all the grabs have been released) be correct. - Script.clearTimeout(setCollidesLaterTimeout); - setCollidesLaterTimeout = null; - grabbedProperties["collidesWith"] = avCollideLater(); + Script.clearTimeout(delayedDeactivateTimeout); + delayedDeactivateTimeout = null; + grabbedProperties["collidesWith"] = delayedDeactivateFunc(); } var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); @@ -2142,7 +2142,27 @@ function MyController(hand) { }); }; - this.deactivateEntity = function (entityID, noVelocity) { + this.delayedDeactivateEntity = function (entityID, collidesWith) { + // If, before the grab started, the held entity collided with myAvatar, we do the deactivation in + // two parts. Most of it is done in deactivateEntity(), but the final collidesWith and refcount + // are delayed a bit. This keeps thrown things from colliding with the avatar's capsule so often. + // The refcount is handled in this delayed fashion so things don't get confused if someone else + // grabs the entity before the timeout fires. + Entities.editEntity(entityID, { collidesWith: collidesWith }); + var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); + if (data && data["refCount"]) { + data["refCount"] = data["refCount"] - 1; + if (data["refCount"] < 1) { + data = null; + } + } else { + data = null; + } + + setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); + }; + + this.deactivateEntity = function (entityID, noVelocity, delayed) { var deactiveProps; if (!this.entityActivated) { @@ -2151,12 +2171,13 @@ function MyController(hand) { this.entityActivated = false; var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); + var doDelayedDeactivate = false; if (data && data["refCount"]) { data["refCount"] = data["refCount"] - 1; if (data["refCount"] < 1) { deactiveProps = { gravity: data["gravity"], - // don't set collidesWith back right away, because thrown things tend to bounce off the + // don't set collidesWith myAvatar back right away, because thrown things tend to bounce off the // avatar's capsule. collidesWith: removeMyAvatarFromCollidesWith(data["collidesWith"]), collisionless: data["collisionless"], @@ -2165,17 +2186,20 @@ function MyController(hand) { parentJointIndex: data["parentJointIndex"] }; - if (data["collidesWith"].indexOf("myAvatar") >= 0) { - var javaScriptScopingIsBrokenData = data; - avCollideLater = function () { + doDelayedDeactivate = (data["collidesWith"].indexOf("myAvatar") >= 0); + + if (doDelayedDeactivate) { + var delayedCollidesWith = data["collidesWith"]; + var delayedEntityID = entityID; + delayedDeactivateFunc = function () { // set collidesWith back to original value a bit later than the rest - _this.setCollidesLaterTimeout = null; - Entities.editEntity(entityID, { collidesWith: javaScriptScopingIsBrokenData["collidesWith"] }); - return javaScriptScopingIsBrokenData["collidesWith"]; + delayedDeactivateTimeout = null; + _this.delayedDeactivateEntity(delayedEntityID, delayedCollidesWith); + return delayedCollidesWith; } - setCollidesLaterTimeout = - Script.setTimeout(avCollideLater, COLLIDE_WITH_AV_AFTER_RELEASE_DELAY * MSECS_PER_SEC); - collideLaterID = entityID; + delayedDeactivateTimeout = + Script.setTimeout(delayedDeactivateFunc, COLLIDE_WITH_AV_AFTER_RELEASE_DELAY * MSECS_PER_SEC); + delayedDeactivateEntityID = entityID; } // things that are held by parenting and dropped with no velocity will end up as "static" in bullet. If @@ -2220,7 +2244,6 @@ function MyController(hand) { // angularVelocity: this.currentAngularVelocity }); } - data = null; } else if (this.shouldResetParentOnRelease) { // we parent-grabbed this from another parent grab. try to put it back where we found it. @@ -2239,7 +2262,9 @@ function MyController(hand) { } else { data = null; } - setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); + if (!doDelayedDeactivate) { + setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); + } }; this.getOtherHandController = function () {