From d03fcb5ed8a50ac4ba1bf813f450945445bea62c Mon Sep 17 00:00:00 2001
From: David Back
Date: Tue, 10 Apr 2018 19:06:27 -0700
Subject: [PATCH 01/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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/47] 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 03e03727dbfa7ca30996419821faf7f65f6a1678 Mon Sep 17 00:00:00 2001
From: Andrew Meadows
Date: Thu, 26 Apr 2018 12:55:28 -0700
Subject: [PATCH 14/47] fix bug: interface sends too many updates on settle
---
libraries/physics/src/EntityMotionState.cpp | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp
index c2bacd4949..68f21eea87 100644
--- a/libraries/physics/src/EntityMotionState.cpp
+++ b/libraries/physics/src/EntityMotionState.cpp
@@ -447,7 +447,12 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) {
// this case is prevented by setting _ownershipState to UNOWNABLE in EntityMotionState::ctor
assert(!(_entity->getClientOnly() && _entity->getOwningAvatarID() != Physics::getSessionUUID()));
- if (_entity->dynamicDataNeedsTransmit() || _entity->queryAACubeNeedsUpdate()) {
+ // shouldSendUpdate() sould NOT be triggering updates to maintain the queryAACube of dynamic entities.
+ // The server is supposed to predict the transform of such moving things. The client performs a "double prediction"
+ // where it predicts what the the server is doing, and only sends updates whent the entity's true transform
+ // differs significantly. That is what the remoteSimulationOutOfSync() logic is all about.
+ if (_entity->dynamicDataNeedsTransmit() ||
+ (!_entity->getDynamic() && _entity->queryAACubeNeedsUpdate())) {
return true;
}
From c8d7dc9b915c6217ba3931c69753a5c96136491c Mon Sep 17 00:00:00 2001
From: Stephen Birarda
Date: Thu, 26 Apr 2018 11:38:50 -0700
Subject: [PATCH 15/47] 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 16/47] 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 2662dc9b4e5ba665556ed60d791b3803ff5eb18f Mon Sep 17 00:00:00 2001
From: Brad Davis
Date: Fri, 27 Apr 2018 08:03:48 -0700
Subject: [PATCH 17/47] Suppress tracing log spam when tracing is not active
---
libraries/shared/src/Trace.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libraries/shared/src/Trace.h b/libraries/shared/src/Trace.h
index 93e2c6c4c2..1e1326968f 100644
--- a/libraries/shared/src/Trace.h
+++ b/libraries/shared/src/Trace.h
@@ -102,6 +102,9 @@ private:
};
inline void traceEvent(const QLoggingCategory& category, const QString& name, EventType type, const QString& id = "", const QVariantMap& args = {}, const QVariantMap& extra = {}) {
+ if (!DependencyManager::isSet()) {
+ return;
+ }
const auto& tracer = DependencyManager::get();
if (tracer) {
tracer->traceEvent(category, name, type, id, args, extra);
From 4db83230ce94b966efdfe07553d368be68a6e893 Mon Sep 17 00:00:00 2001
From: Brad Davis
Date: Fri, 27 Apr 2018 08:09:31 -0700
Subject: [PATCH 18/47] Fix bad virtual cast on qml surface destruction
---
libraries/ui/src/ui/OffscreenQmlSurface.cpp | 23 +++++++++++++--------
libraries/ui/src/ui/OffscreenQmlSurface.h | 4 +++-
2 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
index 43b573a169..b3c1c486e9 100644
--- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp
+++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
@@ -223,6 +223,17 @@ void AudioHandler::run() {
qDebug() << "QML Audio changed to " << _newTargetDevice;
}
+OffscreenQmlSurface::~OffscreenQmlSurface() {
+ clearFocusItem();
+}
+
+void OffscreenQmlSurface::clearFocusItem() {
+ if (_currentFocusItem) {
+ disconnect(_currentFocusItem, &QObject::destroyed, this, &OffscreenQmlSurface::focusDestroyed);
+ }
+ _currentFocusItem = nullptr;
+}
+
void OffscreenQmlSurface::initializeEngine(QQmlEngine* engine) {
Parent::initializeEngine(engine);
new QQmlFileSelector(engine);
@@ -545,17 +556,15 @@ bool OffscreenQmlSurface::handlePointerEvent(const PointerEvent& event, class QT
}
void OffscreenQmlSurface::focusDestroyed(QObject* obj) {
- if (_currentFocusItem) {
- disconnect(_currentFocusItem, &QObject::destroyed, this, &OffscreenQmlSurface::focusDestroyed);
- }
- _currentFocusItem = nullptr;
+ clearFocusItem();
}
void OffscreenQmlSurface::onFocusObjectChanged(QObject* object) {
+ clearFocusItem();
+
QQuickItem* item = static_cast(object);
if (!item) {
setFocusText(false);
- _currentFocusItem = nullptr;
return;
}
@@ -563,10 +572,6 @@ void OffscreenQmlSurface::onFocusObjectChanged(QObject* object) {
qApp->sendEvent(object, &query);
setFocusText(query.value(Qt::ImEnabled).toBool());
- if (_currentFocusItem) {
- disconnect(_currentFocusItem, &QObject::destroyed, this, 0);
- }
-
// Raise and lower keyboard for QML text fields.
// HTML text fields are handled in emitWebEvent() methods - testing READ_ONLY_PROPERTY prevents action for HTML files.
const char* READ_ONLY_PROPERTY = "readOnly";
diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.h b/libraries/ui/src/ui/OffscreenQmlSurface.h
index 9fa86f12a3..b95a8f117d 100644
--- a/libraries/ui/src/ui/OffscreenQmlSurface.h
+++ b/libraries/ui/src/ui/OffscreenQmlSurface.h
@@ -22,7 +22,8 @@ class OffscreenQmlSurface : public hifi::qml::OffscreenSurface {
Q_OBJECT
Q_PROPERTY(bool focusText READ isFocusText NOTIFY focusTextChanged)
public:
-
+ ~OffscreenQmlSurface();
+
static void addWhitelistContextHandler(const std::initializer_list& urls, const QmlContextCallback& callback);
static void addWhitelistContextHandler(const QUrl& url, const QmlContextCallback& callback) { addWhitelistContextHandler({ { url } }, callback); };
@@ -58,6 +59,7 @@ public slots:
void sendToQml(const QVariant& message);
protected:
+ void clearFocusItem();
void setFocusText(bool newFocusText);
void initializeEngine(QQmlEngine* engine) override;
void onRootContextCreated(QQmlContext* qmlContext) override;
From 6640313256e0fadc6401628f6e0316518a01119a Mon Sep 17 00:00:00 2001
From: Brad Davis
Date: Fri, 27 Apr 2018 08:10:22 -0700
Subject: [PATCH 19/47] Fix memory leak in QML surfaces
---
libraries/ui/src/ui/OffscreenQmlSurface.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
index b3c1c486e9..0d8e22cebb 100644
--- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp
+++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
@@ -115,6 +115,7 @@ private:
class UrlHandler : public QObject {
Q_OBJECT
public:
+ UrlHandler(QObject* parent = nullptr) : QObject(parent) {}
Q_INVOKABLE bool canHandleUrl(const QString& url) {
static auto handler = dynamic_cast(qApp);
return handler && handler->canAcceptURL(url);
@@ -257,7 +258,7 @@ void OffscreenQmlSurface::initializeEngine(QQmlEngine* engine) {
auto rootContext = engine->rootContext();
rootContext->setContextProperty("GL", ::getGLContextData());
- rootContext->setContextProperty("urlHandler", new UrlHandler());
+ rootContext->setContextProperty("urlHandler", new UrlHandler(rootContext));
rootContext->setContextProperty("resourceDirectoryUrl", QUrl::fromLocalFile(PathUtils::resourcesPath()));
rootContext->setContextProperty("ApplicationInterface", qApp);
auto javaScriptToInject = getEventBridgeJavascript();
From 1b612d373f845ea4dab1698fb36b12d5814d88ff Mon Sep 17 00:00:00 2001
From: Brad Davis
Date: Fri, 27 Apr 2018 08:11:11 -0700
Subject: [PATCH 20/47] Explicitly delete QML context before releasing engine
---
libraries/qml/src/qml/impl/SharedObject.cpp | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/libraries/qml/src/qml/impl/SharedObject.cpp b/libraries/qml/src/qml/impl/SharedObject.cpp
index 9253c41b39..7bcb216ba8 100644
--- a/libraries/qml/src/qml/impl/SharedObject.cpp
+++ b/libraries/qml/src/qml/impl/SharedObject.cpp
@@ -97,12 +97,13 @@ SharedObject::~SharedObject() {
}
// _rootItem is parented to the quickWindow, so needs no explicit destruction
- //if (_rootItem) {
- // delete _rootItem;
- // _rootItem = nullptr;
- //}
- releaseEngine(_qmlContext->engine());
+ if (_qmlContext) {
+ auto engine = _qmlContext->engine();
+ delete _qmlContext;
+ _qmlContext = nullptr;
+ releaseEngine(engine);
+ }
}
void SharedObject::create(OffscreenSurface* surface) {
@@ -210,9 +211,9 @@ QQmlEngine* SharedObject::acquireEngine(OffscreenSurface* surface) {
if (!globalEngine) {
Q_ASSERT(0 == globalEngineRefCount);
globalEngine = new QQmlEngine();
- surface->initializeQmlEngine(result);
- ++globalEngineRefCount;
+ surface->initializeEngine(result);
}
+ ++globalEngineRefCount;
result = globalEngine;
#else
result = new QQmlEngine();
From e892694bf5bdcf56e5892a71fe7fb2492f7d42ec Mon Sep 17 00:00:00 2001
From: Brad Davis
Date: Fri, 27 Apr 2018 08:13:35 -0700
Subject: [PATCH 21/47] Don't modify URL on web entity on QML shutdown, remove
tablet related code from web entity
---
.../src/RenderableWebEntityItem.cpp | 17 +----------------
1 file changed, 1 insertion(+), 16 deletions(-)
diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
index f333e805ce..7ad74d1eee 100644
--- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
@@ -308,12 +308,7 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
item->setProperty(URL_PROPERTY, _lastSourceUrl);
});
} else if (_contentType == ContentType::QmlContent) {
- _webSurface->load(_lastSourceUrl, [this](QQmlContext* context, QObject* item) {
- if (item && item->objectName() == "tabletRoot") {
- auto tabletScriptingInterface = DependencyManager::get();
- tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data());
- }
- });
+ _webSurface->load(_lastSourceUrl);
}
_fadeStartTime = usecTimestampNow();
_webSurface->resume();
@@ -330,16 +325,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();
- tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", nullptr);
- }
// Fix for crash in QtWebEngineCore when rapidly switching domains
// Call stop on the QWebEngineView before destroying OffscreenQMLSurface.
From f2172d84a00d8add357029821c45f4d74d15d412 Mon Sep 17 00:00:00 2001
From: Brad Davis
Date: Fri, 27 Apr 2018 08:35:20 -0700
Subject: [PATCH 22/47] Add stress test for QML web content
---
tests/qml/qml/controls/WebEntityView.qml | 32 ++++
tests/qml/src/main.cpp | 198 ++++++++++++++++++-----
2 files changed, 187 insertions(+), 43 deletions(-)
create mode 100644 tests/qml/qml/controls/WebEntityView.qml
diff --git a/tests/qml/qml/controls/WebEntityView.qml b/tests/qml/qml/controls/WebEntityView.qml
new file mode 100644
index 0000000000..a6c38f4abd
--- /dev/null
+++ b/tests/qml/qml/controls/WebEntityView.qml
@@ -0,0 +1,32 @@
+//
+// WebEntityView.qml
+//
+// Created by Kunal Gosar on 16 March 2017
+// Copyright 2017 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+import QtQuick 2.5
+import QtWebEngine 1.5
+
+WebEngineView {
+ id: webViewCore
+ objectName: "webEngineView"
+ width: parent !== null ? parent.width : undefined
+ height: parent !== null ? parent.height : undefined
+
+ onFeaturePermissionRequested: {
+ grantFeaturePermission(securityOrigin, feature, true);
+ }
+
+ //disable popup
+ onContextMenuRequested: {
+ request.accepted = true;
+ }
+
+ onNewViewRequested: {
+ newViewRequestedCallback(request)
+ }
+}
diff --git a/tests/qml/src/main.cpp b/tests/qml/src/main.cpp
index 022f7290f4..c23a958da7 100644
--- a/tests/qml/src/main.cpp
+++ b/tests/qml/src/main.cpp
@@ -28,52 +28,82 @@
#include
#include
#include
-
+#include
#include
#include
+#include
+
#include
-#include
#include
#include
#include
#include
#include
#include
+#include
+#include
+
+#pragma optimize("", off)
+
+namespace gl {
+ extern void initModuleGl();
+}
-class OffscreenQmlSurface : public hifi::qml::OffscreenSurface {
+QUrl getTestResource(const QString& relativePath) {
+ static QString dir;
+ if (dir.isEmpty()) {
+ QDir path(__FILE__);
+ path.cdUp();
+ dir = path.cleanPath(path.absoluteFilePath("../")) + "/";
+ qDebug() << "Resources Path: " << dir;
+ }
+ return QUrl::fromLocalFile(dir + relativePath);
+}
+
+#define DIVISIONS_X 5
+#define DIVISIONS_Y 5
+
+using QmlPtr = QSharedPointer;
+using TextureAndFence = hifi::qml::OffscreenSurface::TextureAndFence;
+
+struct QmlInfo {
+ QmlPtr surface;
+ GLuint texture{ 0 };
+ uint64_t lifetime{ 0 };
};
class TestWindow : public QWindow {
-
public:
TestWindow();
-
private:
- using TextureAndFence = hifi::qml::OffscreenSurface::TextureAndFence;
QOpenGLContext _glContext;
OffscreenGLCanvas _sharedContext;
- OffscreenQmlSurface _offscreenQml;
+ std::array, DIVISIONS_X> _surfaces;
+
QOpenGLFunctions_4_5_Core _glf;
- uint32_t _currentTexture{ 0 };
- GLsync _readFence{ 0 };
std::function _discardLamdba;
QSize _size;
+ size_t _surfaceCount{ 0 };
GLuint _fbo{ 0 };
const QSize _qmlSize{ 640, 480 };
bool _aboutToQuit{ false };
void initGl();
+ void updateSurfaces();
+ void buildSurface(QmlInfo& qmlInfo);
+ void destroySurface(QmlInfo& qmlInfo);
void resizeWindow(const QSize& size);
void draw();
void resizeEvent(QResizeEvent* ev) override;
};
TestWindow::TestWindow() {
- setSurfaceType(QSurface::OpenGLSurface);
+ Setting::init();
+ setSurfaceType(QSurface::OpenGLSurface);
QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
@@ -85,11 +115,12 @@ TestWindow::TestWindow() {
show();
+
resize(QSize(800, 600));
auto timer = new QTimer(this);
timer->setTimerType(Qt::PreciseTimer);
- timer->setInterval(5);
+ timer->setInterval(30);
connect(timer, &QTimer::timeout, [&] { draw(); });
timer->start();
@@ -97,7 +128,6 @@ TestWindow::TestWindow() {
timer->stop();
_aboutToQuit = true;
});
-
}
void TestWindow::initGl() {
@@ -105,6 +135,7 @@ void TestWindow::initGl() {
if (!_glContext.create() || !_glContext.makeCurrent(this)) {
qFatal("Unable to intialize Window GL context");
}
+ gl::initModuleGl();
_glf.initializeOpenGLFunctions();
_glf.glCreateFramebuffers(1, &_fbo);
@@ -113,15 +144,104 @@ void TestWindow::initGl() {
qFatal("Unable to intialize Shared GL context");
}
hifi::qml::OffscreenSurface::setSharedContext(_sharedContext.getContext());
- _discardLamdba = _offscreenQml.getDiscardLambda();
- _offscreenQml.resize({ 640, 480 });
- _offscreenQml.load(QUrl::fromLocalFile("C:/Users/bdavi/Git/hifi/tests/qml/qml/main.qml"));
+ _discardLamdba = hifi::qml::OffscreenSurface::getDiscardLambda();
}
void TestWindow::resizeWindow(const QSize& size) {
_size = size;
}
+static const int DEFAULT_MAX_FPS = 10;
+static const int YOUTUBE_MAX_FPS = 30;
+static const QString CONTROL_URL{ "/qml/controls/WebEntityView.qml" };
+static const char* URL_PROPERTY{ "url" };
+
+QString getSourceUrl() {
+ static const std::vector SOURCE_URLS{
+ "https://www.reddit.com/wiki/random",
+ "https://en.wikipedia.org/wiki/Wikipedia:Random",
+ "https://slashdot.org/",
+ //"https://www.youtube.com/watch?v=gDXwhHm4GhM",
+ //"https://www.youtube.com/watch?v=Ch_hoYPPeGc",
+ };
+
+ auto index = rand() % SOURCE_URLS.size();
+ return SOURCE_URLS[index];
+}
+
+
+
+void TestWindow::buildSurface(QmlInfo& qmlInfo) {
+ ++_surfaceCount;
+ auto lifetimeSecs = (uint32_t)(2.0f + (randFloat() * 10.0f));
+ auto lifetimeUsecs = (USECS_PER_SECOND * lifetimeSecs);
+ qmlInfo.lifetime = lifetimeUsecs + usecTimestampNow();
+ qmlInfo.texture = 0;
+ auto& surface = qmlInfo.surface;
+ surface.reset(new hifi::qml::OffscreenSurface());
+ surface->setMaxFps(DEFAULT_MAX_FPS);
+ surface->resize(_qmlSize);
+ surface->setMaxFps(DEFAULT_MAX_FPS);
+ hifi::qml::QmlContextObjectCallback callback = [](QQmlContext* context, QQuickItem* item) {
+ item->setProperty(URL_PROPERTY, getSourceUrl());
+ };
+ surface->load(getTestResource(CONTROL_URL), callback);
+ surface->resume();
+}
+
+void TestWindow::destroySurface(QmlInfo& qmlInfo) {
+ auto& surface = qmlInfo.surface;
+ QQuickItem* rootItem = surface->getRootItem();
+ if (rootItem) {
+ QObject* obj = rootItem->findChild("webEngineView");
+ if (!obj && rootItem->objectName() == "webEngineView") {
+ obj = rootItem;
+ }
+ if (obj) {
+ // stop loading
+ QMetaObject::invokeMethod(obj, "stop");
+ }
+ }
+ surface->pause();
+ surface.reset();
+}
+
+void TestWindow::updateSurfaces() {
+ auto now = usecTimestampNow();
+ // Fetch any new textures
+ for (size_t x = 0; x < DIVISIONS_X; ++x) {
+ for (size_t y = 0; y < DIVISIONS_Y; ++y) {
+ auto& qmlInfo = _surfaces[x][y];
+ if (!qmlInfo.surface) {
+ if (randFloat() > 0.99f) {
+ buildSurface(qmlInfo);
+ } else {
+ continue;
+ }
+ }
+
+ if (now > qmlInfo.lifetime) {
+ destroySurface(qmlInfo);
+ continue;
+ }
+
+ auto& surface = qmlInfo.surface;
+ auto& currentTexture = qmlInfo.texture;
+
+ TextureAndFence newTextureAndFence;
+ if (surface->fetchTexture(newTextureAndFence)) {
+ if (currentTexture != 0) {
+ auto readFence = _glf.glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ glFlush();
+ _discardLamdba(currentTexture, readFence);
+ }
+ currentTexture = newTextureAndFence.first;
+ _glf.glWaitSync((GLsync)newTextureAndFence.second, 0, GL_TIMEOUT_IGNORED);
+ }
+ }
+ }
+}
+
void TestWindow::draw() {
if (_aboutToQuit) {
return;
@@ -140,36 +260,31 @@ void TestWindow::draw() {
return;
}
+ updateSurfaces();
+
+ auto size = this->geometry().size();
+ auto incrementX = size.width() / DIVISIONS_X;
+ auto incrementY = size.height() / DIVISIONS_Y;
+ _glf.glViewport(0, 0, size.width(), size.height());
_glf.glClearColor(1, 0, 0, 1);
_glf.glClear(GL_COLOR_BUFFER_BIT);
- TextureAndFence newTextureAndFence;
- if (_offscreenQml.fetchTexture(newTextureAndFence)) {
- if (_currentTexture) {
- _discardLamdba(_currentTexture, _readFence);
- _readFence = 0;
+ for (uint32_t x = 0; x < DIVISIONS_X; ++x) {
+ for (uint32_t y = 0; y < DIVISIONS_Y; ++y) {
+ auto& qmlInfo = _surfaces[x][y];
+ if (!qmlInfo.surface || !qmlInfo.texture) {
+ continue;
+ }
+ _glf.glNamedFramebufferTexture(_fbo, GL_COLOR_ATTACHMENT0, qmlInfo.texture, 0);
+ _glf.glBlitNamedFramebuffer(_fbo, 0,
+ // src coordinates
+ 0, 0, _qmlSize.width() - 1, _qmlSize.height() - 1,
+ // dst coordinates
+ incrementX * x, incrementY * y, incrementX * (x + 1), incrementY * (y + 1),
+ // blit mask and filter
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
-
- _currentTexture = newTextureAndFence.first;
- _glf.glWaitSync((GLsync)newTextureAndFence.second, 0, GL_TIMEOUT_IGNORED);
- _glf.glNamedFramebufferTexture(_fbo, GL_COLOR_ATTACHMENT0, _currentTexture, 0);
}
-
- auto diff = _size - _qmlSize;
- diff /= 2;
- auto qmlExtent = diff + _qmlSize;
-
- if (_currentTexture) {
- _glf.glBlitNamedFramebuffer(_fbo, 0,
- 0, 0, _qmlSize.width() - 1, _qmlSize.height() - 1,
- diff.width(), diff.height(), qmlExtent.width() - 1, qmlExtent.height() - 2,
- GL_COLOR_BUFFER_BIT, GL_NEAREST);
- }
-
- if (_readFence) {
- _glf.glDeleteSync(_readFence);
- }
- _readFence = _glf.glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
_glf.glFlush();
_glContext.swapBuffers(this);
@@ -180,11 +295,8 @@ void TestWindow::resizeEvent(QResizeEvent* ev) {
}
int main(int argc, char** argv) {
- setupHifiApplication("QML Test");
-
QGuiApplication app(argc, argv);
TestWindow window;
app.exec();
return 0;
}
-
From c163ae63b8954439cebe2d11c8d8902e807ef910 Mon Sep 17 00:00:00 2001
From: Zach Fox
Date: Fri, 27 Apr 2018 10:20:55 -0700
Subject: [PATCH 23/47] 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 24/47] 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 25/47] 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 26/47] 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 27/47] 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 5f8149fd6873ca6ad1163927826283f1809a10c8 Mon Sep 17 00:00:00 2001
From: Brad Davis
Date: Fri, 27 Apr 2018 13:57:22 -0700
Subject: [PATCH 28/47] Remove debugging pragma
---
tests/qml/src/main.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/tests/qml/src/main.cpp b/tests/qml/src/main.cpp
index c23a958da7..cd5a567e95 100644
--- a/tests/qml/src/main.cpp
+++ b/tests/qml/src/main.cpp
@@ -44,8 +44,6 @@
#include
#include
-#pragma optimize("", off)
-
namespace gl {
extern void initModuleGl();
}
From 575520fe3063f3d6deac5e8266b3e886ac25d88a Mon Sep 17 00:00:00 2001
From: Brad Davis
Date: Fri, 27 Apr 2018 15:08:10 -0700
Subject: [PATCH 29/47] Ensure we actually delete the QML scenegraph!
---
libraries/qml/src/qml/impl/SharedObject.cpp | 7 +-
tests/qml/qml/controls/WebEntityView.qml | 15 ++++
tests/qml/src/main.cpp | 84 ++++++++++++++-------
3 files changed, 78 insertions(+), 28 deletions(-)
diff --git a/libraries/qml/src/qml/impl/SharedObject.cpp b/libraries/qml/src/qml/impl/SharedObject.cpp
index 7bcb216ba8..2fde057ca8 100644
--- a/libraries/qml/src/qml/impl/SharedObject.cpp
+++ b/libraries/qml/src/qml/impl/SharedObject.cpp
@@ -90,14 +90,17 @@ SharedObject::~SharedObject() {
_renderControl = nullptr;
}
+ if (_rootItem) {
+ delete _rootItem;
+ _rootItem = nullptr;
+ }
+
if (_quickWindow) {
_quickWindow->destroy();
delete _quickWindow;
_quickWindow = nullptr;
}
- // _rootItem is parented to the quickWindow, so needs no explicit destruction
-
if (_qmlContext) {
auto engine = _qmlContext->engine();
delete _qmlContext;
diff --git a/tests/qml/qml/controls/WebEntityView.qml b/tests/qml/qml/controls/WebEntityView.qml
index a6c38f4abd..5bd29ef457 100644
--- a/tests/qml/qml/controls/WebEntityView.qml
+++ b/tests/qml/qml/controls/WebEntityView.qml
@@ -10,6 +10,21 @@
import QtQuick 2.5
import QtWebEngine 1.5
+import Hifi 1.0
+
+/*
+TestItem {
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 10
+ color: "blue"
+ property string url: ""
+ ColorAnimation on color {
+ loops: Animation.Infinite; from: "blue"; to: "yellow"; duration: 1000
+ }
+ }
+}
+*/
WebEngineView {
id: webViewCore
diff --git a/tests/qml/src/main.cpp b/tests/qml/src/main.cpp
index cd5a567e95..ec4012898f 100644
--- a/tests/qml/src/main.cpp
+++ b/tests/qml/src/main.cpp
@@ -48,6 +48,17 @@ namespace gl {
extern void initModuleGl();
}
+class QTestItem : public QQuickItem {
+ Q_OBJECT
+public:
+ QTestItem(QQuickItem* parent = nullptr) : QQuickItem(parent) {
+ qDebug() << __FUNCTION__;
+ }
+
+ ~QTestItem() {
+ qDebug() << __FUNCTION__;
+ }
+};
QUrl getTestResource(const QString& relativePath) {
static QString dir;
@@ -89,9 +100,10 @@ private:
GLuint _fbo{ 0 };
const QSize _qmlSize{ 640, 480 };
bool _aboutToQuit{ false };
+ uint64_t _createStopTime;
void initGl();
void updateSurfaces();
- void buildSurface(QmlInfo& qmlInfo);
+ void buildSurface(QmlInfo& qmlInfo, bool allowVideo);
void destroySurface(QmlInfo& qmlInfo);
void resizeWindow(const QSize& size);
void draw();
@@ -111,8 +123,10 @@ TestWindow::TestWindow() {
QSurfaceFormat::setDefaultFormat(format);
setFormat(format);
- show();
+ qmlRegisterType("Hifi", 1, 0, "TestItem");
+ show();
+ _createStopTime = usecTimestampNow() + (3000u * USECS_PER_SECOND);
resize(QSize(800, 600));
@@ -167,40 +181,56 @@ QString getSourceUrl() {
return SOURCE_URLS[index];
}
+#define CACHE_WEBVIEWS 0
+#if CACHE_WEBVIEWS
+static std::list _cache;
+#endif
-void TestWindow::buildSurface(QmlInfo& qmlInfo) {
+hifi::qml::QmlContextObjectCallback callback = [](QQmlContext* context, QQuickItem* item) {
+ item->setProperty(URL_PROPERTY, getSourceUrl());
+};
+
+void TestWindow::buildSurface(QmlInfo& qmlInfo, bool allowVideo) {
++_surfaceCount;
- auto lifetimeSecs = (uint32_t)(2.0f + (randFloat() * 10.0f));
+ auto lifetimeSecs = (uint32_t)(5.0f + (randFloat() * 10.0f));
auto lifetimeUsecs = (USECS_PER_SECOND * lifetimeSecs);
qmlInfo.lifetime = lifetimeUsecs + usecTimestampNow();
qmlInfo.texture = 0;
- auto& surface = qmlInfo.surface;
- surface.reset(new hifi::qml::OffscreenSurface());
- surface->setMaxFps(DEFAULT_MAX_FPS);
- surface->resize(_qmlSize);
- surface->setMaxFps(DEFAULT_MAX_FPS);
- hifi::qml::QmlContextObjectCallback callback = [](QQmlContext* context, QQuickItem* item) {
- item->setProperty(URL_PROPERTY, getSourceUrl());
- };
- surface->load(getTestResource(CONTROL_URL), callback);
- surface->resume();
+#if CACHE_WEBVIEWS
+ if (_cache.empty()) {
+ _cache.emplace_back(new hifi::qml::OffscreenSurface());
+ auto& surface = _cache.back();
+ surface->load(getTestResource(CONTROL_URL));
+ surface->setMaxFps(DEFAULT_MAX_FPS);
+ }
+ qmlInfo.surface = _cache.front();
+ _cache.pop_front();
+#else
+ qmlInfo.surface.reset(new hifi::qml::OffscreenSurface());
+ qmlInfo.surface->load(getTestResource(CONTROL_URL));
+ qmlInfo.surface->setMaxFps(DEFAULT_MAX_FPS);
+#endif
+
+ qmlInfo.surface->resize(_qmlSize);
+ auto url = allowVideo ? "https://www.youtube.com/watch?v=gDXwhHm4GhM" : getSourceUrl();
+ qmlInfo.surface->getRootItem()->setProperty(URL_PROPERTY, url);
+ qmlInfo.surface->resume();
}
+
void TestWindow::destroySurface(QmlInfo& qmlInfo) {
auto& surface = qmlInfo.surface;
- QQuickItem* rootItem = surface->getRootItem();
- if (rootItem) {
- QObject* obj = rootItem->findChild("webEngineView");
- if (!obj && rootItem->objectName() == "webEngineView") {
- obj = rootItem;
- }
- if (obj) {
- // stop loading
- QMetaObject::invokeMethod(obj, "stop");
- }
+ auto webView = surface->getRootItem();
+ if (webView) {
+ // stop loading
+ QMetaObject::invokeMethod(webView, "stop");
+ webView->setProperty(URL_PROPERTY, "about:blank");
}
surface->pause();
+#if CACHE_WEBVIEWS
+ _cache.push_back(surface);
+#endif
surface.reset();
}
@@ -211,8 +241,8 @@ void TestWindow::updateSurfaces() {
for (size_t y = 0; y < DIVISIONS_Y; ++y) {
auto& qmlInfo = _surfaces[x][y];
if (!qmlInfo.surface) {
- if (randFloat() > 0.99f) {
- buildSurface(qmlInfo);
+ if (now < _createStopTime && randFloat() > 0.99f) {
+ buildSurface(qmlInfo, x == 0 && y == 0);
} else {
continue;
}
@@ -298,3 +328,5 @@ int main(int argc, char** argv) {
app.exec();
return 0;
}
+
+#include "main.moc"
\ No newline at end of file
From 0962e1fc1658f25f44ded0128d93ed802305ee25 Mon Sep 17 00:00:00 2001
From: David Back
Date: Fri, 27 Apr 2018 11:30:45 -0700
Subject: [PATCH 30/47] 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 31/47] 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 8e42bb8c877e693cdf29bdcb2e206316a2bc8a85 Mon Sep 17 00:00:00 2001
From: Brad Davis
Date: Fri, 27 Apr 2018 16:04:07 -0700
Subject: [PATCH 32/47] Restore the stop functionality for a browser view when
it's being destroyed
---
.../qml/controls/FlickableWebViewCore.qml | 5 ++
interface/resources/qml/controls/WebView.qml | 4 ++
.../src/RenderableWebEntityItem.cpp | 11 ++-
tests/qml/src/main.cpp | 68 +++++--------------
4 files changed, 32 insertions(+), 56 deletions(-)
diff --git a/interface/resources/qml/controls/FlickableWebViewCore.qml b/interface/resources/qml/controls/FlickableWebViewCore.qml
index 8e7db44b7d..943f15e1de 100644
--- a/interface/resources/qml/controls/FlickableWebViewCore.qml
+++ b/interface/resources/qml/controls/FlickableWebViewCore.qml
@@ -21,6 +21,7 @@ Item {
signal newViewRequestedCallback(var request)
signal loadingChangedCallback(var loadRequest)
+
width: parent.width
property bool interactive: false
@@ -29,6 +30,10 @@ Item {
id: hifi
}
+ function stop() {
+ webViewCore.stop();
+ }
+
function unfocus() {
webViewCore.runJavaScript("if (document.activeElement) document.activeElement.blur();", function(result) {
console.log('unfocus completed: ', result);
diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml
index 931c64e1ef..71bf69fdc8 100644
--- a/interface/resources/qml/controls/WebView.qml
+++ b/interface/resources/qml/controls/WebView.qml
@@ -21,6 +21,10 @@ Item {
property bool passwordField: false
property alias flickable: webroot.interactive
+ function stop() {
+ webroot.stop();
+ }
+
// FIXME - Keyboard HMD only: Make Interface either set keyboardRaised property directly in OffscreenQmlSurface
// or provide HMDinfo object to QML in RenderableWebEntityItem and do the following.
/*
diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
index 7ad74d1eee..693e3d0cf4 100644
--- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp
@@ -318,8 +318,10 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
void WebEntityRenderer::destroyWebSurface() {
QSharedPointer webSurface;
+ ContentType contentType{ ContentType::NoContent };
withWriteLock([&] {
webSurface.swap(_webSurface);
+ std::swap(contentType, _contentType);
});
if (webSurface) {
@@ -328,12 +330,9 @@ void WebEntityRenderer::destroyWebSurface() {
// Fix for crash in QtWebEngineCore when rapidly switching domains
// Call stop on the QWebEngineView before destroying OffscreenQMLSurface.
- if (rootItem) {
- QObject* obj = rootItem->findChild("webEngineView");
- if (obj) {
- // stop loading
- QMetaObject::invokeMethod(obj, "stop");
- }
+ if (rootItem && contentType == ContentType::HtmlContent) {
+ // stop loading
+ QMetaObject::invokeMethod(rootItem, "stop");
}
webSurface->pause();
diff --git a/tests/qml/src/main.cpp b/tests/qml/src/main.cpp
index ec4012898f..349ac55d88 100644
--- a/tests/qml/src/main.cpp
+++ b/tests/qml/src/main.cpp
@@ -45,19 +45,15 @@
#include
namespace gl {
- extern void initModuleGl();
+extern void initModuleGl();
}
class QTestItem : public QQuickItem {
Q_OBJECT
public:
- QTestItem(QQuickItem* parent = nullptr) : QQuickItem(parent) {
- qDebug() << __FUNCTION__;
- }
+ QTestItem(QQuickItem* parent = nullptr) : QQuickItem(parent) { qDebug() << __FUNCTION__; }
- ~QTestItem() {
- qDebug() << __FUNCTION__;
- }
+ ~QTestItem() { qDebug() << __FUNCTION__; }
};
QUrl getTestResource(const QString& relativePath) {
@@ -71,7 +67,6 @@ QUrl getTestResource(const QString& relativePath) {
return QUrl::fromLocalFile(dir + relativePath);
}
-
#define DIVISIONS_X 5
#define DIVISIONS_Y 5
@@ -164,61 +159,41 @@ void TestWindow::resizeWindow(const QSize& size) {
}
static const int DEFAULT_MAX_FPS = 10;
-static const int YOUTUBE_MAX_FPS = 30;
static const QString CONTROL_URL{ "/qml/controls/WebEntityView.qml" };
static const char* URL_PROPERTY{ "url" };
-QString getSourceUrl() {
+QString getSourceUrl(bool video) {
static const std::vector SOURCE_URLS{
"https://www.reddit.com/wiki/random",
"https://en.wikipedia.org/wiki/Wikipedia:Random",
"https://slashdot.org/",
- //"https://www.youtube.com/watch?v=gDXwhHm4GhM",
- //"https://www.youtube.com/watch?v=Ch_hoYPPeGc",
};
- auto index = rand() % SOURCE_URLS.size();
- return SOURCE_URLS[index];
+ static const std::vector VIDEO_SOURCE_URLS{
+ "https://www.youtube.com/watch?v=gDXwhHm4GhM",
+ "https://www.youtube.com/watch?v=Ch_hoYPPeGc",
+ };
+
+ const auto& sourceUrls = video ? VIDEO_SOURCE_URLS : SOURCE_URLS;
+ auto index = rand() % sourceUrls.size();
+ return sourceUrls[index];
}
-#define CACHE_WEBVIEWS 0
-
-#if CACHE_WEBVIEWS
-static std::list _cache;
-#endif
-
-hifi::qml::QmlContextObjectCallback callback = [](QQmlContext* context, QQuickItem* item) {
- item->setProperty(URL_PROPERTY, getSourceUrl());
-};
-
-void TestWindow::buildSurface(QmlInfo& qmlInfo, bool allowVideo) {
+void TestWindow::buildSurface(QmlInfo& qmlInfo, bool video) {
++_surfaceCount;
auto lifetimeSecs = (uint32_t)(5.0f + (randFloat() * 10.0f));
auto lifetimeUsecs = (USECS_PER_SECOND * lifetimeSecs);
qmlInfo.lifetime = lifetimeUsecs + usecTimestampNow();
qmlInfo.texture = 0;
-#if CACHE_WEBVIEWS
- if (_cache.empty()) {
- _cache.emplace_back(new hifi::qml::OffscreenSurface());
- auto& surface = _cache.back();
- surface->load(getTestResource(CONTROL_URL));
- surface->setMaxFps(DEFAULT_MAX_FPS);
- }
- qmlInfo.surface = _cache.front();
- _cache.pop_front();
-#else
qmlInfo.surface.reset(new hifi::qml::OffscreenSurface());
- qmlInfo.surface->load(getTestResource(CONTROL_URL));
+ qmlInfo.surface->load(getTestResource(CONTROL_URL), [video](QQmlContext* context, QQuickItem* item) {
+ item->setProperty(URL_PROPERTY, getSourceUrl(video));
+ });
qmlInfo.surface->setMaxFps(DEFAULT_MAX_FPS);
-#endif
-
qmlInfo.surface->resize(_qmlSize);
- auto url = allowVideo ? "https://www.youtube.com/watch?v=gDXwhHm4GhM" : getSourceUrl();
- qmlInfo.surface->getRootItem()->setProperty(URL_PROPERTY, url);
qmlInfo.surface->resume();
}
-
void TestWindow::destroySurface(QmlInfo& qmlInfo) {
auto& surface = qmlInfo.surface;
auto webView = surface->getRootItem();
@@ -228,9 +203,6 @@ void TestWindow::destroySurface(QmlInfo& qmlInfo) {
webView->setProperty(URL_PROPERTY, "about:blank");
}
surface->pause();
-#if CACHE_WEBVIEWS
- _cache.push_back(surface);
-#endif
surface.reset();
}
@@ -296,7 +268,6 @@ void TestWindow::draw() {
_glf.glViewport(0, 0, size.width(), size.height());
_glf.glClearColor(1, 0, 0, 1);
_glf.glClear(GL_COLOR_BUFFER_BIT);
-
for (uint32_t x = 0; x < DIVISIONS_X; ++x) {
for (uint32_t y = 0; y < DIVISIONS_Y; ++y) {
auto& qmlInfo = _surfaces[x][y];
@@ -313,8 +284,6 @@ void TestWindow::draw() {
GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
}
- _glf.glFlush();
-
_glContext.swapBuffers(this);
}
@@ -325,8 +294,7 @@ void TestWindow::resizeEvent(QResizeEvent* ev) {
int main(int argc, char** argv) {
QGuiApplication app(argc, argv);
TestWindow window;
- app.exec();
- return 0;
+ return app.exec();
}
-#include "main.moc"
\ No newline at end of file
+#include "main.moc"
From a245bb2174de3e4509c97d6de37ab483c4e1f89a Mon Sep 17 00:00:00 2001
From: Seth Alves
Date: Sat, 28 Apr 2018 13:30:02 -0700
Subject: [PATCH 33/47] fix libquazip debug filename. link libatomic where
needed
---
cmake/externals/quazip/CMakeLists.txt | 3 +++
tests/controllers/CMakeLists.txt | 6 +++++-
tests/render-perf/CMakeLists.txt | 4 ++++
3 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/cmake/externals/quazip/CMakeLists.txt b/cmake/externals/quazip/CMakeLists.txt
index f2690e0a7d..7bf6f05d9f 100644
--- a/cmake/externals/quazip/CMakeLists.txt
+++ b/cmake/externals/quazip/CMakeLists.txt
@@ -41,6 +41,9 @@ if (APPLE)
elseif (WIN32)
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/quazip5.lib CACHE FILEPATH "Location of QuaZip release library")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/quazip5d.lib CACHE FILEPATH "Location of QuaZip release library")
+elseif (CMAKE_SYSTEM_NAME MATCHES "Linux")
+ set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5.so CACHE FILEPATH "Location of QuaZip release library")
+ set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/libquazip5d.so CACHE FILEPATH "Location of QuaZip release library")
else ()
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libquazip5.so CACHE FILEPATH "Location of QuaZip release library")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/lib/libquazip5.so CACHE FILEPATH "Location of QuaZip release library")
diff --git a/tests/controllers/CMakeLists.txt b/tests/controllers/CMakeLists.txt
index b5e866ccce..ce1c150ed4 100644
--- a/tests/controllers/CMakeLists.txt
+++ b/tests/controllers/CMakeLists.txt
@@ -23,5 +23,9 @@ if (WIN32)
add_dependency_external_projects(wasapi)
endif()
+if (CMAKE_SYSTEM_NAME MATCHES "Linux")
+ target_link_libraries(${TARGET_NAME} atomic)
+endif()
+
package_libraries_for_deployment()
-endif()
\ No newline at end of file
+endif()
diff --git a/tests/render-perf/CMakeLists.txt b/tests/render-perf/CMakeLists.txt
index fd4d8d88dd..d688474379 100644
--- a/tests/render-perf/CMakeLists.txt
+++ b/tests/render-perf/CMakeLists.txt
@@ -27,6 +27,10 @@ if (WIN32)
add_dependency_external_projects(wasapi)
endif()
+if (CMAKE_SYSTEM_NAME MATCHES "Linux")
+ target_link_libraries(${TARGET_NAME} atomic)
+endif()
+
package_libraries_for_deployment()
From a226790295c8ef4c5e21179993bb5cc0d62995e2 Mon Sep 17 00:00:00 2001
From: Oren Hurvitz
Date: Mon, 30 Apr 2018 15:05:27 +0300
Subject: [PATCH 34/47] 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 35/47] 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 7db07db9e2bdfd4bb92544a951e8e94b38f6ac97 Mon Sep 17 00:00:00 2001
From: Liv Erickson
Date: Mon, 30 Apr 2018 13:55:01 -0700
Subject: [PATCH 36/47] remove menu item at cleanup
---
scripts/system/edit.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/scripts/system/edit.js b/scripts/system/edit.js
index 6d2b1f129b..c99c8d401a 100644
--- a/scripts/system/edit.js
+++ b/scripts/system/edit.js
@@ -1291,6 +1291,7 @@ function cleanupModelMenus() {
Menu.removeMenuItem("Edit", MENU_EASE_ON_FOCUS);
Menu.removeMenuItem("Edit", MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE);
Menu.removeMenuItem("Edit", MENU_SHOW_ZONES_IN_EDIT_MODE);
+ Menu.removeMenuItem("Edit", MENU_CREATE_ENTITIES_GRABBABLE);
}
Script.scriptEnding.connect(function () {
From f9bda6df15f125b2352dc19a1f6a70b38cea10a2 Mon Sep 17 00:00:00 2001
From: David Rowe
Date: Tue, 1 May 2018 11:36:37 +1200
Subject: [PATCH 37/47] Fix LODManager JSDoc
---
interface/src/LODManager.h | 49 +++++++++++++++++---------------------
1 file changed, 22 insertions(+), 27 deletions(-)
diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h
index e8737d92ae..96d92e91e9 100644
--- a/interface/src/LODManager.h
+++ b/interface/src/LODManager.h
@@ -9,11 +9,6 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
-/**jsdoc
- * The LOD class manages your Level of Detail functions within interface
- * @namespace LODManager
- */
-
#ifndef hifi_LODManager_h
#define hifi_LODManager_h
@@ -39,10 +34,32 @@ const float ADJUST_LOD_MIN_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE * 0.04f;
class AABox;
+/**jsdoc
+ * The LOD class manages your Level of Detail functions within Interface.
+ * @namespace LODManager
+ * @property {number} presentTime Read-only.
+ * @property {number} engineRunTime Read-only.
+ * @property {number} gpuTime Read-only.
+ * @property {number} avgRenderTime Read-only.
+ * @property {number} fps Read-only.
+ * @property {number} lodLevel Read-only.
+ * @property {number} lodDecreaseFPS Read-only.
+ * @property {number} lodIncreaseFPS Read-only.
+ */
+
class LODManager : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
+ Q_PROPERTY(float presentTime READ getPresentTime)
+ Q_PROPERTY(float engineRunTime READ getEngineRunTime)
+ Q_PROPERTY(float gpuTime READ getGPUTime)
+ Q_PROPERTY(float avgRenderTime READ getAverageRenderTime)
+ Q_PROPERTY(float fps READ getMaxTheoreticalFPS)
+ Q_PROPERTY(float lodLevel READ getLODLevel)
+ Q_PROPERTY(float lodDecreaseFPS READ getLODDecreaseFPS)
+ Q_PROPERTY(float lodIncreaseFPS READ getLODIncreaseFPS)
+
public:
/**jsdoc
@@ -138,28 +155,6 @@ public:
*/
Q_INVOKABLE float getLODIncreaseFPS() const;
- /**jsdoc
- * @namespace LODManager
- * @property {number} presentTime Read-only.
- * @property {number} engineRunTime Read-only.
- * @property {number} gpuTime Read-only.
- * @property {number} avgRenderTime Read-only.
- * @property {number} fps Read-only.
- * @property {number} lodLevel Read-only.
- * @property {number} lodDecreaseFPS Read-only.
- * @property {number} lodIncreaseFPS Read-only.
- */
-
- Q_PROPERTY(float presentTime READ getPresentTime)
- Q_PROPERTY(float engineRunTime READ getEngineRunTime)
- Q_PROPERTY(float gpuTime READ getGPUTime)
- Q_PROPERTY(float avgRenderTime READ getAverageRenderTime)
- Q_PROPERTY(float fps READ getMaxTheoreticalFPS)
- Q_PROPERTY(float lodLevel READ getLODLevel)
-
- Q_PROPERTY(float lodDecreaseFPS READ getLODDecreaseFPS)
- Q_PROPERTY(float lodIncreaseFPS READ getLODIncreaseFPS)
-
float getPresentTime() const { return _presentTime; }
float getEngineRunTime() const { return _engineRunTime; }
float getGPUTime() const { return _gpuTime; }
From f69ee410748700e547c7fffb5e5a5ee2021b20f6 Mon Sep 17 00:00:00 2001
From: Zach Fox
Date: Mon, 30 Apr 2018 17:13:44 -0700
Subject: [PATCH 38/47] Prevent crash in ImageProvider when tablet isn't yet
initialized
---
interface/src/commerce/Wallet.cpp | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp
index 3e0e4adf18..42c8b9973d 100644
--- a/interface/src/commerce/Wallet.cpp
+++ b/interface/src/commerce/Wallet.cpp
@@ -615,9 +615,12 @@ void Wallet::updateImageProvider() {
securityImageProvider->setSecurityImage(_securityImage);
// inform tablet security image provider
- QQmlEngine* tabletEngine = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system")->getTabletSurface()->getSurfaceContext()->engine();
- securityImageProvider = reinterpret_cast(tabletEngine->imageProvider(SecurityImageProvider::PROVIDER_NAME));
- securityImageProvider->setSecurityImage(_securityImage);
+ auto tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system");
+ if (tablet) {
+ QQmlEngine* tabletEngine = tablet->getTabletSurface()->getSurfaceContext()->engine();
+ securityImageProvider = reinterpret_cast(tabletEngine->imageProvider(SecurityImageProvider::PROVIDER_NAME));
+ securityImageProvider->setSecurityImage(_securityImage);
+ }
}
void Wallet::chooseSecurityImage(const QString& filename) {
From a1fc1c4810df8eec32b52969b45fd2e0d5c7448b Mon Sep 17 00:00:00 2001
From: David Rowe
Date: Tue, 1 May 2018 21:55:14 +1200
Subject: [PATCH 39/47] Add JSDoc for Entity preload and unload signals
---
libraries/script-engine/src/ScriptEngine.cpp | 33 ++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp
index c79ffffec7..f0a13cc62b 100644
--- a/libraries/script-engine/src/ScriptEngine.cpp
+++ b/libraries/script-engine/src/ScriptEngine.cpp
@@ -2161,6 +2161,32 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString&
}, forceRedownload);
}
+/**jsdoc
+ * Triggered when the script starts for a user.
+ * Note: Can only be connected to via this.preload = function (...) { ... }
in the entity script.
+ * Available in: | Client Entity Scripts | Server Entity Scripts |
---|
+ * @function Entities.preload
+ * @param {Uuid} entityID - The ID of the entity that the script is running in.
+ * @returns {Signal}
+ * @example Get the ID of the entity that a client entity script is running in.
+ * var entityScript = (function () {
+ * this.entityID = Uuid.NULL;
+ *
+ * this.preload = function (entityID) {
+ * this.entityID = entityID;
+ * print("Entity ID: " + this.entityID);
+ * };
+ * );
+ *
+ * var entityID = Entities.addEntity({
+ * type: "Box",
+ * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -5 })),
+ * dimensions: { x: 0.5, y: 0.5, z: 0.5 },
+ * color: { red: 255, green: 0, blue: 0 },
+ * script: "(" + entityScript + ")", // Could host the script on a Web server instead.
+ * lifetime: 300 // Delete after 5 minutes.
+ * });
+ */
// since all of these operations can be asynch we will always do the actual work in the response handler
// for the download
void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, const QString& scriptOrURL, const QString& contents, bool isURL, bool success , const QString& status) {
@@ -2345,6 +2371,13 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co
processDeferredEntityLoads(entityScript, entityID);
}
+/**jsdoc
+ * Triggered when the script terminates for a user.
+ * Note: Can only be connected to via this.unoad = function () { ... }
in the entity script.
+ * Available in: | Client Entity Scripts | Server Entity Scripts |
---|
+ * @function Entities.unload
+ * @returns {Signal}
+ */
void ScriptEngine::unloadEntityScript(const EntityItemID& entityID, bool shouldRemoveFromMap) {
if (QThread::currentThread() != thread()) {
#ifdef THREAD_DEBUGGING
From 65f5915372912077c51319937415f7396df5d923 Mon Sep 17 00:00:00 2001
From: David Rowe
Date: Tue, 1 May 2018 21:55:27 +1200
Subject: [PATCH 40/47] Add JSDoc for startFarTrigger etc. calls on entity
scripts
---
.../scripting/ControllerScriptingInterface.h | 57 ++++++++++++++++++-
1 file changed, 56 insertions(+), 1 deletion(-)
diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h
index f19caa8478..4fceda3b04 100644
--- a/interface/src/scripting/ControllerScriptingInterface.h
+++ b/interface/src/scripting/ControllerScriptingInterface.h
@@ -28,7 +28,7 @@ class ScriptEngine;
/**jsdoc
* The Controller API provides facilities to interact with computer and controller hardware.
*
- * Functions:
+ * Functions
*
* Properties
*
@@ -143,6 +143,61 @@ class ScriptEngine;
* - {@link Controller.stopInputPlayback|stopInputPlayback}
*
*
+ * Entity Methods:
+ *
+ * The default scripts implement hand controller actions that use {@link Entities.callEntityMethod} to call entity script
+ * methods, if present in the entity being interacted with.
+ *
+ *
+ *
+ * Method Name | Description | Example |
+ *
+ *
+ *
+ * startFarTrigger
continueFarTrigger
stopFarTrigger |
+ * These methods are called when a user is more than 0.3m away from the entity, the entity is triggerable, and the
+ * user starts, continues, or stops squeezing the trigger. |
+ *
+ * A light switch that can be toggled on and off from a distance. |
+ *
+ *
+ * startNearTrigger
continueNearTrigger
stopNearTrigger |
+ * These methods are called when a user is less than 0.3m away from the entity, the entity is triggerable, and the
+ * user starts, continues, or stops squeezing the trigger. |
+ * A doorbell that can be rung when a user is near. |
+ *
+ *
+ * startDistanceGrab
continueDistanceGrab
|
+ * These methods are called when a user is more than 0.3m away from the entity, the entity is either cloneable, or
+ * grabbable and not locked, and the user starts or continues to squeeze the trigger. |
+ * A comet that emits icy particle trails when a user is dragging it through the sky. |
+ *
+ *
+ * startNearGrab
continueNearGrab
|
+ * These methods are called when a user is less than 0.3m away from the entity, the entity is either cloneable, or
+ * grabbable and not locked, and the user starts or continues to squeeze the trigger. |
+ * A ball that glows when it's being held close. |
+ *
+ *
+ * releaseGrab |
+ * This method is called when a user releases the trigger when having been either distance or near grabbing an
+ * entity. |
+ * Turn off the ball glow or comet trail with the user finishes grabbing it. |
+ *
+ *
+ * startEquip
continueEquip
releaseEquip |
+ * These methods are called when a user starts, continues, or stops equipping an entity. |
+ * A glass that stays in the user's hand after the trigger is clicked. |
+ *
+ *
+ *
+ * All the entity methods are called with the following two arguments:
+ *
+ * - The entity ID.
+ * - A string,
"hand,userID"
— where "hand" is "left"
or "right"
, and "userID"
+ * is the user's {@link MyAvatar|MyAvatar.sessionUUID}.
+ *
+ *
* @namespace Controller
*
* @property {Controller.Actions} Actions - Predefined actions on Interface and the user's avatar. These can be used as end
From 2482da3c259752b670fc4f2acbf3c087073b80ad Mon Sep 17 00:00:00 2001
From: David Rowe
Date: Tue, 1 May 2018 21:55:45 +1200
Subject: [PATCH 41/47] Miscellaneous JSDoc fixes noticed in passing
---
.../controllers/src/controllers/impl/MappingBuilderProxy.h | 6 ++++--
.../controllers/src/controllers/impl/RouteBuilderProxy.h | 3 ++-
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h
index 86a43c0c13..3c3858e2ba 100644
--- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h
+++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h
@@ -39,7 +39,9 @@ class UserInputMapper;
* methods.
* Use {@link Controller.parseMapping} or {@link Controller.loadMapping} to load a {@link Controller.MappingJSON}.
*
- * Enable the mapping using {@link MappingObject#enable|enable} or {@link Controller.enableMapping} for it to take effect.
+ *
+ *
Enable the mapping using {@link MappingObject#enable|enable} or {@link Controller.enableMapping} for it to take
+ * effect.
*
* Mappings and their routes are applied according to the following rules:
*
@@ -49,7 +51,7 @@ class UserInputMapper;
* output that already has a route the new route is ignored.
* - New mappings override previous mappings: each output is processed using the route in the most recently enabled
* mapping that contains that output.
- *
+ *
*
* @class MappingObject
*/
diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h
index 0336638068..d33f3e3383 100644
--- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h
+++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h
@@ -29,7 +29,8 @@ class ScriptingInterface;
* A route in a {@link MappingObject} used by the {@link Controller} API.
*
* Create a route using {@link MappingObject} methods and apply this object's methods to process it, terminating with
- * {@link RouteObject#to} to apply it to a Standard
control, action, or script function.
+ * {@link RouteObject#to} to apply it to a Standard
control, action, or script function. Note: Loops are not
+ * permitted.
*
* Some methods apply to routes with number data, some apply routes with {@link Pose} data, and some apply to both route
* types.
From f1e1c6a34817563ac0a9da876a968561361b9ee6 Mon Sep 17 00:00:00 2001
From: Seth Alves
Date: Tue, 1 May 2018 09:15:44 -0700
Subject: [PATCH 42/47] fix physics related crash-on-exit
---
libraries/physics/src/PhysicalEntitySimulation.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp
index ab7c2ec252..3ea3616b15 100644
--- a/libraries/physics/src/PhysicalEntitySimulation.cpp
+++ b/libraries/physics/src/PhysicalEntitySimulation.cpp
@@ -153,6 +153,8 @@ void PhysicalEntitySimulation::clearEntitiesInternal() {
// remove the objects (aka MotionStates) from physics
_physicsEngine->removeSetOfObjects(_physicalObjects);
+ clearOwnershipData();
+
// delete the MotionStates
for (auto stateItr : _physicalObjects) {
EntityMotionState* motionState = static_cast(&(*stateItr));
@@ -165,7 +167,6 @@ void PhysicalEntitySimulation::clearEntitiesInternal() {
_physicalObjects.clear();
// clear all other lists specific to this derived class
- clearOwnershipData();
_entitiesToRemoveFromPhysics.clear();
_entitiesToAddToPhysics.clear();
_incomingChanges.clear();
From cd76336e6a937128a5b8f227ae57a3e856431914 Mon Sep 17 00:00:00 2001
From: Zach Fox
Date: Tue, 1 May 2018 09:54:23 -0700
Subject: [PATCH 43/47] Actually fix
---
interface/src/commerce/Wallet.cpp | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp
index 42c8b9973d..35e6ca1c92 100644
--- a/interface/src/commerce/Wallet.cpp
+++ b/interface/src/commerce/Wallet.cpp
@@ -615,11 +615,14 @@ void Wallet::updateImageProvider() {
securityImageProvider->setSecurityImage(_securityImage);
// inform tablet security image provider
- auto tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system");
+ TabletProxy* tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system");
if (tablet) {
- QQmlEngine* tabletEngine = tablet->getTabletSurface()->getSurfaceContext()->engine();
- securityImageProvider = reinterpret_cast(tabletEngine->imageProvider(SecurityImageProvider::PROVIDER_NAME));
- securityImageProvider->setSecurityImage(_securityImage);
+ OffscreenQmlSurface* tabletSurface = tablet->getTabletSurface();
+ if (tabletSurface) {
+ QQmlEngine* tabletEngine = tabletSurface->getSurfaceContext()->engine();
+ securityImageProvider = reinterpret_cast(tabletEngine->imageProvider(SecurityImageProvider::PROVIDER_NAME));
+ securityImageProvider->setSecurityImage(_securityImage);
+ }
}
}
From cad63ad1071e9a3eb7f742ac7543d9107c089682 Mon Sep 17 00:00:00 2001
From: Stephen Birarda
Date: Tue, 1 May 2018 14:15:12 -0700
Subject: [PATCH 44/47] 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 45/47] 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 46/47] 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 47/47] 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: