From 91db29e92f6e445c6f6ba98fea427e15e26df056 Mon Sep 17 00:00:00 2001 From: Mike Moody Date: Fri, 2 Jun 2017 15:34:25 -0700 Subject: [PATCH 01/70] 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/70] 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/70] 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/70] 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/70] 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 9e822de196ed831ee3c35e31eec19f7f74728820 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 27 Jun 2017 17:40:23 -0700 Subject: [PATCH 06/70] remove local collection of radius ignored nodes --- .../src/avatars/AvatarMixerClientData.cpp | 3 --- interface/src/avatar/AvatarManager.cpp | 4 ---- .../src/avatars-renderer/Avatar.cpp | 3 +-- libraries/avatars/src/AvatarHashMap.cpp | 7 ------ libraries/avatars/src/AvatarHashMap.h | 1 - libraries/networking/src/NodeList.cpp | 22 +------------------ libraries/networking/src/NodeList.h | 4 ---- libraries/networking/src/udt/PacketHeaders.h | 1 - 8 files changed, 2 insertions(+), 43 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index 4d80bc7d17..a4bf8fa253 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -108,9 +108,6 @@ void AvatarMixerClientData::ignoreOther(SharedNodePointer self, SharedNodePointe void AvatarMixerClientData::removeFromRadiusIgnoringSet(SharedNodePointer self, const QUuid& other) { if (isRadiusIgnoring(other)) { _radiusIgnoredOthers.erase(other); - auto exitingSpaceBubblePacket = NLPacket::create(PacketType::ExitingSpaceBubble, NUM_BYTES_RFC4122_UUID); - exitingSpaceBubblePacket->write(other.toRfc4122()); - DependencyManager::get()->sendUnreliablePacket(*exitingSpaceBubblePacket, *self); } } diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 20b3949bc6..74775245a7 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -62,7 +62,6 @@ AvatarManager::AvatarManager(QObject* parent) : packetReceiver.registerListener(PacketType::BulkAvatarData, this, "processAvatarDataPacket"); packetReceiver.registerListener(PacketType::KillAvatar, this, "processKillAvatar"); packetReceiver.registerListener(PacketType::AvatarIdentity, this, "processAvatarIdentityPacket"); - packetReceiver.registerListener(PacketType::ExitingSpaceBubble, this, "processExitingSpaceBubble"); // when we hear that the user has ignored an avatar by session UUID // immediately remove that avatar instead of waiting for the absence of packets from avatar mixer @@ -319,9 +318,6 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble) { emit DependencyManager::get()->enteredIgnoreRadius(); - } - if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble || removalReason == YourAvatarEnteredTheirBubble) { - DependencyManager::get()->radiusIgnoreNodeBySessionID(avatar->getSessionUUID(), true); } else if (removalReason == KillAvatarReason::AvatarDisconnected) { // remove from node sets, if present DependencyManager::get()->removeFromIgnoreMuteSets(avatar->getSessionUUID()); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index a0a348388e..9355b15ed8 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1439,8 +1439,7 @@ void Avatar::addToScene(AvatarSharedPointer myHandle, const render::ScenePointer if (scene) { auto nodelist = DependencyManager::get(); if (showAvatars - && !nodelist->isIgnoringNode(getSessionUUID()) - && !nodelist->isRadiusIgnoringNode(getSessionUUID())) { + && !nodelist->isIgnoringNode(getSessionUUID())) { render::Transaction transaction; addToScene(myHandle, scene, transaction); scene->enqueueTransaction(transaction); diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index e8c37bdaa8..3712080cdb 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -170,13 +170,6 @@ void AvatarHashMap::processKillAvatar(QSharedPointer message, S removeAvatar(sessionUUID, reason); } -void AvatarHashMap::processExitingSpaceBubble(QSharedPointer message, SharedNodePointer sendingNode) { - // read the node id - QUuid sessionUUID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); - auto nodeList = DependencyManager::get(); - nodeList->radiusIgnoreNodeBySessionID(sessionUUID, false); -} - void AvatarHashMap::removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason) { QWriteLocker locker(&_hashLock); diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index 21ea8081c7..68fc232685 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -60,7 +60,6 @@ protected slots: void processAvatarDataPacket(QSharedPointer message, SharedNodePointer sendingNode); void processAvatarIdentityPacket(QSharedPointer message, SharedNodePointer sendingNode); void processKillAvatar(QSharedPointer message, SharedNodePointer sendingNode); - void processExitingSpaceBubble(QSharedPointer message, SharedNodePointer sendingNode); protected: AvatarHashMap(); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index e8506e5263..ef9b131928 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -239,11 +239,7 @@ void NodeList::reset() { LimitedNodeList::reset(); _numNoReplyDomainCheckIns = 0; - - // lock and clear our set of radius ignored IDs - _radiusIgnoredSetLock.lockForWrite(); - _radiusIgnoredNodeIDs.clear(); - _radiusIgnoredSetLock.unlock(); +; // lock and clear our set of ignored IDs _ignoredSetLock.lockForWrite(); _ignoredNodeIDs.clear(); @@ -809,22 +805,6 @@ void NodeList::sendIgnoreRadiusStateToNode(const SharedNodePointer& destinationN sendPacket(std::move(ignorePacket), *destinationNode); } -void NodeList::radiusIgnoreNodeBySessionID(const QUuid& nodeID, bool radiusIgnoreEnabled) { - if (radiusIgnoreEnabled) { - QReadLocker radiusIgnoredSetLocker{ &_radiusIgnoredSetLock }; // read lock for insert - // add this nodeID to our set of ignored IDs - _radiusIgnoredNodeIDs.insert(nodeID); - } else { - QWriteLocker radiusIgnoredSetLocker{ &_radiusIgnoredSetLock }; // write lock for unsafe_erase - _radiusIgnoredNodeIDs.unsafe_erase(nodeID); - } -} - -bool NodeList::isRadiusIgnoringNode(const QUuid& nodeID) const { - QReadLocker radiusIgnoredSetLocker{ &_radiusIgnoredSetLock }; // read lock for reading - return _radiusIgnoredNodeIDs.find(nodeID) != _radiusIgnoredNodeIDs.cend(); -} - void NodeList::ignoreNodeBySessionID(const QUuid& nodeID, bool ignoreEnabled) { // enumerate the nodes to send a reliable ignore packet to each that can leverage it if (!nodeID.isNull() && _sessionUUID != nodeID) { diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 6db760b3ca..b3a12153e5 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -77,8 +77,6 @@ public: void toggleIgnoreRadius() { ignoreNodesInRadius(!getIgnoreRadiusEnabled()); } void enableIgnoreRadius() { ignoreNodesInRadius(true); } void disableIgnoreRadius() { ignoreNodesInRadius(false); } - void radiusIgnoreNodeBySessionID(const QUuid& nodeID, bool radiusIgnoreEnabled); - bool isRadiusIgnoringNode(const QUuid& other) const; void ignoreNodeBySessionID(const QUuid& nodeID, bool ignoreEnabled); bool isIgnoringNode(const QUuid& nodeID) const; void personalMuteNodeBySessionID(const QUuid& nodeID, bool muteEnabled); @@ -166,8 +164,6 @@ private: QTimer _keepAlivePingTimer; bool _requestsDomainListData; - mutable QReadWriteLock _radiusIgnoredSetLock; - tbb::concurrent_unordered_set _radiusIgnoredNodeIDs; mutable QReadWriteLock _ignoredSetLock; tbb::concurrent_unordered_set _ignoredNodeIDs; mutable QReadWriteLock _personalMutedSetLock; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 6c42193e11..848bfd97cf 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -105,7 +105,6 @@ public: UsernameFromIDReply, ViewFrustum, RequestsDomainListData, - ExitingSpaceBubble, PerAvatarGainSet, EntityScriptGetStatus, EntityScriptGetStatusReply, From be37998b47ad185fe53753e679264d7cc0d6d5c0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 28 Jun 2017 10:11:55 -0700 Subject: [PATCH 07/70] remove stray semicolon in NodeList --- libraries/networking/src/NodeList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index ef9b131928..09622ff19d 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -239,7 +239,7 @@ void NodeList::reset() { LimitedNodeList::reset(); _numNoReplyDomainCheckIns = 0; -; + // lock and clear our set of ignored IDs _ignoredSetLock.lockForWrite(); _ignoredNodeIDs.clear(); From f7a3b3a4116498bd0f8b011be8ed4c80ccadc3c6 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 29 Jun 2017 15:55:47 +0200 Subject: [PATCH 08/70] Experimenting faster getters on Avatar for scripts --- libraries/animation/src/Rig.cpp | 19 ++++++++++++++----- .../src/avatars-renderer/Avatar.cpp | 16 ++++++++-------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 3d04b0b26f..3ea03bc5f9 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -404,8 +404,10 @@ void Rig::setJointRotation(int index, bool valid, const glm::quat& rotation, flo } bool Rig::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position, glm::vec3 translation, glm::quat rotation) const { - if (isIndexValid(jointIndex)) { - position = (rotation * _internalPoseSet._absolutePoses[jointIndex].trans()) + translation; + // if (isIndexValid(jointIndex)) { + QReadLocker readLock(&_externalPoseSetLock); + if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._absolutePoses.size()) { + position = (rotation * _externalPoseSet._absolutePoses[jointIndex].trans()) + translation; return true; } else { return false; @@ -413,17 +415,24 @@ bool Rig::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position, glm: } bool Rig::getJointPosition(int jointIndex, glm::vec3& position) const { +/* if (isIndexValid(jointIndex)) { position = _internalPoseSet._absolutePoses[jointIndex].trans(); return true; } else { return false; - } + }*/ + return getAbsoluteJointTranslationInRigFrame(jointIndex, position); } bool Rig::getJointRotationInWorldFrame(int jointIndex, glm::quat& result, const glm::quat& rotation) const { - if (isIndexValid(jointIndex)) { - result = rotation * _internalPoseSet._absolutePoses[jointIndex].rot(); + // if (isIndexValid(jointIndex)) { + // result = rotation * _internalPoseSet._absolutePoses[jointIndex].rot(); + // return true; + + QReadLocker readLock(&_externalPoseSetLock); + if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._absolutePoses.size()) { + result = rotation * _externalPoseSet._absolutePoses[jointIndex].rot(); return true; } else { return false; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index a0a348388e..fbf2254248 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1008,12 +1008,12 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const { } int Avatar::getJointIndex(const QString& name) const { - if (QThread::currentThread() != thread()) { + /* if (QThread::currentThread() != thread()) { int result; QMetaObject::invokeMethod(const_cast(this), "getJointIndex", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, result), Q_ARG(const QString&, name)); return result; - } + } */ int result = getFauxJointIndex(name); if (result != -1) { return result; @@ -1022,34 +1022,34 @@ int Avatar::getJointIndex(const QString& name) const { } QStringList Avatar::getJointNames() const { - if (QThread::currentThread() != thread()) { +/* if (QThread::currentThread() != thread()) { QStringList result; QMetaObject::invokeMethod(const_cast(this), "getJointNames", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QStringList, result)); return result; - } + }*/ return _skeletonModel->isActive() ? _skeletonModel->getFBXGeometry().getJointNames() : QStringList(); } glm::vec3 Avatar::getJointPosition(int index) const { - if (QThread::currentThread() != thread()) { +/* if (QThread::currentThread() != thread()) { glm::vec3 position; QMetaObject::invokeMethod(const_cast(this), "getJointPosition", Qt::BlockingQueuedConnection, Q_RETURN_ARG(glm::vec3, position), Q_ARG(const int, index)); return position; - } + }*/ glm::vec3 position; _skeletonModel->getJointPositionInWorldFrame(index, position); return position; } glm::vec3 Avatar::getJointPosition(const QString& name) const { - if (QThread::currentThread() != thread()) { +/* if (QThread::currentThread() != thread()) { glm::vec3 position; QMetaObject::invokeMethod(const_cast(this), "getJointPosition", Qt::BlockingQueuedConnection, Q_RETURN_ARG(glm::vec3, position), Q_ARG(const QString&, name)); return position; - } + }*/ glm::vec3 position; _skeletonModel->getJointPositionInWorldFrame(getJointIndex(name), position); return position; From 38baeabbe5bf4e4625da9c1242140acbe418a1da Mon Sep 17 00:00:00 2001 From: 1P-Cusack <1p-cusack@1stplayable.com> Date: Mon, 3 Jul 2017 13:52:06 -0400 Subject: [PATCH 09/70] Add View->Enter First Person Mode in HMD checkbox. When checked, changing to an HMD display will switch the user to first person mode. WL 21425. --- interface/src/Application.cpp | 6 ++++++ interface/src/Menu.cpp | 3 +++ interface/src/Menu.h | 1 + 3 files changed, 10 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 75bcee0703..99ff486d5d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6900,6 +6900,12 @@ void Application::updateDisplayMode() { // reset the avatar, to set head and hand palms back to a reasonable default pose. getMyAvatar()->reset(false); + // switch to first person if entering hmd and setting is checked + if (isHmd && menu->isOptionChecked(MenuOption::FirstPersonHMD)) { + menu->setIsOptionChecked(MenuOption::FirstPerson, true); + cameraMenuChanged(); + } + Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 7d4535c681..9bda575305 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -258,6 +258,9 @@ Menu::Menu() { // View > Overlays addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Overlays, 0, true); + // View > Enter First Person Mode in HMD + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPersonHMD, 0, false); + // Navigate menu ---------------------------------- MenuWrapper* navigateMenu = addMenu("Navigate"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index cc8e67c8f7..1848a4add7 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -105,6 +105,7 @@ namespace MenuOption { const QString ExpandPhysicsSimulationTiming = "Expand /physics"; const QString ExpandUpdateTiming = "Expand /update"; const QString FirstPerson = "First Person"; + const QString FirstPersonHMD = "Enter First Person Mode in HMD"; const QString FivePointCalibration = "5 Point Calibration"; const QString FixGaze = "Fix Gaze (no saccade)"; const QString Forward = "Forward"; From e9a8c3f5e816620d168d14b8a166d056c6d3728e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 4 Jul 2017 15:52:03 -0700 Subject: [PATCH 10/70] rename atp-get to atp-client. add ability to list atp file mappings and to upload new files --- tools/CMakeLists.txt | 4 +- tools/{atp-get => atp-client}/CMakeLists.txt | 2 +- .../src/ATPClientApp.cpp} | 201 +++++++++++++----- .../src/ATPClientApp.h} | 29 ++- tools/{atp-get => atp-client}/src/main.cpp | 6 +- 5 files changed, 179 insertions(+), 63 deletions(-) rename tools/{atp-get => atp-client}/CMakeLists.txt (77%) rename tools/{atp-get/src/ATPGetApp.cpp => atp-client/src/ATPClientApp.cpp} (52%) rename tools/{atp-get/src/ATPGetApp.h => atp-client/src/ATPClientApp.h} (64%) rename tools/{atp-get => atp-client}/src/main.cpp (89%) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 0561956709..5de44e8897 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -17,8 +17,8 @@ set_target_properties(ac-client PROPERTIES FOLDER "Tools") add_subdirectory(skeleton-dump) set_target_properties(skeleton-dump PROPERTIES FOLDER "Tools") -add_subdirectory(atp-get) -set_target_properties(atp-get PROPERTIES FOLDER "Tools") +add_subdirectory(atp-client) +set_target_properties(atp-client PROPERTIES FOLDER "Tools") add_subdirectory(oven) set_target_properties(oven PROPERTIES FOLDER "Tools") diff --git a/tools/atp-get/CMakeLists.txt b/tools/atp-client/CMakeLists.txt similarity index 77% rename from tools/atp-get/CMakeLists.txt rename to tools/atp-client/CMakeLists.txt index 75f92b787d..4cee30bcc3 100644 --- a/tools/atp-get/CMakeLists.txt +++ b/tools/atp-client/CMakeLists.txt @@ -1,4 +1,4 @@ -set(TARGET_NAME atp-get) +set(TARGET_NAME atp-client) setup_hifi_project(Core Widgets) setup_memory_debugger() link_hifi_libraries(shared networking) diff --git a/tools/atp-get/src/ATPGetApp.cpp b/tools/atp-client/src/ATPClientApp.cpp similarity index 52% rename from tools/atp-get/src/ATPGetApp.cpp rename to tools/atp-client/src/ATPClientApp.cpp index 4125582c21..ac69da7e96 100644 --- a/tools/atp-get/src/ATPGetApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -1,6 +1,6 @@ // -// ATPGetApp.cpp -// tools/atp-get/src +// ATPClientApp.cpp +// tools/atp-client/src // // Created by Seth Alves on 2017-3-15 // Copyright 2017 High Fidelity, Inc. @@ -15,26 +15,36 @@ #include #include #include + #include #include #include #include #include +#include -#include "ATPGetApp.h" +#include "ATPClientApp.h" -ATPGetApp::ATPGetApp(int argc, char* argv[]) : +#define HIGH_FIDELITY_ATP_CLIENT_USER_AGENT "Mozilla/5.0 (HighFidelityATPClient)" + +ATPClientApp::ATPClientApp(int argc, char* argv[]) : QCoreApplication(argc, argv) { // parse command-line QCommandLineParser parser; - parser.setApplicationDescription("High Fidelity ATP-Get"); + parser.setApplicationDescription("High Fidelity ATP-Client"); const QCommandLineOption helpOption = parser.addHelpOption(); const QCommandLineOption verboseOutput("v", "verbose output"); parser.addOption(verboseOutput); + const QCommandLineOption uploadOption("T", "upload local file", "local-file-to-send"); + parser.addOption(uploadOption); + + const QCommandLineOption outputFilenameOption("o", "output filename", "output-file-name"); + parser.addOption(outputFilenameOption); + const QCommandLineOption domainAddressOption("d", "domain-server address", "127.0.0.1"); parser.addOption(domainAddressOption); @@ -70,67 +80,94 @@ ATPGetApp::ATPGetApp(int argc, char* argv[]) : } - QStringList filenames = parser.positionalArguments(); - if (filenames.empty() || filenames.size() > 2) { - qDebug() << "give remote url and optional local filename as arguments"; + QStringList posArgs = parser.positionalArguments(); + if (posArgs.size() != 1) { + qDebug() << "give remote url argument"; parser.showHelp(); Q_UNREACHABLE(); } - _url = QUrl(filenames[0]); + _url = QUrl(posArgs[0]); if (_url.scheme() != "atp") { qDebug() << "url should start with atp:"; parser.showHelp(); Q_UNREACHABLE(); } - if (filenames.size() == 2) { - _localOutputFile = filenames[1]; + int domainPort = 40103; + if (_url.port() != -1) { + domainPort = _url.port(); } - QString domainServerAddress = "127.0.0.1:40103"; + if (parser.isSet(outputFilenameOption)) { + _localOutputFile = parser.value(outputFilenameOption); + } + + if (parser.isSet(uploadOption)) { + _localUploadFile = parser.value(uploadOption); + } + + + if (parser.isSet(listenPortOption)) { + _listenPort = parser.value(listenPortOption).toInt(); + } + + QString domainServerAddress = QString("127.0.0.1") + ":" + QString::number(domainPort); if (parser.isSet(domainAddressOption)) { domainServerAddress = parser.value(domainAddressOption); + qDebug() << "domainServerAddress is " << domainServerAddress; + connectToDomain(domainServerAddress); + } else if (!_url.host().isEmpty()) { + QUrl domainURL; + domainURL.setScheme("hifi"); + domainURL.setHost(_url.host()); + connectToDomain(domainURL.toString()); + } else { + qDebug() << "domainServerAddress is default " << domainServerAddress; + connectToDomain(domainServerAddress); } +} + + +void ATPClientApp::connectToDomain(QString domainServerAddress) { if (_verbose) { qDebug() << "domain-server address is" << domainServerAddress; } - int listenPort = INVALID_PORT; - if (parser.isSet(listenPortOption)) { - listenPort = parser.value(listenPortOption).toInt(); - } + DependencyManager::set(); + auto accountManager = DependencyManager::get(); + QString username = accountManager->getAccountInfo().getUsername(); + qDebug() << "username is" << username; Setting::init(); DependencyManager::registerInheritance(); - DependencyManager::set([&]{ return QString("Mozilla/5.0 (HighFidelityATPGet)"); }); + DependencyManager::set([&]{ return QString(HIGH_FIDELITY_ATP_CLIENT_USER_AGENT); }); DependencyManager::set(); - DependencyManager::set(NodeType::Agent, listenPort); - + DependencyManager::set(NodeType::Agent, _listenPort); auto nodeList = DependencyManager::get(); nodeList->startThread(); // setup a timer for domain-server check ins - QTimer* domainCheckInTimer = new QTimer(nodeList.data()); - connect(domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn); - domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); + _domainCheckInTimer = new QTimer(nodeList.data()); + connect(_domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn); + _domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); const DomainHandler& domainHandler = nodeList->getDomainHandler(); connect(&domainHandler, SIGNAL(hostnameChanged(const QString&)), SLOT(domainChanged(const QString&))); // connect(&domainHandler, SIGNAL(resetting()), SLOT(resettingDomain())); // connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(clearDomainOctreeDetails())); - connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ATPGetApp::domainConnectionRefused); + connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ATPClientApp::domainConnectionRefused); - connect(nodeList.data(), &NodeList::nodeAdded, this, &ATPGetApp::nodeAdded); - connect(nodeList.data(), &NodeList::nodeKilled, this, &ATPGetApp::nodeKilled); - connect(nodeList.data(), &NodeList::nodeActivated, this, &ATPGetApp::nodeActivated); + connect(nodeList.data(), &NodeList::nodeAdded, this, &ATPClientApp::nodeAdded); + connect(nodeList.data(), &NodeList::nodeKilled, this, &ATPClientApp::nodeKilled); + connect(nodeList.data(), &NodeList::nodeActivated, this, &ATPClientApp::nodeActivated); // connect(nodeList.data(), &NodeList::uuidChanged, getMyAvatar(), &MyAvatar::setSessionUUID); - // connect(nodeList.data(), &NodeList::uuidChanged, this, &ATPGetApp::setSessionUUID); - connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &ATPGetApp::notifyPacketVersionMismatch); + // connect(nodeList.data(), &NodeList::uuidChanged, this, &ATPClientApp::setSessionUUID); + connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &ATPClientApp::notifyPacketVersionMismatch); nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer); @@ -140,63 +177,131 @@ ATPGetApp::ATPGetApp(int argc, char* argv[]) : auto assetClient = DependencyManager::set(); assetClient->init(); - QTimer* doTimer = new QTimer(this); - doTimer->setSingleShot(true); - connect(doTimer, &QTimer::timeout, this, &ATPGetApp::timedOut); - doTimer->start(4000); + QTimer* _timeoutTimer = new QTimer(this); + _timeoutTimer->setSingleShot(true); + connect(_timeoutTimer, &QTimer::timeout, this, &ATPClientApp::timedOut); + _timeoutTimer->start(4000); } -ATPGetApp::~ATPGetApp() { +ATPClientApp::~ATPClientApp() { + delete _domainCheckInTimer; + delete _timeoutTimer; } -void ATPGetApp::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) { +void ATPClientApp::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) { qDebug() << "domainConnectionRefused"; } -void ATPGetApp::domainChanged(const QString& domainHostname) { +void ATPClientApp::domainChanged(const QString& domainHostname) { if (_verbose) { qDebug() << "domainChanged"; } } -void ATPGetApp::nodeAdded(SharedNodePointer node) { +void ATPClientApp::nodeAdded(SharedNodePointer node) { if (_verbose) { qDebug() << "node added: " << node->getType(); } } -void ATPGetApp::nodeActivated(SharedNodePointer node) { +void ATPClientApp::nodeActivated(SharedNodePointer node) { if (node->getType() == NodeType::AssetServer) { - lookup(); + auto path = _url.path(); + + if (_verbose) { + qDebug() << "path is " << path; + } + + qDebug() << "_localUploadFile =" << _localUploadFile; + + if (!_localUploadFile.isEmpty()) { + uploadAsset(); + } else if (path == "/") { + listAssets(); + } else { + lookupAsset(); + } } } -void ATPGetApp::nodeKilled(SharedNodePointer node) { +void ATPClientApp::nodeKilled(SharedNodePointer node) { qDebug() << "nodeKilled"; } -void ATPGetApp::timedOut() { +void ATPClientApp::timedOut() { finish(1); } -void ATPGetApp::notifyPacketVersionMismatch() { +void ATPClientApp::notifyPacketVersionMismatch() { if (_verbose) { qDebug() << "packet version mismatch"; } finish(1); } -void ATPGetApp::lookup() { - +void ATPClientApp::uploadAsset() { auto path = _url.path(); - qDebug() << "path is " << path; + if (path == "/") { + qDebug() << "cannot upload to path of /"; + QCoreApplication::exit(1); + } + auto upload = DependencyManager::get()->createUpload(_localUploadFile); + QObject::connect(upload, &AssetUpload::finished, this, [=](AssetUpload* upload, const QString& hash) mutable { + if (upload->getError() != AssetUpload::NoError) { + qDebug() << "upload failed: " << upload->getErrorString(); + } else { + setMapping(hash); + } + + upload->deleteLater(); + }); + + upload->start(); +} + +void ATPClientApp::setMapping(QString hash) { + auto path = _url.path(); + auto assetClient = DependencyManager::get(); + auto request = assetClient->createSetMappingRequest(path, hash); + + connect(request, &SetMappingRequest::finished, this, [=](SetMappingRequest* request) mutable { + if (request->getError() != SetMappingRequest::NoError) { + qDebug() << "upload succeeded, but couldn't set mapping: " << request->getErrorString(); + } + request->deleteLater(); + }); + + request->start(); +} + +void ATPClientApp::listAssets() { + auto request = DependencyManager::get()->createGetAllMappingsRequest(); + QObject::connect(request, &GetAllMappingsRequest::finished, this, [=](GetAllMappingsRequest* request) mutable { + auto result = request->getError(); + if (result == GetAllMappingsRequest::NotFound) { + qDebug() << "not found: " << request->getErrorString(); + } else if (result == GetAllMappingsRequest::NoError) { + auto mappings = request->getMappings(); + for (auto& kv : mappings ) { + qDebug() << kv.first << kv.second; + } + } else { + qDebug() << "error -- " << request->getError() << " -- " << request->getErrorString(); + } + request->deleteLater(); + }); + request->start(); +} + +void ATPClientApp::lookupAsset() { + auto path = _url.path(); auto request = DependencyManager::get()->createGetMappingRequest(path); QObject::connect(request, &GetMappingRequest::finished, this, [=](GetMappingRequest* request) mutable { auto result = request->getError(); if (result == GetMappingRequest::NotFound) { - qDebug() << "not found"; + qDebug() << "not found: " << request->getErrorString(); } else if (result == GetMappingRequest::NoError) { qDebug() << "found, hash is " << request->getHash(); download(request->getHash()); @@ -208,7 +313,7 @@ void ATPGetApp::lookup() { request->start(); } -void ATPGetApp::download(AssetHash hash) { +void ATPClientApp::download(AssetHash hash) { auto assetClient = DependencyManager::get(); auto assetRequest = new AssetRequest(hash); @@ -217,7 +322,7 @@ void ATPGetApp::download(AssetHash hash) { if (request->getError() == AssetRequest::Error::NoError) { QString data = QString::fromUtf8(request->getData()); - if (_localOutputFile == "") { + if (_localOutputFile == "" || _localOutputFile == "-") { QTextStream cout(stdout); cout << data; } else { @@ -238,7 +343,7 @@ void ATPGetApp::download(AssetHash hash) { assetRequest->start(); } -void ATPGetApp::finish(int exitCode) { +void ATPClientApp::finish(int exitCode) { auto nodeList = DependencyManager::get(); // send the domain a disconnect packet, force stoppage of domain-server check-ins diff --git a/tools/atp-get/src/ATPGetApp.h b/tools/atp-client/src/ATPClientApp.h similarity index 64% rename from tools/atp-get/src/ATPGetApp.h rename to tools/atp-client/src/ATPClientApp.h index 5507d2aa62..ce85d2700e 100644 --- a/tools/atp-get/src/ATPGetApp.h +++ b/tools/atp-client/src/ATPClientApp.h @@ -1,6 +1,6 @@ // -// ATPGetApp.h -// tools/atp-get/src +// ATPClientApp.h +// tools/atp-client/src // // Created by Seth Alves on 2017-3-15 // Copyright 2017 High Fidelity, Inc. @@ -10,8 +10,8 @@ // -#ifndef hifi_ATPGetApp_h -#define hifi_ATPGetApp_h +#ifndef hifi_ATPClientApp_h +#define hifi_ATPClientApp_h #include #include @@ -23,11 +23,11 @@ #include -class ATPGetApp : public QCoreApplication { +class ATPClientApp : public QCoreApplication { Q_OBJECT public: - ATPGetApp(int argc, char* argv[]); - ~ATPGetApp(); + ATPClientApp(int argc, char* argv[]); + ~ATPClientApp(); private slots: void domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo); @@ -38,15 +38,26 @@ private slots: void notifyPacketVersionMismatch(); private: + void connectToDomain(QString domainServerAddress); + NodeList* _nodeList; void timedOut(); - void lookup(); + void uploadAsset(); + void setMapping(QString hash); + void lookupAsset(); + void listAssets(); void download(AssetHash hash); void finish(int exitCode); bool _verbose; QUrl _url; QString _localOutputFile; + QString _localUploadFile; + + int _listenPort { INVALID_PORT }; + + QTimer* _domainCheckInTimer { nullptr }; + QTimer* _timeoutTimer { nullptr }; }; -#endif // hifi_ATPGetApp_h +#endif // hifi_ATPClientApp_h diff --git a/tools/atp-get/src/main.cpp b/tools/atp-client/src/main.cpp similarity index 89% rename from tools/atp-get/src/main.cpp rename to tools/atp-client/src/main.cpp index bddf30c666..88119604cf 100644 --- a/tools/atp-get/src/main.cpp +++ b/tools/atp-client/src/main.cpp @@ -1,6 +1,6 @@ // // main.cpp -// tools/atp-get/src +// tools/atp-client/src // // Created by Seth Alves on 2017-3-15 // Copyright 2017 High Fidelity, Inc. @@ -15,7 +15,7 @@ #include -#include "ATPGetApp.h" +#include "ATPClientApp.h" using namespace std; @@ -25,7 +25,7 @@ int main(int argc, char * argv[]) { QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN); QCoreApplication::setApplicationVersion(BuildInfo::VERSION); - ATPGetApp app(argc, argv); + ATPClientApp app(argc, argv); return app.exec(); } From a6af6015a4de2618aa9f1b791314e266ce2f1011 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 4 Jul 2017 17:00:25 -0700 Subject: [PATCH 11/70] add a way to login on command-line --- tools/atp-client/src/ATPClientApp.cpp | 45 ++++++++++++++++++++++----- tools/atp-client/src/ATPClientApp.h | 3 ++ 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/tools/atp-client/src/ATPClientApp.cpp b/tools/atp-client/src/ATPClientApp.cpp index ac69da7e96..76bf706205 100644 --- a/tools/atp-client/src/ATPClientApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -42,15 +43,15 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : const QCommandLineOption uploadOption("T", "upload local file", "local-file-to-send"); parser.addOption(uploadOption); + const QCommandLineOption authOption("u", "set usename and pass", "username:password"); + parser.addOption(authOption); + const QCommandLineOption outputFilenameOption("o", "output filename", "output-file-name"); parser.addOption(outputFilenameOption); const QCommandLineOption domainAddressOption("d", "domain-server address", "127.0.0.1"); parser.addOption(domainAddressOption); - const QCommandLineOption cacheSTUNOption("s", "cache stun-server response"); - parser.addOption(cacheSTUNOption); - const QCommandLineOption listenPortOption("listenPort", "listen port", QString::number(INVALID_PORT)); parser.addOption(listenPortOption); @@ -107,6 +108,18 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : _localUploadFile = parser.value(uploadOption); } + if (parser.isSet(authOption)) { + QStringList pieces = parser.value(authOption).split(":"); + if (pieces.size() != 2) { + qDebug() << "-u should be followed by username:password"; + parser.showHelp(); + Q_UNREACHABLE(); + } + + _username = pieces[0]; + _password = pieces[1]; + } + if (parser.isSet(listenPortOption)) { _listenPort = parser.value(listenPortOption).toInt(); @@ -135,11 +148,6 @@ void ATPClientApp::connectToDomain(QString domainServerAddress) { qDebug() << "domain-server address is" << domainServerAddress; } - DependencyManager::set(); - auto accountManager = DependencyManager::get(); - QString username = accountManager->getAccountInfo().getUsername(); - qDebug() << "username is" << username; - Setting::init(); DependencyManager::registerInheritance(); @@ -177,6 +185,27 @@ void ATPClientApp::connectToDomain(QString domainServerAddress) { auto assetClient = DependencyManager::set(); assetClient->init(); + auto accountManager = DependencyManager::get(); + accountManager->setIsAgent(true); + accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); + + if (_verbose) { + QString username = accountManager->getAccountInfo().getUsername(); + qDebug() << "cached username is" << username << ", isLoggedIn =" << accountManager->isLoggedIn(); + } + + if (!_username.isEmpty()) { + connect(accountManager.data(), &AccountManager::loginComplete, this, [&](){ + if (_verbose) { + qDebug() << "login successful"; + } + }); + connect(accountManager.data(), &AccountManager::loginFailed, this, [&](){ + qDebug() << "login failed."; + }); + accountManager->requestAccessToken(_username, _password); + } + QTimer* _timeoutTimer = new QTimer(this); _timeoutTimer->setSingleShot(true); connect(_timeoutTimer, &QTimer::timeout, this, &ATPClientApp::timedOut); diff --git a/tools/atp-client/src/ATPClientApp.h b/tools/atp-client/src/ATPClientApp.h index ce85d2700e..c2401e54af 100644 --- a/tools/atp-client/src/ATPClientApp.h +++ b/tools/atp-client/src/ATPClientApp.h @@ -56,6 +56,9 @@ private: int _listenPort { INVALID_PORT }; + QString _username; + QString _password; + QTimer* _domainCheckInTimer { nullptr }; QTimer* _timeoutTimer { nullptr }; }; From 1192e8649431872942b9bf34804218f25e2b0b9c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 4 Jul 2017 17:11:53 -0700 Subject: [PATCH 12/70] add a way to login on command-line --- tools/ac-client/src/ACClientApp.cpp | 38 +++++++++++++++++++++++++++ tools/ac-client/src/ACClientApp.h | 3 +++ tools/atp-client/src/ATPClientApp.cpp | 5 ---- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/tools/ac-client/src/ACClientApp.cpp b/tools/ac-client/src/ACClientApp.cpp index b81d092662..0842a66346 100644 --- a/tools/ac-client/src/ACClientApp.cpp +++ b/tools/ac-client/src/ACClientApp.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,9 @@ ACClientApp::ACClientApp(int argc, char* argv[]) : const QCommandLineOption verboseOutput("v", "verbose output"); parser.addOption(verboseOutput); + const QCommandLineOption authOption("u", "set usename and pass", "username:password"); + parser.addOption(authOption); + const QCommandLineOption domainAddressOption("d", "domain-server address", "127.0.0.1"); parser.addOption(domainAddressOption); @@ -81,6 +85,18 @@ ACClientApp::ACClientApp(int argc, char* argv[]) : listenPort = parser.value(listenPortOption).toInt(); } + if (parser.isSet(authOption)) { + QStringList pieces = parser.value(authOption).split(":"); + if (pieces.size() != 2) { + qDebug() << "-u should be followed by username:password"; + parser.showHelp(); + Q_UNREACHABLE(); + } + + _username = pieces[0]; + _password = pieces[1]; + } + Setting::init(); DependencyManager::registerInheritance(); @@ -117,6 +133,28 @@ ACClientApp::ACClientApp(int argc, char* argv[]) : DependencyManager::get()->handleLookupString(domainServerAddress, false); + auto accountManager = DependencyManager::get(); + accountManager->setIsAgent(true); + accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); + + if (_verbose) { + QString username = accountManager->getAccountInfo().getUsername(); + qDebug() << "cached username is" << username << ", isLoggedIn =" << accountManager->isLoggedIn(); + } + + if (!_username.isEmpty()) { + connect(accountManager.data(), &AccountManager::loginComplete, this, [&](){ + if (_verbose) { + qDebug() << "login successful"; + } + }); + connect(accountManager.data(), &AccountManager::loginFailed, this, [&](){ + qDebug() << "login failed."; + }); + accountManager->requestAccessToken(_username, _password); + } + + QTimer* doTimer = new QTimer(this); doTimer->setSingleShot(true); connect(doTimer, &QTimer::timeout, this, &ACClientApp::timedOut); diff --git a/tools/ac-client/src/ACClientApp.h b/tools/ac-client/src/ACClientApp.h index 29d571688e..e295b17654 100644 --- a/tools/ac-client/src/ACClientApp.h +++ b/tools/ac-client/src/ACClientApp.h @@ -47,6 +47,9 @@ private: bool _sawAvatarMixer { false }; bool _sawAssetServer { false }; bool _sawMessagesMixer { false }; + + QString _username; + QString _password; }; #endif //hifi_ACClientApp_h diff --git a/tools/atp-client/src/ATPClientApp.cpp b/tools/atp-client/src/ATPClientApp.cpp index 76bf706205..cfa0cc81ad 100644 --- a/tools/atp-client/src/ATPClientApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -55,7 +55,6 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : const QCommandLineOption listenPortOption("listenPort", "listen port", QString::number(INVALID_PORT)); parser.addOption(listenPortOption); - if (!parser.parse(QCoreApplication::arguments())) { qCritical() << parser.errorText() << endl; parser.showHelp(); @@ -80,7 +79,6 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : const_cast(&shared())->setEnabled(QtWarningMsg, false); } - QStringList posArgs = parser.positionalArguments(); if (posArgs.size() != 1) { qDebug() << "give remote url argument"; @@ -120,7 +118,6 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : _password = pieces[1]; } - if (parser.isSet(listenPortOption)) { _listenPort = parser.value(listenPortOption).toInt(); } @@ -141,7 +138,6 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : } } - void ATPClientApp::connectToDomain(QString domainServerAddress) { if (_verbose) { @@ -217,7 +213,6 @@ ATPClientApp::~ATPClientApp() { delete _timeoutTimer; } - void ATPClientApp::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) { qDebug() << "domainConnectionRefused"; } From bdbfe25a5380233c19e5302f5645788a417fffa6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 4 Jul 2017 17:46:35 -0700 Subject: [PATCH 13/70] remove some debug prints --- tools/atp-client/src/ATPClientApp.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/atp-client/src/ATPClientApp.cpp b/tools/atp-client/src/ATPClientApp.cpp index cfa0cc81ad..d859346ae2 100644 --- a/tools/atp-client/src/ATPClientApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -125,7 +125,6 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : QString domainServerAddress = QString("127.0.0.1") + ":" + QString::number(domainPort); if (parser.isSet(domainAddressOption)) { domainServerAddress = parser.value(domainAddressOption); - qDebug() << "domainServerAddress is " << domainServerAddress; connectToDomain(domainServerAddress); } else if (!_url.host().isEmpty()) { QUrl domainURL; @@ -133,7 +132,6 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : domainURL.setHost(_url.host()); connectToDomain(domainURL.toString()); } else { - qDebug() << "domainServerAddress is default " << domainServerAddress; connectToDomain(domainServerAddress); } } From a05e9e12c15ab7b31ede11095d8cd577bd4bdf73 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 4 Jul 2017 17:59:56 -0700 Subject: [PATCH 14/70] remove some debug prints --- tools/atp-client/src/ATPClientApp.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/atp-client/src/ATPClientApp.cpp b/tools/atp-client/src/ATPClientApp.cpp index d859346ae2..5029bcd5b3 100644 --- a/tools/atp-client/src/ATPClientApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -235,8 +235,6 @@ void ATPClientApp::nodeActivated(SharedNodePointer node) { qDebug() << "path is " << path; } - qDebug() << "_localUploadFile =" << _localUploadFile; - if (!_localUploadFile.isEmpty()) { uploadAsset(); } else if (path == "/") { From eb354a43339d1ad8b075240eb2ceeca559e5ca33 Mon Sep 17 00:00:00 2001 From: Mohammed Nafees Date: Wed, 5 Jul 2017 14:50:12 +0530 Subject: [PATCH 15/70] Cleanup menu shortcut keys --- interface/src/Application.cpp | 53 ----------------------------------- interface/src/Menu.cpp | 4 +-- scripts/system/edit.js | 9 ------ 3 files changed, 2 insertions(+), 64 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 377819c0a0..65003326aa 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3110,59 +3110,6 @@ void Application::keyPressEvent(QKeyEvent* event) { break; #endif - case Qt::Key_H: { - // whenever switching to/from full screen mirror from the keyboard, remember - // the state you were in before full screen mirror, and return to that. - auto previousMode = _myCamera.getMode(); - if (previousMode != CAMERA_MODE_MIRROR) { - switch (previousMode) { - case CAMERA_MODE_FIRST_PERSON: - _returnFromFullScreenMirrorTo = MenuOption::FirstPerson; - break; - case CAMERA_MODE_THIRD_PERSON: - _returnFromFullScreenMirrorTo = MenuOption::ThirdPerson; - break; - - // FIXME - it's not clear that these modes make sense to return to... - case CAMERA_MODE_INDEPENDENT: - _returnFromFullScreenMirrorTo = MenuOption::IndependentMode; - break; - case CAMERA_MODE_ENTITY: - _returnFromFullScreenMirrorTo = MenuOption::CameraEntityMode; - break; - - default: - _returnFromFullScreenMirrorTo = MenuOption::ThirdPerson; - break; - } - } - - bool isMirrorChecked = Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror); - Menu::getInstance()->setIsOptionChecked(MenuOption::FullscreenMirror, !isMirrorChecked); - if (isMirrorChecked) { - - // if we got here without coming in from a non-Full Screen mirror case, then our - // _returnFromFullScreenMirrorTo is unknown. In that case we'll go to the old - // behavior of returning to ThirdPerson - if (_returnFromFullScreenMirrorTo.isEmpty()) { - _returnFromFullScreenMirrorTo = MenuOption::ThirdPerson; - } - Menu::getInstance()->setIsOptionChecked(_returnFromFullScreenMirrorTo, true); - } - cameraMenuChanged(); - break; - } - - case Qt::Key_P: { - if (!(isShifted || isMeta || isOption)) { - bool isFirstPersonChecked = Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson); - Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, !isFirstPersonChecked); - Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, isFirstPersonChecked); - cameraMenuChanged(); - } - break; - } - case Qt::Key_Slash: Menu::getInstance()->triggerOption(MenuOption::Stats); break; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index a746d72d91..4655951e10 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -223,7 +223,7 @@ Menu::Menu() { // View > First Person cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(viewMenu, - MenuOption::FirstPerson, 0, // QML Qt:: Key_P + MenuOption::FirstPerson, 0, true, qApp, SLOT(cameraMenuChanged()))); // View > Third Person @@ -233,7 +233,7 @@ Menu::Menu() { // View > Mirror cameraModeGroup->addAction(addCheckableActionToQMenuAndActionHash(viewMenu, - MenuOption::FullscreenMirror, 0, // QML Qt::Key_H, + MenuOption::FullscreenMirror, 0, false, qApp, SLOT(cameraMenuChanged()))); // View > Independent [advanced] diff --git a/scripts/system/edit.js b/scripts/system/edit.js index a83d2159bb..acea42237b 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1010,7 +1010,6 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "Edit", menuItemName: "Entity List...", - shortcutKey: "CTRL+META+L", afterItem: "Entities", grouping: "Advanced" }); @@ -1041,7 +1040,6 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", - shortcutKey: "CTRL+META+L", afterItem: GRABBABLE_ENTITIES_MENU_ITEM, isCheckable: true, isChecked: true, @@ -1050,7 +1048,6 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", - shortcutKey: "CTRL+META+S", afterItem: "Allow Selecting of Large Models", isCheckable: true, isChecked: true, @@ -1059,7 +1056,6 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Lights", - shortcutKey: "CTRL+SHIFT+META+L", afterItem: "Allow Selecting of Small Models", isCheckable: true, grouping: "Advanced" @@ -1067,14 +1063,12 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "Edit", menuItemName: "Select All Entities In Box", - shortcutKey: "CTRL+SHIFT+META+A", afterItem: "Allow Selecting of Lights", grouping: "Advanced" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Select All Entities Touching Box", - shortcutKey: "CTRL+SHIFT+META+T", afterItem: "Select All Entities In Box", grouping: "Advanced" }); @@ -1082,21 +1076,18 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "Edit", menuItemName: "Export Entities", - shortcutKey: "CTRL+META+E", afterItem: "Entities", grouping: "Advanced" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Import Entities", - shortcutKey: "CTRL+META+I", afterItem: "Export Entities", grouping: "Advanced" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Import Entities from URL", - shortcutKey: "CTRL+META+U", afterItem: "Import Entities", grouping: "Advanced" }); From ab340530b84ff70d8eef60db75e5b87991aa743c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 5 Jul 2017 11:27:13 -0700 Subject: [PATCH 16/70] 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 17/70] 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 18/70] 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 19/70] 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 20/70] 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 21/70] 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 f7131027e020c89ce38a492119022216c060d4ff Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 5 Jul 2017 17:26:15 -0700 Subject: [PATCH 22/70] if user has provided login credentials, wait for the keypair to be ready before proceeding --- tools/atp-client/src/ATPClientApp.cpp | 119 ++++++++++++++++---------- tools/atp-client/src/ATPClientApp.h | 8 +- 2 files changed, 79 insertions(+), 48 deletions(-) diff --git a/tools/atp-client/src/ATPClientApp.cpp b/tools/atp-client/src/ATPClientApp.cpp index 5029bcd5b3..a0856dbff1 100644 --- a/tools/atp-client/src/ATPClientApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -27,6 +27,7 @@ #include "ATPClientApp.h" #define HIGH_FIDELITY_ATP_CLIENT_USER_AGENT "Mozilla/5.0 (HighFidelityATPClient)" +#define TIMEOUT_MILLISECONDS 8000 ATPClientApp::ATPClientApp(int argc, char* argv[]) : QCoreApplication(argc, argv) @@ -116,30 +117,21 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : _username = pieces[0]; _password = pieces[1]; + _waitingForLogin = true; } if (parser.isSet(listenPortOption)) { _listenPort = parser.value(listenPortOption).toInt(); } - QString domainServerAddress = QString("127.0.0.1") + ":" + QString::number(domainPort); + _domainServerAddress = QString("127.0.0.1") + ":" + QString::number(domainPort); if (parser.isSet(domainAddressOption)) { - domainServerAddress = parser.value(domainAddressOption); - connectToDomain(domainServerAddress); + _domainServerAddress = parser.value(domainAddressOption); } else if (!_url.host().isEmpty()) { QUrl domainURL; domainURL.setScheme("hifi"); domainURL.setHost(_url.host()); - connectToDomain(domainURL.toString()); - } else { - connectToDomain(domainServerAddress); - } -} - -void ATPClientApp::connectToDomain(QString domainServerAddress) { - - if (_verbose) { - qDebug() << "domain-server address is" << domainServerAddress; + _domainServerAddress = domainURL.toString(); } Setting::init(); @@ -149,70 +141,90 @@ void ATPClientApp::connectToDomain(QString domainServerAddress) { DependencyManager::set(); DependencyManager::set(NodeType::Agent, _listenPort); + auto accountManager = DependencyManager::get(); + accountManager->setIsAgent(true); + accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); + auto nodeList = DependencyManager::get(); - nodeList->startThread(); // setup a timer for domain-server check ins _domainCheckInTimer = new QTimer(nodeList.data()); connect(_domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn); _domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); - const DomainHandler& domainHandler = nodeList->getDomainHandler(); + // start the nodeThread so its event loop is running + // (must happen after the checkin timer is created with the nodelist as it's parent) + nodeList->startThread(); + const DomainHandler& domainHandler = nodeList->getDomainHandler(); connect(&domainHandler, SIGNAL(hostnameChanged(const QString&)), SLOT(domainChanged(const QString&))); - // connect(&domainHandler, SIGNAL(resetting()), SLOT(resettingDomain())); - // connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(clearDomainOctreeDetails())); connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ATPClientApp::domainConnectionRefused); connect(nodeList.data(), &NodeList::nodeAdded, this, &ATPClientApp::nodeAdded); connect(nodeList.data(), &NodeList::nodeKilled, this, &ATPClientApp::nodeKilled); connect(nodeList.data(), &NodeList::nodeActivated, this, &ATPClientApp::nodeActivated); - // connect(nodeList.data(), &NodeList::uuidChanged, getMyAvatar(), &MyAvatar::setSessionUUID); - // connect(nodeList.data(), &NodeList::uuidChanged, this, &ATPClientApp::setSessionUUID); connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &ATPClientApp::notifyPacketVersionMismatch); - nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer); - DependencyManager::get()->handleLookupString(domainServerAddress, false); - - auto assetClient = DependencyManager::set(); - assetClient->init(); - - auto accountManager = DependencyManager::get(); - accountManager->setIsAgent(true); - accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); - if (_verbose) { QString username = accountManager->getAccountInfo().getUsername(); qDebug() << "cached username is" << username << ", isLoggedIn =" << accountManager->isLoggedIn(); } if (!_username.isEmpty()) { + + connect(accountManager.data(), &AccountManager::newKeypair, this, [&](){ + if (_verbose) { + qDebug() << "new keypair has been created."; + } + }); + connect(accountManager.data(), &AccountManager::loginComplete, this, [&](){ if (_verbose) { qDebug() << "login successful"; } + _waitingForLogin = false; + go(); }); connect(accountManager.data(), &AccountManager::loginFailed, this, [&](){ qDebug() << "login failed."; + _waitingForLogin = false; + go(); }); accountManager->requestAccessToken(_username, _password); } + auto assetClient = DependencyManager::set(); + assetClient->init(); + + if (_verbose) { + qDebug() << "domain-server address is" << _domainServerAddress; + } + + + DependencyManager::get()->handleLookupString(_domainServerAddress, false); + QTimer* _timeoutTimer = new QTimer(this); _timeoutTimer->setSingleShot(true); connect(_timeoutTimer, &QTimer::timeout, this, &ATPClientApp::timedOut); - _timeoutTimer->start(4000); + _timeoutTimer->start(TIMEOUT_MILLISECONDS); } ATPClientApp::~ATPClientApp() { - delete _domainCheckInTimer; - delete _timeoutTimer; + if (_domainCheckInTimer) { + QMetaObject::invokeMethod(_domainCheckInTimer, "deleteLater", Qt::QueuedConnection); + } + if (_timeoutTimer) { + QMetaObject::invokeMethod(_timeoutTimer, "deleteLater", Qt::QueuedConnection); + } } void ATPClientApp::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) { - qDebug() << "domainConnectionRefused"; + // this is non-fatal if we are trying to get an authenticated connection -- it will be retried. + if (_verbose) { + qDebug() << "domainConnectionRefused"; + } } void ATPClientApp::domainChanged(const QString& domainHostname) { @@ -228,25 +240,36 @@ void ATPClientApp::nodeAdded(SharedNodePointer node) { } void ATPClientApp::nodeActivated(SharedNodePointer node) { - if (node->getType() == NodeType::AssetServer) { - auto path = _url.path(); + if (!_waitingForLogin && node->getType() == NodeType::AssetServer) { + _waitingForNode = false; + go(); + } +} - if (_verbose) { - qDebug() << "path is " << path; - } +void ATPClientApp::go() { + if (_waitingForLogin || _waitingForNode) { + return; + } - if (!_localUploadFile.isEmpty()) { - uploadAsset(); - } else if (path == "/") { - listAssets(); - } else { - lookupAsset(); - } + auto path = _url.path(); + + if (_verbose) { + qDebug() << "path is " << path; + } + + if (!_localUploadFile.isEmpty()) { + uploadAsset(); + } else if (path == "/") { + listAssets(); + } else { + lookupAsset(); } } void ATPClientApp::nodeKilled(SharedNodePointer node) { - qDebug() << "nodeKilled"; + if (_verbose) { + qDebug() << "nodeKilled" << node->getType(); + } } void ATPClientApp::timedOut() { @@ -289,8 +312,11 @@ void ATPClientApp::setMapping(QString hash) { connect(request, &SetMappingRequest::finished, this, [=](SetMappingRequest* request) mutable { if (request->getError() != SetMappingRequest::NoError) { qDebug() << "upload succeeded, but couldn't set mapping: " << request->getErrorString(); + } else if (_verbose) { + qDebug() << "mapping set."; } request->deleteLater(); + finish(0); }); request->start(); @@ -311,6 +337,7 @@ void ATPClientApp::listAssets() { qDebug() << "error -- " << request->getError() << " -- " << request->getErrorString(); } request->deleteLater(); + finish(0); }); request->start(); } diff --git a/tools/atp-client/src/ATPClientApp.h b/tools/atp-client/src/ATPClientApp.h index c2401e54af..a3904d6e50 100644 --- a/tools/atp-client/src/ATPClientApp.h +++ b/tools/atp-client/src/ATPClientApp.h @@ -38,8 +38,7 @@ private slots: void notifyPacketVersionMismatch(); private: - void connectToDomain(QString domainServerAddress); - + void go(); NodeList* _nodeList; void timedOut(); void uploadAsset(); @@ -56,9 +55,14 @@ private: int _listenPort { INVALID_PORT }; + QString _domainServerAddress; + QString _username; QString _password; + bool _waitingForLogin { false }; + bool _waitingForNode { true }; + QTimer* _domainCheckInTimer { nullptr }; QTimer* _timeoutTimer { nullptr }; }; From 98ac2ccb908f04795736b23ddc5eb606544178e9 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 5 Jul 2017 17:36:25 -0700 Subject: [PATCH 23/70] rearrange code so authed connection works better --- tools/ac-client/src/ACClientApp.cpp | 25 ++++++++++++------------- tools/atp-client/src/ATPClientApp.cpp | 1 - 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/tools/ac-client/src/ACClientApp.cpp b/tools/ac-client/src/ACClientApp.cpp index c44d4aa24c..2b92bb744b 100644 --- a/tools/ac-client/src/ACClientApp.cpp +++ b/tools/ac-client/src/ACClientApp.cpp @@ -104,6 +104,9 @@ ACClientApp::ACClientApp(int argc, char* argv[]) : DependencyManager::set(); DependencyManager::set(NodeType::Agent, listenPort); + auto accountManager = DependencyManager::get(); + accountManager->setIsAgent(true); + accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); auto nodeList = DependencyManager::get(); @@ -112,39 +115,34 @@ ACClientApp::ACClientApp(int argc, char* argv[]) : connect(domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn); domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); - // start the nodeThread so its event loop is running + // start the nodeThread so its event loop is running // (must happen after the checkin timer is created with the nodelist as it's parent) nodeList->startThread(); const DomainHandler& domainHandler = nodeList->getDomainHandler(); - connect(&domainHandler, SIGNAL(hostnameChanged(const QString&)), SLOT(domainChanged(const QString&))); - // connect(&domainHandler, SIGNAL(resetting()), SLOT(resettingDomain())); - // connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(clearDomainOctreeDetails())); connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ACClientApp::domainConnectionRefused); connect(nodeList.data(), &NodeList::nodeAdded, this, &ACClientApp::nodeAdded); connect(nodeList.data(), &NodeList::nodeKilled, this, &ACClientApp::nodeKilled); connect(nodeList.data(), &NodeList::nodeActivated, this, &ACClientApp::nodeActivated); - // connect(nodeList.data(), &NodeList::uuidChanged, getMyAvatar(), &MyAvatar::setSessionUUID); - // connect(nodeList.data(), &NodeList::uuidChanged, this, &ACClientApp::setSessionUUID); connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &ACClientApp::notifyPacketVersionMismatch); - nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer); - DependencyManager::get()->handleLookupString(domainServerAddress, false); - - auto accountManager = DependencyManager::get(); - accountManager->setIsAgent(true); - accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); - if (_verbose) { QString username = accountManager->getAccountInfo().getUsername(); qDebug() << "cached username is" << username << ", isLoggedIn =" << accountManager->isLoggedIn(); } if (!_username.isEmpty()) { + + connect(accountManager.data(), &AccountManager::newKeypair, this, [&](){ + if (_verbose) { + qDebug() << "new keypair has been created."; + } + }); + connect(accountManager.data(), &AccountManager::loginComplete, this, [&](){ if (_verbose) { qDebug() << "login successful"; @@ -156,6 +154,7 @@ ACClientApp::ACClientApp(int argc, char* argv[]) : accountManager->requestAccessToken(_username, _password); } + DependencyManager::get()->handleLookupString(domainServerAddress, false); QTimer* doTimer = new QTimer(this); doTimer->setSingleShot(true); diff --git a/tools/atp-client/src/ATPClientApp.cpp b/tools/atp-client/src/ATPClientApp.cpp index a0856dbff1..3e2f8ca71d 100644 --- a/tools/atp-client/src/ATPClientApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -202,7 +202,6 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : qDebug() << "domain-server address is" << _domainServerAddress; } - DependencyManager::get()->handleLookupString(_domainServerAddress, false); QTimer* _timeoutTimer = new QTimer(this); From 20a633eb899475a4d272c419786ebcdbe8f4cb5b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 5 Jul 2017 16:15:53 -0700 Subject: [PATCH 24/70] 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 25/70] 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 2299bb7718c51dabb764b9874f4d229c80036b44 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 5 Jul 2017 09:17:06 -0700 Subject: [PATCH 26/70] supply minimum shape rather than null --- libraries/physics/src/ShapeManager.cpp | 7 ------- libraries/shared/src/ShapeInfo.cpp | 24 ++++++++++++++++++++---- libraries/shared/src/ShapeInfo.h | 2 ++ 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/libraries/physics/src/ShapeManager.cpp b/libraries/physics/src/ShapeManager.cpp index fd3e35d28a..77716f671b 100644 --- a/libraries/physics/src/ShapeManager.cpp +++ b/libraries/physics/src/ShapeManager.cpp @@ -32,13 +32,6 @@ const btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) { if (info.getType() == SHAPE_TYPE_NONE) { return nullptr; } - const float MIN_SHAPE_DIAGONAL_SQUARED = 3.0e-4f; // 1 cm cube - if (4.0f * glm::length2(info.getHalfExtents()) < MIN_SHAPE_DIAGONAL_SQUARED) { - // tiny shapes are not supported - // qCDebug(physics) << "ShapeManager::getShape -- not making shape due to size" << diagonal; - return nullptr; - } - DoubleHashKey key = info.getHash(); ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef) { diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index 583bceeaf2..496e94f8bd 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -15,6 +15,9 @@ #include "NumericalConstants.h" // for MILLIMETERS_PER_METER +// Bullet doesn't support arbitrarily small shapes +const float MIN_HALF_EXTENT = 0.005f; // 0.5 cm + void ShapeInfo::clear() { _url.clear(); _pointCollection.clear(); @@ -26,14 +29,20 @@ void ShapeInfo::clear() { } void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString url) { + _url = ""; _type = type; - _halfExtents = halfExtents; + setHalfExtents(halfExtents); switch(type) { case SHAPE_TYPE_NONE: _halfExtents = glm::vec3(0.0f); break; case SHAPE_TYPE_BOX: - case SHAPE_TYPE_SPHERE: + break; + case SHAPE_TYPE_SPHERE: { + float radius = glm::length(halfExtents) / SQUARE_ROOT_OF_3; + radius = glm::max(radius, MIN_HALF_EXTENT); + _halfExtents = glm::vec3(radius); + } break; case SHAPE_TYPE_COMPOUND: case SHAPE_TYPE_STATIC_MESH: @@ -48,14 +57,15 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString void ShapeInfo::setBox(const glm::vec3& halfExtents) { _url = ""; _type = SHAPE_TYPE_BOX; - _halfExtents = halfExtents; + setHalfExtents(halfExtents); _doubleHashKey.clear(); } void ShapeInfo::setSphere(float radius) { _url = ""; _type = SHAPE_TYPE_SPHERE; - _halfExtents = glm::vec3(radius, radius, radius); + radius = glm::max(radius, MIN_HALF_EXTENT); + _halfExtents = glm::vec3(radius); _doubleHashKey.clear(); } @@ -68,6 +78,8 @@ void ShapeInfo::setPointCollection(const ShapeInfo::PointCollection& pointCollec void ShapeInfo::setCapsuleY(float radius, float halfHeight) { _url = ""; _type = SHAPE_TYPE_CAPSULE_Y; + radius = glm::max(radius, MIN_HALF_EXTENT); + halfHeight = glm::max(halfHeight, 0.0f); _halfExtents = glm::vec3(radius, halfHeight, radius); _doubleHashKey.clear(); } @@ -239,3 +251,7 @@ const DoubleHashKey& ShapeInfo::getHash() const { } return _doubleHashKey; } + +void ShapeInfo::setHalfExtents(const glm::vec3& halfExtents) { + _halfExtents = glm::max(halfExtents, glm::vec3(MIN_HALF_EXTENT)); +} diff --git a/libraries/shared/src/ShapeInfo.h b/libraries/shared/src/ShapeInfo.h index 17e4703fc2..0ffdf1310d 100644 --- a/libraries/shared/src/ShapeInfo.h +++ b/libraries/shared/src/ShapeInfo.h @@ -89,6 +89,8 @@ public: const DoubleHashKey& getHash() const; protected: + void setHalfExtents(const glm::vec3& halfExtents); + QUrl _url; // url for model of convex collision hulls PointCollection _pointCollection; TriangleIndices _triangleIndices; From 1d07ab70f0c5d3e2beb5dffe7cc949dfe8fdb8c0 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 5 Jul 2017 18:07:10 -0700 Subject: [PATCH 27/70] 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 24c8267030734bc6b96b1e853cca43bc0588ad4d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 6 Jul 2017 13:22:14 -0700 Subject: [PATCH 28/70] in Rig joint accessors, if on the Rig's thread use internalPoseSet, else use external --- libraries/animation/src/Rig.cpp | 42 +++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 3ea03bc5f9..cd5d8c6231 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -404,31 +404,41 @@ void Rig::setJointRotation(int index, bool valid, const glm::quat& rotation, flo } bool Rig::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position, glm::vec3 translation, glm::quat rotation) const { - // if (isIndexValid(jointIndex)) { + if (QThread::currentThread() == thread()) { + if (isIndexValid(jointIndex)) { + position = (rotation * _internalPoseSet._absolutePoses[jointIndex].trans()) + translation; + return true; + } + return false; + } + QReadLocker readLock(&_externalPoseSetLock); if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._absolutePoses.size()) { position = (rotation * _externalPoseSet._absolutePoses[jointIndex].trans()) + translation; return true; - } else { - return false; } + return false; } bool Rig::getJointPosition(int jointIndex, glm::vec3& position) const { -/* - if (isIndexValid(jointIndex)) { - position = _internalPoseSet._absolutePoses[jointIndex].trans(); - return true; - } else { + if (QThread::currentThread() == thread()) { + if (isIndexValid(jointIndex)) { + position = _internalPoseSet._absolutePoses[jointIndex].trans(); + return true; + } return false; - }*/ + } return getAbsoluteJointTranslationInRigFrame(jointIndex, position); } bool Rig::getJointRotationInWorldFrame(int jointIndex, glm::quat& result, const glm::quat& rotation) const { - // if (isIndexValid(jointIndex)) { - // result = rotation * _internalPoseSet._absolutePoses[jointIndex].rot(); - // return true; + if (QThread::currentThread() == thread()) { + if (isIndexValid(jointIndex)) { + result = rotation * _internalPoseSet._absolutePoses[jointIndex].rot(); + return true; + } + return false; + } QReadLocker readLock(&_externalPoseSetLock); if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._absolutePoses.size()) { @@ -440,6 +450,14 @@ bool Rig::getJointRotationInWorldFrame(int jointIndex, glm::quat& result, const } bool Rig::getJointRotation(int jointIndex, glm::quat& rotation) const { + if (QThread::currentThread() == thread()) { + if (isIndexValid(jointIndex)) { + rotation = _internalPoseSet._relativePoses[jointIndex].rot(); + return true; + } + return false; + } + QReadLocker readLock(&_externalPoseSetLock); if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._relativePoses.size()) { rotation = _externalPoseSet._relativePoses[jointIndex].rot(); From b0130896d1f8b68a069df9f56526859e4f0dd870 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 6 Jul 2017 22:01:08 +0100 Subject: [PATCH 29/70] fixed spamming from windowRoot.qml --- interface/resources/qml/hifi/tablet/WindowRoot.qml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/WindowRoot.qml b/interface/resources/qml/hifi/tablet/WindowRoot.qml index ea0c2844a1..fdfcfcf806 100644 --- a/interface/resources/qml/hifi/tablet/WindowRoot.qml +++ b/interface/resources/qml/hifi/tablet/WindowRoot.qml @@ -52,8 +52,10 @@ Windows.ScrollingWindow { // used to receive messages from interface script function fromScript(message) { - if (loader.item.hasOwnProperty("fromScript")) { - loader.item.fromScript(message); + if (loader.item !== null) { + if (loader.item.hasOwnProperty("fromScript")) { + loader.item.fromScript(message); + } } } From 0ac8f6efa3dcea0a62fad55f948b46c5b277ebaa Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 6 Jul 2017 14:02:59 -0700 Subject: [PATCH 30/70] cache the jointnames and indexes from FBXGeometry for out-of-thread access --- .../src/avatars-renderer/Avatar.cpp | 43 ++++++------------- .../src/avatars-renderer/Avatar.h | 4 ++ 2 files changed, 18 insertions(+), 29 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 5d4d7af493..3674c003a1 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1009,48 +1009,25 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const { } int Avatar::getJointIndex(const QString& name) const { - /* if (QThread::currentThread() != thread()) { - int result; - BLOCKING_INVOKE_METHOD(const_cast(this), "getJointIndex", - Q_RETURN_ARG(int, result), Q_ARG(const QString&, name)); - return result; - } */ - int result = getFauxJointIndex(name); - if (result != -1) { - return result; + QReadLocker readLock(&_jointIndicesCacheLock); + if (_jointIndicesCache.contains(name)) { + return _jointIndicesCache[name]; } - return _skeletonModel->isActive() ? _skeletonModel->getFBXGeometry().getJointIndex(name) : -1; + return -1; } QStringList Avatar::getJointNames() const { -/* if (QThread::currentThread() != thread()) { - QStringList result; - BLOCKING_INVOKE_METHOD(const_cast(this), "getJointNames", - Q_RETURN_ARG(QStringList, result)); - return result; - }*/ - return _skeletonModel->isActive() ? _skeletonModel->getFBXGeometry().getJointNames() : QStringList(); + QReadLocker readLock(&_jointIndicesCacheLock); + return _jointIndicesCache.keys(); } glm::vec3 Avatar::getJointPosition(int index) const { -/* if (QThread::currentThread() != thread()) { - glm::vec3 position; - BLOCKING_INVOKE_METHOD(const_cast(this), "getJointPosition", - Q_RETURN_ARG(glm::vec3, position), Q_ARG(const int, index)); - return position; - }*/ glm::vec3 position; _skeletonModel->getJointPositionInWorldFrame(index, position); return position; } glm::vec3 Avatar::getJointPosition(const QString& name) const { -/* if (QThread::currentThread() != thread()) { - glm::vec3 position; - BLOCKING_INVOKE_METHOD(const_cast(this), "getJointPosition", - Q_RETURN_ARG(glm::vec3, position), Q_ARG(const QString&, name)); - return position; - }*/ glm::vec3 position; _skeletonModel->getJointPositionInWorldFrame(getJointIndex(name), position); return position; @@ -1071,6 +1048,14 @@ void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { } void Avatar::setModelURLFinished(bool success) { + { + QWriteLocker writeLock(&_jointIndicesCacheLock); + _jointIndicesCache.clear(); + if (_skeletonModel && _skeletonModel->isActive()) { + _jointIndicesCache = _skeletonModel->getFBXGeometry().jointIndices; + } + } + if (!success && _skeletonModelURL != AvatarData::defaultFullAvatarModelUrl()) { const int MAX_SKELETON_DOWNLOAD_ATTEMPTS = 4; // NOTE: we don't want to be as generous as ResourceCache is, we only want 4 attempts if (_skeletonModel->getResourceDownloadAttemptsRemaining() <= 0 || diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 1724d42510..d2c7756257 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -267,6 +267,10 @@ protected: virtual void maybeUpdateSessionDisplayNameFromTransport(const QString& sessionDisplayName) override { _sessionDisplayName = sessionDisplayName; } // don't use no-op setter! SkeletonModelPointer _skeletonModel; + + QHash _jointIndicesCache; + mutable QReadWriteLock _jointIndicesCacheLock; + glm::vec3 _skeletonOffset; std::vector> _attachmentModels; std::vector> _attachmentsToRemove; From e03b902a157be8ef74d7cdc680374cf359716ec6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 6 Jul 2017 15:42:24 -0700 Subject: [PATCH 31/70] change when joint cache is copied --- .../src/avatars-renderer/Avatar.cpp | 49 ++++++++++++++----- .../src/avatars-renderer/Avatar.h | 4 +- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 3674c003a1..445396870f 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1008,17 +1008,48 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const { } } -int Avatar::getJointIndex(const QString& name) const { - QReadLocker readLock(&_jointIndicesCacheLock); - if (_jointIndicesCache.contains(name)) { - return _jointIndicesCache[name]; +void Avatar::cacheJoints() const { + // _jointIndicesCacheLock should be locked for write before calling this. + _jointIndicesCache.clear(); + if (_skeletonModel && _skeletonModel->isActive()) { + _jointIndicesCache = _skeletonModel->getFBXGeometry().jointIndices; + _jointsCached = true; } - return -1; +} + +int Avatar::getJointIndex(const QString& name) const { + auto getJointIndexWorker = [&]() { + if (_jointIndicesCache.contains(name)) { + return _jointIndicesCache[name]; + } + return -1; + }; + QReadLocker readLock(&_jointIndicesCacheLock); + if (!_jointsCached) { + readLock.unlock(); + { + QWriteLocker writeLock(&_jointIndicesCacheLock); + Avatar::cacheJoints(); + return getJointIndexWorker(); + } + } + return getJointIndexWorker(); } QStringList Avatar::getJointNames() const { + auto getJointNamesWorker = [&]() { + return _jointIndicesCache.keys(); + }; QReadLocker readLock(&_jointIndicesCacheLock); - return _jointIndicesCache.keys(); + if (!_jointsCached) { + readLock.unlock(); + { + QWriteLocker writeLock(&_jointIndicesCacheLock); + Avatar::cacheJoints(); + return getJointNamesWorker(); + } + } + return getJointNamesWorker(); } glm::vec3 Avatar::getJointPosition(int index) const { @@ -1050,12 +1081,8 @@ void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { void Avatar::setModelURLFinished(bool success) { { QWriteLocker writeLock(&_jointIndicesCacheLock); - _jointIndicesCache.clear(); - if (_skeletonModel && _skeletonModel->isActive()) { - _jointIndicesCache = _skeletonModel->getFBXGeometry().jointIndices; - } + _jointsCached = false; } - if (!success && _skeletonModelURL != AvatarData::defaultFullAvatarModelUrl()) { const int MAX_SKELETON_DOWNLOAD_ATTEMPTS = 4; // NOTE: we don't want to be as generous as ResourceCache is, we only want 4 attempts if (_skeletonModel->getResourceDownloadAttemptsRemaining() <= 0 || diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index d2c7756257..f19feab9c6 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -268,8 +268,10 @@ protected: SkeletonModelPointer _skeletonModel; - QHash _jointIndicesCache; + void cacheJoints() const; + mutable QHash _jointIndicesCache; mutable QReadWriteLock _jointIndicesCacheLock; + mutable bool _jointsCached { false }; glm::vec3 _skeletonOffset; std::vector> _attachmentModels; From 1ac415aa14d3be3b9782aa813690b7dfe5ff148c Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 6 Jul 2017 23:50:32 +0100 Subject: [PATCH 32/70] dynamic listview height --- interface/resources/qml/hifi/audio/Audio.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index c13bd3281a..519499e35c 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -166,7 +166,7 @@ Rectangle { ListView { anchors { left: parent.left; right: parent.right; leftMargin: 70 } - height: 125; + height: Math.min(250, contentHeight); spacing: 0; snapMode: ListView.SnapToItem; clip: true; From 2e88eca2b983f34dbe2e61fb1d747c987057b8af Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 6 Jul 2017 16:33:37 -0700 Subject: [PATCH 33/70] oopsy crazy --- libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 445396870f..16c0d7516b 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1019,6 +1019,10 @@ void Avatar::cacheJoints() const { int Avatar::getJointIndex(const QString& name) const { auto getJointIndexWorker = [&]() { + int result = getFauxJointIndex(name); + if (result != -1) { + return result; + } if (_jointIndicesCache.contains(name)) { return _jointIndicesCache[name]; } From 15d379cc5ab86be34b6190d91dd7528188ab6194 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 6 Jul 2017 17:36:28 -0700 Subject: [PATCH 34/70] coding style --- libraries/animation/src/Rig.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index cd5d8c6231..6ebb68773f 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -408,16 +408,18 @@ bool Rig::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position, glm: if (isIndexValid(jointIndex)) { position = (rotation * _internalPoseSet._absolutePoses[jointIndex].trans()) + translation; return true; + } else { + return false; } - return false; } QReadLocker readLock(&_externalPoseSetLock); if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._absolutePoses.size()) { position = (rotation * _externalPoseSet._absolutePoses[jointIndex].trans()) + translation; return true; + } else { + return false; } - return false; } bool Rig::getJointPosition(int jointIndex, glm::vec3& position) const { @@ -425,10 +427,12 @@ bool Rig::getJointPosition(int jointIndex, glm::vec3& position) const { if (isIndexValid(jointIndex)) { position = _internalPoseSet._absolutePoses[jointIndex].trans(); return true; + } else { + return false; } - return false; + } else { + return getAbsoluteJointTranslationInRigFrame(jointIndex, position); } - return getAbsoluteJointTranslationInRigFrame(jointIndex, position); } bool Rig::getJointRotationInWorldFrame(int jointIndex, glm::quat& result, const glm::quat& rotation) const { @@ -436,8 +440,9 @@ bool Rig::getJointRotationInWorldFrame(int jointIndex, glm::quat& result, const if (isIndexValid(jointIndex)) { result = rotation * _internalPoseSet._absolutePoses[jointIndex].rot(); return true; + } else { + return false; } - return false; } QReadLocker readLock(&_externalPoseSetLock); @@ -454,8 +459,9 @@ bool Rig::getJointRotation(int jointIndex, glm::quat& rotation) const { if (isIndexValid(jointIndex)) { rotation = _internalPoseSet._relativePoses[jointIndex].rot(); return true; + } else { + return false; } - return false; } QReadLocker readLock(&_externalPoseSetLock); From fc61fcf49488c41bb116c53655b59efda773f60a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 6 Jul 2017 17:40:41 -0700 Subject: [PATCH 35/70] coding style --- libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 16c0d7516b..3fc7bba3d2 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1022,11 +1022,11 @@ int Avatar::getJointIndex(const QString& name) const { int result = getFauxJointIndex(name); if (result != -1) { return result; - } - if (_jointIndicesCache.contains(name)) { + } else if (_jointIndicesCache.contains(name)) { return _jointIndicesCache[name]; + } else { + return -1; } - return -1; }; QReadLocker readLock(&_jointIndicesCacheLock); if (!_jointsCached) { From a543b957efeaf198a60fe45fe69d3034f1372882 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 6 Jul 2017 17:45:57 -0700 Subject: [PATCH 36/70] fix a race --- libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 3fc7bba3d2..e3586fd9a8 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1010,6 +1010,9 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const { void Avatar::cacheJoints() const { // _jointIndicesCacheLock should be locked for write before calling this. + if (_jointsCached) { + return; + } _jointIndicesCache.clear(); if (_skeletonModel && _skeletonModel->isActive()) { _jointIndicesCache = _skeletonModel->getFBXGeometry().jointIndices; From ab8d9f4885dd3bf441fb3a14624cf506d82aedd4 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 6 Jul 2017 18:00:11 -0700 Subject: [PATCH 37/70] check for faux joints before heading into code that needs to lock --- .../avatars-renderer/src/avatars-renderer/Avatar.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index e3586fd9a8..439beb94d6 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1021,11 +1021,13 @@ void Avatar::cacheJoints() const { } int Avatar::getJointIndex(const QString& name) const { + int result = getFauxJointIndex(name); + if (result != -1) { + return result; + } + auto getJointIndexWorker = [&]() { - int result = getFauxJointIndex(name); - if (result != -1) { - return result; - } else if (_jointIndicesCache.contains(name)) { + if (_jointIndicesCache.contains(name)) { return _jointIndicesCache[name]; } else { return -1; From f8b76d65ab3963912ee4ebb730b0790ff5dca469 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 6 Jul 2017 18:01:26 -0700 Subject: [PATCH 38/70] 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 ef4a04b9cf31a201fd5e0dafd3e925913f8af44a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 6 Jul 2017 18:01:58 -0700 Subject: [PATCH 39/70] code style --- .../avatars-renderer/src/avatars-renderer/Avatar.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 439beb94d6..fc604809dc 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1034,7 +1034,9 @@ int Avatar::getJointIndex(const QString& name) const { } }; QReadLocker readLock(&_jointIndicesCacheLock); - if (!_jointsCached) { + if (_jointsCached) { + return getJointIndexWorker(); + } else { readLock.unlock(); { QWriteLocker writeLock(&_jointIndicesCacheLock); @@ -1042,7 +1044,6 @@ int Avatar::getJointIndex(const QString& name) const { return getJointIndexWorker(); } } - return getJointIndexWorker(); } QStringList Avatar::getJointNames() const { @@ -1050,7 +1051,9 @@ QStringList Avatar::getJointNames() const { return _jointIndicesCache.keys(); }; QReadLocker readLock(&_jointIndicesCacheLock); - if (!_jointsCached) { + if (_jointsCached) { + return getJointNamesWorker(); + } else { readLock.unlock(); { QWriteLocker writeLock(&_jointIndicesCacheLock); @@ -1058,7 +1061,6 @@ QStringList Avatar::getJointNames() const { return getJointNamesWorker(); } } - return getJointNamesWorker(); } glm::vec3 Avatar::getJointPosition(int index) const { From 57ba2c5cd6c9c807e46692f3715bf8611c751c39 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 6 Jul 2017 18:16:41 -0700 Subject: [PATCH 40/70] add invalidateJointIndicesCache method --- .../avatars-renderer/src/avatars-renderer/Avatar.cpp | 11 +++++++---- .../avatars-renderer/src/avatars-renderer/Avatar.h | 1 + 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index fc604809dc..2206d67c2c 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1020,6 +1020,11 @@ void Avatar::cacheJoints() const { } } +void Avatar::invalidateJointIndicesCache() const { + QWriteLocker writeLock(&_jointIndicesCacheLock); + _jointsCached = false; +} + int Avatar::getJointIndex(const QString& name) const { int result = getFauxJointIndex(name); if (result != -1) { @@ -1090,10 +1095,8 @@ void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { } void Avatar::setModelURLFinished(bool success) { - { - QWriteLocker writeLock(&_jointIndicesCacheLock); - _jointsCached = false; - } + invalidateJointIndicesCache(); + if (!success && _skeletonModelURL != AvatarData::defaultFullAvatarModelUrl()) { const int MAX_SKELETON_DOWNLOAD_ATTEMPTS = 4; // NOTE: we don't want to be as generous as ResourceCache is, we only want 4 attempts if (_skeletonModel->getResourceDownloadAttemptsRemaining() <= 0 || diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index f19feab9c6..2069e36998 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -269,6 +269,7 @@ protected: SkeletonModelPointer _skeletonModel; void cacheJoints() const; + void invalidateJointIndicesCache() const; mutable QHash _jointIndicesCache; mutable QReadWriteLock _jointIndicesCacheLock; mutable bool _jointsCached { false }; From 801c45898ffd4a23e5a738d5540d0c59ce2bc33e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 6 Jul 2017 18:41:11 -0700 Subject: [PATCH 41/70] dry up some code --- .../src/avatars-renderer/Avatar.cpp | 71 ++++++++----------- .../src/avatars-renderer/Avatar.h | 2 +- 2 files changed, 30 insertions(+), 43 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 2206d67c2c..4ffacf9fa6 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1008,64 +1008,51 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const { } } -void Avatar::cacheJoints() const { - // _jointIndicesCacheLock should be locked for write before calling this. - if (_jointsCached) { - return; - } - _jointIndicesCache.clear(); - if (_skeletonModel && _skeletonModel->isActive()) { - _jointIndicesCache = _skeletonModel->getFBXGeometry().jointIndices; - _jointsCached = true; - } -} - void Avatar::invalidateJointIndicesCache() const { QWriteLocker writeLock(&_jointIndicesCacheLock); _jointsCached = false; } +void Avatar::withValidCache(std::function const& worker) const { + QReadLocker readLock(&_jointIndicesCacheLock); + if (_jointsCached) { + worker(); + } else { + readLock.unlock(); + { + QWriteLocker writeLock(&_jointIndicesCacheLock); + if (!_jointsCached) { + _jointIndicesCache.clear(); + if (_skeletonModel && _skeletonModel->isActive()) { + _jointIndicesCache = _skeletonModel->getFBXGeometry().jointIndices; + _jointsCached = true; + } + } + worker(); + } + } +} + int Avatar::getJointIndex(const QString& name) const { int result = getFauxJointIndex(name); if (result != -1) { return result; } - auto getJointIndexWorker = [&]() { + withValidCache([&]() { if (_jointIndicesCache.contains(name)) { - return _jointIndicesCache[name]; - } else { - return -1; + result = _jointIndicesCache[name]; } - }; - QReadLocker readLock(&_jointIndicesCacheLock); - if (_jointsCached) { - return getJointIndexWorker(); - } else { - readLock.unlock(); - { - QWriteLocker writeLock(&_jointIndicesCacheLock); - Avatar::cacheJoints(); - return getJointIndexWorker(); - } - } + }); + return result; } QStringList Avatar::getJointNames() const { - auto getJointNamesWorker = [&]() { - return _jointIndicesCache.keys(); - }; - QReadLocker readLock(&_jointIndicesCacheLock); - if (_jointsCached) { - return getJointNamesWorker(); - } else { - readLock.unlock(); - { - QWriteLocker writeLock(&_jointIndicesCacheLock); - Avatar::cacheJoints(); - return getJointNamesWorker(); - } - } + QStringList result; + withValidCache([&]() { + result = _jointIndicesCache.keys(); + }); + return result; } glm::vec3 Avatar::getJointPosition(int index) const { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 2069e36998..6566e79d79 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -268,8 +268,8 @@ protected: SkeletonModelPointer _skeletonModel; - void cacheJoints() const; void invalidateJointIndicesCache() const; + void withValidCache(std::function const& worker) const; mutable QHash _jointIndicesCache; mutable QReadWriteLock _jointIndicesCacheLock; mutable bool _jointsCached { false }; From 0c18f04e58736cb39c6810be7b500b8d19afaa04 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 6 Jul 2017 18:40:14 -0700 Subject: [PATCH 42/70] 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 ddabe940d699b8054f7e4aba67e7581ccdeaecce Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 6 Jul 2017 18:42:00 -0700 Subject: [PATCH 43/70] dry up some code --- libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp | 6 +++--- libraries/avatars-renderer/src/avatars-renderer/Avatar.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 4ffacf9fa6..664b9f5959 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1013,7 +1013,7 @@ void Avatar::invalidateJointIndicesCache() const { _jointsCached = false; } -void Avatar::withValidCache(std::function const& worker) const { +void Avatar::withValidJointIndicesCache(std::function const& worker) const { QReadLocker readLock(&_jointIndicesCacheLock); if (_jointsCached) { worker(); @@ -1039,7 +1039,7 @@ int Avatar::getJointIndex(const QString& name) const { return result; } - withValidCache([&]() { + withValidJointIndicesCache([&]() { if (_jointIndicesCache.contains(name)) { result = _jointIndicesCache[name]; } @@ -1049,7 +1049,7 @@ int Avatar::getJointIndex(const QString& name) const { QStringList Avatar::getJointNames() const { QStringList result; - withValidCache([&]() { + withValidJointIndicesCache([&]() { result = _jointIndicesCache.keys(); }); return result; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 6566e79d79..ce7e53656e 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -269,7 +269,7 @@ protected: SkeletonModelPointer _skeletonModel; void invalidateJointIndicesCache() const; - void withValidCache(std::function const& worker) const; + void withValidJointIndicesCache(std::function const& worker) const; mutable QHash _jointIndicesCache; mutable QReadWriteLock _jointIndicesCacheLock; mutable bool _jointsCached { false }; From ee9cdaff901f40f596c423158a113bfd23fdd624 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 6 Jul 2017 23:26:40 -0700 Subject: [PATCH 44/70] Set admin status even if QML can't find user in PAL --- interface/resources/qml/hifi/Pal.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index bbb42e61ac..e300af98b4 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -1099,9 +1099,9 @@ Rectangle { case 'nearbyUsers': var data = message.params; var index = -1; + iAmAdmin = Users.canKick; index = findNearbySessionIndex('', data); if (index !== -1) { - iAmAdmin = Users.canKick; myData = data[index]; data.splice(index, 1); } else { From ea77557e387500c6342077d6344f05cbe9a3d678 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 7 Jul 2017 08:08:52 -0700 Subject: [PATCH 45/70] Correctly close PAL when switching domains --- scripts/system/pal.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 0500c13f9b..264066558e 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -865,6 +865,9 @@ function avatarDisconnected(nodeID) { function clearLocalQMLDataAndClosePAL() { sendToQml({ method: 'clearLocalQMLData' }); + if (onPalScreen) { + tablet.gotoHomeScreen(); + } } function avatarAdded(avatarID) { From 88c39f3237ecaa00fc713114f86295b00fdafd6b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 7 Jul 2017 09:15:42 -0700 Subject: [PATCH 46/70] off-by-one --- libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 664b9f5959..20a85331d9 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1041,7 +1041,7 @@ int Avatar::getJointIndex(const QString& name) const { withValidJointIndicesCache([&]() { if (_jointIndicesCache.contains(name)) { - result = _jointIndicesCache[name]; + result = _jointIndicesCache[name] - 1; } }); return result; From c3dd25e4994837de299a3928f855f4f1a6e97ecc Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 7 Jul 2017 18:26:10 +0200 Subject: [PATCH 47/70] Drafting the mechanism to add shape pipeline --- .../RenderableParticleEffectEntityItem.cpp | 9 ++++++++ libraries/render/src/render/DrawTask.cpp | 23 +++++++++++++++++-- libraries/render/src/render/Item.h | 4 ++++ libraries/render/src/render/ShapePipeline.h | 20 ++++++++++++++++ 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 10bd70be13..5ea8af4d7a 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -142,6 +142,15 @@ namespace render { payload->render(args); } } + template <> + const ShapeKey shapeGetShapeKey(const ParticlePayloadData::Pointer& payload) { + return ShapeKey::Builder().withCustom(75).build(); + } + + template <> + bool shapeDefineCustomShapePipeline(const ParticlePayloadData::Pointer& payload, ShapePlumber& plumber, const ShapeKey& key) { + return false; + } } diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 13d454e393..ce6e26faf2 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -44,10 +44,17 @@ void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, cons auto key = item.getShapeKey() | globalKey; if (key.isValid() && !key.hasOwnPipeline()) { args->_pipeline = shapeContext->pickPipeline(args, key); + if (!args->_pipeline) { + if (key.isCustom()) { + if (item.defineCustomShapePipeline(*shapeContext, key)) { + args->_pipeline = shapeContext->pickPipeline(args, key); + } + } + } if (args->_pipeline) { args->_pipeline->prepareShapeItem(args, key, item); item.render(args); - } + } args->_pipeline = nullptr; } else if (key.hasOwnPipeline()) { item.render(args); @@ -111,7 +118,19 @@ void render::renderStateSortShapes(const RenderContextPointer& renderContext, for (auto& pipelineKey : sortedPipelines) { auto& bucket = sortedShapes[pipelineKey]; args->_pipeline = shapeContext->pickPipeline(args, pipelineKey); - if (!args->_pipeline) { + if (!args->_pipeline) { + if (pipelineKey.isCustom()) { + if (bucket.front().defineCustomShapePipeline(*shapeContext, pipelineKey)) { + args->_pipeline = shapeContext->pickPipeline(args, pipelineKey); + if (!args->_pipeline) { + + } else { + continue; + } + } else { + continue; + } + } continue; } for (auto& item : bucket) { diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 007b34395d..8ec80a7d7e 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -320,6 +320,7 @@ public: virtual void render(RenderArgs* args) = 0; virtual const ShapeKey getShapeKey() const = 0; + virtual bool defineCustomShapePipeline(ShapePlumber& plumber, const ShapeKey& key) const = 0; virtual uint32_t fetchMetaSubItems(ItemIDs& subItems) const = 0; @@ -369,6 +370,7 @@ public: // Shape Type Interface const ShapeKey getShapeKey() const { return _payload->getShapeKey(); } + bool defineCustomShapePipeline(ShapePlumber& plumber, const ShapeKey& key) const { return _payload->defineCustomShapePipeline(plumber, key); } // Meta Type Interface uint32_t fetchMetaSubItems(ItemIDs& subItems) const { return _payload->fetchMetaSubItems(subItems); } @@ -415,6 +417,7 @@ template void payloadRender(const std::shared_ptr& payloadData, Ren // When creating a new shape payload you need to create a specialized version, or the ShapeKey will be ownPipeline, // implying that the shape will setup its own pipeline without the use of the ShapeKey. template const ShapeKey shapeGetShapeKey(const std::shared_ptr& payloadData) { return ShapeKey::Builder::ownPipeline(); } +template bool shapeDefineCustomShapePipeline(const std::shared_ptr& payloadData, ShapePlumber& plumber, const ShapeKey& key) { return false; } // Meta Type Interface // Meta items act as the grouping object for several sub items (typically shapes). @@ -441,6 +444,7 @@ public: // Shape Type interface virtual const ShapeKey getShapeKey() const override { return shapeGetShapeKey(_data); } + virtual bool defineCustomShapePipeline(ShapePlumber& plumber, const ShapeKey& key) const override { return shapeDefineCustomShapePipeline(_data, plumber, key); } // Meta Type Interface virtual uint32_t fetchMetaSubItems(ItemIDs& subItems) const override { return metaFetchMetaSubItems(_data, subItems); } diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 7b2eff994f..afc0eac011 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -39,7 +39,19 @@ public: OWN_PIPELINE, INVALID, + CUSTOM_0, + CUSTOM_1, + CUSTOM_2, + CUSTOM_3, + CUSTOM_4, + CUSTOM_5, + CUSTOM_6, + CUSTOM_7, + NUM_FLAGS, // Not a valid flag + + CUSTOM_MASK = (0xFF << CUSTOM_0), + }; using Flags = std::bitset; @@ -74,6 +86,8 @@ public: Builder& withOwnPipeline() { _flags.set(OWN_PIPELINE); return (*this); } Builder& invalidate() { _flags.set(INVALID); return (*this); } + Builder& withCustom(uint8_t custom) { _flags &= (~CUSTOM_MASK); _flags |= (custom << CUSTOM_0); return (*this); } + static const ShapeKey ownPipeline() { return Builder().withOwnPipeline(); } static const ShapeKey invalid() { return Builder().invalidate(); } @@ -128,6 +142,9 @@ public: Builder& withCullFace() { _flags.reset(NO_CULL_FACE); _mask.set(NO_CULL_FACE); return (*this); } Builder& withoutCullFace() { _flags.set(NO_CULL_FACE); _mask.set(NO_CULL_FACE); return (*this); } + Builder& withCustom(uint8_t custom) { _flags &= (~CUSTOM_MASK); _flags |= (custom << CUSTOM_0); _mask |= (CUSTOM_MASK); return (*this); } + Builder& withoutCustom() { _flags &= (~CUSTOM_MASK); _mask |= (CUSTOM_MASK); return (*this); } + protected: friend class Filter; Flags _flags{0}; @@ -156,6 +173,9 @@ public: bool hasOwnPipeline() const { return _flags[OWN_PIPELINE]; } bool isValid() const { return !_flags[INVALID]; } + uint8_t getCustom() const { return (_flags.to_ulong() & CUSTOM_MASK) >> CUSTOM_0; } + bool isCustom() const { return (_flags.to_ulong() & CUSTOM_MASK); } + // Comparator for use in stl containers class Hash { public: From bff54d260e4db966d34bfe32ed517c33bd7ffc2e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Jul 2017 10:11:13 -0700 Subject: [PATCH 48/70] fix for baking FBX with external textures --- tools/oven/src/FBXBaker.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/oven/src/FBXBaker.cpp b/tools/oven/src/FBXBaker.cpp index 8a72784d7c..0259a6baf8 100644 --- a/tools/oven/src/FBXBaker.cpp +++ b/tools/oven/src/FBXBaker.cpp @@ -354,8 +354,8 @@ void FBXBaker::rewriteAndBakeSceneTextures() { FbxFileTexture* fileTexture = property.GetSrcObject(j); // use QFileInfo to easily split up the existing texture filename into its components - QString fbxFileName { fileTexture->GetFileName() }; - QFileInfo textureFileInfo { fbxFileName.replace("\\", "/") }; + QString fbxTextureFileName { fileTexture->GetFileName() }; + QFileInfo textureFileInfo { fbxTextureFileName.replace("\\", "/") }; // make sure this texture points to something and isn't one we've already re-mapped if (!textureFileInfo.filePath().isEmpty() @@ -372,6 +372,9 @@ void FBXBaker::rewriteAndBakeSceneTextures() { qCDebug(model_baking).noquote() << "Re-mapping" << fileTexture->GetFileName() << "to" << bakedTextureFilePath; + // figure out the URL to this texture, embedded or external + auto urlToTexture = getTextureURL(textureFileInfo, fileTexture); + // write the new filename into the FBX scene fileTexture->SetFileName(bakedTextureFilePath.toLocal8Bit()); @@ -379,9 +382,6 @@ void FBXBaker::rewriteAndBakeSceneTextures() { // be right beside the FBX fileTexture->SetRelativeFileName(bakedTextureFileName.toLocal8Bit().constData()); - // figure out the URL to this texture, embedded or external - auto urlToTexture = getTextureURL(textureFileInfo, fileTexture); - if (!_bakingTextures.contains(urlToTexture)) { // bake this texture asynchronously bakeTexture(urlToTexture, textureType, _uniqueOutputPath + BAKED_OUTPUT_SUBFOLDER); From e22a3c6af97eb7646f9de612d66a11866ff6a8d1 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 6 Jul 2017 18:01:26 -0700 Subject: [PATCH 49/70] 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 6782a891d04c0ae887c68c09386b8d7a0b0d1282 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 7 Jul 2017 10:35:45 -0700 Subject: [PATCH 50/70] rename the joint-name caches in AvatarData and Avatar so it's more clear that they are different --- .../src/avatars-renderer/Avatar.cpp | 24 +++++++++---------- .../src/avatars-renderer/Avatar.h | 6 ++--- libraries/avatars/src/AvatarData.cpp | 18 +++++++------- libraries/avatars/src/AvatarData.h | 4 ++-- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 20a85331d9..7e1e51572f 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1009,23 +1009,23 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const { } void Avatar::invalidateJointIndicesCache() const { - QWriteLocker writeLock(&_jointIndicesCacheLock); - _jointsCached = false; + QWriteLocker writeLock(&_modelJointIndicesCacheLock); + _modelJointsCached = false; } void Avatar::withValidJointIndicesCache(std::function const& worker) const { - QReadLocker readLock(&_jointIndicesCacheLock); - if (_jointsCached) { + QReadLocker readLock(&_modelJointIndicesCacheLock); + if (_modelJointsCached) { worker(); } else { readLock.unlock(); { - QWriteLocker writeLock(&_jointIndicesCacheLock); - if (!_jointsCached) { - _jointIndicesCache.clear(); + QWriteLocker writeLock(&_modelJointIndicesCacheLock); + if (!_modelJointsCached) { + _modelJointIndicesCache.clear(); if (_skeletonModel && _skeletonModel->isActive()) { - _jointIndicesCache = _skeletonModel->getFBXGeometry().jointIndices; - _jointsCached = true; + _modelJointIndicesCache = _skeletonModel->getFBXGeometry().jointIndices; + _modelJointsCached = true; } } worker(); @@ -1040,8 +1040,8 @@ int Avatar::getJointIndex(const QString& name) const { } withValidJointIndicesCache([&]() { - if (_jointIndicesCache.contains(name)) { - result = _jointIndicesCache[name] - 1; + if (_modelJointIndicesCache.contains(name)) { + result = _modelJointIndicesCache[name] - 1; } }); return result; @@ -1050,7 +1050,7 @@ int Avatar::getJointIndex(const QString& name) const { QStringList Avatar::getJointNames() const { QStringList result; withValidJointIndicesCache([&]() { - result = _jointIndicesCache.keys(); + result = _modelJointIndicesCache.keys(); }); return result; } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index ce7e53656e..89db519abc 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -270,9 +270,9 @@ protected: void invalidateJointIndicesCache() const; void withValidJointIndicesCache(std::function const& worker) const; - mutable QHash _jointIndicesCache; - mutable QReadWriteLock _jointIndicesCacheLock; - mutable bool _jointsCached { false }; + mutable QHash _modelJointIndicesCache; + mutable QReadWriteLock _modelJointIndicesCacheLock; + mutable bool _modelJointsCached { false }; glm::vec3 _skeletonOffset; std::vector> _attachmentModels; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 6eed23fb5b..cc64d21f0f 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1462,12 +1462,12 @@ int AvatarData::getJointIndex(const QString& name) const { return result; } QReadLocker readLock(&_jointDataLock); - return _jointIndices.value(name) - 1; + return _fstJointIndices.value(name) - 1; } QStringList AvatarData::getJointNames() const { QReadLocker readLock(&_jointDataLock); - return _jointNames; + return _fstJointNames; } glm::quat AvatarData::getOrientationOutbound() const { @@ -1720,14 +1720,14 @@ void AvatarData::setJointMappingsFromNetworkReply() { bool ok; int jointIndex = line.mid(secondSeparatorIndex + 1).trimmed().toInt(&ok); if (ok) { - while (_jointNames.size() < jointIndex + 1) { - _jointNames.append(QString()); + while (_fstJointNames.size() < jointIndex + 1) { + _fstJointNames.append(QString()); } - _jointNames[jointIndex] = jointName; + _fstJointNames[jointIndex] = jointName; } } - for (int i = 0; i < _jointNames.size(); i++) { - _jointIndices.insert(_jointNames.at(i), i + 1); + for (int i = 0; i < _fstJointNames.size(); i++) { + _fstJointIndices.insert(_fstJointNames.at(i), i + 1); } } @@ -1781,8 +1781,8 @@ void AvatarData::sendIdentityPacket() { void AvatarData::updateJointMappings() { { QWriteLocker writeLock(&_jointDataLock); - _jointIndices.clear(); - _jointNames.clear(); + _fstJointIndices.clear(); + _fstJointNames.clear(); _jointData.clear(); } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index d6241c2c50..1f672328ba 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -704,8 +704,8 @@ protected: QString _displayName; QString _sessionDisplayName { }; - QHash _jointIndices; ///< 1-based, since zero is returned for missing keys - QStringList _jointNames; ///< in order of depth-first traversal + QHash _fstJointIndices; ///< 1-based, since zero is returned for missing keys + QStringList _fstJointNames; ///< in order of depth-first traversal quint64 _errorLogExpiry; ///< time in future when to log an error From 060e3a9c5afdaa3ddbf15d37b87cdd81456f77d8 Mon Sep 17 00:00:00 2001 From: Liv Date: Fri, 7 Jul 2017 11:48:12 -0700 Subject: [PATCH 51/70] 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 77001712abec8cba03815bfaf2a1c3acabd8b041 Mon Sep 17 00:00:00 2001 From: 1P-Cusack <1p-cusack@1stplayable.com> Date: Fri, 7 Jul 2017 15:35:32 -0400 Subject: [PATCH 52/70] Default 'Enter First Person Mode in HMD' to true. --- interface/src/Menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 9bda575305..042719362b 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -259,7 +259,7 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Overlays, 0, true); // View > Enter First Person Mode in HMD - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPersonHMD, 0, false); + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPersonHMD, 0, true); // Navigate menu ---------------------------------- MenuWrapper* navigateMenu = addMenu("Navigate"); From 420e9233b6e4d15d4969400ebc09db263b534935 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 7 Jul 2017 16:50:28 -0700 Subject: [PATCH 53/70] Revert "fix for invisible avatars after radius ignore" --- .../src/avatars/AvatarMixerClientData.cpp | 3 +++ interface/src/avatar/AvatarManager.cpp | 4 ++++ .../src/avatars-renderer/Avatar.cpp | 3 ++- libraries/avatars/src/AvatarHashMap.cpp | 7 +++++++ libraries/avatars/src/AvatarHashMap.h | 1 + libraries/networking/src/NodeList.cpp | 20 +++++++++++++++++++ libraries/networking/src/NodeList.h | 4 ++++ libraries/networking/src/udt/PacketHeaders.h | 1 + 8 files changed, 42 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index a4bf8fa253..4d80bc7d17 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -108,6 +108,9 @@ void AvatarMixerClientData::ignoreOther(SharedNodePointer self, SharedNodePointe void AvatarMixerClientData::removeFromRadiusIgnoringSet(SharedNodePointer self, const QUuid& other) { if (isRadiusIgnoring(other)) { _radiusIgnoredOthers.erase(other); + auto exitingSpaceBubblePacket = NLPacket::create(PacketType::ExitingSpaceBubble, NUM_BYTES_RFC4122_UUID); + exitingSpaceBubblePacket->write(other.toRfc4122()); + DependencyManager::get()->sendUnreliablePacket(*exitingSpaceBubblePacket, *self); } } diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 3272bc3255..c46d61cf68 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -63,6 +63,7 @@ AvatarManager::AvatarManager(QObject* parent) : packetReceiver.registerListener(PacketType::BulkAvatarData, this, "processAvatarDataPacket"); packetReceiver.registerListener(PacketType::KillAvatar, this, "processKillAvatar"); packetReceiver.registerListener(PacketType::AvatarIdentity, this, "processAvatarIdentityPacket"); + packetReceiver.registerListener(PacketType::ExitingSpaceBubble, this, "processExitingSpaceBubble"); // when we hear that the user has ignored an avatar by session UUID // immediately remove that avatar instead of waiting for the absence of packets from avatar mixer @@ -319,6 +320,9 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble) { emit DependencyManager::get()->enteredIgnoreRadius(); + } + if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble || removalReason == YourAvatarEnteredTheirBubble) { + DependencyManager::get()->radiusIgnoreNodeBySessionID(avatar->getSessionUUID(), true); } else if (removalReason == KillAvatarReason::AvatarDisconnected) { // remove from node sets, if present DependencyManager::get()->removeFromIgnoreMuteSets(avatar->getSessionUUID()); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 63009d7a28..d303b2e66d 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1440,7 +1440,8 @@ void Avatar::addToScene(AvatarSharedPointer myHandle, const render::ScenePointer if (scene) { auto nodelist = DependencyManager::get(); if (showAvatars - && !nodelist->isIgnoringNode(getSessionUUID())) { + && !nodelist->isIgnoringNode(getSessionUUID()) + && !nodelist->isRadiusIgnoringNode(getSessionUUID())) { render::Transaction transaction; addToScene(myHandle, scene, transaction); scene->enqueueTransaction(transaction); diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 3712080cdb..e8c37bdaa8 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -170,6 +170,13 @@ void AvatarHashMap::processKillAvatar(QSharedPointer message, S removeAvatar(sessionUUID, reason); } +void AvatarHashMap::processExitingSpaceBubble(QSharedPointer message, SharedNodePointer sendingNode) { + // read the node id + QUuid sessionUUID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + auto nodeList = DependencyManager::get(); + nodeList->radiusIgnoreNodeBySessionID(sessionUUID, false); +} + void AvatarHashMap::removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason) { QWriteLocker locker(&_hashLock); diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index 68fc232685..21ea8081c7 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -60,6 +60,7 @@ protected slots: void processAvatarDataPacket(QSharedPointer message, SharedNodePointer sendingNode); void processAvatarIdentityPacket(QSharedPointer message, SharedNodePointer sendingNode); void processKillAvatar(QSharedPointer message, SharedNodePointer sendingNode); + void processExitingSpaceBubble(QSharedPointer message, SharedNodePointer sendingNode); protected: AvatarHashMap(); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 7c479e1bff..262f0318b6 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -241,6 +241,10 @@ void NodeList::reset() { _numNoReplyDomainCheckIns = 0; + // lock and clear our set of radius ignored IDs + _radiusIgnoredSetLock.lockForWrite(); + _radiusIgnoredNodeIDs.clear(); + _radiusIgnoredSetLock.unlock(); // lock and clear our set of ignored IDs _ignoredSetLock.lockForWrite(); _ignoredNodeIDs.clear(); @@ -806,6 +810,22 @@ void NodeList::sendIgnoreRadiusStateToNode(const SharedNodePointer& destinationN sendPacket(std::move(ignorePacket), *destinationNode); } +void NodeList::radiusIgnoreNodeBySessionID(const QUuid& nodeID, bool radiusIgnoreEnabled) { + if (radiusIgnoreEnabled) { + QReadLocker radiusIgnoredSetLocker{ &_radiusIgnoredSetLock }; // read lock for insert + // add this nodeID to our set of ignored IDs + _radiusIgnoredNodeIDs.insert(nodeID); + } else { + QWriteLocker radiusIgnoredSetLocker{ &_radiusIgnoredSetLock }; // write lock for unsafe_erase + _radiusIgnoredNodeIDs.unsafe_erase(nodeID); + } +} + +bool NodeList::isRadiusIgnoringNode(const QUuid& nodeID) const { + QReadLocker radiusIgnoredSetLocker{ &_radiusIgnoredSetLock }; // read lock for reading + return _radiusIgnoredNodeIDs.find(nodeID) != _radiusIgnoredNodeIDs.cend(); +} + void NodeList::ignoreNodeBySessionID(const QUuid& nodeID, bool ignoreEnabled) { // enumerate the nodes to send a reliable ignore packet to each that can leverage it if (!nodeID.isNull() && _sessionUUID != nodeID) { diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index b3a12153e5..6db760b3ca 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -77,6 +77,8 @@ public: void toggleIgnoreRadius() { ignoreNodesInRadius(!getIgnoreRadiusEnabled()); } void enableIgnoreRadius() { ignoreNodesInRadius(true); } void disableIgnoreRadius() { ignoreNodesInRadius(false); } + void radiusIgnoreNodeBySessionID(const QUuid& nodeID, bool radiusIgnoreEnabled); + bool isRadiusIgnoringNode(const QUuid& other) const; void ignoreNodeBySessionID(const QUuid& nodeID, bool ignoreEnabled); bool isIgnoringNode(const QUuid& nodeID) const; void personalMuteNodeBySessionID(const QUuid& nodeID, bool muteEnabled); @@ -164,6 +166,8 @@ private: QTimer _keepAlivePingTimer; bool _requestsDomainListData; + mutable QReadWriteLock _radiusIgnoredSetLock; + tbb::concurrent_unordered_set _radiusIgnoredNodeIDs; mutable QReadWriteLock _ignoredSetLock; tbb::concurrent_unordered_set _ignoredNodeIDs; mutable QReadWriteLock _personalMutedSetLock; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 848bfd97cf..6c42193e11 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -105,6 +105,7 @@ public: UsernameFromIDReply, ViewFrustum, RequestsDomainListData, + ExitingSpaceBubble, PerAvatarGainSet, EntityScriptGetStatus, EntityScriptGetStatusReply, From 7e9ea596a086fd0a1512938ae1cd7e60742b359b Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 7 Jul 2017 19:07:19 -0700 Subject: [PATCH 54/70] 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 148eece065c3a8c2dc34daac1f6c8d098d3b0f96 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 7 Jul 2017 13:56:28 -0700 Subject: [PATCH 55/70] 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 7d397adf96..3cbc6208ad 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2729,56 +2729,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 cd11f5cfa6edda943b9015e13d0bc645a6f83024 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 7 Jul 2017 22:02:56 -0700 Subject: [PATCH 56/70] 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 3cbc6208ad..565d86cc69 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2751,7 +2751,7 @@ bool Application::event(QEvent* event) { idle(nsecsElapsed); postEvent(this, new QEvent(static_cast(Paint)), Qt::HighEventPriority); } - } + } return true; case Event::Paint: @@ -2759,6 +2759,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 4b593d1ab43edf3725af8d68f77f257652f4a5ac Mon Sep 17 00:00:00 2001 From: Mike Moody Date: Sat, 8 Jul 2017 15:18:27 -0700 Subject: [PATCH 57/70] 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 58/70] 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 59/70] 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 60/70] 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 4edea433ce0eac525dbda824498511eb29a8cf93 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 10 Jul 2017 12:16:53 +0200 Subject: [PATCH 61/70] Rename the _pipeline into _shapePipeline in the render::Args --- interface/src/ui/overlays/Circle3DOverlay.cpp | 4 ++-- interface/src/ui/overlays/Cube3DOverlay.cpp | 10 +++++----- interface/src/ui/overlays/Shape3DOverlay.cpp | 10 +++++----- interface/src/ui/overlays/Sphere3DOverlay.cpp | 10 +++++----- interface/src/ui/overlays/Text3DOverlay.cpp | 4 ++-- libraries/render-utils/src/MeshPartPayload.cpp | 4 ++-- libraries/render-utils/src/RenderShadowTask.cpp | 6 +++--- libraries/render/src/render/Args.h | 2 +- libraries/render/src/render/DrawTask.cpp | 12 ++++++------ 9 files changed, 31 insertions(+), 31 deletions(-) diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index ae0173f054..827417a912 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -80,8 +80,8 @@ void Circle3DOverlay::render(RenderArgs* args) { Q_ASSERT(args->_batch); auto& batch = *args->_batch; - if (args->_pipeline) { - batch.setPipeline(args->_pipeline->pipeline); + if (args->_shapePipeline) { + batch.setPipeline(args->_shapePipeline->pipeline); } // FIXME: THe line width of _lineWidth is not supported anymore, we ll need a workaround diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 707aabc241..a353545245 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -65,15 +65,15 @@ void Cube3DOverlay::render(RenderArgs* args) { transform.setTranslation(position); transform.setRotation(rotation); auto geometryCache = DependencyManager::get(); - auto pipeline = args->_pipeline; - if (!pipeline) { - pipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline(); + auto shapePipeline = args->_shapePipeline; + if (!shapePipeline) { + shapePipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline(); } if (_isSolid) { transform.setScale(dimensions); batch->setModelTransform(transform); - geometryCache->renderSolidCubeInstance(args, *batch, cubeColor, pipeline); + geometryCache->renderSolidCubeInstance(args, *batch, cubeColor, shapePipeline); } else { geometryCache->bindSimpleProgram(*batch, false, false, false, true, true); if (getIsDashedLine()) { @@ -109,7 +109,7 @@ void Cube3DOverlay::render(RenderArgs* args) { } else { transform.setScale(dimensions); batch->setModelTransform(transform); - geometryCache->renderWireCubeInstance(args, *batch, cubeColor, pipeline); + geometryCache->renderWireCubeInstance(args, *batch, cubeColor, shapePipeline); } } } diff --git a/interface/src/ui/overlays/Shape3DOverlay.cpp b/interface/src/ui/overlays/Shape3DOverlay.cpp index 72c57565d4..a6fcacc769 100644 --- a/interface/src/ui/overlays/Shape3DOverlay.cpp +++ b/interface/src/ui/overlays/Shape3DOverlay.cpp @@ -45,17 +45,17 @@ void Shape3DOverlay::render(RenderArgs* args) { transform.setTranslation(position); transform.setRotation(rotation); auto geometryCache = DependencyManager::get(); - auto pipeline = args->_pipeline; - if (!pipeline) { - pipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline(); + auto shapePipeline = args->_shapePipeline; + if (!shapePipeline) { + shapePipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline(); } transform.setScale(dimensions); batch->setModelTransform(transform); if (_isSolid) { - geometryCache->renderSolidShapeInstance(args, *batch, _shape, cubeColor, pipeline); + geometryCache->renderSolidShapeInstance(args, *batch, _shape, cubeColor, shapePipeline); } else { - geometryCache->renderWireShapeInstance(args, *batch, _shape, cubeColor, pipeline); + geometryCache->renderWireShapeInstance(args, *batch, _shape, cubeColor, shapePipeline); } } } diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 67e11cf1d8..5bbf41eb94 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -44,15 +44,15 @@ void Sphere3DOverlay::render(RenderArgs* args) { batch->setModelTransform(transform); auto geometryCache = DependencyManager::get(); - auto pipeline = args->_pipeline; - if (!pipeline) { - pipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline(); + auto shapePipeline = args->_shapePipeline; + if (!shapePipeline) { + shapePipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline(); } if (_isSolid) { - geometryCache->renderSolidSphereInstance(args, *batch, sphereColor, pipeline); + geometryCache->renderSolidSphereInstance(args, *batch, sphereColor, shapePipeline); } else { - geometryCache->renderWireSphereInstance(args, *batch, sphereColor, pipeline); + geometryCache->renderWireSphereInstance(args, *batch, sphereColor, shapePipeline); } } } diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index ed29bc4e1b..4b110b8099 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -137,8 +137,8 @@ void Text3DOverlay::render(RenderArgs* args) { // Text renderer sets its own pipeline, _textRenderer->draw(batch, 0, 0, getText(), textColor, glm::vec2(-1.0f), getDrawInFront()); // so before we continue, we must reset the pipeline - batch.setPipeline(args->_pipeline->pipeline); - args->_pipeline->prepare(batch, args); + batch.setPipeline(args->_shapePipeline->pipeline); + args->_shapePipeline->prepare(batch, args); } const render::ShapeKey Text3DOverlay::getShapeKey() { diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index b16134db5f..f6cb55deed 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -259,7 +259,7 @@ void MeshPartPayload::render(RenderArgs* args) { gpu::Batch& batch = *(args->_batch); - auto locations = args->_pipeline->locations; + auto locations = args->_shapePipeline->locations; assert(locations); // Bind the model transform and the skinCLusterMatrices if needed @@ -583,7 +583,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) { } gpu::Batch& batch = *(args->_batch); - auto locations = args->_pipeline->locations; + auto locations = args->_shapePipeline->locations; assert(locations); bindTransform(batch, locations, args->_renderMode); diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index a817a6abff..5b840bd330 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -68,7 +68,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, std::vector skinnedShapeKeys{}; // Iterate through all inShapes and render the unskinned - args->_pipeline = shadowPipeline; + args->_shapePipeline = shadowPipeline; batch.setPipeline(shadowPipeline->pipeline); for (auto items : inShapes) { if (items.first.isSkinned()) { @@ -79,13 +79,13 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, } // Reiterate to render the skinned - args->_pipeline = shadowSkinnedPipeline; + args->_shapePipeline = shadowSkinnedPipeline; batch.setPipeline(shadowSkinnedPipeline->pipeline); for (const auto& key : skinnedShapeKeys) { renderItems(renderContext, inShapes.at(key)); } - args->_pipeline = nullptr; + args->_shapePipeline = nullptr; args->_batch = nullptr; }); } diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index c2e03d4f46..449a3ac22b 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -103,7 +103,7 @@ namespace render { std::shared_ptr _context; std::shared_ptr _blitFramebuffer; - std::shared_ptr _pipeline; + std::shared_ptr _shapePipeline; QSharedPointer _renderData; std::stack _viewFrustums; glm::ivec4 _viewport { 0.0f, 0.0f, 1.0f, 1.0f }; diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index b6f3440d5c..1153a737a1 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -43,11 +43,11 @@ void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, cons assert(item.getKey().isShape()); auto key = item.getShapeKey() | globalKey; if (key.isValid() && !key.hasOwnPipeline()) { - args->_pipeline = shapeContext->pickPipeline(args, key); - if (args->_pipeline) { + args->_shapePipeline = shapeContext->pickPipeline(args, key); + if (args->_shapePipeline) { item.render(args); } - args->_pipeline = nullptr; + args->_shapePipeline = nullptr; } else if (key.hasOwnPipeline()) { item.render(args); } else { @@ -109,15 +109,15 @@ void render::renderStateSortShapes(const RenderContextPointer& renderContext, // Then render for (auto& pipelineKey : sortedPipelines) { auto& bucket = sortedShapes[pipelineKey]; - args->_pipeline = shapeContext->pickPipeline(args, pipelineKey); - if (!args->_pipeline) { + args->_shapePipeline = shapeContext->pickPipeline(args, pipelineKey); + if (!args->_shapePipeline) { continue; } for (auto& item : bucket) { item.render(args); } } - args->_pipeline = nullptr; + args->_shapePipeline = nullptr; for (auto& item : ownPipelineBucket) { item.render(args); } From 0c3755483b99ecc1a88af17ac9bb8bd1ba598e6a Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 10 Jul 2017 12:37:26 +0200 Subject: [PATCH 62/70] adding assert or checks whenever getting a scene stage --- .../entities-renderer/src/RenderableZoneEntityItem.cpp | 2 ++ libraries/render-utils/src/BackgroundStage.cpp | 2 ++ libraries/render-utils/src/DebugDeferredBuffer.cpp | 1 + libraries/render-utils/src/DeferredLightingEffect.cpp | 2 ++ libraries/render-utils/src/LightClusters.cpp | 1 + libraries/render-utils/src/LightPayload.cpp | 2 ++ libraries/render-utils/src/RenderShadowTask.cpp | 3 ++- libraries/render-utils/src/SubsurfaceScattering.cpp | 3 ++- libraries/render-utils/src/ZoneRenderer.cpp | 8 +++++--- 9 files changed, 19 insertions(+), 5 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index a57a6e5d52..eda304ef91 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -555,10 +555,12 @@ void RenderableZoneEntityItemMeta::setProceduralUserData(QString userData) { void RenderableZoneEntityItemMeta::render(RenderArgs* args) { if (!_stage) { _stage = args->_scene->getStage(); + assert(_stage); } if (!_backgroundStage) { _backgroundStage = args->_scene->getStage(); + assert(_backgroundStage); } { // Sun diff --git a/libraries/render-utils/src/BackgroundStage.cpp b/libraries/render-utils/src/BackgroundStage.cpp index 5d04f188f1..2ea3683c4a 100644 --- a/libraries/render-utils/src/BackgroundStage.cpp +++ b/libraries/render-utils/src/BackgroundStage.cpp @@ -61,6 +61,8 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, // Background rendering decision auto backgroundStage = renderContext->_scene->getStage(); + assert(backgroundStage); + model::SunSkyStagePointer background; model::SkyboxPointer skybox; if (backgroundStage->_currentFrame._backgrounds.size()) { diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 8887de81ef..44e2bd290b 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -433,6 +433,7 @@ void DebugDeferredBuffer::run(const RenderContextPointer& renderContext, const I } auto lightStage = renderContext->_scene->getStage(); + assert(lightStage); assert(lightStage->getNumLights() > 0); auto lightAndShadow = lightStage->getLightAndShadow(0); const auto& globalShadow = lightAndShadow.second; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 7b1ea1768d..2b5fdc1d74 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -429,6 +429,7 @@ void PrepareDeferred::run(const RenderContextPointer& renderContext, const Input // Prepare a fresh Light Frame auto lightStage = renderContext->_scene->getStage(); + assert(lightStage); lightStage->_currentFrame.clear(); } @@ -493,6 +494,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, // Global directional light and ambient pass auto lightStage = renderContext->_scene->getStage(); + assert(lightStage); assert(lightStage->getNumLights() > 0); auto lightAndShadow = lightStage->getLightAndShadow(0); const auto& globalShadow = lightAndShadow.second; diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 74209ce951..ab1e194498 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -575,6 +575,7 @@ void LightClusteringPass::run(const render::RenderContextPointer& renderContext, // From the LightStage and the current frame, update the light cluster Grid auto lightStage = renderContext->_scene->getStage(); + assert(lightStage); _lightClusters->updateLightStage(lightStage); _lightClusters->updateLightFrame(lightStage->_currentFrame, lightingModel->isPointLightEnabled(), lightingModel->isSpotLightEnabled()); diff --git a/libraries/render-utils/src/LightPayload.cpp b/libraries/render-utils/src/LightPayload.cpp index 5f7f7236f2..afa17bee19 100644 --- a/libraries/render-utils/src/LightPayload.cpp +++ b/libraries/render-utils/src/LightPayload.cpp @@ -56,6 +56,7 @@ LightPayload::~LightPayload() { void LightPayload::render(RenderArgs* args) { if (!_stage) { _stage = args->_scene->getStage(); + assert(_stage); } // Do we need to allocate the light in the stage ? if (LightStage::isIndexInvalid(_index)) { @@ -124,6 +125,7 @@ KeyLightPayload::~KeyLightPayload() { void KeyLightPayload::render(RenderArgs* args) { if (!_stage) { _stage = args->_scene->getStage(); + assert(_stage); } // Do we need to allocate the light in the stage ? if (LightStage::isIndexInvalid(_index)) { diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 5b840bd330..03a2a4f9b1 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -36,7 +36,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, assert(renderContext->args->hasViewFrustum()); auto lightStage = renderContext->_scene->getStage(); - + assert(lightStage); LightStage::Index globalLightIndex { 0 }; const auto globalLight = lightStage->getLight(globalLightIndex); @@ -141,6 +141,7 @@ void RenderShadowTask::configure(const Config& configuration) { void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, Output& output) { auto lightStage = renderContext->_scene->getStage(); + assert(lightStage); const auto globalShadow = lightStage->getShadow(0); // Cache old render args diff --git a/libraries/render-utils/src/SubsurfaceScattering.cpp b/libraries/render-utils/src/SubsurfaceScattering.cpp index d67369774c..1786898e57 100644 --- a/libraries/render-utils/src/SubsurfaceScattering.cpp +++ b/libraries/render-utils/src/SubsurfaceScattering.cpp @@ -532,7 +532,8 @@ void DebugSubsurfaceScattering::run(const render::RenderContextPointer& renderCo - auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); + auto lightStage = renderContext->_scene->getStage(); + assert(lightStage); // const auto light = DependencyManager::get()->getLightStage()->getLight(0); const auto light = lightStage->getLight(0); diff --git a/libraries/render-utils/src/ZoneRenderer.cpp b/libraries/render-utils/src/ZoneRenderer.cpp index 8fa243c13b..787ef47282 100644 --- a/libraries/render-utils/src/ZoneRenderer.cpp +++ b/libraries/render-utils/src/ZoneRenderer.cpp @@ -52,19 +52,21 @@ void ZoneRendererTask::build(JobModel& task, const Varying& input, Varying& oupu } void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs) { - auto backgroundStage = context->_scene->getStage("BACKGROUND_STAGE"); + auto backgroundStage = context->_scene->getStage(); + assert(backgroundStage); backgroundStage->_currentFrame.clear(); // call render in the correct order first... render::renderItems(context, inputs); // Finally add the default lights and background: - auto lightStage = context->_scene->getStage("LIGHT_STAGE"); + auto lightStage = context->_scene->getStage(); + assert(lightStage); + lightStage->_currentFrame.pushSunLight(0); lightStage->_currentFrame.pushAmbientLight(0); backgroundStage->_currentFrame.pushBackground(0); - } const gpu::PipelinePointer& DebugZoneLighting::getKeyLightPipeline() { From 75e1b265d55a81ffa583b4058ed3153e1b9089cc Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 10 Jul 2017 17:48:53 +0100 Subject: [PATCH 63/70] 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 64/70] 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 65/70] 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 66/70] 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 67/70] 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 68/70] 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 } From 98cc8c0683097b13140235c7d7401a4ed6802685 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 12 Jul 2017 14:13:58 +0200 Subject: [PATCH 69/70] Refining the custom shader pipeline design and registration mechanism --- .../RenderableParticleEffectEntityItem.cpp | 90 +++++++++---------- .../src/RenderableParticleEffectEntityItem.h | 7 +- .../src/untextured_particle.slf | 5 +- libraries/gl/src/gl/GLShaders.cpp | 1 - libraries/render/src/render/DrawTask.cpp | 8 +- libraries/render/src/render/Item.h | 4 - libraries/render/src/render/ShapePipeline.cpp | 29 +++++- libraries/render/src/render/ShapePipeline.h | 14 ++- 8 files changed, 87 insertions(+), 71 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 5ea8af4d7a..276ffb279f 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include "EntitiesRendererLogging.h" @@ -29,6 +30,16 @@ class ParticlePayloadData { public: static const size_t VERTEX_PER_PARTICLE = 4; + static uint8_t CUSTOM_PIPELINE_NUMBER; + static render::ShapePipelinePointer shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key); + static std::weak_ptr _texturedPipeline; + + static void registerShapePipeline() { + if (!CUSTOM_PIPELINE_NUMBER) { + ParticlePayloadData::CUSTOM_PIPELINE_NUMBER = render::ShapePipeline::registerCustomShapePipelineFactory(ParticlePayloadData::shapePipelineFactory); + } + } + template struct InterpolationData { T start; @@ -70,9 +81,6 @@ public: offsetof(ParticlePrimitive, uv), gpu::Stream::PER_INSTANCE); } - void setPipeline(PipelinePointer pipeline) { _pipeline = pipeline; } - const PipelinePointer& getPipeline() const { return _pipeline; } - const Transform& getModelTransform() const { return _modelTransform; } void setModelTransform(const Transform& modelTransform) { _modelTransform = modelTransform; } @@ -90,15 +98,16 @@ public: bool getVisibleFlag() const { return _visibleFlag; } void setVisibleFlag(bool visibleFlag) { _visibleFlag = visibleFlag; } - + void render(RenderArgs* args) const { assert(_pipeline); gpu::Batch& batch = *args->_batch; - batch.setPipeline(_pipeline); if (_texture) { batch.setResourceTexture(0, _texture); + } else { + batch.setResourceTexture(0, DependencyManager::get()->getWhiteTexture()); } batch.setModelTransform(_modelTransform); @@ -144,30 +153,47 @@ namespace render { } template <> const ShapeKey shapeGetShapeKey(const ParticlePayloadData::Pointer& payload) { - return ShapeKey::Builder().withCustom(75).build(); - } - - template <> - bool shapeDefineCustomShapePipeline(const ParticlePayloadData::Pointer& payload, ShapePlumber& plumber, const ShapeKey& key) { - return false; + return render::ShapeKey::Builder().withCustom(ParticlePayloadData::CUSTOM_PIPELINE_NUMBER).withTranslucent().build(); } } +uint8_t ParticlePayloadData::CUSTOM_PIPELINE_NUMBER = 0; +std::weak_ptr ParticlePayloadData::_texturedPipeline; + +render::ShapePipelinePointer ParticlePayloadData::shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key) { + auto texturedPipeline = _texturedPipeline.lock(); + if (!texturedPipeline) { + auto state = std::make_shared(); + state->setCullMode(gpu::State::CULL_BACK); + state->setDepthTest(true, false, gpu::LESS_EQUAL); + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + PrepareStencil::testMask(*state); + + auto vertShader = gpu::Shader::createVertex(std::string(textured_particle_vert)); + auto fragShader = gpu::Shader::createPixel(std::string(textured_particle_frag)); + + auto program = gpu::Shader::createProgram(vertShader, fragShader); + _texturedPipeline = texturedPipeline = gpu::Pipeline::create(program, state); + } + + return std::make_shared(texturedPipeline, nullptr, nullptr, nullptr); +} EntityItemPointer RenderableParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { auto entity = std::make_shared(entityID); entity->setProperties(properties); + + // As we create the first ParticuleSystem entity, let s register its special shapePIpeline factory: + ParticlePayloadData::registerShapePipeline(); + return entity; } RenderableParticleEffectEntityItem::RenderableParticleEffectEntityItem(const EntityItemID& entityItemID) : ParticleEffectEntityItem(entityItemID) { - // lazy creation of particle system pipeline - if (!_untexturedPipeline || !_texturedPipeline) { - createPipelines(); - } } bool RenderableParticleEffectEntityItem::addToScene(const EntityItemPointer& self, @@ -176,7 +202,6 @@ bool RenderableParticleEffectEntityItem::addToScene(const EntityItemPointer& sel _scene = scene; _renderItemId = _scene->allocateID(); auto particlePayloadData = std::make_shared(); - particlePayloadData->setPipeline(_untexturedPipeline); auto renderPayload = std::make_shared(particlePayloadData); render::Item::Status::Getters statusGetters; makeEntityItemStatusGetters(getThisPointer(), statusGetters); @@ -285,47 +310,14 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { if (_texture && _texture->isLoaded()) { payload.setTexture(_texture->getGPUTexture()); - payload.setPipeline(_texturedPipeline); } else { payload.setTexture(nullptr); - payload.setPipeline(_untexturedPipeline); } }); _scene->enqueueTransaction(transaction); } -void RenderableParticleEffectEntityItem::createPipelines() { - if (!_untexturedPipeline) { - auto state = std::make_shared(); - state->setCullMode(gpu::State::CULL_BACK); - state->setDepthTest(true, false, gpu::LESS_EQUAL); - state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - PrepareStencil::testMask(*state); - - auto vertShader = gpu::Shader::createVertex(std::string(untextured_particle_vert)); - auto fragShader = gpu::Shader::createPixel(std::string(untextured_particle_frag)); - - auto program = gpu::Shader::createProgram(vertShader, fragShader); - _untexturedPipeline = gpu::Pipeline::create(program, state); - } - if (!_texturedPipeline) { - auto state = std::make_shared(); - state->setCullMode(gpu::State::CULL_BACK); - state->setDepthTest(true, false, gpu::LESS_EQUAL); - state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - PrepareStencil::testMask(*state); - - auto vertShader = gpu::Shader::createVertex(std::string(textured_particle_vert)); - auto fragShader = gpu::Shader::createPixel(std::string(textured_particle_frag)); - - auto program = gpu::Shader::createProgram(vertShader, fragShader); - _texturedPipeline = gpu::Pipeline::create(program, state); - } -} - void RenderableParticleEffectEntityItem::notifyBoundChanged() { if (!render::Item::isValidID(_renderItemId)) { return; diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index 678b582b41..b0d7e1c920 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -34,16 +34,13 @@ protected: virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); notifyBoundChanged(); } virtual void dimensionsChanged() override { EntityItem::dimensionsChanged(); notifyBoundChanged(); } - void notifyBoundChanged(); + void notifyBoundChanged(); - void createPipelines(); - render::ScenePointer _scene; render::ItemID _renderItemId{ render::Item::INVALID_ITEM_ID }; NetworkTexturePointer _texture; - gpu::PipelinePointer _untexturedPipeline; - gpu::PipelinePointer _texturedPipeline; + }; diff --git a/libraries/entities-renderer/src/untextured_particle.slf b/libraries/entities-renderer/src/untextured_particle.slf index 11f25bb693..a8062f0024 100644 --- a/libraries/entities-renderer/src/untextured_particle.slf +++ b/libraries/entities-renderer/src/untextured_particle.slf @@ -9,10 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -in vec4 _color; +in vec4 varColor; +in vec2 varTexcoord; out vec4 outFragColor; void main(void) { - outFragColor = _color; + outFragColor = varColor; } diff --git a/libraries/gl/src/gl/GLShaders.cpp b/libraries/gl/src/gl/GLShaders.cpp index fd0c6788cb..8ef0198676 100644 --- a/libraries/gl/src/gl/GLShaders.cpp +++ b/libraries/gl/src/gl/GLShaders.cpp @@ -182,7 +182,6 @@ GLuint compileProgram(const std::vector& glshaders, std::string& error) filestream.close(); } */ - delete[] temp; glDeleteProgram(glprogram); return 0; diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 550092c90e..f7712f59e7 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -44,13 +44,13 @@ void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, cons auto key = item.getShapeKey() | globalKey; if (key.isValid() && !key.hasOwnPipeline()) { args->_shapePipeline = shapeContext->pickPipeline(args, key); - if (!args->_shapePipeline) { + /* if (!args->_shapePipeline) { if (key.isCustom()) { if (item.defineCustomShapePipeline(*shapeContext, key)) { args->_shapePipeline = shapeContext->pickPipeline(args, key); } } - } + }*/ if (args->_shapePipeline) { args->_shapePipeline->prepareShapeItem(args, key, item); item.render(args); @@ -119,7 +119,7 @@ void render::renderStateSortShapes(const RenderContextPointer& renderContext, auto& bucket = sortedShapes[pipelineKey]; args->_shapePipeline = shapeContext->pickPipeline(args, pipelineKey); if (!args->_shapePipeline) { - if (pipelineKey.isCustom()) { + /* if (pipelineKey.isCustom()) { if (bucket.front().defineCustomShapePipeline(*shapeContext, pipelineKey)) { args->_shapePipeline = shapeContext->pickPipeline(args, pipelineKey); if (!args->_shapePipeline) { @@ -130,7 +130,7 @@ void render::renderStateSortShapes(const RenderContextPointer& renderContext, } else { continue; } - } + }*/ continue; } for (auto& item : bucket) { diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 8ec80a7d7e..007b34395d 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -320,7 +320,6 @@ public: virtual void render(RenderArgs* args) = 0; virtual const ShapeKey getShapeKey() const = 0; - virtual bool defineCustomShapePipeline(ShapePlumber& plumber, const ShapeKey& key) const = 0; virtual uint32_t fetchMetaSubItems(ItemIDs& subItems) const = 0; @@ -370,7 +369,6 @@ public: // Shape Type Interface const ShapeKey getShapeKey() const { return _payload->getShapeKey(); } - bool defineCustomShapePipeline(ShapePlumber& plumber, const ShapeKey& key) const { return _payload->defineCustomShapePipeline(plumber, key); } // Meta Type Interface uint32_t fetchMetaSubItems(ItemIDs& subItems) const { return _payload->fetchMetaSubItems(subItems); } @@ -417,7 +415,6 @@ template void payloadRender(const std::shared_ptr& payloadData, Ren // When creating a new shape payload you need to create a specialized version, or the ShapeKey will be ownPipeline, // implying that the shape will setup its own pipeline without the use of the ShapeKey. template const ShapeKey shapeGetShapeKey(const std::shared_ptr& payloadData) { return ShapeKey::Builder::ownPipeline(); } -template bool shapeDefineCustomShapePipeline(const std::shared_ptr& payloadData, ShapePlumber& plumber, const ShapeKey& key) { return false; } // Meta Type Interface // Meta items act as the grouping object for several sub items (typically shapes). @@ -444,7 +441,6 @@ public: // Shape Type interface virtual const ShapeKey getShapeKey() const override { return shapeGetShapeKey(_data); } - virtual bool defineCustomShapePipeline(ShapePlumber& plumber, const ShapeKey& key) const override { return shapeDefineCustomShapePipeline(_data, plumber, key); } // Meta Type Interface virtual uint32_t fetchMetaSubItems(ItemIDs& subItems) const override { return metaFetchMetaSubItems(_data, subItems); } diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index ba506699b2..c83c0b44fc 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -17,6 +17,15 @@ using namespace render; +ShapePipeline::CustomFactoryMap ShapePipeline::_globalCustomFactoryMap; + +ShapePipeline::CustomKey ShapePipeline::registerCustomShapePipelineFactory(CustomFactory factory) { + ShapePipeline::CustomKey custom = (ShapePipeline::CustomKey) _globalCustomFactoryMap.size() + 1; + _globalCustomFactoryMap[custom] = factory; + return custom; +} + + void ShapePipeline::prepare(gpu::Batch& batch, RenderArgs* args) { if (_batchSetter) { _batchSetter(*this, batch, args); @@ -35,7 +44,7 @@ ShapeKey::Filter::Builder::Builder() { _mask.set(INVALID); } -void ShapePlumber::addPipelineHelper(const Filter& filter, ShapeKey key, int bit, const PipelinePointer& pipeline) { +void ShapePlumber::addPipelineHelper(const Filter& filter, ShapeKey key, int bit, const PipelinePointer& pipeline) const { // Iterate over all keys if (bit < (int)ShapeKey::FlagBit::NUM_FLAGS) { addPipelineHelper(filter, key, bit + 1, pipeline); @@ -110,10 +119,22 @@ const ShapePipelinePointer ShapePlumber::pickPipeline(RenderArgs* args, const Ke const auto& pipelineIterator = _pipelineMap.find(key); if (pipelineIterator == _pipelineMap.end()) { - // The first time we can't find a pipeline, we should log it + // The first time we can't find a pipeline, we should try things to solve that if (_missingKeys.find(key) == _missingKeys.end()) { - _missingKeys.insert(key); - qCDebug(renderlogging) << "Couldn't find a pipeline for" << key; + if (key.isCustom()) { + auto factoryIt = ShapePipeline::_globalCustomFactoryMap.find(key.getCustom()); + if ((factoryIt != ShapePipeline::_globalCustomFactoryMap.end()) && (factoryIt)->second) { + // found a factory for the custom key, can now generate a shape pipeline for this case: + addPipelineHelper(Filter(key), key, 0, (factoryIt)->second(*this, key)); + + return pickPipeline(args, key); + } else { + qCDebug(renderlogging) << "ShapePlumber::Couldn't find a custom pipeline factory for " << key.getCustom() << " key is: " << key; + } + } + + _missingKeys.insert(key); + qCDebug(renderlogging) << "ShapePlumber::Couldn't find a pipeline for" << key; } return PipelinePointer(nullptr); } diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index afc0eac011..3951e41e44 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -285,6 +285,15 @@ protected: BatchSetter _batchSetter; ItemSetter _itemSetter; +public: + using CustomKey = uint8_t; + using CustomFactory = std::function (const ShapePlumber& plumber, const ShapeKey& key)>; + using CustomFactoryMap = std::map; + + static CustomFactoryMap _globalCustomFactoryMap; + + static CustomKey registerCustomShapePipelineFactory(CustomFactory factory); + }; using ShapePipelinePointer = std::shared_ptr; @@ -309,13 +318,14 @@ public: const PipelinePointer pickPipeline(RenderArgs* args, const Key& key) const; protected: - void addPipelineHelper(const Filter& filter, Key key, int bit, const PipelinePointer& pipeline); - PipelineMap _pipelineMap; + void addPipelineHelper(const Filter& filter, Key key, int bit, const PipelinePointer& pipeline) const; + mutable PipelineMap _pipelineMap; private: mutable std::unordered_set _missingKeys; }; + using ShapePlumberPointer = std::shared_ptr; } From 49779754ff063a57d6b57b97aeb6f64a3be1967d Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 12 Jul 2017 15:50:06 +0200 Subject: [PATCH 70/70] Remove unecessary shaders and apply the custom shader pipeline to polyvox --- .../RenderableParticleEffectEntityItem.cpp | 10 +-- .../src/RenderablePolyVoxEntityItem.cpp | 68 ++++++++++++++++--- .../src/RenderablePolyVoxEntityItem.h | 17 ++++- .../src/untextured_particle.slf | 19 ------ .../src/untextured_particle.slv | 25 ------- tests/shaders/src/main.cpp | 3 - 6 files changed, 76 insertions(+), 66 deletions(-) delete mode 100644 libraries/entities-renderer/src/untextured_particle.slf delete mode 100644 libraries/entities-renderer/src/untextured_particle.slv diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 276ffb279f..a3c0d9877e 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -20,8 +20,6 @@ #include "RenderableParticleEffectEntityItem.h" -#include "untextured_particle_vert.h" -#include "untextured_particle_frag.h" #include "textured_particle_vert.h" #include "textured_particle_frag.h" @@ -32,14 +30,14 @@ public: static uint8_t CUSTOM_PIPELINE_NUMBER; static render::ShapePipelinePointer shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key); - static std::weak_ptr _texturedPipeline; - static void registerShapePipeline() { if (!CUSTOM_PIPELINE_NUMBER) { - ParticlePayloadData::CUSTOM_PIPELINE_NUMBER = render::ShapePipeline::registerCustomShapePipelineFactory(ParticlePayloadData::shapePipelineFactory); + CUSTOM_PIPELINE_NUMBER = render::ShapePipeline::registerCustomShapePipelineFactory(shapePipelineFactory); } } + static std::weak_ptr _texturedPipeline; + template struct InterpolationData { T start; @@ -100,7 +98,6 @@ public: void setVisibleFlag(bool visibleFlag) { _visibleFlag = visibleFlag; } void render(RenderArgs* args) const { - assert(_pipeline); gpu::Batch& batch = *args->_batch; @@ -122,7 +119,6 @@ public: protected: Transform _modelTransform; AABox _bound; - PipelinePointer _pipeline; FormatPointer _vertexFormat { std::make_shared() }; BufferPointer _particleBuffer { std::make_shared() }; BufferView _uniformBuffer; diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 88a5d2b873..364195ae0b 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -59,8 +59,8 @@ #include "EntityEditPacketSender.h" #include "PhysicalEntitySimulation.h" -gpu::PipelinePointer RenderablePolyVoxEntityItem::_pipeline = nullptr; -gpu::PipelinePointer RenderablePolyVoxEntityItem::_wireframePipeline = nullptr; +//gpu::PipelinePointer RenderablePolyVoxEntityItem::_pipeline = nullptr; +//gpu::PipelinePointer RenderablePolyVoxEntityItem::_wireframePipeline = nullptr; const float MARCHING_CUBE_COLLISION_HULL_OFFSET = 0.5; @@ -116,6 +116,10 @@ EntityItemPointer RenderablePolyVoxEntityItem::factory(const EntityItemID& entit EntityItemPointer entity{ new RenderablePolyVoxEntityItem(entityID) }; entity->setProperties(properties); std::static_pointer_cast(entity)->initializePolyVox(); + + // As we create the first Polyvox entity, let's register its special shapePipeline factory: + PolyVoxPayload::registerShapePipeline(); + return entity; } @@ -733,7 +737,7 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { return; } - if (!_pipeline) { + /* if (!_pipeline) { gpu::ShaderPointer vertexShader = gpu::Shader::createVertex(std::string(polyvox_vert)); gpu::ShaderPointer pixelShader = gpu::Shader::createPixel(std::string(polyvox_frag)); @@ -760,7 +764,7 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { PrepareStencil::testMaskDrawShape(*wireframeState); _wireframePipeline = gpu::Pipeline::create(program, wireframeState); - } + }*/ if (!_vertexFormat) { auto vf = std::make_shared(); @@ -772,9 +776,9 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { gpu::Batch& batch = *args->_batch; // Pick correct Pipeline - bool wireframe = (render::ShapeKey(args->_globalShapeKey).isWireframe()); - auto pipeline = (wireframe ? _wireframePipeline : _pipeline); - batch.setPipeline(pipeline); + // bool wireframe = (render::ShapeKey(args->_globalShapeKey).isWireframe()); + // auto pipeline = (wireframe ? _wireframePipeline : _pipeline); + // batch.setPipeline(pipeline); Transform transform(voxelToWorldMatrix()); batch.setModelTransform(transform); @@ -817,7 +821,7 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { batch.setResourceTexture(2, DependencyManager::get()->getWhiteTexture()); } - int voxelVolumeSizeLocation = pipeline->getProgram()->getUniforms().findLocation("voxelVolumeSize"); + int voxelVolumeSizeLocation = args->_shapePipeline->pipeline->getProgram()->getUniforms().findLocation("voxelVolumeSize"); batch._glUniform3f(voxelVolumeSizeLocation, voxelVolumeSize.x, voxelVolumeSize.y, voxelVolumeSize.z); batch.drawIndexed(gpu::TRIANGLES, (gpu::uint32)mesh->getNumIndices(), 0); @@ -848,6 +852,48 @@ void RenderablePolyVoxEntityItem::removeFromScene(const EntityItemPointer& self, render::Item::clearID(_myItem); } +uint8_t PolyVoxPayload::CUSTOM_PIPELINE_NUMBER = 0; + +std::shared_ptr PolyVoxPayload::_pipeline; +std::shared_ptr PolyVoxPayload::_wireframePipeline; + +render::ShapePipelinePointer PolyVoxPayload::shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key) { + if (!_pipeline) { + gpu::ShaderPointer vertexShader = gpu::Shader::createVertex(std::string(polyvox_vert)); + gpu::ShaderPointer pixelShader = gpu::Shader::createPixel(std::string(polyvox_frag)); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), PolyVoxPayload::MATERIAL_GPU_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("xMap"), 0)); + slotBindings.insert(gpu::Shader::Binding(std::string("yMap"), 1)); + slotBindings.insert(gpu::Shader::Binding(std::string("zMap"), 2)); + + gpu::ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader); + gpu::Shader::makeProgram(*program, slotBindings); + + auto state = std::make_shared(); + state->setCullMode(gpu::State::CULL_BACK); + state->setDepthTest(true, true, gpu::LESS_EQUAL); + PrepareStencil::testMaskDrawShape(*state); + + _pipeline = gpu::Pipeline::create(program, state); + + auto wireframeState = std::make_shared(); + wireframeState->setCullMode(gpu::State::CULL_BACK); + wireframeState->setDepthTest(true, true, gpu::LESS_EQUAL); + wireframeState->setFillMode(gpu::State::FILL_LINE); + PrepareStencil::testMaskDrawShape(*wireframeState); + + _wireframePipeline = gpu::Pipeline::create(program, wireframeState); + } + + if (key.isWireframe()) { + return std::make_shared(_wireframePipeline, nullptr, nullptr, nullptr); + } else { + return std::make_shared(_pipeline, nullptr, nullptr, nullptr); + } +} + namespace render { template <> const ItemKey payloadGetKey(const PolyVoxPayload::Pointer& payload) { return ItemKey::Builder::opaqueShape(); @@ -871,6 +917,10 @@ namespace render { payload->_owner->getRenderableInterface()->render(args); } } + + template <> const ShapeKey shapeGetShapeKey(const PolyVoxPayload::Pointer& payload) { + return ShapeKey::Builder().withCustom(PolyVoxPayload::CUSTOM_PIPELINE_NUMBER).build(); + } } @@ -1619,7 +1669,7 @@ void RenderablePolyVoxEntityItem::bonkNeighbors() { void RenderablePolyVoxEntityItem::locationChanged(bool tellPhysics) { EntityItem::locationChanged(tellPhysics); - if (!_pipeline || !render::Item::isValidID(_myItem)) { + if (/*!_pipeline || */!render::Item::isValidID(_myItem)) { return; } render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 45625ada6d..8f20a7a298 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -28,6 +28,19 @@ class PolyVoxPayload { public: + + static uint8_t CUSTOM_PIPELINE_NUMBER; + static render::ShapePipelinePointer shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key); + static void registerShapePipeline() { + if (!CUSTOM_PIPELINE_NUMBER) { + CUSTOM_PIPELINE_NUMBER = render::ShapePipeline::registerCustomShapePipelineFactory(shapePipelineFactory); + } + } + + static const int MATERIAL_GPU_SLOT = 3; + static std::shared_ptr _pipeline; + static std::shared_ptr _wireframePipeline; + PolyVoxPayload(EntityItemPointer owner) : _owner(owner), _bounds(AABox()) { } typedef render::Payload Payload; typedef Payload::DataPointer Pointer; @@ -40,6 +53,7 @@ namespace render { template <> const ItemKey payloadGetKey(const PolyVoxPayload::Pointer& payload); template <> const Item::Bound payloadGetBound(const PolyVoxPayload::Pointer& payload); template <> void payloadRender(const PolyVoxPayload::Pointer& payload, RenderArgs* args); + template <> const ShapeKey shapeGetShapeKey(const PolyVoxPayload::Pointer& payload); } @@ -168,10 +182,7 @@ private: NetworkTexturePointer _yTexture; NetworkTexturePointer _zTexture; - const int MATERIAL_GPU_SLOT = 3; render::ItemID _myItem{ render::Item::INVALID_ITEM_ID }; - static gpu::PipelinePointer _pipeline; - static gpu::PipelinePointer _wireframePipeline; ShapeInfo _shapeInfo; diff --git a/libraries/entities-renderer/src/untextured_particle.slf b/libraries/entities-renderer/src/untextured_particle.slf deleted file mode 100644 index a8062f0024..0000000000 --- a/libraries/entities-renderer/src/untextured_particle.slf +++ /dev/null @@ -1,19 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// fragment shader -// -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -in vec4 varColor; -in vec2 varTexcoord; - -out vec4 outFragColor; - -void main(void) { - outFragColor = varColor; -} diff --git a/libraries/entities-renderer/src/untextured_particle.slv b/libraries/entities-renderer/src/untextured_particle.slv deleted file mode 100644 index 85f9d438bf..0000000000 --- a/libraries/entities-renderer/src/untextured_particle.slv +++ /dev/null @@ -1,25 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// particle vertex shader -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Inputs.slh@> -<@include gpu/Color.slh@> -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> - -out vec4 _color; - -void main(void) { - // pass along the color - _color = colorToLinearRGBA(inColor); - - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> -} \ No newline at end of file diff --git a/tests/shaders/src/main.cpp b/tests/shaders/src/main.cpp index d10ab1ddbe..9847e9f7b9 100644 --- a/tests/shaders/src/main.cpp +++ b/tests/shaders/src/main.cpp @@ -57,8 +57,6 @@ #include #include -#include -#include #include #include @@ -172,7 +170,6 @@ void QTestWindow::draw() { testShaderBuild(skin_model_normal_map_vert, model_translucent_frag); testShaderBuild(model_shadow_vert, model_shadow_frag); - testShaderBuild(untextured_particle_vert, untextured_particle_frag); testShaderBuild(textured_particle_vert, textured_particle_frag); /* FIXME: Bring back the ssao shader tests testShaderBuild(gaussian_blur_vertical_vert, gaussian_blur_frag);