From 91db29e92f6e445c6f6ba98fea427e15e26df056 Mon Sep 17 00:00:00 2001 From: Mike Moody Date: Fri, 2 Jun 2017 15:34:25 -0700 Subject: [PATCH 01/27] laser initial commit --- .../marketplace/laser/laser-a.svg | 107 ++++++++ .../marketplace/laser/laser.svg | 106 ++++++++ .../marketplace/laser/laserPointerApp.js | 237 ++++++++++++++++++ 3 files changed, 450 insertions(+) create mode 100644 unpublishedScripts/marketplace/laser/laser-a.svg create mode 100644 unpublishedScripts/marketplace/laser/laser.svg create mode 100644 unpublishedScripts/marketplace/laser/laserPointerApp.js diff --git a/unpublishedScripts/marketplace/laser/laser-a.svg b/unpublishedScripts/marketplace/laser/laser-a.svg new file mode 100644 index 0000000000..74033b3e7a --- /dev/null +++ b/unpublishedScripts/marketplace/laser/laser-a.svg @@ -0,0 +1,107 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/unpublishedScripts/marketplace/laser/laser.svg b/unpublishedScripts/marketplace/laser/laser.svg new file mode 100644 index 0000000000..a1f8887e90 --- /dev/null +++ b/unpublishedScripts/marketplace/laser/laser.svg @@ -0,0 +1,106 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/unpublishedScripts/marketplace/laser/laserPointerApp.js b/unpublishedScripts/marketplace/laser/laserPointerApp.js new file mode 100644 index 0000000000..e77f7fae67 --- /dev/null +++ b/unpublishedScripts/marketplace/laser/laserPointerApp.js @@ -0,0 +1,237 @@ +'use strict'; + +(function () { + Script.include("/~/system/libraries/controllers.js"); + + var APP_NAME = 'LASER', + APP_ICON = 'https://binaryrelay.com/files/public-docs/hifi/laser/laser.svg', + APP_ICON_ACTIVE = 'https://binaryrelay.com/files/public-docs/hifi/laser/laser-a.svg'; + + + var POINT_INDEX_CHANNEL = "Hifi-Point-Index", + GRAB_DISABLE_CHANNEL = "Hifi-Grab-Disable", + POINTER_DISABLE_CHANNEL = "Hifi-Pointer-Disable"; + + var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system'); + + var button = tablet.addButton({ + icon: APP_ICON, + activeIcon: APP_ICON_ACTIVE, + text: APP_NAME + }); + + var laserEntities = { + left: { + beam: null, + sphere: null + }, + right: { + beam: null, + sphere: null + } + + }; + var rayExclusionList = []; + + + function laser(hand) { + + var PICK_MAX_DISTANCE = 500; + + var isNewEntityNeeded = (laserEntities[hand].beam === null); + + var _hand = hand === 'right' ? Controller.Standard.RightHand : Controller.Standard.LeftHand; + var _joint = hand === 'right' ? 'RightHand' : 'LeftHand'; //'RightHandIndex4' : 'LeftHandIndex4' + var controllerLocation = getControllerWorldLocation(_hand, true); + + var worldHandRotation = controllerLocation.orientation; + + var pickRay = { + origin: MyAvatar.getJointPosition(_joint), + direction: Quat.getUp(worldHandRotation), + length: PICK_MAX_DISTANCE + }; + + + var ray = Entities.findRayIntersection(pickRay, true, [], rayExclusionList, true); + var avatarRay = AvatarManager.findRayIntersection(pickRay, true, [], rayExclusionList, true); + + var dist = PICK_MAX_DISTANCE; + var intersection = null; + + if (avatarRay.intersects) { + intersection = avatarRay.intersection; + dist = Vec3.distance(pickRay.origin, avatarRay.intersection); + } else if (ray.intersects) { + intersection = ray.intersection; + dist = Vec3.distance(pickRay.origin, ray.intersection); + } + + if (!ray.intersects && !avatarRay.intersects && laserEntities[hand].sphere !== null) { + Entities.editEntity(laserEntities[hand].sphere, { + visible: false + }); + } else { + Entities.editEntity(laserEntities[hand].sphere, { + visible: true + }); + } + + var sphereSize = dist * 0.01; + + if (isNewEntityNeeded) { + + var sphere = { + lifetime: 360, + type: 'Shape', + shape: 'circle3d', + dimensions: {x: sphereSize, y: sphereSize, z: sphereSize}, + color: {red: 0, green: 255, blue: 0}, + position: intersection, + collisionless: true + + }; + + var beam = { + lifetime: 360, + type: 'Line', + glow: 1.0, + lineWidth: 5, + alpha: 0.5, + ignoreRayIntersection: true, + drawInFront: true, + color: {red: 0, green: 255, blue: 0}, + parentID: MyAvatar.sessionUUID, + parentJointIndex: MyAvatar.getJointIndex(_joint), + localPosition: {x: 0, y: .2, z: 0}, + localRotation: Quat.normalize({}), + dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), + linePoints: [Vec3.ZERO, {x: 0, y: dist, z: 0}] + }; + + + laserEntities[hand].beam = Entities.addEntity(beam); + rayExclusionList.push(laserEntities[hand].beam); + + if (ray.intersects || avatarRay.intersects) { + laserEntities[hand].sphere = Entities.addEntity(sphere); + rayExclusionList.push(laserEntities[hand].sphere); + } + + } else { + if (ray.intersects || avatarRay.intersects) { + + Entities.editEntity(laserEntities[hand].beam, { + parentID: MyAvatar.sessionUUID, + parentJointIndex: MyAvatar.getJointIndex(_joint), + localPosition: {x: 0, y: .2, z: 0}, + localRotation: Quat.normalize({}), + dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), + linePoints: [Vec3.ZERO, {x: 0, y: dist, z: 0}] + }); + + Entities.editEntity(laserEntities[hand].sphere, { + dimensions: {x: sphereSize, y: sphereSize, z: sphereSize}, + position: intersection + + }); + } else { + Entities.editEntity(laserEntities[hand].beam, { + parentID: MyAvatar.sessionUUID, + parentJointIndex: MyAvatar.getJointIndex(_joint), + localPosition: {x: 0, y: .2, z: 0}, + localRotation: Quat.normalize({}), + dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), + linePoints: [Vec3.ZERO, {x: 0, y: dist, z: 0}] + }); + } + + } + + } + + function triggerWatcher(deltaTime) { + + var deleteBeamLeft = true, + deleteBeamRight = true; + + if (Controller.getValue(Controller.Standard.LT) > .95) { + deleteBeamLeft = false; + laser('left', deltaTime); + } + + if (Controller.getValue(Controller.Standard.RT) > .95) { + deleteBeamRight = false; + laser('right', deltaTime); + } + + if (deleteBeamLeft && laserEntities.left.beam !== null) { + Entities.deleteEntity(laserEntities.left.beam); + Entities.deleteEntity(laserEntities.left.sphere); + + laserEntities.left.beam = null; + laserEntities.left.sphere = null; + + } + if (deleteBeamRight && laserEntities.right.beam !== null) { + Entities.deleteEntity(laserEntities.right.beam); + Entities.deleteEntity(laserEntities.right.sphere); + + laserEntities.right.beam = null; + laserEntities.right.sphere = null; + + } + if (deleteBeamRight && laserEntities.right.beam !== null && deleteBeamLeft && laserEntities.left.beam !== null) { + rayExclusionList = []; + } + } + + function selectionBeamSwitch(bool) { + Messages.sendMessage(GRAB_DISABLE_CHANNEL, JSON.stringify({ + holdEnabled: bool, + nearGrabEnabled: bool, + farGrabEnabled: bool + }), true); + Messages.sendMessage(POINTER_DISABLE_CHANNEL, JSON.stringify({ + pointerEnabled: bool + }), true); + Messages.sendMessage(POINT_INDEX_CHANNEL, JSON.stringify({ + pointIndex: !bool + }), true); + } + + var _switch = true; + + function bSwitch() { + if (_switch) { + Script.update.connect(triggerWatcher); + Messages.subscribe(POINT_INDEX_CHANNEL); + Messages.subscribe(GRAB_DISABLE_CHANNEL); + Messages.subscribe(POINTER_DISABLE_CHANNEL); + } else { + Script.update.disconnect(triggerWatcher); + Messages.unsubscribe(POINT_INDEX_CHANNEL); + Messages.unsubscribe(GRAB_DISABLE_CHANNEL); + Messages.unsubscribe(POINTER_DISABLE_CHANNEL); + } + button.editProperties({isActive: _switch}); + + selectionBeamSwitch(!_switch); + + _switch = !_switch; + } + + button.clicked.connect(bSwitch); + + function clean() { + tablet.removeButton(button); + Script.update.disconnect(triggerWatcher); + + Messages.unsubscribe(POINT_INDEX_CHANNEL); + Messages.unsubscribe(GRAB_DISABLE_CHANNEL); + Messages.unsubscribe(POINTER_DISABLE_CHANNEL); + rayExclusionList = []; + } + + Script.scriptEnding.connect(clean); +}()); \ No newline at end of file From fb869034f2ce8a39e68c6495d4ece469f34346d2 Mon Sep 17 00:00:00 2001 From: Mike Moody Date: Sun, 4 Jun 2017 21:05:30 -0700 Subject: [PATCH 02/27] fixing magic numbers changing to local entity making var names more friendly --- .../marketplace/laser/laserPointerApp.js | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/unpublishedScripts/marketplace/laser/laserPointerApp.js b/unpublishedScripts/marketplace/laser/laserPointerApp.js index e77f7fae67..1180278103 100644 --- a/unpublishedScripts/marketplace/laser/laserPointerApp.js +++ b/unpublishedScripts/marketplace/laser/laserPointerApp.js @@ -7,11 +7,12 @@ APP_ICON = 'https://binaryrelay.com/files/public-docs/hifi/laser/laser.svg', APP_ICON_ACTIVE = 'https://binaryrelay.com/files/public-docs/hifi/laser/laser-a.svg'; - var POINT_INDEX_CHANNEL = "Hifi-Point-Index", GRAB_DISABLE_CHANNEL = "Hifi-Grab-Disable", POINTER_DISABLE_CHANNEL = "Hifi-Pointer-Disable"; + var TRIGGER_PRESSURE = 0.95; + var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system'); var button = tablet.addButton({ @@ -29,8 +30,8 @@ beam: null, sphere: null } - }; + var rayExclusionList = []; @@ -40,14 +41,14 @@ var isNewEntityNeeded = (laserEntities[hand].beam === null); - var _hand = hand === 'right' ? Controller.Standard.RightHand : Controller.Standard.LeftHand; - var _joint = hand === 'right' ? 'RightHand' : 'LeftHand'; //'RightHandIndex4' : 'LeftHandIndex4' - var controllerLocation = getControllerWorldLocation(_hand, true); + var currentHand = hand === 'right' ? Controller.Standard.RightHand : Controller.Standard.LeftHand; + var jointName = hand === 'right' ? 'RightHand' : 'LeftHand'; //'RightHandIndex4' : 'LeftHandIndex4' + var controllerLocation = getControllerWorldLocation(currentHand, true); var worldHandRotation = controllerLocation.orientation; var pickRay = { - origin: MyAvatar.getJointPosition(_joint), + origin: MyAvatar.getJointPosition(jointName), direction: Quat.getUp(worldHandRotation), length: PICK_MAX_DISTANCE }; @@ -83,8 +84,7 @@ var sphere = { lifetime: 360, - type: 'Shape', - shape: 'circle3d', + type: 'Sphere', dimensions: {x: sphereSize, y: sphereSize, z: sphereSize}, color: {red: 0, green: 255, blue: 0}, position: intersection, @@ -102,7 +102,7 @@ drawInFront: true, color: {red: 0, green: 255, blue: 0}, parentID: MyAvatar.sessionUUID, - parentJointIndex: MyAvatar.getJointIndex(_joint), + parentJointIndex: MyAvatar.getJointIndex(jointName), localPosition: {x: 0, y: .2, z: 0}, localRotation: Quat.normalize({}), dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), @@ -110,11 +110,11 @@ }; - laserEntities[hand].beam = Entities.addEntity(beam); + laserEntities[hand].beam = Entities.addEntity(beam,true); rayExclusionList.push(laserEntities[hand].beam); if (ray.intersects || avatarRay.intersects) { - laserEntities[hand].sphere = Entities.addEntity(sphere); + laserEntities[hand].sphere = Entities.addEntity(sphere,true); rayExclusionList.push(laserEntities[hand].sphere); } @@ -123,7 +123,7 @@ Entities.editEntity(laserEntities[hand].beam, { parentID: MyAvatar.sessionUUID, - parentJointIndex: MyAvatar.getJointIndex(_joint), + parentJointIndex: MyAvatar.getJointIndex(jointName), localPosition: {x: 0, y: .2, z: 0}, localRotation: Quat.normalize({}), dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), @@ -138,7 +138,7 @@ } else { Entities.editEntity(laserEntities[hand].beam, { parentID: MyAvatar.sessionUUID, - parentJointIndex: MyAvatar.getJointIndex(_joint), + parentJointIndex: MyAvatar.getJointIndex(jointName), localPosition: {x: 0, y: .2, z: 0}, localRotation: Quat.normalize({}), dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), @@ -155,14 +155,14 @@ var deleteBeamLeft = true, deleteBeamRight = true; - if (Controller.getValue(Controller.Standard.LT) > .95) { + if (Controller.getValue(Controller.Standard.LT) > TRIGGER_PRESSURE) { deleteBeamLeft = false; - laser('left', deltaTime); + laser('left'); } - if (Controller.getValue(Controller.Standard.RT) > .95) { + if (Controller.getValue(Controller.Standard.RT) > TRIGGER_PRESSURE) { deleteBeamRight = false; - laser('right', deltaTime); + laser('right'); } if (deleteBeamLeft && laserEntities.left.beam !== null) { @@ -181,7 +181,7 @@ laserEntities.right.sphere = null; } - if (deleteBeamRight && laserEntities.right.beam !== null && deleteBeamLeft && laserEntities.left.beam !== null) { + if (deleteBeamRight && deleteBeamLeft) { rayExclusionList = []; } } @@ -202,7 +202,7 @@ var _switch = true; - function bSwitch() { + function buttonSwitch() { if (_switch) { Script.update.connect(triggerWatcher); Messages.subscribe(POINT_INDEX_CHANNEL); @@ -221,7 +221,7 @@ _switch = !_switch; } - button.clicked.connect(bSwitch); + button.clicked.connect(buttonSwitch); function clean() { tablet.removeButton(button); From 9f669748f43bae51201f21faa08b83f89dc578c2 Mon Sep 17 00:00:00 2001 From: Mike Moody Date: Sun, 4 Jun 2017 21:34:56 -0700 Subject: [PATCH 03/27] header and cleanup. --- unpublishedScripts/marketplace/laser/laserPointerApp.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/unpublishedScripts/marketplace/laser/laserPointerApp.js b/unpublishedScripts/marketplace/laser/laserPointerApp.js index 1180278103..7c8e606658 100644 --- a/unpublishedScripts/marketplace/laser/laserPointerApp.js +++ b/unpublishedScripts/marketplace/laser/laserPointerApp.js @@ -1,3 +1,7 @@ +// +// Created by Alan-Michael Moody on 6/4/2017 +// + 'use strict'; (function () { @@ -34,7 +38,6 @@ var rayExclusionList = []; - function laser(hand) { var PICK_MAX_DISTANCE = 500; @@ -53,7 +56,6 @@ length: PICK_MAX_DISTANCE }; - var ray = Entities.findRayIntersection(pickRay, true, [], rayExclusionList, true); var avatarRay = AvatarManager.findRayIntersection(pickRay, true, [], rayExclusionList, true); @@ -109,7 +111,6 @@ linePoints: [Vec3.ZERO, {x: 0, y: dist, z: 0}] }; - laserEntities[hand].beam = Entities.addEntity(beam,true); rayExclusionList.push(laserEntities[hand].beam); From 6e34971889ca52c72766101028fd664d571731a9 Mon Sep 17 00:00:00 2001 From: Mike Moody Date: Wed, 21 Jun 2017 20:43:16 -0700 Subject: [PATCH 04/27] Changed to use with Index finger and minor cleanup. --- .../marketplace/laser/laserPointerApp.js | 42 ++++++++----------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/unpublishedScripts/marketplace/laser/laserPointerApp.js b/unpublishedScripts/marketplace/laser/laserPointerApp.js index 7c8e606658..e048d4126a 100644 --- a/unpublishedScripts/marketplace/laser/laserPointerApp.js +++ b/unpublishedScripts/marketplace/laser/laserPointerApp.js @@ -44,15 +44,11 @@ var isNewEntityNeeded = (laserEntities[hand].beam === null); - var currentHand = hand === 'right' ? Controller.Standard.RightHand : Controller.Standard.LeftHand; - var jointName = hand === 'right' ? 'RightHand' : 'LeftHand'; //'RightHandIndex4' : 'LeftHandIndex4' - var controllerLocation = getControllerWorldLocation(currentHand, true); - - var worldHandRotation = controllerLocation.orientation; + var jointName = hand === 'right' ? 'RightHandIndex4' : 'LeftHandIndex4'; //'RightHand' : 'LeftHand'; var pickRay = { origin: MyAvatar.getJointPosition(jointName), - direction: Quat.getUp(worldHandRotation), + direction: MyAvatar.jointToWorldDirection(Vec3.UP, MyAvatar.getJointIndex(jointName)), length: PICK_MAX_DISTANCE }; @@ -70,16 +66,6 @@ dist = Vec3.distance(pickRay.origin, ray.intersection); } - if (!ray.intersects && !avatarRay.intersects && laserEntities[hand].sphere !== null) { - Entities.editEntity(laserEntities[hand].sphere, { - visible: false - }); - } else { - Entities.editEntity(laserEntities[hand].sphere, { - visible: true - }); - } - var sphereSize = dist * 0.01; if (isNewEntityNeeded) { @@ -90,8 +76,8 @@ dimensions: {x: sphereSize, y: sphereSize, z: sphereSize}, color: {red: 0, green: 255, blue: 0}, position: intersection, - collisionless: true - + collisionless: true, + visible: false }; var beam = { @@ -105,7 +91,7 @@ color: {red: 0, green: 255, blue: 0}, parentID: MyAvatar.sessionUUID, parentJointIndex: MyAvatar.getJointIndex(jointName), - localPosition: {x: 0, y: .2, z: 0}, + localPosition: {x: 0, y: .05, z: 0}, localRotation: Quat.normalize({}), dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), linePoints: [Vec3.ZERO, {x: 0, y: dist, z: 0}] @@ -114,9 +100,13 @@ laserEntities[hand].beam = Entities.addEntity(beam,true); rayExclusionList.push(laserEntities[hand].beam); + laserEntities[hand].sphere = Entities.addEntity(sphere,true); + rayExclusionList.push(laserEntities[hand].sphere); + if (ray.intersects || avatarRay.intersects) { - laserEntities[hand].sphere = Entities.addEntity(sphere,true); - rayExclusionList.push(laserEntities[hand].sphere); + Entities.editEntity(laserEntities[hand].sphere, { + visible: true + }); } } else { @@ -125,7 +115,7 @@ Entities.editEntity(laserEntities[hand].beam, { parentID: MyAvatar.sessionUUID, parentJointIndex: MyAvatar.getJointIndex(jointName), - localPosition: {x: 0, y: .2, z: 0}, + localPosition: {x: 0, y: .05, z: 0}, localRotation: Quat.normalize({}), dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), linePoints: [Vec3.ZERO, {x: 0, y: dist, z: 0}] @@ -133,18 +123,22 @@ Entities.editEntity(laserEntities[hand].sphere, { dimensions: {x: sphereSize, y: sphereSize, z: sphereSize}, - position: intersection + position: intersection, + visible: true }); } else { Entities.editEntity(laserEntities[hand].beam, { parentID: MyAvatar.sessionUUID, parentJointIndex: MyAvatar.getJointIndex(jointName), - localPosition: {x: 0, y: .2, z: 0}, + localPosition: {x: 0, y: .05, z: 0}, localRotation: Quat.normalize({}), dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), linePoints: [Vec3.ZERO, {x: 0, y: dist, z: 0}] }); + Entities.editEntity(laserEntities[hand].sphere, { + visible: false + }); } } From ae960b840af0056605d71cfcd10cfa5b490e5c2d Mon Sep 17 00:00:00 2001 From: Mike Moody Date: Wed, 21 Jun 2017 21:24:34 -0700 Subject: [PATCH 05/27] accounted for the forward offset --- .../marketplace/laser/laserPointerApp.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/unpublishedScripts/marketplace/laser/laserPointerApp.js b/unpublishedScripts/marketplace/laser/laserPointerApp.js index e048d4126a..282fe4dc8d 100644 --- a/unpublishedScripts/marketplace/laser/laserPointerApp.js +++ b/unpublishedScripts/marketplace/laser/laserPointerApp.js @@ -41,6 +41,7 @@ function laser(hand) { var PICK_MAX_DISTANCE = 500; + var FORWARD_OFFSET = 0.05; var isNewEntityNeeded = (laserEntities[hand].beam === null); @@ -91,7 +92,7 @@ color: {red: 0, green: 255, blue: 0}, parentID: MyAvatar.sessionUUID, parentJointIndex: MyAvatar.getJointIndex(jointName), - localPosition: {x: 0, y: .05, z: 0}, + localPosition: {x: 0, y: FORWARD_OFFSET, z: 0}, localRotation: Quat.normalize({}), dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), linePoints: [Vec3.ZERO, {x: 0, y: dist, z: 0}] @@ -115,26 +116,25 @@ Entities.editEntity(laserEntities[hand].beam, { parentID: MyAvatar.sessionUUID, parentJointIndex: MyAvatar.getJointIndex(jointName), - localPosition: {x: 0, y: .05, z: 0}, + localPosition: {x: 0, y: FORWARD_OFFSET, z: 0}, localRotation: Quat.normalize({}), dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), - linePoints: [Vec3.ZERO, {x: 0, y: dist, z: 0}] + linePoints: [Vec3.ZERO, {x: 0, y: dist - FORWARD_OFFSET, z: 0}] }); Entities.editEntity(laserEntities[hand].sphere, { dimensions: {x: sphereSize, y: sphereSize, z: sphereSize}, position: intersection, visible: true - }); } else { Entities.editEntity(laserEntities[hand].beam, { parentID: MyAvatar.sessionUUID, parentJointIndex: MyAvatar.getJointIndex(jointName), - localPosition: {x: 0, y: .05, z: 0}, + localPosition: {x: 0, y: FORWARD_OFFSET, z: 0}, localRotation: Quat.normalize({}), dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), - linePoints: [Vec3.ZERO, {x: 0, y: dist, z: 0}] + linePoints: [Vec3.ZERO, {x: 0, y: dist - FORWARD_OFFSET, z: 0}] }); Entities.editEntity(laserEntities[hand].sphere, { visible: false From ab340530b84ff70d8eef60db75e5b87991aa743c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 5 Jul 2017 11:27:13 -0700 Subject: [PATCH 06/27] don't do a lot of processing during the mouse-move event handler --- scripts/system/controllers/grab.js | 35 +++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) 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) { From d9178786382067d9f6efa005da6207241d1bff1a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 5 Jul 2017 11:29:09 -0700 Subject: [PATCH 07/27] fix whitespace --- scripts/system/controllers/grab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index d46724184c..9f06aac3a6 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -460,7 +460,7 @@ Grabber.prototype.moveEvent = function(event) { if (!this.moveEventTimer) { this.moveEventTimer = Script.setTimeout(function() { _this.moveEventProcess(); - } , DELAY_FOR_30HZ); + }, DELAY_FOR_30HZ); } }; From 7c55370f268333dac6252a152d9178742b6bba6e Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 5 Jul 2017 18:39:09 +0200 Subject: [PATCH 08/27] Fixing the bug appearing on Nvidia 284.76 --- libraries/render-utils/src/local_lights_shading.slf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index a4e28a9757..c6310cb079 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -34,6 +34,8 @@ in vec2 _texCoord0; out vec4 _fragColor; void main(void) { + _fragColor = vec4(0.0); + // Grab the fragment data from the uv vec2 texCoord = _texCoord0.st; From 55b7c2d767f08d674eba5fc8eaa823e237b991b2 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 5 Jul 2017 15:50:05 -0700 Subject: [PATCH 09/27] avoid doing a lot of work during mouse-move event-handlers --- scripts/system/controllers/grab.js | 27 +++++++++++++------------- scripts/system/libraries/WebTablet.js | 28 +++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index 9f06aac3a6..da8add5117 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -447,15 +447,7 @@ 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); - +Grabber.prototype.scheduleMouseMoveProcessor = function(event) { var _this = this; if (!this.moveEventTimer) { this.moveEventTimer = Script.setTimeout(function() { @@ -464,7 +456,19 @@ Grabber.prototype.moveEvent = 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); + this.scheduleMouseMoveProcessor(); +}; + Grabber.prototype.moveEventProcess = function() { + this.moveEventTimer = null; // see if something added/restored gravity var entityProperties = Entities.getEntityProperties(this.entityID); if (!entityProperties || !entityProperties.gravity) { @@ -559,10 +563,7 @@ Grabber.prototype.moveEventProcess = function() { Entities.updateAction(this.entityID, this.actionID, actionArgs); } - var _this = this; - this.moveEventTimer = Script.setTimeout(function() { - _this.moveEventProcess(); - }, DELAY_FOR_30HZ); + this.scheduleMouseMoveProcessor(); }; Grabber.prototype.keyReleaseEvent = function(event) { diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index b429a9f3ae..142ed6e7b6 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -14,8 +14,6 @@ Script.include(Script.resolvePath("../libraries/utils.js")); Script.include(Script.resolvePath("../libraries/controllers.js")); Script.include(Script.resolvePath("../libraries/Xform.js")); -var VEC3_ZERO = {x: 0, y: 0, z: 0}; -var X_AXIS = {x: 1, y: 0, z: 0}; var Y_AXIS = {x: 0, y: 1, z: 0}; var DEFAULT_DPI = 34; var DEFAULT_WIDTH = 0.4375; @@ -25,12 +23,13 @@ var CAMERA_MATRIX = -7; var ROT_Y_180 = {x: 0.0, y: 1.0, z: 0, w: 0}; var ROT_LANDSCAPE = {x: 1.0, y: 1.0, z: 0, w: 0}; var ROT_LANDSCAPE_WINDOW = {x: 0.0, y: 0.0, z: 0.0, w: 0}; -var ROT_IDENT = {x: 0, y: 0, z: 0, w: 1}; var TABLET_TEXTURE_RESOLUTION = { x: 480, y: 706 }; var INCHES_TO_METERS = 1 / 39.3701; var AVATAR_SELF_ID = "{00000000-0000-0000-0000-000000000001}"; var NO_HANDS = -1; +var DELAY_FOR_30HZ = 33; // milliseconds + // will need to be recaclulated if dimensions of fbx model change. var TABLET_NATURAL_DIMENSIONS = {x: 33.797, y: 50.129, z: 2.269}; @@ -561,9 +560,29 @@ function rayIntersectPlane(planePosition, planeNormal, rayStart, rayDirection) { } } +WebTablet.prototype.scheduleMouseMoveProcessor = function() { + var _this = this; + if (!this.moveEventTimer) { + this.moveEventTimer = Script.setTimeout(function() { + _this.mouseMoveProcessor(); + }, DELAY_FOR_30HZ); + } +}; + WebTablet.prototype.mouseMoveEvent = function (event) { if (this.dragging) { - var pickRay = Camera.computePickRay(event.x, event.y); + this.currentMouse = { + x: event.x, + y: event.y + }; + this.scheduleMouseMoveProcessor(); + } +}; + +WebTablet.prototype.mouseMoveProcessor = function () { + this.moveEventTimer = null; + if (this.dragging) { + var pickRay = Camera.computePickRay(this.currentMouse.x, this.currentMouse.y); // transform pickRay into camera local coordinates var invCameraXform = new Xform(Camera.orientation, Camera.position).inv(); @@ -582,6 +601,7 @@ WebTablet.prototype.mouseMoveEvent = function (event) { localPosition: localPosition }); } + this.scheduleMouseMoveProcessor(); } }; From 7e9ce5a58bfa14ac9bd4e5a228a554fdd62e1e3e Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 5 Jul 2017 14:18:51 -0700 Subject: [PATCH 10/27] Don't overflow during AvatarData::toByteArray --- libraries/avatars/src/AvatarData.cpp | 44 ++++++++++++++++++++++++---- libraries/avatars/src/AvatarData.h | 23 +++++++++++++-- libraries/avatars/src/HeadData.cpp | 5 ++++ libraries/avatars/src/HeadData.h | 1 + 4 files changed, 64 insertions(+), 9 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 6eed23fb5b..6a0b668bfa 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -57,6 +57,27 @@ static const float DEFAULT_AVATAR_DENSITY = 1000.0f; // density of water #define ASSERT(COND) do { if (!(COND)) { abort(); } } while(0) +size_t AvatarDataPacket::maxFaceTrackerInfoSize(size_t numBlendshapeCoefficients) { + return FACE_TRACKER_INFO_SIZE + numBlendshapeCoefficients * sizeof(float); +} + +size_t AvatarDataPacket::maxJointDataSize(size_t numJoints) { + const size_t validityBitsSize = (size_t)std::ceil(numJoints / (float)BITS_IN_BYTE); + + size_t totalSize = sizeof(uint8_t); // numJoints + + totalSize += validityBitsSize; // Orientations mask + totalSize += numJoints * sizeof(SixByteQuat); // Orientations + totalSize += validityBitsSize; // Translations mask + totalSize += numJoints * sizeof(SixByteTrans); // Translations + + size_t NUM_FAUX_JOINT = 2; + totalSize += NUM_FAUX_JOINT * (sizeof(SixByteQuat) + sizeof(SixByteTrans)); // faux joints + + return totalSize; +} + + AvatarData::AvatarData() : SpatiallyNestable(NestableType::Avatar, QUuid()), _handPosition(0.0f), @@ -189,15 +210,11 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent lazyInitHeadData(); - QByteArray avatarDataByteArray(udt::MAX_PACKET_SIZE, 0); - unsigned char* destinationBuffer = reinterpret_cast(avatarDataByteArray.data()); - unsigned char* startPosition = destinationBuffer; - // special case, if we were asked for no data, then just include the flags all set to nothing if (dataDetail == NoData) { AvatarDataPacket::HasFlags packetStateFlags = 0; - memcpy(destinationBuffer, &packetStateFlags, sizeof(packetStateFlags)); - return avatarDataByteArray.left(sizeof(packetStateFlags)); + QByteArray avatarDataByteArray(reinterpret_cast(&packetStateFlags), sizeof(packetStateFlags)); + return avatarDataByteArray; } // FIXME - @@ -258,6 +275,15 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent hasJointData = sendAll || !sendMinimum; } + + const size_t byteArraySize = AvatarDataPacket::MAX_CONSTANT_HEADER_SIZE + + (hasFaceTrackerInfo ? AvatarDataPacket::maxFaceTrackerInfoSize(_headData->getNumSummedBlendshapeCoefficients()) : 0) + + (hasJointData ? AvatarDataPacket::maxJointDataSize(_jointData.size()) : 0); + + QByteArray avatarDataByteArray(byteArraySize, 0); + unsigned char* destinationBuffer = reinterpret_cast(avatarDataByteArray.data()); + unsigned char* startPosition = destinationBuffer; + // Leading flags, to indicate how much data is actually included in the packet... AvatarDataPacket::HasFlags packetStateFlags = (hasAvatarGlobalPosition ? AvatarDataPacket::PACKET_HAS_AVATAR_GLOBAL_POSITION : 0) @@ -624,6 +650,12 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent } int avatarDataSize = destinationBuffer - startPosition; + + if (avatarDataSize > byteArraySize) { + qCCritical(avatars) << "AvatarData::toByteArray buffer overflow"; // We've overflown into the heap + ASSERT(false); + } + return avatarDataByteArray.left(avatarDataSize); } // NOTE: This is never used in a "distanceAdjust" mode, so it's ok that it doesn't use a variable minimum rotation/translation diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index d6241c2c50..0ddf4e7d0a 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -140,6 +140,9 @@ namespace AvatarDataPacket { const HasFlags PACKET_HAS_JOINT_DATA = 1U << 11; const size_t AVATAR_HAS_FLAGS_SIZE = 2; + using SixByteQuat = uint8_t[6]; + using SixByteTrans = uint8_t[6]; + // NOTE: AvatarDataPackets start with a uint16_t sequence number that is not reflected in the Header structure. PACKED_BEGIN struct Header { @@ -158,8 +161,6 @@ namespace AvatarDataPacket { } PACKED_END; const size_t AVATAR_BOUNDING_BOX_SIZE = 24; - - using SixByteQuat = uint8_t[6]; PACKED_BEGIN struct AvatarOrientation { SixByteQuat avatarOrientation; // encodeded and compressed by packOrientationQuatToSixBytes() } PACKED_END; @@ -219,6 +220,21 @@ namespace AvatarDataPacket { } PACKED_END; const size_t AVATAR_LOCAL_POSITION_SIZE = 12; + const size_t MAX_CONSTANT_HEADER_SIZE = HEADER_SIZE + + AVATAR_GLOBAL_POSITION_SIZE + + AVATAR_BOUNDING_BOX_SIZE + + AVATAR_ORIENTATION_SIZE + + AVATAR_SCALE_SIZE + + LOOK_AT_POSITION_SIZE + + AUDIO_LOUDNESS_SIZE + + SENSOR_TO_WORLD_SIZE + + ADDITIONAL_FLAGS_SIZE + + PARENT_INFO_SIZE + + AVATAR_LOCAL_POSITION_SIZE; + + + // variable length structure follows + // only present if IS_FACE_TRACKER_CONNECTED flag is set in AvatarInfo.flags PACKED_BEGIN struct FaceTrackerInfo { float leftEyeBlink; @@ -229,8 +245,8 @@ namespace AvatarDataPacket { // float blendshapeCoefficients[numBlendshapeCoefficients]; } PACKED_END; const size_t FACE_TRACKER_INFO_SIZE = 17; + size_t maxFaceTrackerInfoSize(size_t numBlendshapeCoefficients); - // variable length structure follows /* struct JointData { uint8_t numJoints; @@ -240,6 +256,7 @@ namespace AvatarDataPacket { SixByteTrans translation[numValidTranslations]; // encodeded and compressed by packFloatVec3ToSignedTwoByteFixed() }; */ + size_t maxJointDataSize(size_t numJoints); } static const float MAX_AVATAR_SCALE = 1000.0f; diff --git a/libraries/avatars/src/HeadData.cpp b/libraries/avatars/src/HeadData.cpp index 8ae33a1b4f..1fda984e78 100644 --- a/libraries/avatars/src/HeadData.cpp +++ b/libraries/avatars/src/HeadData.cpp @@ -83,6 +83,11 @@ static const QMap& getBlendshapesLookupMap() { return blendshapeLookupMap; } +int HeadData::getNumSummedBlendshapeCoefficients() const { + int maxSize = std::max(_blendshapeCoefficients.size(), _transientBlendshapeCoefficients.size()); + return maxSize; +} + const QVector& HeadData::getSummedBlendshapeCoefficients() { int maxSize = std::max(_blendshapeCoefficients.size(), _transientBlendshapeCoefficients.size()); if (_summedBlendshapeCoefficients.size() != maxSize) { diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index c15714bd73..bcc2cacde5 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -57,6 +57,7 @@ public: void setBlendshape(QString name, float val); const QVector& getBlendshapeCoefficients() const { return _blendshapeCoefficients; } const QVector& getSummedBlendshapeCoefficients(); + int getNumSummedBlendshapeCoefficients() const; void setBlendshapeCoefficients(const QVector& blendshapeCoefficients) { _blendshapeCoefficients = blendshapeCoefficients; } const glm::vec3& getLookAtPosition() const { return _lookAtPosition; } From 95abbd0ad4a8392a4dfbe62d1dce8068489effeb Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 5 Jul 2017 16:54:33 -0700 Subject: [PATCH 11/27] Prevent Interface from trying to send packets bigger than an MTU --- assignment-client/src/Agent.cpp | 18 +++++++++++++++ .../src/avatars/ScriptableAvatar.cpp | 2 +- .../src/avatars/ScriptableAvatar.h | 2 +- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/avatar/MyAvatar.h | 2 +- libraries/avatars/src/AvatarData.cpp | 22 +++++++++++++++++-- libraries/avatars/src/AvatarData.h | 2 +- 7 files changed, 43 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 8aec5adb1f..908acba5ad 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -604,6 +604,24 @@ void Agent::processAgentAvatar() { AvatarData::AvatarDataDetail dataDetail = (randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO) ? AvatarData::SendAllData : AvatarData::CullSmallData; QByteArray avatarByteArray = scriptedAvatar->toByteArrayStateful(dataDetail); + + auto maximumByteArraySize = NLPacket::maxPayloadSize(PacketType::AvatarData) - sizeof(AvatarDataSequenceNumber); + + if (avatarByteArray.size() > maximumByteArraySize) { + qWarning() << " scriptedAvatar->toByteArrayStateful() resulted in very large buffer:" << avatarByteArray.size() << "... attempt to drop facial data"; + avatarByteArray = scriptedAvatar->toByteArrayStateful(dataDetail, true); + + if (avatarByteArray.size() > maximumByteArraySize) { + qWarning() << " scriptedAvatar->toByteArrayStateful() without facial data resulted in very large buffer:" << avatarByteArray.size() << "... reduce to MinimumData"; + avatarByteArray = scriptedAvatar->toByteArrayStateful(AvatarData::MinimumData, true); + } + + if (avatarByteArray.size() > maximumByteArraySize) { + qWarning() << " scriptedAvatar->toByteArrayStateful() MinimumData resulted in very large buffer:" << avatarByteArray.size() << "... FAIL!!"; + return; + } + } + scriptedAvatar->doneEncoding(true); static AvatarDataSequenceNumber sequenceNumber = 0; diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp index 6443e7bf4b..c7715d4014 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.cpp +++ b/assignment-client/src/avatars/ScriptableAvatar.cpp @@ -19,7 +19,7 @@ #include "ScriptableAvatar.h" -QByteArray ScriptableAvatar::toByteArrayStateful(AvatarDataDetail dataDetail) { +QByteArray ScriptableAvatar::toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking) { _globalPosition = getPosition(); return AvatarData::toByteArrayStateful(dataDetail); } diff --git a/assignment-client/src/avatars/ScriptableAvatar.h b/assignment-client/src/avatars/ScriptableAvatar.h index 1028912e55..b1039b5ac0 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.h +++ b/assignment-client/src/avatars/ScriptableAvatar.h @@ -28,7 +28,7 @@ public: Q_INVOKABLE AnimationDetails getAnimationDetails(); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; - virtual QByteArray toByteArrayStateful(AvatarDataDetail dataDetail) override; + virtual QByteArray toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking = false) override; private slots: diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 8cd39b298f..6478fe38a6 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -295,7 +295,7 @@ void MyAvatar::simulateAttachments(float deltaTime) { // don't update attachments here, do it in harvestResultsFromPhysicsSimulation() } -QByteArray MyAvatar::toByteArrayStateful(AvatarDataDetail dataDetail) { +QByteArray MyAvatar::toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking) { CameraMode mode = qApp->getCamera().getMode(); _globalPosition = getPosition(); // This might not be right! Isn't the capsule local offset in avatar space, and don't we need to add the radius to the y as well? -HRS 5/26/17 diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 8ad4bf4436..ba102eb27c 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -611,7 +611,7 @@ private: bool requiresSafeLanding(const glm::vec3& positionIn, glm::vec3& positionOut); - virtual QByteArray toByteArrayStateful(AvatarDataDetail dataDetail) override; + virtual QByteArray toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking) override; void simulate(float deltaTime); void updateFromTrackers(float deltaTime); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 6a0b668bfa..1e12158de1 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -190,12 +190,12 @@ float AvatarData::getDistanceBasedMinTranslationDistance(glm::vec3 viewerPositio // we want to track outbound data in this case... -QByteArray AvatarData::toByteArrayStateful(AvatarDataDetail dataDetail) { +QByteArray AvatarData::toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking) { AvatarDataPacket::HasFlags hasFlagsOut; auto lastSentTime = _lastToByteArray; _lastToByteArray = usecTimestampNow(); return AvatarData::toByteArray(dataDetail, lastSentTime, getLastSentJointData(), - hasFlagsOut, false, false, glm::vec3(0), nullptr, + hasFlagsOut, dropFaceTracking, false, glm::vec3(0), nullptr, &_outboundDataRate); } @@ -1775,6 +1775,24 @@ void AvatarData::sendAvatarDataPacket() { bool cullSmallData = (randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO); auto dataDetail = cullSmallData ? SendAllData : CullSmallData; QByteArray avatarByteArray = toByteArrayStateful(dataDetail); + + auto maximumByteArraySize = NLPacket::maxPayloadSize(PacketType::AvatarData) - sizeof(AvatarDataSequenceNumber); + + if (avatarByteArray.size() > maximumByteArraySize) { + qCWarning(avatars) << "toByteArrayStateful() resulted in very large buffer:" << avatarByteArray.size() << "... attempt to drop facial data"; + avatarByteArray = toByteArrayStateful(dataDetail, true); + + if (avatarByteArray.size() > maximumByteArraySize) { + qCWarning(avatars) << "toByteArrayStateful() without facial data resulted in very large buffer:" << avatarByteArray.size() << "... reduce to MinimumData"; + avatarByteArray = toByteArrayStateful(MinimumData, true); + } + + if (avatarByteArray.size() > maximumByteArraySize) { + qCWarning(avatars) << "toByteArrayStateful() MinimumData resulted in very large buffer:" << avatarByteArray.size() << "... FAIL!!"; + return; + } + } + doneEncoding(cullSmallData); static AvatarDataSequenceNumber sequenceNumber = 0; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 0ddf4e7d0a..4a1c951397 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -404,7 +404,7 @@ public: SendAllData } AvatarDataDetail; - virtual QByteArray toByteArrayStateful(AvatarDataDetail dataDetail); + virtual QByteArray toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking = false); virtual QByteArray toByteArray(AvatarDataDetail dataDetail, quint64 lastSentTime, const QVector& lastSentJointData, AvatarDataPacket::HasFlags& hasFlagsOut, bool dropFaceTracking, bool distanceAdjust, glm::vec3 viewerPosition, From 20a633eb899475a4d272c419786ebcdbe8f4cb5b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 5 Jul 2017 16:15:53 -0700 Subject: [PATCH 12/27] Check struct sizes at compile time --- libraries/avatars/src/AvatarData.cpp | 13 ------------- libraries/avatars/src/AvatarData.h | 12 ++++++++++++ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 1e12158de1..3b2ec9fb86 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -94,19 +94,6 @@ AvatarData::AvatarData() : setBodyPitch(0.0f); setBodyYaw(-90.0f); setBodyRoll(0.0f); - - ASSERT(sizeof(AvatarDataPacket::Header) == AvatarDataPacket::HEADER_SIZE); - ASSERT(sizeof(AvatarDataPacket::AvatarGlobalPosition) == AvatarDataPacket::AVATAR_GLOBAL_POSITION_SIZE); - ASSERT(sizeof(AvatarDataPacket::AvatarLocalPosition) == AvatarDataPacket::AVATAR_LOCAL_POSITION_SIZE); - ASSERT(sizeof(AvatarDataPacket::AvatarBoundingBox) == AvatarDataPacket::AVATAR_BOUNDING_BOX_SIZE); - ASSERT(sizeof(AvatarDataPacket::AvatarOrientation) == AvatarDataPacket::AVATAR_ORIENTATION_SIZE); - ASSERT(sizeof(AvatarDataPacket::AvatarScale) == AvatarDataPacket::AVATAR_SCALE_SIZE); - ASSERT(sizeof(AvatarDataPacket::LookAtPosition) == AvatarDataPacket::LOOK_AT_POSITION_SIZE); - ASSERT(sizeof(AvatarDataPacket::AudioLoudness) == AvatarDataPacket::AUDIO_LOUDNESS_SIZE); - ASSERT(sizeof(AvatarDataPacket::SensorToWorldMatrix) == AvatarDataPacket::SENSOR_TO_WORLD_SIZE); - ASSERT(sizeof(AvatarDataPacket::AdditionalFlags) == AvatarDataPacket::ADDITIONAL_FLAGS_SIZE); - ASSERT(sizeof(AvatarDataPacket::ParentInfo) == AvatarDataPacket::PARENT_INFO_SIZE); - ASSERT(sizeof(AvatarDataPacket::FaceTrackerInfo) == AvatarDataPacket::FACE_TRACKER_INFO_SIZE); } AvatarData::~AvatarData() { diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 4a1c951397..cb5aead050 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -149,27 +149,32 @@ namespace AvatarDataPacket { HasFlags packetHasFlags; // state flags, indicated which additional records are included in the packet } PACKED_END; const size_t HEADER_SIZE = 2; + static_assert(sizeof(Header) == HEADER_SIZE, "AvatarDataPacket::Header size doesn't match."); PACKED_BEGIN struct AvatarGlobalPosition { float globalPosition[3]; // avatar's position } PACKED_END; const size_t AVATAR_GLOBAL_POSITION_SIZE = 12; + static_assert(sizeof(AvatarGlobalPosition) == AVATAR_GLOBAL_POSITION_SIZE, "AvatarDataPacket::AvatarGlobalPosition size doesn't match."); PACKED_BEGIN struct AvatarBoundingBox { float avatarDimensions[3]; // avatar's bounding box in world space units, but relative to the position. float boundOriginOffset[3]; // offset from the position of the avatar to the origin of the bounding box } PACKED_END; const size_t AVATAR_BOUNDING_BOX_SIZE = 24; + static_assert(sizeof(AvatarBoundingBox) == AVATAR_BOUNDING_BOX_SIZE, "AvatarDataPacket::AvatarBoundingBox size doesn't match."); PACKED_BEGIN struct AvatarOrientation { SixByteQuat avatarOrientation; // encodeded and compressed by packOrientationQuatToSixBytes() } PACKED_END; const size_t AVATAR_ORIENTATION_SIZE = 6; + static_assert(sizeof(AvatarOrientation) == AVATAR_ORIENTATION_SIZE, "AvatarDataPacket::AvatarOrientation size doesn't match."); PACKED_BEGIN struct AvatarScale { SmallFloat scale; // avatar's scale, compressed by packFloatRatioToTwoByte() } PACKED_END; const size_t AVATAR_SCALE_SIZE = 2; + static_assert(sizeof(AvatarScale) == AVATAR_SCALE_SIZE, "AvatarDataPacket::AvatarScale size doesn't match."); PACKED_BEGIN struct LookAtPosition { float lookAtPosition[3]; // world space position that eyes are focusing on. @@ -181,11 +186,13 @@ namespace AvatarDataPacket { // POTENTIAL SAVINGS - 12 bytes } PACKED_END; const size_t LOOK_AT_POSITION_SIZE = 12; + static_assert(sizeof(LookAtPosition) == LOOK_AT_POSITION_SIZE, "AvatarDataPacket::LookAtPosition size doesn't match."); PACKED_BEGIN struct AudioLoudness { uint8_t audioLoudness; // current loudness of microphone compressed with packFloatGainToByte() } PACKED_END; const size_t AUDIO_LOUDNESS_SIZE = 1; + static_assert(sizeof(AudioLoudness) == AUDIO_LOUDNESS_SIZE, "AvatarDataPacket::AudioLoudness size doesn't match."); PACKED_BEGIN struct SensorToWorldMatrix { // FIXME - these 20 bytes are only used by viewers if my avatar has "attachments" @@ -200,11 +207,13 @@ namespace AvatarDataPacket { // relative to the avatar position. } PACKED_END; const size_t SENSOR_TO_WORLD_SIZE = 20; + static_assert(sizeof(SensorToWorldMatrix) == SENSOR_TO_WORLD_SIZE, "AvatarDataPacket::SensorToWorldMatrix size doesn't match."); PACKED_BEGIN struct AdditionalFlags { uint8_t flags; // additional flags: hand state, key state, eye tracking } PACKED_END; const size_t ADDITIONAL_FLAGS_SIZE = 1; + static_assert(sizeof(AdditionalFlags) == ADDITIONAL_FLAGS_SIZE, "AvatarDataPacket::AdditionalFlags size doesn't match."); // only present if HAS_REFERENTIAL flag is set in AvatarInfo.flags PACKED_BEGIN struct ParentInfo { @@ -212,6 +221,7 @@ namespace AvatarDataPacket { uint16_t parentJointIndex; } PACKED_END; const size_t PARENT_INFO_SIZE = 18; + static_assert(sizeof(ParentInfo) == PARENT_INFO_SIZE, "AvatarDataPacket::ParentInfo size doesn't match."); // will only ever be included if the avatar has a parent but can change independent of changes to parent info // and so we keep it a separate record @@ -219,6 +229,7 @@ namespace AvatarDataPacket { float localPosition[3]; // parent frame translation of the avatar } PACKED_END; const size_t AVATAR_LOCAL_POSITION_SIZE = 12; + static_assert(sizeof(AvatarLocalPosition) == AVATAR_LOCAL_POSITION_SIZE, "AvatarDataPacket::AvatarLocalPosition size doesn't match."); const size_t MAX_CONSTANT_HEADER_SIZE = HEADER_SIZE + AVATAR_GLOBAL_POSITION_SIZE + @@ -245,6 +256,7 @@ namespace AvatarDataPacket { // float blendshapeCoefficients[numBlendshapeCoefficients]; } PACKED_END; const size_t FACE_TRACKER_INFO_SIZE = 17; + static_assert(sizeof(FaceTrackerInfo) == FACE_TRACKER_INFO_SIZE, "AvatarDataPacket::FaceTrackerInfo size doesn't match."); size_t maxFaceTrackerInfoSize(size_t numBlendshapeCoefficients); /* From 9a1d38384d4693fc34ae4b3bd4875a47ea6266fb Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 5 Jul 2017 17:22:16 -0700 Subject: [PATCH 13/27] Remove unecessary loops --- libraries/avatars/src/AvatarData.cpp | 46 +++++++++------------------- 1 file changed, 14 insertions(+), 32 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 3b2ec9fb86..4236565e04 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -491,12 +491,15 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent unsigned char* validityPosition = destinationBuffer; unsigned char validity = 0; int validityBit = 0; + int numValidityBytes = (int)std::ceil(numJoints / (float)BITS_IN_BYTE); #ifdef WANT_DEBUG int rotationSentCount = 0; unsigned char* beforeRotations = destinationBuffer; #endif + destinationBuffer += numValidityBytes; // Move pointer past the validity bytes + if (sentJointDataOut) { sentJointDataOut->resize(_jointData.size()); // Make sure the destination is resized before using it } @@ -516,6 +519,8 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent #ifdef WANT_DEBUG rotationSentCount++; #endif + destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, data.rotation); + if (sentJointDataOut) { auto jointDataOut = *sentJointDataOut; jointDataOut[i].rotation = data.rotation; @@ -525,28 +530,14 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent } } if (++validityBit == BITS_IN_BYTE) { - *destinationBuffer++ = validity; + *validityPosition++ = validity; validityBit = validity = 0; } } if (validityBit != 0) { - *destinationBuffer++ = validity; + *validityPosition++ = validity; } - validityBit = 0; - validity = *validityPosition++; - for (int i = 0; i < _jointData.size(); i++) { - const JointData& data = _jointData[i]; - if (validity & (1 << validityBit)) { - destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, data.rotation); - } - if (++validityBit == BITS_IN_BYTE) { - validityBit = 0; - validity = *validityPosition++; - } - } - - // joint translation data validityPosition = destinationBuffer; validity = 0; @@ -557,6 +548,8 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent unsigned char* beforeTranslations = destinationBuffer; #endif + destinationBuffer += numValidityBytes; // Move pointer past the validity bytes + float minTranslation = !distanceAdjust ? AVATAR_MIN_TRANSLATION : getDistanceBasedMinTranslationDistance(viewerPosition); float maxTranslationDimension = 0.0; @@ -575,6 +568,9 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent maxTranslationDimension = glm::max(fabsf(data.translation.y), maxTranslationDimension); maxTranslationDimension = glm::max(fabsf(data.translation.z), maxTranslationDimension); + destinationBuffer += + packFloatVec3ToSignedTwoByteFixed(destinationBuffer, data.translation, TRANSLATION_COMPRESSION_RADIX); + if (sentJointDataOut) { auto jointDataOut = *sentJointDataOut; jointDataOut[i].translation = data.translation; @@ -584,27 +580,13 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent } } if (++validityBit == BITS_IN_BYTE) { - *destinationBuffer++ = validity; + *validityPosition++ = validity; validityBit = validity = 0; } } if (validityBit != 0) { - *destinationBuffer++ = validity; - } - - validityBit = 0; - validity = *validityPosition++; - for (int i = 0; i < _jointData.size(); i++) { - const JointData& data = _jointData[i]; - if (validity & (1 << validityBit)) { - destinationBuffer += - packFloatVec3ToSignedTwoByteFixed(destinationBuffer, data.translation, TRANSLATION_COMPRESSION_RADIX); - } - if (++validityBit == BITS_IN_BYTE) { - validityBit = 0; - validity = *validityPosition++; - } + *validityPosition++ = validity; } // faux joints From 1d07ab70f0c5d3e2beb5dffe7cc949dfe8fdb8c0 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 5 Jul 2017 18:07:10 -0700 Subject: [PATCH 14/27] Fix warnings --- assignment-client/src/Agent.cpp | 2 +- libraries/avatars/src/AvatarData.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 908acba5ad..beeae7527e 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -605,7 +605,7 @@ void Agent::processAgentAvatar() { AvatarData::AvatarDataDetail dataDetail = (randFloat() < AVATAR_SEND_FULL_UPDATE_RATIO) ? AvatarData::SendAllData : AvatarData::CullSmallData; QByteArray avatarByteArray = scriptedAvatar->toByteArrayStateful(dataDetail); - auto maximumByteArraySize = NLPacket::maxPayloadSize(PacketType::AvatarData) - sizeof(AvatarDataSequenceNumber); + int maximumByteArraySize = NLPacket::maxPayloadSize(PacketType::AvatarData) - sizeof(AvatarDataSequenceNumber); if (avatarByteArray.size() > maximumByteArraySize) { qWarning() << " scriptedAvatar->toByteArrayStateful() resulted in very large buffer:" << avatarByteArray.size() << "... attempt to drop facial data"; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 4236565e04..036d67da17 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -267,7 +267,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent (hasFaceTrackerInfo ? AvatarDataPacket::maxFaceTrackerInfoSize(_headData->getNumSummedBlendshapeCoefficients()) : 0) + (hasJointData ? AvatarDataPacket::maxJointDataSize(_jointData.size()) : 0); - QByteArray avatarDataByteArray(byteArraySize, 0); + QByteArray avatarDataByteArray((int)byteArraySize, 0); unsigned char* destinationBuffer = reinterpret_cast(avatarDataByteArray.data()); unsigned char* startPosition = destinationBuffer; @@ -620,7 +620,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent int avatarDataSize = destinationBuffer - startPosition; - if (avatarDataSize > byteArraySize) { + if (avatarDataSize > (int)byteArraySize) { qCCritical(avatars) << "AvatarData::toByteArray buffer overflow"; // We've overflown into the heap ASSERT(false); } @@ -1745,7 +1745,7 @@ void AvatarData::sendAvatarDataPacket() { auto dataDetail = cullSmallData ? SendAllData : CullSmallData; QByteArray avatarByteArray = toByteArrayStateful(dataDetail); - auto maximumByteArraySize = NLPacket::maxPayloadSize(PacketType::AvatarData) - sizeof(AvatarDataSequenceNumber); + int maximumByteArraySize = NLPacket::maxPayloadSize(PacketType::AvatarData) - sizeof(AvatarDataSequenceNumber); if (avatarByteArray.size() > maximumByteArraySize) { qCWarning(avatars) << "toByteArrayStateful() resulted in very large buffer:" << avatarByteArray.size() << "... attempt to drop facial data"; From 0c18f04e58736cb39c6810be7b500b8d19afaa04 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 6 Jul 2017 18:40:14 -0700 Subject: [PATCH 15/27] Fix Audio Mixer crash --- libraries/networking/src/LimitedNodeList.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index ab61c71952..5d602cc0c0 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -197,8 +197,12 @@ public: *lockWaitOut = (endLock - start); } - std::vector nodes(_nodeHash.size()); - std::transform(_nodeHash.cbegin(), _nodeHash.cend(), nodes.begin(), [](const NodeHash::value_type& it) { + // Size of _nodeHash could change at any time, + // so reserve enough memory for the current size + // and then back insert all the nodes found + std::vector nodes; + nodes.reserve(_nodeHash.size()); + std::transform(_nodeHash.cbegin(), _nodeHash.cend(), std::back_inserter(nodes), [&](const NodeHash::value_type& it) { return it.second; }); auto endTransform = usecTimestampNow(); From e22a3c6af97eb7646f9de612d66a11866ff6a8d1 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 6 Jul 2017 18:01:26 -0700 Subject: [PATCH 16/27] Fixing overlay crashes, for real --- interface/src/ui/overlays/Overlays.cpp | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 399c730dbd..bcf9897dd8 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -307,6 +307,7 @@ void Overlays::deleteOverlay(OverlayID id) { } #endif + _overlaysToDelete.push_back(overlayToDelete); emit overlayDeleted(id); } @@ -606,22 +607,16 @@ QSizeF Overlays::textSize(OverlayID id, const QString& text) { return result; } - Overlay::Pointer thisOverlay; - { - QMutexLocker locker(&_mutex); - thisOverlay = _overlaysHUD[id]; - } + Overlay::Pointer thisOverlay = getOverlay(id); if (thisOverlay) { - if (auto textOverlay = std::dynamic_pointer_cast(thisOverlay)) { - return textOverlay->textSize(text); - } - } else { - { - QMutexLocker locker(&_mutex); - thisOverlay = _overlaysWorld[id]; - } - if (auto text3dOverlay = std::dynamic_pointer_cast(thisOverlay)) { - return text3dOverlay->textSize(text); + if (thisOverlay->is3D()) { + if (auto text3dOverlay = std::dynamic_pointer_cast(thisOverlay)) { + return text3dOverlay->textSize(text); + } + } else { + if (auto textOverlay = std::dynamic_pointer_cast(thisOverlay)) { + return textOverlay->textSize(text); + } } } return QSizeF(0.0f, 0.0f); From 060e3a9c5afdaa3ddbf15d37b87cdd81456f77d8 Mon Sep 17 00:00:00 2001 From: Liv Date: Fri, 7 Jul 2017 11:48:12 -0700 Subject: [PATCH 17/27] Add signal for avatar skeleton changing --- interface/src/avatar/MyAvatar.cpp | 1 + interface/src/avatar/MyAvatar.h | 1 + 2 files changed, 2 insertions(+) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index afbcd170e5..f6fb87dad9 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1356,6 +1356,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { Avatar::setSkeletonModelURL(skeletonModelURL); _skeletonModel->setVisibleInScene(true, qApp->getMain3DScene()); _headBoneSet.clear(); + emit skeletonChanged(); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 8ad4bf4436..4d599230fb 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -606,6 +606,7 @@ signals: void onLoadComplete(); void wentAway(); void wentActive(); + void skeletonChanged(); private: From 4b593d1ab43edf3725af8d68f77f257652f4a5ac Mon Sep 17 00:00:00 2001 From: Mike Moody Date: Sat, 8 Jul 2017 15:18:27 -0700 Subject: [PATCH 18/27] Added fallback method using controllers if joints do not exist. --- .../marketplace/laser/laserPointerApp.js | 92 ++++++++++++++----- 1 file changed, 67 insertions(+), 25 deletions(-) diff --git a/unpublishedScripts/marketplace/laser/laserPointerApp.js b/unpublishedScripts/marketplace/laser/laserPointerApp.js index 282fe4dc8d..515a2c3a76 100644 --- a/unpublishedScripts/marketplace/laser/laserPointerApp.js +++ b/unpublishedScripts/marketplace/laser/laserPointerApp.js @@ -8,8 +8,8 @@ Script.include("/~/system/libraries/controllers.js"); var APP_NAME = 'LASER', - APP_ICON = 'https://binaryrelay.com/files/public-docs/hifi/laser/laser.svg', - APP_ICON_ACTIVE = 'https://binaryrelay.com/files/public-docs/hifi/laser/laser-a.svg'; + APP_ICON = Script.resolvePath('laser.svg'), + APP_ICON_ACTIVE = Script.resolvePath('laser-a.svg'); var POINT_INDEX_CHANNEL = "Hifi-Point-Index", GRAB_DISABLE_CHANNEL = "Hifi-Grab-Disable", @@ -47,12 +47,26 @@ var jointName = hand === 'right' ? 'RightHandIndex4' : 'LeftHandIndex4'; //'RightHand' : 'LeftHand'; + var _hand = hand === 'right' ? Controller.Standard.RightHand : Controller.Standard.LeftHand; + var controllerLocation = getControllerWorldLocation(_hand, true); + + var worldControllerPosition = controllerLocation.position; + var worldControllerRotation = controllerLocation.orientation; + + var jointExists = (MyAvatar.getJointIndex(jointName) > 0) ; + var CONTROLLER_FORWARD_OFFSET = Vec3.multiply(Quat.getUp(worldControllerRotation), FORWARD_OFFSET); + var pickRay = { - origin: MyAvatar.getJointPosition(jointName), - direction: MyAvatar.jointToWorldDirection(Vec3.UP, MyAvatar.getJointIndex(jointName)), + origin: worldControllerPosition, + direction: Quat.getUp(worldControllerRotation), length: PICK_MAX_DISTANCE }; + if (jointExists) { + pickRay.origin = MyAvatar.getJointPosition(jointName); + pickRay.direction = MyAvatar.jointToWorldDirection(Vec3.UP, MyAvatar.getJointIndex(jointName)); + } + var ray = Entities.findRayIntersection(pickRay, true, [], rayExclusionList, true); var avatarRay = AvatarManager.findRayIntersection(pickRay, true, [], rayExclusionList, true); @@ -91,13 +105,19 @@ drawInFront: true, color: {red: 0, green: 255, blue: 0}, parentID: MyAvatar.sessionUUID, - parentJointIndex: MyAvatar.getJointIndex(jointName), - localPosition: {x: 0, y: FORWARD_OFFSET, z: 0}, - localRotation: Quat.normalize({}), dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), - linePoints: [Vec3.ZERO, {x: 0, y: dist, z: 0}] + linePoints: [Vec3.ZERO, {x: 0, y: dist - FORWARD_OFFSET, z: 0}] }; + if(jointExists) { + beam.parentJointIndex = MyAvatar.getJointIndex(jointName); + beam.localPosition = {x: 0, y: FORWARD_OFFSET, z: 0}; + beam.localRotation = Quat.normalize({}); + } else { + beam.position = Vec3.sum(pickRay.origin, CONTROLLER_FORWARD_OFFSET); + beam.rotation = worldControllerRotation; + } + laserEntities[hand].beam = Entities.addEntity(beam,true); rayExclusionList.push(laserEntities[hand].beam); @@ -112,15 +132,25 @@ } else { if (ray.intersects || avatarRay.intersects) { - - Entities.editEntity(laserEntities[hand].beam, { - parentID: MyAvatar.sessionUUID, - parentJointIndex: MyAvatar.getJointIndex(jointName), - localPosition: {x: 0, y: FORWARD_OFFSET, z: 0}, - localRotation: Quat.normalize({}), - dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), - linePoints: [Vec3.ZERO, {x: 0, y: dist - FORWARD_OFFSET, z: 0}] - }); + if(jointExists) { + Entities.editEntity(laserEntities[hand].beam, { + parentID: MyAvatar.sessionUUID, + parentJointIndex: MyAvatar.getJointIndex(jointName), + localPosition: {x: 0, y: FORWARD_OFFSET, z: 0}, + localRotation: Quat.normalize({}), + dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), + linePoints: [Vec3.ZERO, {x: 0, y: dist - FORWARD_OFFSET, z: 0}] + }); + } else { + Entities.editEntity(laserEntities[hand].beam, { + parentID: MyAvatar.sessionUUID, + parentJointIndex: MyAvatar.getJointIndex(jointName), + position: Vec3.sum(pickRay.origin, CONTROLLER_FORWARD_OFFSET), + rotation: worldControllerRotation, + dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), + linePoints: [Vec3.ZERO, {x: 0, y: dist - FORWARD_OFFSET, z: 0}] + }); + } Entities.editEntity(laserEntities[hand].sphere, { dimensions: {x: sphereSize, y: sphereSize, z: sphereSize}, @@ -128,14 +158,26 @@ visible: true }); } else { - Entities.editEntity(laserEntities[hand].beam, { - parentID: MyAvatar.sessionUUID, - parentJointIndex: MyAvatar.getJointIndex(jointName), - localPosition: {x: 0, y: FORWARD_OFFSET, z: 0}, - localRotation: Quat.normalize({}), - dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), - linePoints: [Vec3.ZERO, {x: 0, y: dist - FORWARD_OFFSET, z: 0}] - }); + if(jointExists) { + Entities.editEntity(laserEntities[hand].beam, { + parentID: MyAvatar.sessionUUID, + parentJointIndex: MyAvatar.getJointIndex(jointName), + localPosition: {x: 0, y: FORWARD_OFFSET, z: 0}, + localRotation: Quat.normalize({}), + dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), + linePoints: [Vec3.ZERO, {x: 0, y: dist - FORWARD_OFFSET, z: 0}] + }); + } else { + Entities.editEntity(laserEntities[hand].beam, { + parentID: MyAvatar.sessionUUID, + parentJointIndex: MyAvatar.getJointIndex(jointName), + position: Vec3.sum(pickRay.origin, CONTROLLER_FORWARD_OFFSET), + rotation: worldControllerRotation, + dimensions: Vec3.multiply(PICK_MAX_DISTANCE * 2, Vec3.ONE), + linePoints: [Vec3.ZERO, {x: 0, y: dist - FORWARD_OFFSET, z: 0}] + }); + } + Entities.editEntity(laserEntities[hand].sphere, { visible: false }); From e52c7f4395e0f19fe66ccd6534136c935a657d6e Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 7 Jul 2017 19:07:19 -0700 Subject: [PATCH 19/27] Add more efficient overlay getters, don't use blocking calls --- interface/src/ui/overlays/Overlays.cpp | 41 +++++++++++++++++++++----- interface/src/ui/overlays/Overlays.h | 4 +++ 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index bcf9897dd8..2f22b62306 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -414,20 +414,47 @@ OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) { } OverlayPropertyResult Overlays::getProperty(OverlayID id, const QString& property) { - if (QThread::currentThread() != thread()) { - OverlayPropertyResult result; - BLOCKING_INVOKE_METHOD(this, "getProperty", Q_RETURN_ARG(OverlayPropertyResult, result), Q_ARG(OverlayID, id), Q_ARG(QString, property)); - return result; - } - - OverlayPropertyResult result; Overlay::Pointer thisOverlay = getOverlay(id); + OverlayPropertyResult result; if (thisOverlay && thisOverlay->supportsGetProperty()) { result.value = thisOverlay->getProperty(property); } return result; } +OverlayPropertyResult Overlays::getProperties(const OverlayID& id, const QStringList& properties) { + Overlay::Pointer thisOverlay = getOverlay(id); + OverlayPropertyResult result; + if (thisOverlay && thisOverlay->supportsGetProperty()) { + QVariantMap mapResult; + for (const auto& property : properties) { + mapResult.insert(property, thisOverlay->getProperty(property)); + } + result.value = mapResult; + } + return result; +} + +OverlayPropertyResult Overlays::getOverlaysProperties(const QVariant& propertiesById) { + QVariantMap map = propertiesById.toMap(); + OverlayPropertyResult result; + QVariantMap resultMap; + for (const auto& key : map.keys()) { + OverlayID id = OverlayID(key); + QVariantMap overlayResult; + Overlay::Pointer thisOverlay = getOverlay(id); + if (thisOverlay && thisOverlay->supportsGetProperty()) { + QStringList propertiesToFetch = map[key].toStringList(); + for (const auto& property : propertiesToFetch) { + overlayResult[property] = thisOverlay->getProperty(property); + } + } + resultMap[key] = overlayResult; + } + result.value = resultMap; + return result; +} + OverlayPropertyResult::OverlayPropertyResult() { } diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index bfb775b041..100f853a96 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -190,6 +190,10 @@ public slots: */ OverlayPropertyResult getProperty(OverlayID id, const QString& property); + OverlayPropertyResult getProperties(const OverlayID& id, const QStringList& properties); + + OverlayPropertyResult getOverlaysProperties(const QVariant& overlaysProperties); + /*jsdoc * Find the closest 3D overlay hit by a pick ray. * From 9afe0bc12448278492a98e33e74498fb8abd195b Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 7 Jul 2017 13:56:28 -0700 Subject: [PATCH 20/27] Tweak frame timing to avoid overloading the main thread --- interface/src/Application.cpp | 67 ++++++++++++++--------------------- 1 file changed, 26 insertions(+), 41 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6f94e74120..fe5f78a50b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2719,56 +2719,41 @@ bool Application::importSVOFromURL(const QString& urlString) { return true; } +bool _renderRequested { false }; + bool Application::event(QEvent* event) { if (!Menu::getInstance()) { return false; } - // Presentation/painting logic - // TODO: Decouple presentation and painting loops - static bool isPaintingThrottled = false; - if ((int)event->type() == (int)Present) { - if (isPaintingThrottled) { - // If painting (triggered by presentation) is hogging the main thread, - // repost as low priority to avoid hanging the GUI. - // This has the effect of allowing presentation to exceed the paint budget by X times and - // only dropping every (1/X) frames, instead of every ceil(X) frames - // (e.g. at a 60FPS target, painting for 17us would fall to 58.82FPS instead of 30FPS). - removePostedEvents(this, Present); - postEvent(this, new QEvent(static_cast(Present)), Qt::LowEventPriority); - isPaintingThrottled = false; + int type = event->type(); + switch (type) { + case Event::Lambda: + static_cast(event)->call(); return true; - } - float nsecsElapsed = (float)_lastTimeUpdated.nsecsElapsed(); - if (shouldPaint(nsecsElapsed)) { - _lastTimeUpdated.start(); - idle(nsecsElapsed); - postEvent(this, new QEvent(static_cast(Paint)), Qt::HighEventPriority); - } - isPaintingThrottled = true; + case Event::Present: + if (!_renderRequested) { + float nsecsElapsed = (float)_lastTimeUpdated.nsecsElapsed(); + if (shouldPaint(nsecsElapsed)) { + _renderRequested = true; + _lastTimeUpdated.start(); + idle(nsecsElapsed); + postEvent(this, new QEvent(static_cast(Paint)), Qt::HighEventPriority); + } + } + return true; - return true; - } else if ((int)event->type() == (int)Paint) { - // NOTE: This must be updated as close to painting as possible, - // or AvatarInputs will mysteriously move to the bottom-right - AvatarInputs::getInstance()->update(); + case Event::Paint: + // NOTE: This must be updated as close to painting as possible, + // or AvatarInputs will mysteriously move to the bottom-right + AvatarInputs::getInstance()->update(); + paintGL(); + _renderRequested = false; + return true; - paintGL(); - - isPaintingThrottled = false; - - return true; - } else if ((int)event->type() == (int)Idle) { - float nsecsElapsed = (float)_lastTimeUpdated.nsecsElapsed(); - idle(nsecsElapsed); - - return true; - } - - if ((int)event->type() == (int)Lambda) { - static_cast(event)->call(); - return true; + default: + break; } { From ee1f6dfa4220754465891e8abe9313638177a2d3 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 7 Jul 2017 22:02:56 -0700 Subject: [PATCH 21/27] More tweaks for improved script performance --- interface/src/Application.cpp | 4 ++- interface/src/ui/overlays/Overlays.cpp | 37 +++++++++++--------------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fe5f78a50b..a59b745b78 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2741,7 +2741,7 @@ bool Application::event(QEvent* event) { idle(nsecsElapsed); postEvent(this, new QEvent(static_cast(Paint)), Qt::HighEventPriority); } - } + } return true; case Event::Paint: @@ -2749,6 +2749,8 @@ bool Application::event(QEvent* event) { // or AvatarInputs will mysteriously move to the bottom-right AvatarInputs::getInstance()->update(); paintGL(); + // wait for the next present event before starting idle / paint again + removePostedEvents(this, Present); _renderRequested = false; return true; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 2f22b62306..72682fcb8c 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -152,6 +152,7 @@ Overlay::Pointer Overlays::getOverlay(OverlayID id) const { OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties) { if (QThread::currentThread() != thread()) { OverlayID result; + PROFILE_RANGE(script, __FUNCTION__); BLOCKING_INVOKE_METHOD(this, "addOverlay", Q_RETURN_ARG(OverlayID, result), Q_ARG(QString, type), Q_ARG(QVariant, properties)); return result; } @@ -220,6 +221,7 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) { OverlayID Overlays::cloneOverlay(OverlayID id) { if (QThread::currentThread() != thread()) { OverlayID result; + PROFILE_RANGE(script, __FUNCTION__); BLOCKING_INVOKE_METHOD(this, "cloneOverlay", Q_RETURN_ARG(OverlayID, result), Q_ARG(OverlayID, id)); return result; } @@ -315,6 +317,7 @@ void Overlays::deleteOverlay(OverlayID id) { QString Overlays::getOverlayType(OverlayID overlayId) { if (QThread::currentThread() != thread()) { QString result; + PROFILE_RANGE(script, __FUNCTION__); BLOCKING_INVOKE_METHOD(this, "getOverlayType", Q_RETURN_ARG(QString, result), Q_ARG(OverlayID, overlayId)); return result; } @@ -329,6 +332,7 @@ QString Overlays::getOverlayType(OverlayID overlayId) { QObject* Overlays::getOverlayObject(OverlayID id) { if (QThread::currentThread() != thread()) { QObject* result; + PROFILE_RANGE(script, __FUNCTION__); BLOCKING_INVOKE_METHOD(this, "getOverlayObject", Q_RETURN_ARG(QObject*, result), Q_ARG(OverlayID, id)); return result; } @@ -384,12 +388,6 @@ void Overlays::setParentPanel(OverlayID childId, OverlayID panelId) { #endif OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) { - if (QThread::currentThread() != thread()) { - OverlayID result; - BLOCKING_INVOKE_METHOD(this, "getOverlayAtPoint", Q_RETURN_ARG(OverlayID, result), Q_ARG(glm::vec2, point)); - return result; - } - if (!_enabled) { return UNKNOWN_OVERLAY_ID; } @@ -486,18 +484,6 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionInternal(const PickR const QVector& overlaysToInclude, const QVector& overlaysToDiscard, bool visibleOnly, bool collidableOnly) { - if (QThread::currentThread() != thread()) { - RayToOverlayIntersectionResult result; - BLOCKING_INVOKE_METHOD(this, "findRayIntersectionInternal", Q_RETURN_ARG(RayToOverlayIntersectionResult, result), - Q_ARG(PickRay, ray), - Q_ARG(bool, precisionPicking), - Q_ARG(QVector, overlaysToInclude), - Q_ARG(QVector, overlaysToDiscard), - Q_ARG(bool, visibleOnly), - Q_ARG(bool, collidableOnly)); - return result; - } - float bestDistance = std::numeric_limits::max(); bool bestIsFront = false; @@ -616,6 +602,7 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& objectVar bool Overlays::isLoaded(OverlayID id) { if (QThread::currentThread() != thread()) { bool result; + PROFILE_RANGE(script, __FUNCTION__); BLOCKING_INVOKE_METHOD(this, "isLoaded", Q_RETURN_ARG(bool, result), Q_ARG(OverlayID, id)); return result; } @@ -630,6 +617,7 @@ bool Overlays::isLoaded(OverlayID id) { QSizeF Overlays::textSize(OverlayID id, const QString& text) { if (QThread::currentThread() != thread()) { QSizeF result; + PROFILE_RANGE(script, __FUNCTION__); BLOCKING_INVOKE_METHOD(this, "textSize", Q_RETURN_ARG(QSizeF, result), Q_ARG(OverlayID, id), Q_ARG(QString, text)); return result; } @@ -708,6 +696,7 @@ void Overlays::deletePanel(OverlayID panelId) { bool Overlays::isAddedOverlay(OverlayID id) { if (QThread::currentThread() != thread()) { bool result; + PROFILE_RANGE(script, __FUNCTION__); BLOCKING_INVOKE_METHOD(this, "isAddedOverlay", Q_RETURN_ARG(bool, result), Q_ARG(OverlayID, id)); return result; } @@ -743,6 +732,7 @@ void Overlays::sendHoverLeaveOverlay(OverlayID id, PointerEvent event) { OverlayID Overlays::getKeyboardFocusOverlay() { if (QThread::currentThread() != thread()) { OverlayID result; + PROFILE_RANGE(script, __FUNCTION__); BLOCKING_INVOKE_METHOD(this, "getKeyboardFocusOverlay", Q_RETURN_ARG(OverlayID, result)); return result; } @@ -762,6 +752,7 @@ void Overlays::setKeyboardFocusOverlay(OverlayID id) { float Overlays::width() { if (QThread::currentThread() != thread()) { float result; + PROFILE_RANGE(script, __FUNCTION__); BLOCKING_INVOKE_METHOD(this, "width", Q_RETURN_ARG(float, result)); return result; } @@ -773,6 +764,7 @@ float Overlays::width() { float Overlays::height() { if (QThread::currentThread() != thread()) { float result; + PROFILE_RANGE(script, __FUNCTION__); BLOCKING_INVOKE_METHOD(this, "height", Q_RETURN_ARG(float, result)); return result; } @@ -982,10 +974,11 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) { QVector Overlays::findOverlays(const glm::vec3& center, float radius) { QVector result; - if (QThread::currentThread() != thread()) { - BLOCKING_INVOKE_METHOD(this, "findOverlays", Q_RETURN_ARG(QVector, result), Q_ARG(glm::vec3, center), Q_ARG(float, radius)); - return result; - } + //if (QThread::currentThread() != thread()) { + // PROFILE_RANGE(script, __FUNCTION__); + // BLOCKING_INVOKE_METHOD(this, "findOverlays", Q_RETURN_ARG(QVector, result), Q_ARG(glm::vec3, center), Q_ARG(float, radius)); + // return result; + //} QMutexLocker locker(&_mutex); QMapIterator i(_overlaysWorld); From 75e1b265d55a81ffa583b4058ed3153e1b9089cc Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 10 Jul 2017 17:48:53 +0100 Subject: [PATCH 22/27] comment out code that causes a crash on launch from fresh install --- libraries/ui/src/ui/OffscreenQmlSurface.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 19cd37a6cb..9df727424f 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -831,7 +831,9 @@ bool OffscreenQmlSurface::eventFilter(QObject* originalDestination, QEvent* even mouseEvent->screenPos(), mouseEvent->button(), mouseEvent->buttons(), mouseEvent->modifiers()); if (event->type() == QEvent::MouseMove) { - _qmlContext->setContextProperty("lastMousePosition", transformedPos); + // TODO - this line necessary for the QML Tooltop to work (which is not currently being used), but it causes interface to crash on launch on a fresh install + // need to investigate into why this crash is happening. + //_qmlContext->setContextProperty("lastMousePosition", transformedPos); } mappedEvent.ignore(); if (QCoreApplication::sendEvent(_quickWindow, &mappedEvent)) { From 89a072cfeed52dcfd22281b232aa4084a1c8cac1 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 10 Jul 2017 19:05:07 +0100 Subject: [PATCH 23/27] fixed hmd keyboard for goto --- .../resources/qml/hifi/tablet/TabletAddressDialog.qml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index a02e79a5e2..8bf13bad76 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -99,7 +99,13 @@ StackView { height: parent.height MouseArea { - anchors.fill: parent + anchors { + top: parent.top + left: parent.left + right: parent.right + bottom: keyboard.top + } + propagateComposedEvents: true onPressed: { parent.forceActiveFocus(); From 98ccfa80a229fa37aa2f7c21dd0f1079583f24e5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 22 Jun 2017 14:32:11 -0700 Subject: [PATCH 24/27] don't add node missing from a replicated kill packet --- assignment-client/src/avatars/AvatarMixer.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index b4aae40c10..eea44f031e 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -85,7 +85,22 @@ void AvatarMixer::handleReplicatedPacket(QSharedPointer message auto nodeList = DependencyManager::get(); auto nodeID = QUuid::fromRfc4122(message->peek(NUM_BYTES_RFC4122_UUID)); - auto replicatedNode = addOrUpdateReplicatedNode(nodeID, message->getSenderSockAddr()); + SharedNodePointer replicatedNode; + + if (message->getType() == PacketType::ReplicatedKillAvatar) { + // this is a kill packet, which we should only process if we already have the node in our list + // since it of course does not make sense to add a node just to remove it an instant later + replicatedNode = nodeList->nodeWithUUID(nodeID); + + if (!replicatedNode) { + return; + } + } else { + replicatedNode = addOrUpdateReplicatedNode(nodeID, message->getSenderSockAddr()); + } + + // we better have a node to work with at this point + assert(replicatedNode); if (message->getType() == PacketType::ReplicatedAvatarIdentity) { handleAvatarIdentityPacket(message, replicatedNode); From c32f4ab0d3e0d82974c6d6b5f8c787d331e833ce Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 10 Jul 2017 14:24:53 -0700 Subject: [PATCH 25/27] CR --- assignment-client/src/Agent.cpp | 8 ++++---- assignment-client/src/avatars/AvatarMixerSlave.cpp | 8 ++++---- libraries/avatars/src/AvatarData.cpp | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index beeae7527e..1de7fa135b 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -614,11 +614,11 @@ void Agent::processAgentAvatar() { if (avatarByteArray.size() > maximumByteArraySize) { qWarning() << " scriptedAvatar->toByteArrayStateful() without facial data resulted in very large buffer:" << avatarByteArray.size() << "... reduce to MinimumData"; avatarByteArray = scriptedAvatar->toByteArrayStateful(AvatarData::MinimumData, true); - } - if (avatarByteArray.size() > maximumByteArraySize) { - qWarning() << " scriptedAvatar->toByteArrayStateful() MinimumData resulted in very large buffer:" << avatarByteArray.size() << "... FAIL!!"; - return; + if (avatarByteArray.size() > maximumByteArraySize) { + qWarning() << " scriptedAvatar->toByteArrayStateful() MinimumData resulted in very large buffer:" << avatarByteArray.size() << "... FAIL!!"; + return; + } } } diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 7e37f583ff..34feafbd4d 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -383,11 +383,11 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) qCWarning(avatars) << "otherAvatar.toByteArray() without facial data resulted in very large buffer:" << bytes.size() << "... reduce to MinimumData"; bytes = otherAvatar->toByteArray(AvatarData::MinimumData, lastEncodeForOther, lastSentJointsForOther, hasFlagsOut, dropFaceTracking, distanceAdjust, viewerPosition, &lastSentJointsForOther); - } - if (bytes.size() > MAX_ALLOWED_AVATAR_DATA) { - qCWarning(avatars) << "otherAvatar.toByteArray() MinimumData resulted in very large buffer:" << bytes.size() << "... FAIL!!"; - includeThisAvatar = false; + if (bytes.size() > MAX_ALLOWED_AVATAR_DATA) { + qCWarning(avatars) << "otherAvatar.toByteArray() MinimumData resulted in very large buffer:" << bytes.size() << "... FAIL!!"; + includeThisAvatar = false; + } } } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 036d67da17..96475159f2 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1754,11 +1754,11 @@ void AvatarData::sendAvatarDataPacket() { if (avatarByteArray.size() > maximumByteArraySize) { qCWarning(avatars) << "toByteArrayStateful() without facial data resulted in very large buffer:" << avatarByteArray.size() << "... reduce to MinimumData"; avatarByteArray = toByteArrayStateful(MinimumData, true); - } - if (avatarByteArray.size() > maximumByteArraySize) { - qCWarning(avatars) << "toByteArrayStateful() MinimumData resulted in very large buffer:" << avatarByteArray.size() << "... FAIL!!"; - return; + if (avatarByteArray.size() > maximumByteArraySize) { + qCWarning(avatars) << "toByteArrayStateful() MinimumData resulted in very large buffer:" << avatarByteArray.size() << "... FAIL!!"; + return; + } } } From 01ca1926131ebf8fcd1a544094e9d61fbccd3356 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 11 Jul 2017 21:16:13 +0100 Subject: [PATCH 26/27] fixed tablet scrolling --- interface/src/ui/overlays/Web3DOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index 80f11fa552..1c01bd3781 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -451,7 +451,7 @@ void Web3DOverlay::handlePointerEventAsTouch(const PointerEvent& event) { // In Qt 5.9 mouse events must be sent before touch events to make sure some QtQuick components will // receive mouse events #if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) - if (!(this->_pressed && event.getType() == PointerEvent::Move)) { + if (event.getType() == PointerEvent::Move) { QMouseEvent* mouseEvent = new QMouseEvent(mouseType, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier); QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent); } From 2f192fd48a23e8895c7e898ebfcdf74bb5bd7fe7 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 11 Jul 2017 21:19:06 +0100 Subject: [PATCH 27/27] added scroll fix for qt 5.6 --- interface/src/ui/overlays/Web3DOverlay.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index 1c01bd3781..acba15d2ec 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -459,11 +459,10 @@ void Web3DOverlay::handlePointerEventAsTouch(const PointerEvent& event) { QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent); #if QT_VERSION < QT_VERSION_CHECK(5, 9, 0) - if (this->_pressed && event.getType() == PointerEvent::Move) { - return; + if (event.getType() == PointerEvent::Move) { + QMouseEvent* mouseEvent = new QMouseEvent(mouseType, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier); + QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent); } - QMouseEvent* mouseEvent = new QMouseEvent(mouseType, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier); - QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent); #endif }