diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index 14a86510c2..d46724184c 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -14,7 +14,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global MyAvatar, Entities, Script, Camera, Vec3, Reticle, Overlays, getEntityCustomData, Messages, Quat, Controller */ +/* global MyAvatar, Entities, Script, Camera, Vec3, Reticle, Overlays, getEntityCustomData, Messages, Quat, Controller, + isInEditMode, HMD */ (function() { // BEGIN LOCAL_SCOPE @@ -22,6 +23,8 @@ Script.include("/~/system/libraries/utils.js"); var MAX_SOLID_ANGLE = 0.01; // objects that appear smaller than this can't be grabbed +var DELAY_FOR_30HZ = 33; // milliseconds + var ZERO_VEC3 = { x: 0, y: 0, @@ -46,7 +49,7 @@ var ACTION_TTL = 10; // seconds function getTag() { return "grab-" + MyAvatar.sessionUUID; } - + var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position var DISTANCE_HOLDING_UNITY_MASS = 1200; // The mass at which the distance holding action timeframe is unmodified var DISTANCE_HOLDING_UNITY_DISTANCE = 6; // The distance at which the distance holding action timeframe is unmodified @@ -411,10 +414,15 @@ Grabber.prototype.pressEvent = function(event) { }; Grabber.prototype.releaseEvent = function(event) { - if (event.isLeftButton!==true ||event.isRightButton===true || event.isMiddleButton===true) { + if (event.isLeftButton!==true || event.isRightButton===true || event.isMiddleButton===true) { return; } + if (this.moveEventTimer) { + Script.clearTimeout(this.moveEventTimer); + this.moveEventTimer = null; + } + if (this.isGrabbing) { // this.deactivateEntity(this.entityID); this.isGrabbing = false; @@ -440,11 +448,23 @@ Grabber.prototype.releaseEvent = function(event) { }; Grabber.prototype.moveEvent = function(event) { + // during the handling of the event, do as little as possible. We save the updated mouse position, + // and start a timer to react to the change. If more changes arrive before the timer fires, only + // the last update will be considered. This is done to avoid backing-up Qt's event queue. if (!this.isGrabbing) { return; } mouse.updateDrag(event); + var _this = this; + if (!this.moveEventTimer) { + this.moveEventTimer = Script.setTimeout(function() { + _this.moveEventProcess(); + } , DELAY_FOR_30HZ); + } +}; + +Grabber.prototype.moveEventProcess = function() { // see if something added/restored gravity var entityProperties = Entities.getEntityProperties(this.entityID); if (!entityProperties || !entityProperties.gravity) { @@ -489,7 +509,7 @@ Grabber.prototype.moveEvent = function(event) { } else { var newPointOnPlane; - + if (this.mode === "verticalCylinder") { // for this mode we recompute the plane based on current Camera var planeNormal = Quat.getForward(Camera.getOrientation()); @@ -505,7 +525,7 @@ Grabber.prototype.moveEvent = function(event) { }; } else { - + newPointOnPlane = mouseIntersectionWithPlane( this.pointOnPlane, this.planeNormal, mouse.current, this.maxDistance); var relativePosition = Vec3.subtract(newPointOnPlane, cameraPosition); @@ -538,6 +558,11 @@ Grabber.prototype.moveEvent = function(event) { } else { Entities.updateAction(this.entityID, this.actionID, actionArgs); } + + var _this = this; + this.moveEventTimer = Script.setTimeout(function() { + _this.moveEventProcess(); + }, DELAY_FOR_30HZ); }; Grabber.prototype.keyReleaseEvent = function(event) {