From d03fcb5ed8a50ac4ba1bf813f450945445bea62c Mon Sep 17 00:00:00 2001 From: David Back Date: Tue, 10 Apr 2018 19:06:27 -0700 Subject: [PATCH 01/28] desktop equip --- .../controllerModules/equipEntity.js | 117 +++++++++++++++++- scripts/system/controllers/grab.js | 2 +- 2 files changed, 115 insertions(+), 4 deletions(-) diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 252f6efa9e..33091696f3 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -21,6 +21,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); var DEFAULT_SPHERE_MODEL_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/equip-Fresnel-3.fbx"; var EQUIP_SPHERE_SCALE_FACTOR = 0.65; +var EMPTY_PARENT_ID = "{00000000-0000-0000-0000-000000000000}"; // Each overlayInfoSet describes a single equip hotspot. @@ -176,6 +177,8 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa var TRIGGER_OFF_VALUE = 0.1; var TRIGGER_ON_VALUE = TRIGGER_OFF_VALUE + 0.05; // Squeezed just enough to activate search or near grab var BUMPER_ON_VALUE = 0.5; + + var UNEQUIP_KEY = "u"; function getWearableData(props) { @@ -270,6 +273,8 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa this.shouldSendStart = false; this.equipedWithSecondary = false; this.handHasBeenRightsideUp = false; + this.mouseEquip = false; + this.mouseEquipAnimationHandler; this.parameters = makeDispatcherModuleParameters( 300, @@ -279,10 +284,11 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa var equipHotspotBuddy = new EquipHotspotBuddy(); - this.setMessageGrabData = function(entityProperties) { + this.setMessageGrabData = function(entityProperties, mouseEquip) { if (entityProperties) { this.messageGrabEntity = true; this.grabEntityProps = entityProperties; + this.mouseEquip = mouseEquip; } }; @@ -552,6 +558,15 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa // 100 ms seems to be sufficient time to force the check even occur after the object has been initialized. Script.setTimeout(grabEquipCheck, 100); } + + if (this.mouseEquip) { + this.removeMouseEquipAnimation(); + if (this.hand === RIGHT_HAND) { + this.mouseEquipAnimationHandler = MyAvatar.addAnimationStateHandler(this.rightHandMouseEquipAnimation, []); + } else { + this.mouseEquipAnimationHandler = MyAvatar.addAnimationStateHandler(this.leftHandMouseEquipAnimation, []); + } + } }; this.endEquipEntity = function () { @@ -574,6 +589,11 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa this.targetEntityID = null; this.messageGrabEntity = false; this.grabEntityProps = null; + + if (this.mouseEquip) { + this.removeMouseEquipAnimation(); + this.mouseEquip = false; + } }; this.updateInputs = function (controllerData) { @@ -650,7 +670,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa var timestamp = Date.now(); this.updateInputs(controllerData); - if (!this.isTargetIDValid(controllerData)) { + if (!this.mouseEquip && !this.isTargetIDValid(controllerData)) { this.endEquipEntity(); return makeRunningValues(false, [], []); } @@ -740,6 +760,40 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa this.endEquipEntity(); } }; + + this.removeMouseEquipAnimation = function() { + if (this.mouseEquipAnimationHandler) { + this.mouseEquipAnimationHandler = MyAvatar.removeAnimationStateHandler(this.mouseEquipAnimationHandler); + } + }; + + this.leftHandMouseEquipAnimation = function() { + var result = {}; + var leftHandPosition = MyAvatar.getJointPosition("LeftHand"); + var leftShoulderPosition = MyAvatar.getJointPosition("LeftShoulder"); + var cameraToLeftShoulder = Vec3.subtract(leftShoulderPosition, Camera.position); + var cameraToLeftShoulderNormalized = Vec3.normalize(cameraToLeftShoulder); + var leftHandPositionNew = Vec3.sum(leftShoulderPosition, cameraToLeftShoulderNormalized); + var leftHandPositionNewAvatarFrame = Vec3.subtract(leftHandPositionNew, MyAvatar.position); + result.leftHandType = 1; + result.leftHandPosition = leftHandPositionNewAvatarFrame; + result.leftHandRotation = Quat.multiply(Quat.lookAtSimple(leftHandPositionNew, Camera.position), Quat.fromPitchYawRollDegrees(90, 0, -90)); + return result; + }; + + this.rightHandMouseEquipAnimation = function() { + var result = {}; + var rightHandPosition = MyAvatar.getJointPosition("RightHand"); + var rightShoulderPosition = MyAvatar.getJointPosition("RightShoulder"); + var cameraToRightShoulder = Vec3.subtract(rightShoulderPosition, Camera.position); + var cameraToRightShoulderNormalized = Vec3.normalize(cameraToRightShoulder); + var rightHandPositionNew = Vec3.sum(rightShoulderPosition, cameraToRightShoulderNormalized); + var rightHandPositionNewAvatarFrame = Vec3.subtract(rightHandPositionNew, MyAvatar.position); + result.rightHandType = 1; + result.rightHandPosition = rightHandPositionNewAvatarFrame; + result.rightHandRotation = Quat.multiply(Quat.lookAtSimple(rightHandPositionNew, Camera.position), Quat.fromPitchYawRollDegrees(90, 0, 90)); + return result; + }; } var handleMessage = function(channel, message, sender) { @@ -751,7 +805,8 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa var equipModule = (data.hand === "left") ? leftEquipEntity : rightEquipEntity; var entityProperties = Entities.getEntityProperties(data.entityID, DISPATCHER_PROPERTIES); entityProperties.id = data.entityID; - equipModule.setMessageGrabData(entityProperties); + var mouseEquip = false; + equipModule.setMessageGrabData(entityProperties, mouseEquip); } catch (e) { print("WARNING: equipEntity.js -- error parsing Hifi-Hand-Grab message: " + message); @@ -768,10 +823,63 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa } } }; + + var clearGrabActions = function(entityID) { + var actionIDs = Entities.getActionIDs(entityID); + for (var actionIndex = 0; actionIndex < actionIDs.length; actionIndex++) { + var actionID = actionIDs[actionIndex]; + var actionArguments = Entities.getActionArguments(entityID, actionID); + var tag = actionArguments.tag; + if (tag.slice(0, 5) == "grab-") { + Entities.deleteAction(entityID, actionID); + } + } + }; + + var onMousePress = function(event) { + if (isInEditMode()) { // ignore any mouse clicks on the entity while create/edit is open + return; + } + var pickRay = Camera.computePickRay(event.x, event.y); + var intersection = Entities.findRayIntersection(pickRay, true); + if (intersection.intersects) { + var entityProperties = Entities.getEntityProperties(intersection.entityID, DISPATCHER_PROPERTIES); + if (entityProperties.parentID === EMPTY_PARENT_ID) { + entityProperties.id = intersection.entityID; + var rightHandPosition = MyAvatar.getJointPosition("RightHand"); + var leftHandPosition = MyAvatar.getJointPosition("LeftHand"); + var distanceToRightHand = Vec3.distance(entityProperties.position, rightHandPosition); + var distanceToLeftHand = Vec3.distance(entityProperties.position, leftHandPosition); + var leftHandAvailable = leftEquipEntity.targetEntityID === null; + var rightHandAvailable = rightEquipEntity.targetEntityID === null; + var mouseEquip = true; + if (rightHandAvailable && (distanceToRightHand < distanceToLeftHand || !leftHandAvailable)) { + clearGrabActions(intersection.entityID); + rightEquipEntity.setMessageGrabData(entityProperties, mouseEquip); + } else if (leftHandAvailable && (distanceToLeftHand < distanceToRightHand || !rightHandAvailable)) { + clearGrabActions(intersection.entityID); + leftEquipEntity.setMessageGrabData(entityProperties, mouseEquip); + } + } + } + }; + + var onKeyPress = function(event) { + if (event.text === UNEQUIP_KEY) { + if (rightEquipEntity.mouseEquip) { + rightEquipEntity.endEquipEntity(); + } + if (leftEquipEntity.mouseEquip) { + leftEquipEntity.endEquipEntity(); + } + } + }; Messages.subscribe('Hifi-Hand-Grab'); Messages.subscribe('Hifi-Hand-Drop'); Messages.messageReceived.connect(handleMessage); + Controller.mousePressEvent.connect(onMousePress); + Controller.keyPressEvent.connect(onKeyPress); var leftEquipEntity = new EquipEntity(LEFT_HAND); var rightEquipEntity = new EquipEntity(RIGHT_HAND); @@ -785,6 +893,9 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa disableDispatcherModule("LeftEquipEntity"); disableDispatcherModule("RightEquipEntity"); clearAttachPoints(); + Messages.messageReceived.disconnect(handleMessage); + Controller.mousePressEvent.disconnect(onMousePress); + Controller.keyPressEvent.disconnect(onKeyPress); } Script.scriptEnding.connect(cleanup); }()); diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index 1171703847..b32c64d189 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -567,7 +567,7 @@ Grabber.prototype.moveEventProcess = function() { } if (!this.actionID) { - if (!entityIsGrabbedByOther(this.entityID)) { + if (!entityIsGrabbedByOther(this.entityID) ) && Entities.getEntityProperties(this.entityID, ['parentID']).parentID !== MyAvatar.SELF_ID) { this.actionID = Entities.addAction("far-grab", this.entityID, actionArgs); } } else { From de4aff630ade00fe38d379d34c7575740b7e2a3a Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 12 Apr 2018 12:41:36 -0700 Subject: [PATCH 02/28] fix grab.js change --- 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 b32c64d189..4af2d97a8f 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -567,7 +567,7 @@ Grabber.prototype.moveEventProcess = function() { } if (!this.actionID) { - if (!entityIsGrabbedByOther(this.entityID) ) && Entities.getEntityProperties(this.entityID, ['parentID']).parentID !== MyAvatar.SELF_ID) { + if (!entityIsGrabbedByOther(this.entityID) && Entities.getEntityProperties(this.entityID, ['parentID']).parentID !== MyAvatar.SELF_ID) { this.actionID = Entities.addAction("far-grab", this.entityID, actionArgs); } } else { From 4446ef853f8c396171a4d51a4cec4b23fd8d880c Mon Sep 17 00:00:00 2001 From: David Back Date: Mon, 16 Apr 2018 12:56:22 -0700 Subject: [PATCH 03/28] remove animations --- .../controllerModules/equipEntity.js | 60 ++----------------- 1 file changed, 5 insertions(+), 55 deletions(-) diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 33091696f3..7b9640047c 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -22,6 +22,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); var DEFAULT_SPHERE_MODEL_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/equip-Fresnel-3.fbx"; var EQUIP_SPHERE_SCALE_FACTOR = 0.65; var EMPTY_PARENT_ID = "{00000000-0000-0000-0000-000000000000}"; +var UNEQUIP_KEY = "u"; // Each overlayInfoSet describes a single equip hotspot. @@ -176,10 +177,8 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa var TRIGGER_SMOOTH_RATIO = 0.1; // Time averaging of trigger - 0.0 disables smoothing var TRIGGER_OFF_VALUE = 0.1; var TRIGGER_ON_VALUE = TRIGGER_OFF_VALUE + 0.05; // Squeezed just enough to activate search or near grab - var BUMPER_ON_VALUE = 0.5; - - var UNEQUIP_KEY = "u"; - + var BUMPER_ON_VALUE = 0.5 + function getWearableData(props) { var wearable = {}; @@ -274,7 +273,6 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa this.equipedWithSecondary = false; this.handHasBeenRightsideUp = false; this.mouseEquip = false; - this.mouseEquipAnimationHandler; this.parameters = makeDispatcherModuleParameters( 300, @@ -558,15 +556,6 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa // 100 ms seems to be sufficient time to force the check even occur after the object has been initialized. Script.setTimeout(grabEquipCheck, 100); } - - if (this.mouseEquip) { - this.removeMouseEquipAnimation(); - if (this.hand === RIGHT_HAND) { - this.mouseEquipAnimationHandler = MyAvatar.addAnimationStateHandler(this.rightHandMouseEquipAnimation, []); - } else { - this.mouseEquipAnimationHandler = MyAvatar.addAnimationStateHandler(this.leftHandMouseEquipAnimation, []); - } - } }; this.endEquipEntity = function () { @@ -575,7 +564,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa parentID: Uuid.NULL, parentJointIndex: -1 }); - +; var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(this.targetEntityID, "releaseEquip", args); @@ -589,11 +578,6 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa this.targetEntityID = null; this.messageGrabEntity = false; this.grabEntityProps = null; - - if (this.mouseEquip) { - this.removeMouseEquipAnimation(); - this.mouseEquip = false; - } }; this.updateInputs = function (controllerData) { @@ -760,40 +744,6 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa this.endEquipEntity(); } }; - - this.removeMouseEquipAnimation = function() { - if (this.mouseEquipAnimationHandler) { - this.mouseEquipAnimationHandler = MyAvatar.removeAnimationStateHandler(this.mouseEquipAnimationHandler); - } - }; - - this.leftHandMouseEquipAnimation = function() { - var result = {}; - var leftHandPosition = MyAvatar.getJointPosition("LeftHand"); - var leftShoulderPosition = MyAvatar.getJointPosition("LeftShoulder"); - var cameraToLeftShoulder = Vec3.subtract(leftShoulderPosition, Camera.position); - var cameraToLeftShoulderNormalized = Vec3.normalize(cameraToLeftShoulder); - var leftHandPositionNew = Vec3.sum(leftShoulderPosition, cameraToLeftShoulderNormalized); - var leftHandPositionNewAvatarFrame = Vec3.subtract(leftHandPositionNew, MyAvatar.position); - result.leftHandType = 1; - result.leftHandPosition = leftHandPositionNewAvatarFrame; - result.leftHandRotation = Quat.multiply(Quat.lookAtSimple(leftHandPositionNew, Camera.position), Quat.fromPitchYawRollDegrees(90, 0, -90)); - return result; - }; - - this.rightHandMouseEquipAnimation = function() { - var result = {}; - var rightHandPosition = MyAvatar.getJointPosition("RightHand"); - var rightShoulderPosition = MyAvatar.getJointPosition("RightShoulder"); - var cameraToRightShoulder = Vec3.subtract(rightShoulderPosition, Camera.position); - var cameraToRightShoulderNormalized = Vec3.normalize(cameraToRightShoulder); - var rightHandPositionNew = Vec3.sum(rightShoulderPosition, cameraToRightShoulderNormalized); - var rightHandPositionNewAvatarFrame = Vec3.subtract(rightHandPositionNew, MyAvatar.position); - result.rightHandType = 1; - result.rightHandPosition = rightHandPositionNewAvatarFrame; - result.rightHandRotation = Quat.multiply(Quat.lookAtSimple(rightHandPositionNew, Camera.position), Quat.fromPitchYawRollDegrees(90, 0, 90)); - return result; - }; } var handleMessage = function(channel, message, sender) { @@ -874,7 +824,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa } } }; - + Messages.subscribe('Hifi-Hand-Grab'); Messages.subscribe('Hifi-Hand-Drop'); Messages.messageReceived.connect(handleMessage); From 0f2679b725ec0ae28dbda35c2ec016688807b348 Mon Sep 17 00:00:00 2001 From: David Back Date: Mon, 16 Apr 2018 13:12:33 -0700 Subject: [PATCH 04/28] pre PR adjustments --- .../controllerModules/equipEntity.js | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 7b9640047c..ccd0c750df 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -21,8 +21,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); var DEFAULT_SPHERE_MODEL_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/equip-Fresnel-3.fbx"; var EQUIP_SPHERE_SCALE_FACTOR = 0.65; -var EMPTY_PARENT_ID = "{00000000-0000-0000-0000-000000000000}"; -var UNEQUIP_KEY = "u"; // Each overlayInfoSet describes a single equip hotspot. @@ -177,9 +175,13 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa var TRIGGER_SMOOTH_RATIO = 0.1; // Time averaging of trigger - 0.0 disables smoothing var TRIGGER_OFF_VALUE = 0.1; var TRIGGER_ON_VALUE = TRIGGER_OFF_VALUE + 0.05; // Squeezed just enough to activate search or near grab - var BUMPER_ON_VALUE = 0.5 - + var BUMPER_ON_VALUE = 0.5; + + var EMPTY_PARENT_ID = "{00000000-0000-0000-0000-000000000000}"; + + var UNEQUIP_KEY = "u"; + function getWearableData(props) { var wearable = {}; try { @@ -564,7 +566,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa parentID: Uuid.NULL, parentJointIndex: -1 }); -; + var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(this.targetEntityID, "releaseEquip", args); @@ -780,14 +782,14 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa var actionID = actionIDs[actionIndex]; var actionArguments = Entities.getActionArguments(entityID, actionID); var tag = actionArguments.tag; - if (tag.slice(0, 5) == "grab-") { + if (tag.slice(0, 5) === "grab-") { Entities.deleteAction(entityID, actionID); } } }; var onMousePress = function(event) { - if (isInEditMode()) { // ignore any mouse clicks on the entity while create/edit is open + if (isInEditMode()) { // don't consider any mouse clicks on the entity while in edit return; } var pickRay = Camera.computePickRay(event.x, event.y); @@ -804,9 +806,11 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa var rightHandAvailable = rightEquipEntity.targetEntityID === null; var mouseEquip = true; if (rightHandAvailable && (distanceToRightHand < distanceToLeftHand || !leftHandAvailable)) { + // clear any existing grab actions on the entity now (their later removal could affect bootstrapping flags) clearGrabActions(intersection.entityID); rightEquipEntity.setMessageGrabData(entityProperties, mouseEquip); - } else if (leftHandAvailable && (distanceToLeftHand < distanceToRightHand || !rightHandAvailable)) { + } else if (leftHandAvailable && (distanceToLeftHand < distanceToRightHand || !rightHandAvailable)) + // clear any existing grab actions on the entity now (their later removal could affect bootstrapping flags) clearGrabActions(intersection.entityID); leftEquipEntity.setMessageGrabData(entityProperties, mouseEquip); } @@ -824,7 +828,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa } } }; - + Messages.subscribe('Hifi-Hand-Grab'); Messages.subscribe('Hifi-Hand-Drop'); Messages.messageReceived.connect(handleMessage); From a869b58dfb3cfa525dba1ba1dd0112304f29bb28 Mon Sep 17 00:00:00 2001 From: David Back Date: Mon, 16 Apr 2018 13:33:17 -0700 Subject: [PATCH 05/28] fix bracket --- scripts/system/controllers/controllerModules/equipEntity.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index ccd0c750df..00fc1e581a 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -181,7 +181,6 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa var UNEQUIP_KEY = "u"; - function getWearableData(props) { var wearable = {}; try { @@ -809,7 +808,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa // clear any existing grab actions on the entity now (their later removal could affect bootstrapping flags) clearGrabActions(intersection.entityID); rightEquipEntity.setMessageGrabData(entityProperties, mouseEquip); - } else if (leftHandAvailable && (distanceToLeftHand < distanceToRightHand || !rightHandAvailable)) + } else if (leftHandAvailable && (distanceToLeftHand < distanceToRightHand || !rightHandAvailable)) { // clear any existing grab actions on the entity now (their later removal could affect bootstrapping flags) clearGrabActions(intersection.entityID); leftEquipEntity.setMessageGrabData(entityProperties, mouseEquip); From 3a35fa1c08c7802e4af20466b1f4c54be2a239f1 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Apr 2018 16:13:10 -0700 Subject: [PATCH 06/28] missing reset flag on end equip, remove mouseEquip check on unequip via U --- .../system/controllers/controllerModules/equipEntity.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 00fc1e581a..4e960c37f1 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -579,6 +579,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa this.targetEntityID = null; this.messageGrabEntity = false; this.grabEntityProps = null; + this.mouseEquip = false; }; this.updateInputs = function (controllerData) { @@ -796,7 +797,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa if (intersection.intersects) { var entityProperties = Entities.getEntityProperties(intersection.entityID, DISPATCHER_PROPERTIES); if (entityProperties.parentID === EMPTY_PARENT_ID) { - entityProperties.id = intersection.entityID; + entityProperties.id = intersection.entityID; var rightHandPosition = MyAvatar.getJointPosition("RightHand"); var leftHandPosition = MyAvatar.getJointPosition("LeftHand"); var distanceToRightHand = Vec3.distance(entityProperties.position, rightHandPosition); @@ -819,10 +820,10 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa var onKeyPress = function(event) { if (event.text === UNEQUIP_KEY) { - if (rightEquipEntity.mouseEquip) { + if (rightEquipEntity.targetEntityID) { rightEquipEntity.endEquipEntity(); } - if (leftEquipEntity.mouseEquip) { + if (leftEquipEntity.targetEntityID) { leftEquipEntity.endEquipEntity(); } } From 4a08a6c147a4ab29bde9af35edec8d151c7873e4 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Apr 2018 16:26:33 -0700 Subject: [PATCH 07/28] ensure target mouse entity has equip data --- scripts/system/controllers/controllerModules/equipEntity.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 4e960c37f1..6406b8593f 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -796,7 +796,8 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa var intersection = Entities.findRayIntersection(pickRay, true); if (intersection.intersects) { var entityProperties = Entities.getEntityProperties(intersection.entityID, DISPATCHER_PROPERTIES); - if (entityProperties.parentID === EMPTY_PARENT_ID) { + var hasEquipData = getWearableData(entityProperties).joints || getEquipHotspotsData(entityProperties).length > 0; + if (hasEquipData && entityProperties.parentID === EMPTY_PARENT_ID) { entityProperties.id = intersection.entityID; var rightHandPosition = MyAvatar.getJointPosition("RightHand"); var leftHandPosition = MyAvatar.getJointPosition("LeftHand"); From 07fb604090795e837f348eb471b38d85b65251eb Mon Sep 17 00:00:00 2001 From: David Back Date: Wed, 18 Apr 2018 15:00:10 -0700 Subject: [PATCH 08/28] add entityIsEquipped utils for grab.js check --- scripts/system/controllers/grab.js | 2 +- scripts/system/libraries/controllerDispatcherUtils.js | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index 4af2d97a8f..12cc1a2f7c 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -567,7 +567,7 @@ Grabber.prototype.moveEventProcess = function() { } if (!this.actionID) { - if (!entityIsGrabbedByOther(this.entityID) && Entities.getEntityProperties(this.entityID, ['parentID']).parentID !== MyAvatar.SELF_ID) { + if (!entityIsGrabbedByOther(this.entityID) && !entityIsEquipped(this.entityID)) { this.actionID = Entities.addAction("far-grab", this.entityID, actionArgs); } } else { diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index 75e1d6668b..41b4458bc5 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -384,6 +384,14 @@ distanceBetweenPointAndEntityBoundingBox = function(point, entityProps) { return Vec3.distance(v, localPoint); }; +entityIsEquipped = function(entityID) { + var rightEquipEntity = getEnabledModuleByName("RightEquipEntity"); + var leftEquipEntity = getEnabledModuleByName("LeftEquipEntity"); + var equippedInRightHand = rightEquipEntity ? rightEquipEntity.targetEntityID === entityID : false; + var equippedInLeftHand = leftEquipEntity ? leftEquipEntity.targetEntityID === entityID : false; + return equippedInRightHand || equippedInLeftHand; +}; + if (typeof module !== 'undefined') { module.exports = { makeDispatcherModuleParameters: makeDispatcherModuleParameters, From 5bf48041df0c1dc8d0eecbb98b30bf1460346e3e Mon Sep 17 00:00:00 2001 From: David Back Date: Wed, 18 Apr 2018 15:01:14 -0700 Subject: [PATCH 09/28] tabs --- scripts/system/libraries/controllerDispatcherUtils.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index 41b4458bc5..61b54ca156 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -385,11 +385,11 @@ distanceBetweenPointAndEntityBoundingBox = function(point, entityProps) { }; entityIsEquipped = function(entityID) { - var rightEquipEntity = getEnabledModuleByName("RightEquipEntity"); - var leftEquipEntity = getEnabledModuleByName("LeftEquipEntity"); - var equippedInRightHand = rightEquipEntity ? rightEquipEntity.targetEntityID === entityID : false; - var equippedInLeftHand = leftEquipEntity ? leftEquipEntity.targetEntityID === entityID : false; - return equippedInRightHand || equippedInLeftHand; + var rightEquipEntity = getEnabledModuleByName("RightEquipEntity"); + var leftEquipEntity = getEnabledModuleByName("LeftEquipEntity"); + var equippedInRightHand = rightEquipEntity ? rightEquipEntity.targetEntityID === entityID : false; + var equippedInLeftHand = leftEquipEntity ? leftEquipEntity.targetEntityID === entityID : false; + return equippedInRightHand || equippedInLeftHand; }; if (typeof module !== 'undefined') { From 6a3303fe3ead895273cfd7a596b5c8bb1b5dce44 Mon Sep 17 00:00:00 2001 From: David Back Date: Wed, 18 Apr 2018 15:05:29 -0700 Subject: [PATCH 10/28] tabs --- scripts/system/controllers/controllerModules/equipEntity.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 6406b8593f..5807465abb 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -579,7 +579,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa this.targetEntityID = null; this.messageGrabEntity = false; this.grabEntityProps = null; - this.mouseEquip = false; + this.mouseEquip = false; }; this.updateInputs = function (controllerData) { @@ -796,7 +796,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa var intersection = Entities.findRayIntersection(pickRay, true); if (intersection.intersects) { var entityProperties = Entities.getEntityProperties(intersection.entityID, DISPATCHER_PROPERTIES); - var hasEquipData = getWearableData(entityProperties).joints || getEquipHotspotsData(entityProperties).length > 0; + var hasEquipData = getWearableData(entityProperties).joints || getEquipHotspotsData(entityProperties).length > 0; if (hasEquipData && entityProperties.parentID === EMPTY_PARENT_ID) { entityProperties.id = intersection.entityID; var rightHandPosition = MyAvatar.getJointPosition("RightHand"); From 3c441f0312b4559d12cde9c9242ad2d26238f118 Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 19 Apr 2018 11:17:26 -0700 Subject: [PATCH 11/28] safer clear grab actions --- scripts/system/controllers/controllerModules/equipEntity.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 5807465abb..3134ec6736 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -778,11 +778,12 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa var clearGrabActions = function(entityID) { var actionIDs = Entities.getActionIDs(entityID); + var myGrabTag = "grab-" + MyAvatar.sessionUUID; for (var actionIndex = 0; actionIndex < actionIDs.length; actionIndex++) { var actionID = actionIDs[actionIndex]; var actionArguments = Entities.getActionArguments(entityID, actionID); var tag = actionArguments.tag; - if (tag.slice(0, 5) === "grab-") { + if (tag === myGrabTag) { Entities.deleteAction(entityID, actionID); } } From 86b64fe3ab2a8b83216d4ecd4de16fc4a5b6eaca Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 19 Apr 2018 16:29:49 -0700 Subject: [PATCH 12/28] fix mouse equipping while someone else far grabbing --- .../controllerModules/equipEntity.js | 11 +++++----- .../libraries/controllerDispatcherUtils.js | 20 +++++++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 3134ec6736..0dca6f11f4 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -796,10 +796,11 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa var pickRay = Camera.computePickRay(event.x, event.y); var intersection = Entities.findRayIntersection(pickRay, true); if (intersection.intersects) { - var entityProperties = Entities.getEntityProperties(intersection.entityID, DISPATCHER_PROPERTIES); + var entityID = intersection.entityID; + var entityProperties = Entities.getEntityProperties(entityID, DISPATCHER_PROPERTIES); var hasEquipData = getWearableData(entityProperties).joints || getEquipHotspotsData(entityProperties).length > 0; - if (hasEquipData && entityProperties.parentID === EMPTY_PARENT_ID) { - entityProperties.id = intersection.entityID; + if (hasEquipData && entityProperties.parentID === EMPTY_PARENT_ID && !entityIsFarGrabbedByOther(entityID)) { + entityProperties.id = entityID; var rightHandPosition = MyAvatar.getJointPosition("RightHand"); var leftHandPosition = MyAvatar.getJointPosition("LeftHand"); var distanceToRightHand = Vec3.distance(entityProperties.position, rightHandPosition); @@ -809,11 +810,11 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa var mouseEquip = true; if (rightHandAvailable && (distanceToRightHand < distanceToLeftHand || !leftHandAvailable)) { // clear any existing grab actions on the entity now (their later removal could affect bootstrapping flags) - clearGrabActions(intersection.entityID); + clearGrabActions(entityID); rightEquipEntity.setMessageGrabData(entityProperties, mouseEquip); } else if (leftHandAvailable && (distanceToLeftHand < distanceToRightHand || !rightHandAvailable)) { // clear any existing grab actions on the entity now (their later removal could affect bootstrapping flags) - clearGrabActions(intersection.entityID); + clearGrabActions(entityID); leftEquipEntity.setMessageGrabData(entityProperties, mouseEquip); } } diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index 61b54ca156..a8a7c9da2c 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -392,6 +392,26 @@ entityIsEquipped = function(entityID) { return equippedInRightHand || equippedInLeftHand; }; +entityIsFarGrabbedByOther = function(entityID) { + // by convention, a far grab sets the tag of its action to be far-grab-*owner-session-id*. + var actionIDs = Entities.getActionIDs(entityID); + var myFarGrabTag = "far-grab-" + MyAvatar.sessionUUID; + for (var actionIndex = 0; actionIndex < actionIDs.length; actionIndex++) { + var actionID = actionIDs[actionIndex]; + var actionArguments = Entities.getActionArguments(entityID, actionID); + var tag = actionArguments.tag; + if (tag == myFarGrabTag) { + // we see a far-grab-*uuid* shaped tag, but it's our tag, so that's okay. + continue; + } + if (tag.slice(0, 9) == "far-grab-") { + // we see a far-grab-*uuid* shaped tag and it's not ours, so someone else is grabbing it. + return true; + } + } + return false; +}; + if (typeof module !== 'undefined') { module.exports = { makeDispatcherModuleParameters: makeDispatcherModuleParameters, From f30e34e8648ba02b33c5616848f75bc15b590518 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 25 Apr 2018 18:18:19 -0700 Subject: [PATCH 13/28] update serverless content with uncompressed KTX skyboxes --- cmake/externals/serverless-content/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/serverless-content/CMakeLists.txt b/cmake/externals/serverless-content/CMakeLists.txt index a08b589ec2..3514260840 100644 --- a/cmake/externals/serverless-content/CMakeLists.txt +++ b/cmake/externals/serverless-content/CMakeLists.txt @@ -4,8 +4,8 @@ set(EXTERNAL_NAME serverless-content) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC66-v4.zip - URL_MD5 d4f42f630986c83427ff39e1fe9908c6 + URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC66-v5.zip + URL_MD5 4e1837bdbf0ee053b413ac92adce94b5 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" From c8d7dc9b915c6217ba3931c69753a5c96136491c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Apr 2018 11:38:50 -0700 Subject: [PATCH 14/28] hide default port from addresses, fix localhost scheme --- libraries/networking/src/AddressManager.cpp | 10 ++++++---- libraries/networking/src/DomainHandler.cpp | 15 +++++++++------ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index daebcfb40d..72bca8ba3b 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -329,12 +329,14 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) { return false; } +static const QString LOCALHOST = "localhost"; + bool isPossiblePlaceName(QString possiblePlaceName) { bool result { false }; int length = possiblePlaceName.length(); static const int MINIMUM_PLACENAME_LENGTH = 1; static const int MAXIMUM_PLACENAME_LENGTH = 64; - if (possiblePlaceName.toLower() != "localhost" && + if (possiblePlaceName.toLower() != LOCALHOST && length >= MINIMUM_PLACENAME_LENGTH && length <= MAXIMUM_PLACENAME_LENGTH) { const QRegExp PLACE_NAME_REGEX = QRegExp("^[0-9A-Za-z](([0-9A-Za-z]|-(?!-))*[^\\W_]$|$)"); result = PLACE_NAME_REGEX.indexIn(possiblePlaceName) == 0; @@ -354,7 +356,7 @@ void AddressManager::handleLookupString(const QString& lookupString, bool fromSu sanitizedString = sanitizedString.remove(HIFI_SCHEME_REGEX); lookupURL = QUrl(sanitizedString); - if (lookupURL.scheme().isEmpty()) { + if (lookupURL.scheme().isEmpty() || lookupURL.scheme().toLower() == LOCALHOST) { lookupURL = QUrl("hifi://" + sanitizedString); } } else { @@ -603,7 +605,7 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString, LookupTri if (ipAddressRegex.indexIn(lookupString) != -1) { QString domainIPString = ipAddressRegex.cap(1); - quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT; + quint16 domainPort = 0; if (!ipAddressRegex.cap(2).isEmpty()) { domainPort = (quint16) ipAddressRegex.cap(2).toInt(); } @@ -625,7 +627,7 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString, LookupTri if (hostnameRegex.indexIn(lookupString) != -1) { QString domainHostname = hostnameRegex.cap(1); - quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT; + quint16 domainPort = 0; if (!hostnameRegex.cap(2).isEmpty()) { domainPort = (quint16)hostnameRegex.cap(2).toInt(); diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index cd8064c4c0..871dc26899 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -166,7 +166,12 @@ void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) { } } - if (_domainURL != domainURL || _sockAddr.getPort() != domainURL.port()) { + auto domainPort = domainURL.port(); + if (domainPort == -1) { + domainPort = DEFAULT_DOMAIN_SERVER_PORT; + } + + if (_domainURL != domainURL || _sockAddr.getPort() != domainPort) { // re-set the domain info so that auth information is reloaded hardReset(); @@ -192,12 +197,10 @@ void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) { emit domainURLChanged(_domainURL); - if (_sockAddr.getPort() != domainURL.port()) { - qCDebug(networking) << "Updated domain port to" << domainURL.port(); + if (_sockAddr.getPort() != domainPort) { + qCDebug(networking) << "Updated domain port to" << domainPort; + _sockAddr.setPort(domainPort); } - - // grab the port by reading the string after the colon - _sockAddr.setPort(domainURL.port()); } } From d87adcec92da330476ec3529fe561aeeb8167c86 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 26 Apr 2018 17:47:12 -0700 Subject: [PATCH 15/28] make home go to DEFAULT_HIFI_ADDRESS by default --- interface/src/ui/AddressBarDialog.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp index 87bf09a252..789a2a2bdf 100644 --- a/interface/src/ui/AddressBarDialog.cpp +++ b/interface/src/ui/AddressBarDialog.cpp @@ -58,9 +58,8 @@ void AddressBarDialog::loadHome() { qDebug() << "Called LoadHome"; auto locationBookmarks = DependencyManager::get(); QString homeLocation = locationBookmarks->addressForBookmark(LocationBookmarks::HOME_BOOKMARK); - const QString DEFAULT_HOME_LOCATION = "localhost"; if (homeLocation == "") { - homeLocation = DEFAULT_HOME_LOCATION; + homeLocation = DEFAULT_HIFI_ADDRESS; } DependencyManager::get()->handleLookupString(homeLocation); } From c163ae63b8954439cebe2d11c8d8902e807ef910 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 27 Apr 2018 10:20:55 -0700 Subject: [PATCH 16/28] Allow gifting of Pending items; remove PoP verification rescheduling on Pending items --- .../hifi/commerce/purchases/PurchasedItem.qml | 1 - libraries/entities/src/EntityTree.cpp | 33 ++----------------- libraries/entities/src/EntityTree.h | 3 +- 3 files changed, 4 insertions(+), 33 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 7d7a882ee0..4db98091c1 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -239,7 +239,6 @@ Item { width: 62; onLoaded: { - item.enabled = (root.purchaseStatus === "confirmed"); item.buttonGlyphText = hifi.glyphs.gift; item.buttonText = "Gift"; item.buttonClicked = function() { diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index d391dc8be1..b56f367e0a 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1172,16 +1172,6 @@ void EntityTree::startChallengeOwnershipTimer(const EntityItemID& entityItemID) _challengeOwnershipTimeoutTimer->start(5000); } -void EntityTree::startPendingTransferStatusTimer(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode) { - qCDebug(entities) << "'transfer_status' is 'pending', checking again in 90 seconds..." << entityItemID; - QTimer* transferStatusRetryTimer = new QTimer(this); - connect(transferStatusRetryTimer, &QTimer::timeout, this, [=]() { - validatePop(certID, entityItemID, senderNode, true); - }); - transferStatusRetryTimer->setSingleShot(true); - transferStatusRetryTimer->start(90000); -} - QByteArray EntityTree::computeNonce(const QString& certID, const QString ownerKey) { QUuid nonce = QUuid::createUuid(); //random, 5-hex value, separated by "-" QByteArray nonceBytes = nonce.toByteArray(); @@ -1321,7 +1311,7 @@ void EntityTree::sendChallengeOwnershipRequestPacket(const QByteArray& certID, c nodeList->sendPacket(std::move(challengeOwnershipPacket), *(nodeList->nodeWithUUID(QUuid::fromRfc4122(nodeToChallenge)))); } -void EntityTree::validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation) { +void EntityTree::validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode) { // Start owner verification. auto nodeList = DependencyManager::get(); // First, asynchronously hit "proof_of_purchase_status?transaction_type=transfer" endpoint. @@ -1352,30 +1342,13 @@ void EntityTree::validatePop(const QString& certID, const EntityItemID& entityIt withWriteLock([&] { deleteEntity(entityItemID, true); }); - } else if (jsonObject["transfer_status"].toArray().first().toString() == "pending") { - if (isRetryingValidation) { - qCDebug(entities) << "'transfer_status' is 'pending' after retry, deleting entity" << entityItemID; - withWriteLock([&] { - deleteEntity(entityItemID, true); - }); - } else { - if (thread() != QThread::currentThread()) { - QMetaObject::invokeMethod(this, "startPendingTransferStatusTimer", - Q_ARG(const QString&, certID), - Q_ARG(const EntityItemID&, entityItemID), - Q_ARG(const SharedNodePointer&, senderNode)); - return; - } else { - startPendingTransferStatusTimer(certID, entityItemID, senderNode); - } - } } else { // Second, challenge ownership of the PoP cert + // (ignore pending status; a failure will be cleaned up during DDV) sendChallengeOwnershipPacket(certID, jsonObject["transfer_recipient_key"].toString(), entityItemID, senderNode); - } } else { qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() << "; deleting entity" << entityItemID @@ -1619,7 +1592,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c // Delete the entity we just added if it doesn't pass static certificate verification deleteEntity(entityItemID, true); } else { - validatePop(properties.getCertificateID(), entityItemID, senderNode, false); + validatePop(properties.getCertificateID(), entityItemID, senderNode); } } diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index a080801a0e..3289101967 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -397,12 +397,11 @@ protected: QHash _entitiesToAdd; Q_INVOKABLE void startChallengeOwnershipTimer(const EntityItemID& entityItemID); - Q_INVOKABLE void startPendingTransferStatusTimer(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode); private: void sendChallengeOwnershipPacket(const QString& certID, const QString& ownerKey, const EntityItemID& entityItemID, const SharedNodePointer& senderNode); void sendChallengeOwnershipRequestPacket(const QByteArray& certID, const QByteArray& text, const QByteArray& nodeToChallenge, const SharedNodePointer& senderNode); - void validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation); + void validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode); std::shared_ptr _myAvatar{ nullptr }; From acb21cc96a459721bf51638bba15855e36892cd2 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Wed, 25 Apr 2018 09:43:20 -0700 Subject: [PATCH 17/28] Revert "HOTFIX version of PR 12969: Attempt to shutdown web surfaces more consistently" --- interface/src/Application.cpp | 13 +--- interface/src/Application.h | 7 +-- interface/src/ui/overlays/Web3DOverlay.cpp | 12 ++-- .../src/RenderableWebEntityItem.cpp | 39 +++++------- libraries/qml/src/qml/OffscreenSurface.cpp | 6 +- .../qml/src/qml/impl/RenderEventHandler.cpp | 11 ++-- libraries/qml/src/qml/impl/SharedObject.cpp | 62 +++++++------------ .../src/AbstractViewStateInterface.h | 19 ++---- tests/render-perf/src/main.cpp | 6 +- 9 files changed, 71 insertions(+), 104 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c38caca090..789f60bdb1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4750,7 +4750,7 @@ void Application::updateLOD(float deltaTime) const { } } -void Application::pushPostUpdateLambda(void* key, const std::function& func) { +void Application::pushPostUpdateLambda(void* key, std::function func) { std::unique_lock guard(_postUpdateLambdasLock); _postUpdateLambdas[key] = func; } @@ -7360,7 +7360,7 @@ void Application::windowMinimizedChanged(bool minimized) { } } -void Application::postLambdaEvent(const std::function& f) { +void Application::postLambdaEvent(std::function f) { if (this->thread() == QThread::currentThread()) { f(); } else { @@ -7368,15 +7368,6 @@ void Application::postLambdaEvent(const std::function& f) { } } -void Application::sendLambdaEvent(const std::function& f) { - if (this->thread() == QThread::currentThread()) { - f(); - } else { - LambdaEvent event(f); - QCoreApplication::sendEvent(this, &event); - } -} - void Application::initPlugins(const QStringList& arguments) { QCommandLineOption display("display", "Preferred displays", "displays"); QCommandLineOption disableDisplays("disable-displays", "Displays to disable", "displays"); diff --git a/interface/src/Application.h b/interface/src/Application.h index 74b0e5a110..769658b0d6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -136,8 +136,7 @@ public: Application(int& argc, char** argv, QElapsedTimer& startup_time, bool runningMarkerExisted); ~Application(); - void postLambdaEvent(const std::function& f) override; - void sendLambdaEvent(const std::function& f) override; + void postLambdaEvent(std::function f) override; QString getPreviousScriptLocation(); void setPreviousScriptLocation(const QString& previousScriptLocation); @@ -241,7 +240,7 @@ public: qint64 getCurrentSessionRuntime() const { return _sessionRunTimer.elapsed(); } - bool isAboutToQuit() const { return _aboutToQuit; } + bool isAboutToQuit() const override { return _aboutToQuit; } bool isPhysicsEnabled() const { return _physicsEnabled; } // the isHMDMode is true whenever we use the interface from an HMD and not a standard flat display @@ -265,7 +264,7 @@ public: render::EnginePointer getRenderEngine() override { return _renderEngine; } gpu::ContextPointer getGPUContext() const { return _gpuContext; } - virtual void pushPostUpdateLambda(void* key, const std::function& func) override; + virtual void pushPostUpdateLambda(void* key, std::function func) override; void updateMyAvatarLookAtPosition(); diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index fcdac8c00c..1e0b50f091 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -65,10 +65,14 @@ const QString Web3DOverlay::TYPE = "web3d"; const QString Web3DOverlay::QML = "Web3DOverlay.qml"; static auto qmlSurfaceDeleter = [](OffscreenQmlSurface* surface) { - AbstractViewStateInterface::instance()->sendLambdaEvent([surface] { - // WebEngineView may run other threads (wasapi), so they must be deleted for a clean shutdown - // if the application has already stopped its event loop, delete must be explicit - delete surface; + AbstractViewStateInterface::instance()->postLambdaEvent([surface] { + if (AbstractViewStateInterface::instance()->isAboutToQuit()) { + // WebEngineView may run other threads (wasapi), so they must be deleted for a clean shutdown + // if the application has already stopped its event loop, delete must be explicit + delete surface; + } else { + surface->deleteLater(); + } }); }; diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index f333e805ce..3b46c530cc 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -25,7 +25,7 @@ #include #include "EntitiesRendererLogging.h" -#include + using namespace render; using namespace render::entities; @@ -45,7 +45,6 @@ static int DEFAULT_MAX_FPS = 10; static int YOUTUBE_MAX_FPS = 30; static QTouchDevice _touchDevice; -static const char* URL_PROPERTY = "url"; WebEntityRenderer::ContentType WebEntityRenderer::getContentType(const QString& urlString) { if (urlString.isEmpty()) { @@ -53,7 +52,7 @@ WebEntityRenderer::ContentType WebEntityRenderer::getContentType(const QString& } const QUrl url(urlString); - if (url.scheme() == URL_SCHEME_HTTP || url.scheme() == URL_SCHEME_HTTPS || + if (url.scheme() == "http" || url.scheme() == "https" || urlString.toLower().endsWith(".htm") || urlString.toLower().endsWith(".html")) { return ContentType::HtmlContent; } @@ -165,8 +164,6 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene if (urlChanged) { if (newContentType != ContentType::HtmlContent || currentContentType != ContentType::HtmlContent) { destroyWebSurface(); - // If we destroyed the surface, the URL change will be implicitly handled by the re-creation - urlChanged = false; } withWriteLock([&] { @@ -188,8 +185,8 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene return; } - if (urlChanged && _contentType == ContentType::HtmlContent) { - _webSurface->getRootItem()->setProperty(URL_PROPERTY, _lastSourceUrl); + if (urlChanged) { + _webSurface->getRootItem()->setProperty("url", _lastSourceUrl); } if (_contextPosition != entity->getWorldPosition()) { @@ -260,14 +257,6 @@ bool WebEntityRenderer::hasWebSurface() { return (bool)_webSurface && _webSurface->getRootItem(); } -static const auto WebSurfaceDeleter = [](OffscreenQmlSurface* webSurface) { - AbstractViewStateInterface::instance()->sendLambdaEvent([webSurface] { - // WebEngineView may run other threads (wasapi), so they must be deleted for a clean shutdown - // if the application has already stopped its event loop, delete must be explicit - delete webSurface; - }); -}; - bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) { if (_currentWebCount >= MAX_CONCURRENT_WEB_VIEWS) { qWarning() << "Too many concurrent web views to create new view"; @@ -275,9 +264,20 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) { } ++_currentWebCount; + auto deleter = [](OffscreenQmlSurface* webSurface) { + AbstractViewStateInterface::instance()->postLambdaEvent([webSurface] { + if (AbstractViewStateInterface::instance()->isAboutToQuit()) { + // WebEngineView may run other threads (wasapi), so they must be deleted for a clean shutdown + // if the application has already stopped its event loop, delete must be explicit + delete webSurface; + } else { + webSurface->deleteLater(); + } + }); + }; // FIXME use the surface cache instead of explicit creation - _webSurface = QSharedPointer(new OffscreenQmlSurface(), WebSurfaceDeleter); + _webSurface = QSharedPointer(new OffscreenQmlSurface(), deleter); // FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces // and the current rendering load) _webSurface->setMaxFps(DEFAULT_MAX_FPS); @@ -305,7 +305,7 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) { _webSurface->setMaxFps(DEFAULT_MAX_FPS); } _webSurface->load("controls/WebEntityView.qml", [this](QQmlContext* context, QObject* item) { - item->setProperty(URL_PROPERTY, _lastSourceUrl); + item->setProperty("url", _lastSourceUrl); }); } else if (_contentType == ContentType::QmlContent) { _webSurface->load(_lastSourceUrl, [this](QQmlContext* context, QObject* item) { @@ -330,11 +330,6 @@ void WebEntityRenderer::destroyWebSurface() { if (webSurface) { --_currentWebCount; QQuickItem* rootItem = webSurface->getRootItem(); - // Explicitly set the web URL to an empty string, in an effort to get a - // faster shutdown of any chromium processes interacting with audio - if (rootItem && _contentType == ContentType::HtmlContent) { - rootItem->setProperty(URL_PROPERTY, ""); - } if (rootItem && rootItem->objectName() == "tabletRoot") { auto tabletScriptingInterface = DependencyManager::get(); diff --git a/libraries/qml/src/qml/OffscreenSurface.cpp b/libraries/qml/src/qml/OffscreenSurface.cpp index 688f3fdb5f..2da1c41340 100644 --- a/libraries/qml/src/qml/OffscreenSurface.cpp +++ b/libraries/qml/src/qml/OffscreenSurface.cpp @@ -66,10 +66,14 @@ OffscreenSurface::OffscreenSurface() } OffscreenSurface::~OffscreenSurface() { - delete _sharedObject; + disconnect(qApp); + _sharedObject->destroy(); } bool OffscreenSurface::fetchTexture(TextureAndFence& textureAndFence) { + if (!_sharedObject) { + return false; + } hifi::qml::impl::TextureAndFence typedTextureAndFence; bool result = _sharedObject->fetchTexture(typedTextureAndFence); textureAndFence = typedTextureAndFence; diff --git a/libraries/qml/src/qml/impl/RenderEventHandler.cpp b/libraries/qml/src/qml/impl/RenderEventHandler.cpp index 945a469611..6b66ce9314 100644 --- a/libraries/qml/src/qml/impl/RenderEventHandler.cpp +++ b/libraries/qml/src/qml/impl/RenderEventHandler.cpp @@ -49,8 +49,8 @@ RenderEventHandler::RenderEventHandler(SharedObject* shared, QThread* targetThre qFatal("Unable to create new offscreen GL context"); } - _canvas.moveToThreadWithContext(targetThread); moveToThread(targetThread); + _canvas.moveToThreadWithContext(targetThread); } void RenderEventHandler::onInitalize() { @@ -160,8 +160,11 @@ void RenderEventHandler::onQuit() { } _shared->shutdownRendering(_canvas, _currentSize); - _canvas.doneCurrent(); - _canvas.moveToThreadWithContext(qApp->thread()); - moveToThread(qApp->thread()); + // Release the reference to the shared object. This will allow it to + // be destroyed (should happen on it's own thread). + _shared->deleteLater(); + + deleteLater(); + QThread::currentThread()->quit(); } diff --git a/libraries/qml/src/qml/impl/SharedObject.cpp b/libraries/qml/src/qml/impl/SharedObject.cpp index 9253c41b39..b2057117f6 100644 --- a/libraries/qml/src/qml/impl/SharedObject.cpp +++ b/libraries/qml/src/qml/impl/SharedObject.cpp @@ -72,35 +72,26 @@ SharedObject::SharedObject() { QObject::connect(qApp, &QCoreApplication::aboutToQuit, this, &SharedObject::onAboutToQuit); } - SharedObject::~SharedObject() { - // After destroy returns, the rendering thread should be gone - destroy(); - - // _renderTimer is created with `this` as the parent, so need no explicit destruction - - // Destroy the event hand - if (_renderObject) { - delete _renderObject; - _renderObject = nullptr; - } - - if (_renderControl) { - delete _renderControl; - _renderControl = nullptr; - } - if (_quickWindow) { _quickWindow->destroy(); - delete _quickWindow; _quickWindow = nullptr; } - // _rootItem is parented to the quickWindow, so needs no explicit destruction - //if (_rootItem) { - // delete _rootItem; - // _rootItem = nullptr; - //} + if (_renderControl) { + _renderControl->deleteLater(); + _renderControl = nullptr; + } + + if (_renderThread) { + _renderThread->quit(); + _renderThread->deleteLater(); + } + + if (_rootItem) { + _rootItem->deleteLater(); + _rootItem = nullptr; + } releaseEngine(_qmlContext->engine()); } @@ -128,10 +119,6 @@ void SharedObject::create(OffscreenSurface* surface) { } void SharedObject::setRootItem(QQuickItem* rootItem) { - if (_quit) { - return; - } - _rootItem = rootItem; _rootItem->setSize(_quickWindow->size()); @@ -140,6 +127,7 @@ void SharedObject::setRootItem(QQuickItem* rootItem) { _renderThread->setObjectName(objectName()); _renderThread->start(); + // Create event handler for the render thread _renderObject = new RenderEventHandler(this, _renderThread); QCoreApplication::postEvent(this, new OffscreenEvent(OffscreenEvent::Initialize)); @@ -149,43 +137,35 @@ void SharedObject::setRootItem(QQuickItem* rootItem) { } void SharedObject::destroy() { - // `destroy` is idempotent, it can be called multiple times without issues if (_quit) { return; } if (!_rootItem) { + deleteLater(); return; } + _paused = true; if (_renderTimer) { - _renderTimer->stop(); QObject::disconnect(_renderTimer); + _renderTimer->deleteLater(); } - if (_renderControl) { - QObject::disconnect(_renderControl); - } - + QObject::disconnect(_renderControl); QObject::disconnect(qApp); { QMutexLocker lock(&_mutex); _quit = true; - if (_renderObject) { - QCoreApplication::postEvent(_renderObject, new OffscreenEvent(OffscreenEvent::Quit), Qt::HighEventPriority); - } + QCoreApplication::postEvent(_renderObject, new OffscreenEvent(OffscreenEvent::Quit), Qt::HighEventPriority); } // Block until the rendering thread has stopped // FIXME this is undesirable because this is blocking the main thread, // but I haven't found a reliable way to do this only at application // shutdown - if (_renderThread) { - _renderThread->wait(); - delete _renderThread; - _renderThread = nullptr; - } + _renderThread->wait(); } diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h index 54fdc903ca..96e9f4d222 100644 --- a/libraries/render-utils/src/AbstractViewStateInterface.h +++ b/libraries/render-utils/src/AbstractViewStateInterface.h @@ -37,25 +37,15 @@ public: virtual glm::vec3 getAvatarPosition() const = 0; - // Unfortunately, having this here is a bad idea. Lots of objects connect to - // the aboutToQuit signal, and it's impossible to know the order in which - // the receivers will be called, so this might return false negatives - //virtual bool isAboutToQuit() const = 0; - - // Queue code to execute on the main thread. - // If called from the main thread, the lambda will execute synchronously - virtual void postLambdaEvent(const std::function& f) = 0; - // Synchronously execute code on the main thread. This function will - // not return until the code is executed, regardles of which thread it - // is called from - virtual void sendLambdaEvent(const std::function& f) = 0; + virtual bool isAboutToQuit() const = 0; + virtual void postLambdaEvent(std::function f) = 0; virtual qreal getDevicePixelRatio() = 0; virtual render::ScenePointer getMain3DScene() = 0; virtual render::EnginePointer getRenderEngine() = 0; - virtual void pushPostUpdateLambda(void* key, const std::function& func) = 0; + virtual void pushPostUpdateLambda(void* key, std::function func) = 0; virtual bool isHMDMode() const = 0; @@ -64,4 +54,5 @@ public: static void setInstance(AbstractViewStateInterface* instance); }; -#endif // hifi_AbstractViewStateInterface_h + +#endif // hifi_AbstractViewStateInterface_h diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index 9249b3d957..93672cc5a2 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -453,8 +453,8 @@ protected: return vec3(); } - void postLambdaEvent(const std::function& f) override {} - void sendLambdaEvent(const std::function& f) override {} + bool isAboutToQuit() const override { return false; } + void postLambdaEvent(std::function f) override {} qreal getDevicePixelRatio() override { return 1.0f; @@ -469,7 +469,7 @@ protected: } std::map> _postUpdateLambdas; - void pushPostUpdateLambda(void* key, const std::function& func) override { + void pushPostUpdateLambda(void* key, std::function func) override { _postUpdateLambdas[key] = func; } From db5e5ba99beab1a45c1aa6b21794414f5eff93ce Mon Sep 17 00:00:00 2001 From: David Back Date: Fri, 27 Apr 2018 11:30:45 -0700 Subject: [PATCH 18/28] ignore right clicks --- scripts/system/controllers/controllerModules/equipEntity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 0dca6f11f4..6de62eef85 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -790,7 +790,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa }; var onMousePress = function(event) { - if (isInEditMode()) { // don't consider any mouse clicks on the entity while in edit + if (isInEditMode() || event.isRightButton) { // don't consider any mouse clicks on the entity while in edit return; } var pickRay = Camera.computePickRay(event.x, event.y); From 684d2b08ba6206ff1e1f49f925a7e651004a36d9 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 27 Apr 2018 11:04:46 -0700 Subject: [PATCH 19/28] Finalize work on MS14295 and MS14559 --- .../qml/hifi/commerce/common/sendAsset/SendAsset.qml | 9 +++++---- scripts/system/commerce/wallet.js | 12 +++++++----- scripts/system/marketplaces/marketplaces.js | 12 +++++++----- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml index 8411a24bf5..c7c72e5f7c 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml @@ -1308,7 +1308,7 @@ Item { anchors.right: parent.right; anchors.rightMargin: root.assetName === "" ? 15 : 50; anchors.bottom: parent.bottom; - anchors.bottomMargin: root.assetName === "" ? 15 : 300; + anchors.bottomMargin: root.assetName === "" ? 15 : 240; color: "#FFFFFF"; RalewaySemiBold { @@ -1403,12 +1403,12 @@ Item { id: giftContainer_paymentSuccess; visible: root.assetName !== ""; anchors.top: sendToContainer_paymentSuccess.bottom; - anchors.topMargin: 16; + anchors.topMargin: 8; anchors.left: parent.left; anchors.leftMargin: 20; anchors.right: parent.right; anchors.rightMargin: 20; - height: 80; + height: 30; RalewaySemiBold { id: gift_paymentSuccess; @@ -1431,6 +1431,7 @@ Item { anchors.top: parent.top; anchors.left: gift_paymentSuccess.right; anchors.right: parent.right; + height: parent.height; // Text size size: 18; // Style @@ -1522,7 +1523,7 @@ Item { colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; anchors.horizontalCenter: parent.horizontalCenter; anchors.bottom: parent.bottom; - anchors.bottomMargin: 80; + anchors.bottomMargin: root.assetName === "" ? 80 : 30; height: 50; width: 120; text: "Close"; diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index 2fbeaec317..aea752c565 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -557,12 +557,14 @@ } if (onWalletScreen) { + if (!isWired) { + Users.usernameFromIDReply.connect(usernameFromIDReply); + Controller.mousePressEvent.connect(handleMouseEvent); + Controller.mouseMoveEvent.connect(handleMouseMoveEvent); + triggerMapping.enable(); + triggerPressMapping.enable(); + } isWired = true; - Users.usernameFromIDReply.connect(usernameFromIDReply); - Controller.mousePressEvent.connect(handleMouseEvent); - Controller.mouseMoveEvent.connect(handleMouseMoveEvent); - triggerMapping.enable(); - triggerPressMapping.enable(); } else { off(); } diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index b128e100a1..a05778e2dd 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -1055,12 +1055,14 @@ var selectionDisplay = null; // for gridTool.js to ignore } if (onCommerceScreen) { + if (!isWired) { + Users.usernameFromIDReply.connect(usernameFromIDReply); + Controller.mousePressEvent.connect(handleMouseEvent); + Controller.mouseMoveEvent.connect(handleMouseMoveEvent); + triggerMapping.enable(); + triggerPressMapping.enable(); + } isWired = true; - Users.usernameFromIDReply.connect(usernameFromIDReply); - Controller.mousePressEvent.connect(handleMouseEvent); - Controller.mouseMoveEvent.connect(handleMouseMoveEvent); - triggerMapping.enable(); - triggerPressMapping.enable(); Wallet.refreshWalletStatus(); } else { off(); From f731a2d08eed6eaede593d3fe17b23a1256b7038 Mon Sep 17 00:00:00 2001 From: David Back Date: Fri, 27 Apr 2018 13:32:05 -0700 Subject: [PATCH 20/28] change to not left button --- scripts/system/controllers/controllerModules/equipEntity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 6de62eef85..d6e18376bf 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -790,7 +790,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa }; var onMousePress = function(event) { - if (isInEditMode() || event.isRightButton) { // don't consider any mouse clicks on the entity while in edit + if (isInEditMode() || !event.isLeftButton) { // don't consider any left clicks on the entity while in edit return; } var pickRay = Camera.computePickRay(event.x, event.y); From 0962e1fc1658f25f44ded0128d93ed802305ee25 Mon Sep 17 00:00:00 2001 From: David Back Date: Fri, 27 Apr 2018 11:30:45 -0700 Subject: [PATCH 21/28] ignore right clicks --- scripts/system/controllers/controllerModules/equipEntity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 53dbee829d..1588a17538 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -796,7 +796,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa }; var onMousePress = function(event) { - if (isInEditMode()) { // don't consider any mouse clicks on the entity while in edit + if (isInEditMode() || event.isRightButton) { // don't consider any mouse clicks on the entity while in edit return; } var pickRay = Camera.computePickRay(event.x, event.y); From 61afd12eeb91539a7fa50362aeda9276ac3fd718 Mon Sep 17 00:00:00 2001 From: David Back Date: Fri, 27 Apr 2018 13:32:05 -0700 Subject: [PATCH 22/28] change to not left button --- scripts/system/controllers/controllerModules/equipEntity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 1588a17538..1fce772ec8 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -796,7 +796,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa }; var onMousePress = function(event) { - if (isInEditMode() || event.isRightButton) { // don't consider any mouse clicks on the entity while in edit + if (isInEditMode() || !event.isLeftButton) { // don't consider any left clicks on the entity while in edit return; } var pickRay = Camera.computePickRay(event.x, event.y); From a226790295c8ef4c5e21179993bb5cc0d62995e2 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Mon, 30 Apr 2018 15:05:27 +0300 Subject: [PATCH 23/28] Eliminated warnings in gcc Note that the call to encodeNode() in FBXWriter.cpp can never be reached, so it's safe to remove it. --- assignment-client/src/assets/AssetServer.h | 2 +- libraries/audio/src/InboundAudioStream.cpp | 3 +++ libraries/entities/src/EntityTree.cpp | 3 +++ libraries/fbx/src/FBXWriter.cpp | 1 - libraries/networking/src/ResourceCache.cpp | 6 ++++++ libraries/shared/src/Gzip.cpp | 3 +++ 6 files changed, 16 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/assets/AssetServer.h b/assignment-client/src/assets/AssetServer.h index fb88df0171..f83545c25c 100644 --- a/assignment-client/src/assets/AssetServer.h +++ b/assignment-client/src/assets/AssetServer.h @@ -63,7 +63,7 @@ struct AssetMeta { AssetMeta() { } - BakeVersion bakeVersion; + BakeVersion bakeVersion { INITIAL_BAKE_VERSION }; bool failedLastBake { false }; QString lastBakeErrors; }; diff --git a/libraries/audio/src/InboundAudioStream.cpp b/libraries/audio/src/InboundAudioStream.cpp index 172ec9411a..bbaedc003b 100644 --- a/libraries/audio/src/InboundAudioStream.cpp +++ b/libraries/audio/src/InboundAudioStream.cpp @@ -149,6 +149,9 @@ int InboundAudioStream::parseData(ReceivedMessage& message) { lostAudioData(packetsDropped); // fall through to OnTime case +#if defined(__GNUC__) + [[gnu::fallthrough]]; +#endif } case SequenceNumberStats::OnTime: { // Packet is on time; parse its data to the ringbuffer diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index b56f367e0a..e9e4f2631a 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1402,6 +1402,9 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c case PacketType::EntityAdd: isAdd = true; // fall through to next case +#if defined(__GNUC__) + [[gnu::fallthrough]]; +#endif case PacketType::EntityPhysics: case PacketType::EntityEdit: { quint64 startDecode = 0, endDecode = 0; diff --git a/libraries/fbx/src/FBXWriter.cpp b/libraries/fbx/src/FBXWriter.cpp index 511f253193..e6adff0df9 100644 --- a/libraries/fbx/src/FBXWriter.cpp +++ b/libraries/fbx/src/FBXWriter.cpp @@ -142,7 +142,6 @@ void FBXWriter::encodeFBXProperty(QDataStream& out, const QVariant& prop) { out << prop.toInt(); break; - encodeNode(out, FBXNode()); case QMetaType::Float: out.device()->write("F", 1); out << prop.toFloat(); diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 7ba7cca96d..3b8c9fdac0 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -749,6 +749,9 @@ bool Resource::handleFailedRequest(ResourceRequest::Result result) { case ResourceRequest::Result::Timeout: { qCDebug(networking) << "Timed out loading" << _url << "received" << _bytesReceived << "total" << _bytesTotal; // Fall through to other cases +#if defined(__GNUC__) + [[gnu::fallthrough]]; +#endif } case ResourceRequest::Result::ServerUnavailable: { _attempts++; @@ -767,6 +770,9 @@ bool Resource::handleFailedRequest(ResourceRequest::Result result) { break; } // fall through to final failure +#if defined(__GNUC__) + [[gnu::fallthrough]]; +#endif } default: { _attemptsRemaining = 0; diff --git a/libraries/shared/src/Gzip.cpp b/libraries/shared/src/Gzip.cpp index a77f459fc9..44fe13f439 100644 --- a/libraries/shared/src/Gzip.cpp +++ b/libraries/shared/src/Gzip.cpp @@ -60,6 +60,9 @@ bool gunzip(QByteArray source, QByteArray &destination) { switch (status) { case Z_NEED_DICT: status = Z_DATA_ERROR; +#if defined(__GNUC__) + [[gnu::fallthrough]]; +#endif case Z_DATA_ERROR: case Z_MEM_ERROR: case Z_STREAM_ERROR: From ed47cd84581d062dc5127a9f09b6a8d655a1f93b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 30 Apr 2018 12:35:48 -0700 Subject: [PATCH 24/28] add a missing unsafe_erase for local node ID map --- libraries/networking/src/LimitedNodeList.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 31500be682..2bdd688a73 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -302,6 +302,7 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe } } else { NLPacket::LocalID sourceLocalID = Node::NULL_LOCAL_ID; + // check if we were passed a sourceNode hint or if we need to look it up if (!sourceNode) { // figure out which node this is from @@ -608,6 +609,7 @@ bool LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID, ConnectionID newCo { QWriteLocker writeLocker(&_nodeMutex); + _localIDMap.unsafe_erase(matchingNode->getLocalID()); _nodeHash.unsafe_erase(it); } From cad63ad1071e9a3eb7f742ac7543d9107c089682 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 1 May 2018 14:15:12 -0700 Subject: [PATCH 25/28] Revert "Revert "HOTFIX version of PR 12969: Attempt to shutdown web surfaces more consistently"" This reverts commit acb21cc96a459721bf51638bba15855e36892cd2. --- interface/src/Application.cpp | 13 ++++- interface/src/Application.h | 7 ++- interface/src/ui/overlays/Web3DOverlay.cpp | 12 ++-- .../src/RenderableWebEntityItem.cpp | 39 +++++++------ libraries/qml/src/qml/OffscreenSurface.cpp | 6 +- .../qml/src/qml/impl/RenderEventHandler.cpp | 11 ++-- libraries/qml/src/qml/impl/SharedObject.cpp | 56 +++++++++++++------ .../src/AbstractViewStateInterface.h | 19 +++++-- tests/render-perf/src/main.cpp | 6 +- 9 files changed, 101 insertions(+), 68 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 789f60bdb1..c38caca090 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4750,7 +4750,7 @@ void Application::updateLOD(float deltaTime) const { } } -void Application::pushPostUpdateLambda(void* key, std::function func) { +void Application::pushPostUpdateLambda(void* key, const std::function& func) { std::unique_lock guard(_postUpdateLambdasLock); _postUpdateLambdas[key] = func; } @@ -7360,7 +7360,7 @@ void Application::windowMinimizedChanged(bool minimized) { } } -void Application::postLambdaEvent(std::function f) { +void Application::postLambdaEvent(const std::function& f) { if (this->thread() == QThread::currentThread()) { f(); } else { @@ -7368,6 +7368,15 @@ void Application::postLambdaEvent(std::function f) { } } +void Application::sendLambdaEvent(const std::function& f) { + if (this->thread() == QThread::currentThread()) { + f(); + } else { + LambdaEvent event(f); + QCoreApplication::sendEvent(this, &event); + } +} + void Application::initPlugins(const QStringList& arguments) { QCommandLineOption display("display", "Preferred displays", "displays"); QCommandLineOption disableDisplays("disable-displays", "Displays to disable", "displays"); diff --git a/interface/src/Application.h b/interface/src/Application.h index 769658b0d6..74b0e5a110 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -136,7 +136,8 @@ public: Application(int& argc, char** argv, QElapsedTimer& startup_time, bool runningMarkerExisted); ~Application(); - void postLambdaEvent(std::function f) override; + void postLambdaEvent(const std::function& f) override; + void sendLambdaEvent(const std::function& f) override; QString getPreviousScriptLocation(); void setPreviousScriptLocation(const QString& previousScriptLocation); @@ -240,7 +241,7 @@ public: qint64 getCurrentSessionRuntime() const { return _sessionRunTimer.elapsed(); } - bool isAboutToQuit() const override { return _aboutToQuit; } + bool isAboutToQuit() const { return _aboutToQuit; } bool isPhysicsEnabled() const { return _physicsEnabled; } // the isHMDMode is true whenever we use the interface from an HMD and not a standard flat display @@ -264,7 +265,7 @@ public: render::EnginePointer getRenderEngine() override { return _renderEngine; } gpu::ContextPointer getGPUContext() const { return _gpuContext; } - virtual void pushPostUpdateLambda(void* key, std::function func) override; + virtual void pushPostUpdateLambda(void* key, const std::function& func) override; void updateMyAvatarLookAtPosition(); diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index 1e0b50f091..fcdac8c00c 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -65,14 +65,10 @@ const QString Web3DOverlay::TYPE = "web3d"; const QString Web3DOverlay::QML = "Web3DOverlay.qml"; static auto qmlSurfaceDeleter = [](OffscreenQmlSurface* surface) { - AbstractViewStateInterface::instance()->postLambdaEvent([surface] { - if (AbstractViewStateInterface::instance()->isAboutToQuit()) { - // WebEngineView may run other threads (wasapi), so they must be deleted for a clean shutdown - // if the application has already stopped its event loop, delete must be explicit - delete surface; - } else { - surface->deleteLater(); - } + AbstractViewStateInterface::instance()->sendLambdaEvent([surface] { + // WebEngineView may run other threads (wasapi), so they must be deleted for a clean shutdown + // if the application has already stopped its event loop, delete must be explicit + delete surface; }); }; diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 3b46c530cc..f333e805ce 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -25,7 +25,7 @@ #include #include "EntitiesRendererLogging.h" - +#include using namespace render; using namespace render::entities; @@ -45,6 +45,7 @@ static int DEFAULT_MAX_FPS = 10; static int YOUTUBE_MAX_FPS = 30; static QTouchDevice _touchDevice; +static const char* URL_PROPERTY = "url"; WebEntityRenderer::ContentType WebEntityRenderer::getContentType(const QString& urlString) { if (urlString.isEmpty()) { @@ -52,7 +53,7 @@ WebEntityRenderer::ContentType WebEntityRenderer::getContentType(const QString& } const QUrl url(urlString); - if (url.scheme() == "http" || url.scheme() == "https" || + if (url.scheme() == URL_SCHEME_HTTP || url.scheme() == URL_SCHEME_HTTPS || urlString.toLower().endsWith(".htm") || urlString.toLower().endsWith(".html")) { return ContentType::HtmlContent; } @@ -164,6 +165,8 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene if (urlChanged) { if (newContentType != ContentType::HtmlContent || currentContentType != ContentType::HtmlContent) { destroyWebSurface(); + // If we destroyed the surface, the URL change will be implicitly handled by the re-creation + urlChanged = false; } withWriteLock([&] { @@ -185,8 +188,8 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene return; } - if (urlChanged) { - _webSurface->getRootItem()->setProperty("url", _lastSourceUrl); + if (urlChanged && _contentType == ContentType::HtmlContent) { + _webSurface->getRootItem()->setProperty(URL_PROPERTY, _lastSourceUrl); } if (_contextPosition != entity->getWorldPosition()) { @@ -257,6 +260,14 @@ bool WebEntityRenderer::hasWebSurface() { return (bool)_webSurface && _webSurface->getRootItem(); } +static const auto WebSurfaceDeleter = [](OffscreenQmlSurface* webSurface) { + AbstractViewStateInterface::instance()->sendLambdaEvent([webSurface] { + // WebEngineView may run other threads (wasapi), so they must be deleted for a clean shutdown + // if the application has already stopped its event loop, delete must be explicit + delete webSurface; + }); +}; + bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) { if (_currentWebCount >= MAX_CONCURRENT_WEB_VIEWS) { qWarning() << "Too many concurrent web views to create new view"; @@ -264,20 +275,9 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) { } ++_currentWebCount; - auto deleter = [](OffscreenQmlSurface* webSurface) { - AbstractViewStateInterface::instance()->postLambdaEvent([webSurface] { - if (AbstractViewStateInterface::instance()->isAboutToQuit()) { - // WebEngineView may run other threads (wasapi), so they must be deleted for a clean shutdown - // if the application has already stopped its event loop, delete must be explicit - delete webSurface; - } else { - webSurface->deleteLater(); - } - }); - }; // FIXME use the surface cache instead of explicit creation - _webSurface = QSharedPointer(new OffscreenQmlSurface(), deleter); + _webSurface = QSharedPointer(new OffscreenQmlSurface(), WebSurfaceDeleter); // FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces // and the current rendering load) _webSurface->setMaxFps(DEFAULT_MAX_FPS); @@ -305,7 +305,7 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) { _webSurface->setMaxFps(DEFAULT_MAX_FPS); } _webSurface->load("controls/WebEntityView.qml", [this](QQmlContext* context, QObject* item) { - item->setProperty("url", _lastSourceUrl); + item->setProperty(URL_PROPERTY, _lastSourceUrl); }); } else if (_contentType == ContentType::QmlContent) { _webSurface->load(_lastSourceUrl, [this](QQmlContext* context, QObject* item) { @@ -330,6 +330,11 @@ void WebEntityRenderer::destroyWebSurface() { if (webSurface) { --_currentWebCount; QQuickItem* rootItem = webSurface->getRootItem(); + // Explicitly set the web URL to an empty string, in an effort to get a + // faster shutdown of any chromium processes interacting with audio + if (rootItem && _contentType == ContentType::HtmlContent) { + rootItem->setProperty(URL_PROPERTY, ""); + } if (rootItem && rootItem->objectName() == "tabletRoot") { auto tabletScriptingInterface = DependencyManager::get(); diff --git a/libraries/qml/src/qml/OffscreenSurface.cpp b/libraries/qml/src/qml/OffscreenSurface.cpp index 2da1c41340..688f3fdb5f 100644 --- a/libraries/qml/src/qml/OffscreenSurface.cpp +++ b/libraries/qml/src/qml/OffscreenSurface.cpp @@ -66,14 +66,10 @@ OffscreenSurface::OffscreenSurface() } OffscreenSurface::~OffscreenSurface() { - disconnect(qApp); - _sharedObject->destroy(); + delete _sharedObject; } bool OffscreenSurface::fetchTexture(TextureAndFence& textureAndFence) { - if (!_sharedObject) { - return false; - } hifi::qml::impl::TextureAndFence typedTextureAndFence; bool result = _sharedObject->fetchTexture(typedTextureAndFence); textureAndFence = typedTextureAndFence; diff --git a/libraries/qml/src/qml/impl/RenderEventHandler.cpp b/libraries/qml/src/qml/impl/RenderEventHandler.cpp index 6b66ce9314..945a469611 100644 --- a/libraries/qml/src/qml/impl/RenderEventHandler.cpp +++ b/libraries/qml/src/qml/impl/RenderEventHandler.cpp @@ -49,8 +49,8 @@ RenderEventHandler::RenderEventHandler(SharedObject* shared, QThread* targetThre qFatal("Unable to create new offscreen GL context"); } - moveToThread(targetThread); _canvas.moveToThreadWithContext(targetThread); + moveToThread(targetThread); } void RenderEventHandler::onInitalize() { @@ -160,11 +160,8 @@ void RenderEventHandler::onQuit() { } _shared->shutdownRendering(_canvas, _currentSize); - // Release the reference to the shared object. This will allow it to - // be destroyed (should happen on it's own thread). - _shared->deleteLater(); - - deleteLater(); - + _canvas.doneCurrent(); + _canvas.moveToThreadWithContext(qApp->thread()); + moveToThread(qApp->thread()); QThread::currentThread()->quit(); } diff --git a/libraries/qml/src/qml/impl/SharedObject.cpp b/libraries/qml/src/qml/impl/SharedObject.cpp index b2057117f6..9253c41b39 100644 --- a/libraries/qml/src/qml/impl/SharedObject.cpp +++ b/libraries/qml/src/qml/impl/SharedObject.cpp @@ -72,26 +72,35 @@ SharedObject::SharedObject() { QObject::connect(qApp, &QCoreApplication::aboutToQuit, this, &SharedObject::onAboutToQuit); } + SharedObject::~SharedObject() { - if (_quickWindow) { - _quickWindow->destroy(); - _quickWindow = nullptr; + // After destroy returns, the rendering thread should be gone + destroy(); + + // _renderTimer is created with `this` as the parent, so need no explicit destruction + + // Destroy the event hand + if (_renderObject) { + delete _renderObject; + _renderObject = nullptr; } if (_renderControl) { - _renderControl->deleteLater(); + delete _renderControl; _renderControl = nullptr; } - if (_renderThread) { - _renderThread->quit(); - _renderThread->deleteLater(); + if (_quickWindow) { + _quickWindow->destroy(); + delete _quickWindow; + _quickWindow = nullptr; } - if (_rootItem) { - _rootItem->deleteLater(); - _rootItem = nullptr; - } + // _rootItem is parented to the quickWindow, so needs no explicit destruction + //if (_rootItem) { + // delete _rootItem; + // _rootItem = nullptr; + //} releaseEngine(_qmlContext->engine()); } @@ -119,6 +128,10 @@ void SharedObject::create(OffscreenSurface* surface) { } void SharedObject::setRootItem(QQuickItem* rootItem) { + if (_quit) { + return; + } + _rootItem = rootItem; _rootItem->setSize(_quickWindow->size()); @@ -127,7 +140,6 @@ void SharedObject::setRootItem(QQuickItem* rootItem) { _renderThread->setObjectName(objectName()); _renderThread->start(); - // Create event handler for the render thread _renderObject = new RenderEventHandler(this, _renderThread); QCoreApplication::postEvent(this, new OffscreenEvent(OffscreenEvent::Initialize)); @@ -137,35 +149,43 @@ void SharedObject::setRootItem(QQuickItem* rootItem) { } void SharedObject::destroy() { + // `destroy` is idempotent, it can be called multiple times without issues if (_quit) { return; } if (!_rootItem) { - deleteLater(); return; } - _paused = true; if (_renderTimer) { + _renderTimer->stop(); QObject::disconnect(_renderTimer); - _renderTimer->deleteLater(); } - QObject::disconnect(_renderControl); + if (_renderControl) { + QObject::disconnect(_renderControl); + } + QObject::disconnect(qApp); { QMutexLocker lock(&_mutex); _quit = true; - QCoreApplication::postEvent(_renderObject, new OffscreenEvent(OffscreenEvent::Quit), Qt::HighEventPriority); + if (_renderObject) { + QCoreApplication::postEvent(_renderObject, new OffscreenEvent(OffscreenEvent::Quit), Qt::HighEventPriority); + } } // Block until the rendering thread has stopped // FIXME this is undesirable because this is blocking the main thread, // but I haven't found a reliable way to do this only at application // shutdown - _renderThread->wait(); + if (_renderThread) { + _renderThread->wait(); + delete _renderThread; + _renderThread = nullptr; + } } diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h index 96e9f4d222..54fdc903ca 100644 --- a/libraries/render-utils/src/AbstractViewStateInterface.h +++ b/libraries/render-utils/src/AbstractViewStateInterface.h @@ -37,15 +37,25 @@ public: virtual glm::vec3 getAvatarPosition() const = 0; - virtual bool isAboutToQuit() const = 0; - virtual void postLambdaEvent(std::function f) = 0; + // Unfortunately, having this here is a bad idea. Lots of objects connect to + // the aboutToQuit signal, and it's impossible to know the order in which + // the receivers will be called, so this might return false negatives + //virtual bool isAboutToQuit() const = 0; + + // Queue code to execute on the main thread. + // If called from the main thread, the lambda will execute synchronously + virtual void postLambdaEvent(const std::function& f) = 0; + // Synchronously execute code on the main thread. This function will + // not return until the code is executed, regardles of which thread it + // is called from + virtual void sendLambdaEvent(const std::function& f) = 0; virtual qreal getDevicePixelRatio() = 0; virtual render::ScenePointer getMain3DScene() = 0; virtual render::EnginePointer getRenderEngine() = 0; - virtual void pushPostUpdateLambda(void* key, std::function func) = 0; + virtual void pushPostUpdateLambda(void* key, const std::function& func) = 0; virtual bool isHMDMode() const = 0; @@ -54,5 +64,4 @@ public: static void setInstance(AbstractViewStateInterface* instance); }; - -#endif // hifi_AbstractViewStateInterface_h +#endif // hifi_AbstractViewStateInterface_h diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index 93672cc5a2..9249b3d957 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -453,8 +453,8 @@ protected: return vec3(); } - bool isAboutToQuit() const override { return false; } - void postLambdaEvent(std::function f) override {} + void postLambdaEvent(const std::function& f) override {} + void sendLambdaEvent(const std::function& f) override {} qreal getDevicePixelRatio() override { return 1.0f; @@ -469,7 +469,7 @@ protected: } std::map> _postUpdateLambdas; - void pushPostUpdateLambda(void* key, std::function func) override { + void pushPostUpdateLambda(void* key, const std::function& func) override { _postUpdateLambdas[key] = func; } From 0627099667378534ca182f3874e4a2e6df70fe79 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Tue, 1 May 2018 14:33:48 -0700 Subject: [PATCH 26/28] In packetSourceAndHashMatchAndTrackBandwidth() check LocalID after check for DS source Makes check more robust in case domain server itself reaches this point, since LimitedNodeList::getDomainLocalID() debug-asserts. --- libraries/networking/src/LimitedNodeList.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 31500be682..af26a2ea72 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -314,9 +314,9 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe QUuid sourceID = sourceNode ? sourceNode->getUUID() : QUuid(); if (!sourceNode && - sourceLocalID == getDomainLocalID() && packet.getSenderSockAddr() == getDomainSockAddr() && - PacketTypeEnum::getDomainSourcedPackets().contains(headerType)) { + PacketTypeEnum::getDomainSourcedPackets().contains(headerType) && + sourceLocalID == getDomainLocalID()) { // This is a packet sourced by the domain server emit dataReceived(NodeType::Unassigned, packet.getPayloadSize()); From bbcb07d9ab7aaea8b88bd1e79c00d2604bdfd91c Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Tue, 1 May 2018 15:07:44 -0700 Subject: [PATCH 27/28] Brute force it with isDomainServer() --- libraries/networking/src/LimitedNodeList.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index af26a2ea72..e897fd13e0 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -314,9 +314,10 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe QUuid sourceID = sourceNode ? sourceNode->getUUID() : QUuid(); if (!sourceNode && + !isDomainServer() && + sourceLocalID == getDomainLocalID() && packet.getSenderSockAddr() == getDomainSockAddr() && - PacketTypeEnum::getDomainSourcedPackets().contains(headerType) && - sourceLocalID == getDomainLocalID()) { + PacketTypeEnum::getDomainSourcedPackets().contains(headerType)) { // This is a packet sourced by the domain server emit dataReceived(NodeType::Unassigned, packet.getPayloadSize()); From 26ffb3213cce98f585c979268afc381527395173 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Wed, 2 May 2018 09:01:11 +0300 Subject: [PATCH 28/28] Changed "[[gnu::fallthrough]]" to "// FALLTHRU" --- libraries/audio/src/InboundAudioStream.cpp | 4 +--- libraries/entities/src/EntityTree.cpp | 4 +--- libraries/networking/src/ResourceCache.cpp | 8 ++------ libraries/shared/src/Gzip.cpp | 4 +--- 4 files changed, 5 insertions(+), 15 deletions(-) diff --git a/libraries/audio/src/InboundAudioStream.cpp b/libraries/audio/src/InboundAudioStream.cpp index bbaedc003b..d60c5ba4ab 100644 --- a/libraries/audio/src/InboundAudioStream.cpp +++ b/libraries/audio/src/InboundAudioStream.cpp @@ -149,10 +149,8 @@ int InboundAudioStream::parseData(ReceivedMessage& message) { lostAudioData(packetsDropped); // fall through to OnTime case -#if defined(__GNUC__) - [[gnu::fallthrough]]; -#endif } + // FALLTHRU case SequenceNumberStats::OnTime: { // Packet is on time; parse its data to the ringbuffer if (message.getType() == PacketType::SilentAudioFrame diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index e9e4f2631a..3149527216 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1402,9 +1402,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c case PacketType::EntityAdd: isAdd = true; // fall through to next case -#if defined(__GNUC__) - [[gnu::fallthrough]]; -#endif + // FALLTHRU case PacketType::EntityPhysics: case PacketType::EntityEdit: { quint64 startDecode = 0, endDecode = 0; diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 3b8c9fdac0..d3583687e8 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -749,10 +749,8 @@ bool Resource::handleFailedRequest(ResourceRequest::Result result) { case ResourceRequest::Result::Timeout: { qCDebug(networking) << "Timed out loading" << _url << "received" << _bytesReceived << "total" << _bytesTotal; // Fall through to other cases -#if defined(__GNUC__) - [[gnu::fallthrough]]; -#endif } + // FALLTHRU case ResourceRequest::Result::ServerUnavailable: { _attempts++; _attemptsRemaining--; @@ -770,10 +768,8 @@ bool Resource::handleFailedRequest(ResourceRequest::Result result) { break; } // fall through to final failure -#if defined(__GNUC__) - [[gnu::fallthrough]]; -#endif } + // FALLTHRU default: { _attemptsRemaining = 0; qCDebug(networking) << "Error loading " << _url << "attempt:" << _attempts << "attemptsRemaining:" << _attemptsRemaining; diff --git a/libraries/shared/src/Gzip.cpp b/libraries/shared/src/Gzip.cpp index 44fe13f439..25e214fffb 100644 --- a/libraries/shared/src/Gzip.cpp +++ b/libraries/shared/src/Gzip.cpp @@ -60,9 +60,7 @@ bool gunzip(QByteArray source, QByteArray &destination) { switch (status) { case Z_NEED_DICT: status = Z_DATA_ERROR; -#if defined(__GNUC__) - [[gnu::fallthrough]]; -#endif + // FALLTHRU case Z_DATA_ERROR: case Z_MEM_ERROR: case Z_STREAM_ERROR: