From 18db5f1724b180d7a518007f6144a7931fbdeab0 Mon Sep 17 00:00:00 2001 From: Faye Li Date: Wed, 15 Feb 2017 14:19:03 -0800 Subject: [PATCH 001/128] add a tablet button for photobooth --- .../utilities/render/photobooth/photobooth.js | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/scripts/developer/utilities/render/photobooth/photobooth.js b/scripts/developer/utilities/render/photobooth/photobooth.js index 3e86d83a98..19528f7173 100644 --- a/scripts/developer/utilities/render/photobooth/photobooth.js +++ b/scripts/developer/utilities/render/photobooth/photobooth.js @@ -1,9 +1,28 @@ +// +// photobooth.js +// scripts/developer/utilities/render/photobooth +// +// Created by Howard Stearns on 2 Nov 2016 +// Copyright 2016 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 +// +/* globals Tablet, Toolbars, Script, HMD, Controller, Menu */ (function () { var SNAPSHOT_DELAY = 500; // 500ms var PHOTOBOOTH_WINDOW_HTML_URL = Script.resolvePath("./html/photobooth.html"); var PHOTOBOOTH_SETUP_JSON_URL = Script.resolvePath("./photoboothSetup.json"); - var toolbar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); var MODEL_BOUNDING_BOX_DIMENSIONS = {x: 1.0174,y: 1.1925,z: 1.0165}; + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + icon: "icons/tablet-icons/snap-i.svg", + text: "PHOTOBOOTH" + }); + function onClicked() { + PhotoBooth.init(); + } + button.clicked.connect(onClicked); var PhotoBooth = {}; PhotoBooth.init = function () { @@ -96,7 +115,6 @@ }; var main = function () { - PhotoBooth.init(); var photoboothWindowListener = {}; photoboothWindowListener.onLoad = function (event) { @@ -172,6 +190,7 @@ function cleanup() { Camera.mode = "first person"; PhotoBooth.destroy(); + tablet.removeButton(button); } Script.scriptEnding.connect(cleanup); }()); \ No newline at end of file From 3149f02de6f30f32b0b654c12c2194c52f9e7fb3 Mon Sep 17 00:00:00 2001 From: Faye Li Date: Wed, 15 Feb 2017 14:25:57 -0800 Subject: [PATCH 002/128] display HTML in tablet instead of overlay web window --- .../developer/utilities/render/photobooth/photobooth.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/scripts/developer/utilities/render/photobooth/photobooth.js b/scripts/developer/utilities/render/photobooth/photobooth.js index 19528f7173..ab881ede4d 100644 --- a/scripts/developer/utilities/render/photobooth/photobooth.js +++ b/scripts/developer/utilities/render/photobooth/photobooth.js @@ -20,6 +20,7 @@ text: "PHOTOBOOTH" }); function onClicked() { + tablet.gotoWebScreen(PHOTOBOOTH_WINDOW_HTML_URL); PhotoBooth.init(); } button.clicked.connect(onClicked); @@ -169,14 +170,6 @@ print("clicked reload model button " + event.value); PhotoBooth.changeModel(event.value); }; - - var photoboothWindow = new OverlayWebWindow({ - title: 'Photo Booth', - source: PHOTOBOOTH_WINDOW_HTML_URL, - width: 450, - height: 450, - visible: true - }); photoboothWindow.webEventReceived.connect(function (data) { var event = JSON.parse(data); From f3fdb7c315e6451a6398657e046e4c3e01bfce84 Mon Sep 17 00:00:00 2001 From: Faye Li Date: Wed, 15 Feb 2017 15:02:10 -0800 Subject: [PATCH 003/128] added top bar title --- .../render/photobooth/html/photobooth.html | 81 ++++++++++++------- 1 file changed, 53 insertions(+), 28 deletions(-) diff --git a/scripts/developer/utilities/render/photobooth/html/photobooth.html b/scripts/developer/utilities/render/photobooth/html/photobooth.html index 8964a51f05..a7740330fb 100644 --- a/scripts/developer/utilities/render/photobooth/html/photobooth.html +++ b/scripts/developer/utilities/render/photobooth/html/photobooth.html @@ -2,7 +2,37 @@ Photo Booth + + - + + + +
+
Photobooth
+
+
+
+
+ + + +
+ +
+ +
+
+
+ - - - - -
-
Photobooth
-
-
-
-
- - - -
- -
- -
-
-
diff --git a/scripts/developer/utilities/render/photobooth/photobooth.js b/scripts/developer/utilities/render/photobooth/photoboothApp.js similarity index 95% rename from scripts/developer/utilities/render/photobooth/photobooth.js rename to scripts/developer/utilities/render/photobooth/photoboothApp.js index ab881ede4d..ca298d00de 100644 --- a/scripts/developer/utilities/render/photobooth/photobooth.js +++ b/scripts/developer/utilities/render/photobooth/photoboothApp.js @@ -19,11 +19,24 @@ icon: "icons/tablet-icons/snap-i.svg", text: "PHOTOBOOTH" }); + function onClicked() { tablet.gotoWebScreen(PHOTOBOOTH_WINDOW_HTML_URL); PhotoBooth.init(); } button.clicked.connect(onClicked); + tablet.webEventReceived.connect(onWebEventReceived); + + function onWebEventReceived(event) { + print("photobooth.js received a web event:" + event); + // Converts the event to a JavasScript Object + if (typeof event === "string") { + event = JSON.parse(event); + } + if (event.app === "photobooth") { + + } + } var PhotoBooth = {}; PhotoBooth.init = function () { @@ -170,20 +183,13 @@ print("clicked reload model button " + event.value); PhotoBooth.changeModel(event.value); }; - - photoboothWindow.webEventReceived.connect(function (data) { - var event = JSON.parse(data); - if (photoboothWindowListener[event.type]) { - photoboothWindowListener[event.type](event); - } - }); }; main(); function cleanup() { + tablet.removeButton(button); Camera.mode = "first person"; PhotoBooth.destroy(); - tablet.removeButton(button); } Script.scriptEnding.connect(cleanup); }()); \ No newline at end of file From 19bff20ebffdd457c8ed97814b2c29374cc0be67 Mon Sep 17 00:00:00 2001 From: Faye Li Date: Wed, 15 Feb 2017 16:19:56 -0800 Subject: [PATCH 005/128] event handling - can now load models --- .../render/photobooth/html/photobooth.html | 12 +++- .../render/photobooth/photoboothApp.js | 62 +++++++------------ 2 files changed, 32 insertions(+), 42 deletions(-) diff --git a/scripts/developer/utilities/render/photobooth/html/photobooth.html b/scripts/developer/utilities/render/photobooth/html/photobooth.html index 0250084a54..6165896bf0 100644 --- a/scripts/developer/utilities/render/photobooth/html/photobooth.html +++ b/scripts/developer/utilities/render/photobooth/html/photobooth.html @@ -93,13 +93,19 @@ elPictureButton.addEventListener('click', function() { emit("onClickPictureButton", {value: "faye"}); }); - - }); + } $(document).ready(function() { // Send a ready event to hifi emit("ready", null); - + // Send an event to hifi to trigger snapshot + $("#picture-button").click(function() { + emit("onClickPictureButton", null); + }); + // Send an event to hifi for loading the given model URL + $("#reload-model-button").click(function() { + emit("onClickReloadModelButton", {value: $("#model-url").val()}); + }); }); diff --git a/scripts/developer/utilities/render/photobooth/photoboothApp.js b/scripts/developer/utilities/render/photobooth/photoboothApp.js index ca298d00de..c32744fe63 100644 --- a/scripts/developer/utilities/render/photobooth/photoboothApp.js +++ b/scripts/developer/utilities/render/photobooth/photoboothApp.js @@ -34,7 +34,29 @@ event = JSON.parse(event); } if (event.app === "photobooth") { - + if (event.type === "onClickPictureButton") { + print("clicked picture button"); + // // hide HUD tool bar + // toolbar.writeProperty("visible", false); + // // hide Overlays (such as Running Scripts or other Dialog UI) + // Menu.setIsOptionChecked("Overlays", false); + // // hide mouse cursor + // Reticle.visible = false; + // // giving a delay here before snapshotting so that there is time to hide toolbar and other UIs + // // void WindowScriptingInterface::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio) + // Script.setTimeout(function () { + // Window.takeSnapshot(false, false, 1.91); + // // show hidden items after snapshot is taken + // toolbar.writeProperty("visible", true); + // Menu.setIsOptionChecked("Overlays", true); + // // unknown issue: somehow we don't need to reset cursor to visible in script and the mouse still returns after snapshot + // // Reticle.visible = true; + // }, SNAPSHOT_DELAY); + + } else if (event.type === "onClickReloadModelButton"){ + print("clicked reload model button " + event.data.value); + PhotoBooth.changeModel(event.data.value); + } } } @@ -131,12 +153,6 @@ var main = function () { var photoboothWindowListener = {}; - photoboothWindowListener.onLoad = function (event) { - print("loaded" + event.value); - if (!event.hasOwnProperty("value")){ - return; - } - }; photoboothWindowListener.onSelectCamera = function (event) { print("selected camera " + event.value); @@ -151,38 +167,6 @@ Camera.setCameraEntity(cameraID); } }; - - photoboothWindowListener.onSelectLightingPreset = function (event) { - print("selected lighting preset" + event.value); - if (!event.hasOwnProperty("value")){ - return; - } - }; - - photoboothWindowListener.onClickPictureButton = function (event) { - print("clicked picture button"); - // hide HUD tool bar - toolbar.writeProperty("visible", false); - // hide Overlays (such as Running Scripts or other Dialog UI) - Menu.setIsOptionChecked("Overlays", false); - // hide mouse cursor - Reticle.visible = false; - // giving a delay here before snapshotting so that there is time to hide toolbar and other UIs - // void WindowScriptingInterface::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio) - Script.setTimeout(function () { - Window.takeSnapshot(false, false, 1.91); - // show hidden items after snapshot is taken - toolbar.writeProperty("visible", true); - Menu.setIsOptionChecked("Overlays", true); - // unknown issue: somehow we don't need to reset cursor to visible in script and the mouse still returns after snapshot - // Reticle.visible = true; - }, SNAPSHOT_DELAY); - }; - - photoboothWindowListener.onClickReloadModelButton = function (event) { - print("clicked reload model button " + event.value); - PhotoBooth.changeModel(event.value); - }; }; main(); From 1e5090ad27f762663e93a2011441944a2c6a46e8 Mon Sep 17 00:00:00 2001 From: Faye Li Date: Wed, 15 Feb 2017 16:47:06 -0800 Subject: [PATCH 006/128] end of day commit --- .../render/photobooth/html/photobooth.html | 4 ++++ .../utilities/render/photobooth/photoboothApp.js | 14 +++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/scripts/developer/utilities/render/photobooth/html/photobooth.html b/scripts/developer/utilities/render/photobooth/html/photobooth.html index 6165896bf0..b23b65cfdd 100644 --- a/scripts/developer/utilities/render/photobooth/html/photobooth.html +++ b/scripts/developer/utilities/render/photobooth/html/photobooth.html @@ -98,6 +98,10 @@ $(document).ready(function() { // Send a ready event to hifi emit("ready", null); + $("#property-camera").on('change', function() { + console.log("ok"); + emit("onSelectCamera", {value: this.val()}); + }); // Send an event to hifi to trigger snapshot $("#picture-button").click(function() { emit("onClickPictureButton", null); diff --git a/scripts/developer/utilities/render/photobooth/photoboothApp.js b/scripts/developer/utilities/render/photobooth/photoboothApp.js index c32744fe63..0b58e51224 100644 --- a/scripts/developer/utilities/render/photobooth/photoboothApp.js +++ b/scripts/developer/utilities/render/photobooth/photoboothApp.js @@ -53,9 +53,21 @@ // // Reticle.visible = true; // }, SNAPSHOT_DELAY); - } else if (event.type === "onClickReloadModelButton"){ + } else if (event.type === "onClickReloadModelButton") { print("clicked reload model button " + event.data.value); PhotoBooth.changeModel(event.data.value); + } else if (event.type === "onSelectCamera") { + print("selected camera " + event.data.value); + if (!event.data.hasOwnProperty("value")){ + return; + } + if (event.data.value === "First Person Camera") { + Camera.mode = "first person"; + } else { + Camera.mode = "entity"; + var cameraID = PhotoBooth.cameraEntities[event.data.value]; + Camera.setCameraEntity(cameraID); + } } } } From 217ec46222babb371830b0365b0211a175ee0a5e Mon Sep 17 00:00:00 2001 From: Faye Li Date: Fri, 17 Feb 2017 10:54:40 -0800 Subject: [PATCH 007/128] able to switch camera and clean up code --- .../render/photobooth/html/photobooth.html | 31 +++---------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/scripts/developer/utilities/render/photobooth/html/photobooth.html b/scripts/developer/utilities/render/photobooth/html/photobooth.html index b23b65cfdd..e60cb2764d 100644 --- a/scripts/developer/utilities/render/photobooth/html/photobooth.html +++ b/scripts/developer/utilities/render/photobooth/html/photobooth.html @@ -69,38 +69,15 @@ "data": eventData }; EventBridge.emitWebEvent(JSON.stringify(eventObject)); - }; - - function loaded () { - openEventBridge(function () { - emit("onLoad", {value: "faye"}); - - var elModelURL = document.getElementById("model-url"); - var elReloadModelButton = document.getElementById("reload-model-button"); - var elCamera = document.getElementById("property-camera"); - //var elLightingPreset = document.getElementById("property-lighting-preset"); - var elPictureButton = document.getElementById("picture-button"); - - elReloadModelButton.addEventListener('click', function() { - emit("onClickReloadModelButton", {value: elModelURL.value}); - }); - elCamera.addEventListener('change', function() { - emit("onSelectCamera", {value: this.value}); - }); - // elLightingPreset.addEventListener('change', function() { - // emit("onSelectLightingPreset", {value: "faye"}); - // }); - elPictureButton.addEventListener('click', function() { - emit("onClickPictureButton", {value: "faye"}); - }); - }); } + $(document).ready(function() { // Send a ready event to hifi emit("ready", null); + // Send an event when camera selection changes $("#property-camera").on('change', function() { - console.log("ok"); - emit("onSelectCamera", {value: this.val()}); + console.log($("#property-camera").val()); + emit("onSelectCamera", {value: $("#property-camera").val()}); }); // Send an event to hifi to trigger snapshot $("#picture-button").click(function() { From 27b619030d304a00558ff733b55a844e435a3cbf Mon Sep 17 00:00:00 2001 From: Faye Li Date: Fri, 17 Feb 2017 11:32:53 -0800 Subject: [PATCH 008/128] ability to hide tablet and take picture --- .../render/photobooth/photoboothApp.js | 51 +++++++------------ 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/scripts/developer/utilities/render/photobooth/photoboothApp.js b/scripts/developer/utilities/render/photobooth/photoboothApp.js index 0b58e51224..8389516c7d 100644 --- a/scripts/developer/utilities/render/photobooth/photoboothApp.js +++ b/scripts/developer/utilities/render/photobooth/photoboothApp.js @@ -38,20 +38,23 @@ print("clicked picture button"); // // hide HUD tool bar // toolbar.writeProperty("visible", false); - // // hide Overlays (such as Running Scripts or other Dialog UI) - // Menu.setIsOptionChecked("Overlays", false); - // // hide mouse cursor - // Reticle.visible = false; - // // giving a delay here before snapshotting so that there is time to hide toolbar and other UIs - // // void WindowScriptingInterface::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio) - // Script.setTimeout(function () { - // Window.takeSnapshot(false, false, 1.91); - // // show hidden items after snapshot is taken - // toolbar.writeProperty("visible", true); - // Menu.setIsOptionChecked("Overlays", true); - // // unknown issue: somehow we don't need to reset cursor to visible in script and the mouse still returns after snapshot - // // Reticle.visible = true; - // }, SNAPSHOT_DELAY); + // hide tablet + HMD.closeTablet(); + // hide Overlays (such as Running Scripts or other Dialog UI) + Menu.setIsOptionChecked("Overlays", false); + // hide mouse cursor + Reticle.visible = false; + // // giving a delay here before snapshotting so that there is time to hide other UIs + // void WindowScriptingInterface::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio) + Script.setTimeout(function () { + Window.takeSnapshot(false, false, 1.91); + // show hidden items after snapshot is taken + // issue: currently there's no way to show tablet via a script command. user will have to manually open tablet again + // toolbar.writeProperty("visible", true); + Menu.setIsOptionChecked("Overlays", true); + // issue: somehow we don't need to reset cursor to visible in script and the mouse still returns after snapshot + // Reticle.visible = true; + }, SNAPSHOT_DELAY); } else if (event.type === "onClickReloadModelButton") { print("clicked reload model button " + event.data.value); @@ -161,26 +164,6 @@ }); Entities.deleteEntity(this.modelEntityID); }; - - var main = function () { - - var photoboothWindowListener = {}; - - photoboothWindowListener.onSelectCamera = function (event) { - print("selected camera " + event.value); - if (!event.hasOwnProperty("value")){ - return; - } - if (event.value === "First Person Camera") { - Camera.mode = "first person"; - } else { - Camera.mode = "entity"; - var cameraID = PhotoBooth.cameraEntities[event.value]; - Camera.setCameraEntity(cameraID); - } - }; - }; - main(); function cleanup() { tablet.removeButton(button); From 0e8d008b8c295ff6ccbd09f0bedaad9dff9883dc Mon Sep 17 00:00:00 2001 From: Faye Li Date: Fri, 17 Feb 2017 13:38:23 -0800 Subject: [PATCH 009/128] only have one instance of photobooth at a time --- .../render/photobooth/photoboothApp.js | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/scripts/developer/utilities/render/photobooth/photoboothApp.js b/scripts/developer/utilities/render/photobooth/photoboothApp.js index 8389516c7d..f6a968a97b 100644 --- a/scripts/developer/utilities/render/photobooth/photoboothApp.js +++ b/scripts/developer/utilities/render/photobooth/photoboothApp.js @@ -14,15 +14,21 @@ var PHOTOBOOTH_WINDOW_HTML_URL = Script.resolvePath("./html/photobooth.html"); var PHOTOBOOTH_SETUP_JSON_URL = Script.resolvePath("./photoboothSetup.json"); var MODEL_BOUNDING_BOX_DIMENSIONS = {x: 1.0174,y: 1.1925,z: 1.0165}; + var PhotoBooth = {}; + var photoboothCreated = false; var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: "icons/tablet-icons/snap-i.svg", - text: "PHOTOBOOTH" + text: "TOP MODEL" }); function onClicked() { tablet.gotoWebScreen(PHOTOBOOTH_WINDOW_HTML_URL); - PhotoBooth.init(); + // Initialise the photobooth if it wasn't created already + if (!photoboothCreated) { + PhotoBooth.init(); + photoboothCreated = true; + } } button.clicked.connect(onClicked); tablet.webEventReceived.connect(onWebEventReceived); @@ -38,24 +44,23 @@ print("clicked picture button"); // // hide HUD tool bar // toolbar.writeProperty("visible", false); - // hide tablet - HMD.closeTablet(); // hide Overlays (such as Running Scripts or other Dialog UI) Menu.setIsOptionChecked("Overlays", false); // hide mouse cursor Reticle.visible = false; + // hide tablet + HMD.closeTablet(); // // giving a delay here before snapshotting so that there is time to hide other UIs // void WindowScriptingInterface::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio) Script.setTimeout(function () { Window.takeSnapshot(false, false, 1.91); // show hidden items after snapshot is taken // issue: currently there's no way to show tablet via a script command. user will have to manually open tablet again - // toolbar.writeProperty("visible", true); - Menu.setIsOptionChecked("Overlays", true); // issue: somehow we don't need to reset cursor to visible in script and the mouse still returns after snapshot // Reticle.visible = true; + // toolbar.writeProperty("visible", true); + Menu.setIsOptionChecked("Overlays", true); }, SNAPSHOT_DELAY); - } else if (event.type === "onClickReloadModelButton") { print("clicked reload model button " + event.data.value); PhotoBooth.changeModel(event.data.value); @@ -75,7 +80,6 @@ } } - var PhotoBooth = {}; PhotoBooth.init = function () { var success = Clipboard.importEntities(PHOTOBOOTH_SETUP_JSON_URL); var frontFactor = 10; @@ -163,6 +167,7 @@ Entities.deleteEntity(id); }); Entities.deleteEntity(this.modelEntityID); + photoboothCreated = false; }; function cleanup() { From bd10b5d48fadaabaccfd4509db549345c6bbc54e Mon Sep 17 00:00:00 2001 From: Faye Li Date: Tue, 28 Feb 2017 11:34:07 -0800 Subject: [PATCH 010/128] fix camera drop down issue --- .../render/photobooth/html/photobooth.html | 53 +++++++++++++++---- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/scripts/developer/utilities/render/photobooth/html/photobooth.html b/scripts/developer/utilities/render/photobooth/html/photobooth.html index e60cb2764d..57d33f850a 100644 --- a/scripts/developer/utilities/render/photobooth/html/photobooth.html +++ b/scripts/developer/utilities/render/photobooth/html/photobooth.html @@ -3,6 +3,7 @@ Photo Booth + @@ -44,14 +68,20 @@ - + + diff --git a/scripts/developer/utilities/render/photobooth/photoboothApp.js b/scripts/developer/utilities/render/photobooth/photoboothApp.js index f6a968a97b..09c141b277 100644 --- a/scripts/developer/utilities/render/photobooth/photoboothApp.js +++ b/scripts/developer/utilities/render/photobooth/photoboothApp.js @@ -29,10 +29,12 @@ PhotoBooth.init(); photoboothCreated = true; } + } button.clicked.connect(onClicked); tablet.webEventReceived.connect(onWebEventReceived); + function onWebEventReceived(event) { print("photobooth.js received a web event:" + event); // Converts the event to a JavasScript Object @@ -76,6 +78,10 @@ var cameraID = PhotoBooth.cameraEntities[event.data.value]; Camera.setCameraEntity(cameraID); } + } else if (event.type === "onRotateSlider") { + var props = {}; + props.rotation = Quat.fromPitchYawRollDegrees(0, event.data.value, 0); + Entities.editEntity(PhotoBooth.modelEntityID, props); } } } From 067faad9cde341576543ea1be7e1daf597f94d11 Mon Sep 17 00:00:00 2001 From: Faye Li Date: Fri, 24 Mar 2017 10:22:08 -0700 Subject: [PATCH 013/128] Fix careless math mistake --- .../developer/utilities/render/photobooth/photoboothApp.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/developer/utilities/render/photobooth/photoboothApp.js b/scripts/developer/utilities/render/photobooth/photoboothApp.js index 09c141b277..4e1ed6a1ae 100644 --- a/scripts/developer/utilities/render/photobooth/photoboothApp.js +++ b/scripts/developer/utilities/render/photobooth/photoboothApp.js @@ -2,7 +2,7 @@ // photobooth.js // scripts/developer/utilities/render/photobooth // -// Created by Howard Stearns on 2 Nov 2016 +// Created by Faye Li on 2 Nov 2016 // Copyright 2016 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -93,7 +93,8 @@ var frontOffset = Vec3.multiply(frontUnitVec,frontFactor); var rightFactor = 3; var rightUnitVec = Vec3.normalize(Quat.getRight(MyAvatar.orientation)); - var spawnLocation = Vec3.sum(Vec3.sum(MyAvatar.position,frontOffset),rightFactor); + var rightOffset = Vec3.multiply(rightUnitVec,rightFactor); + var spawnLocation = Vec3.sum(Vec3.sum(MyAvatar.position,frontOffset),rightOffset); if (success) { this.pastedEntityIDs = Clipboard.pasteEntities(spawnLocation); this.processPastedEntities(); From ccd4fdb5407e90c3b3e764e6547d3dd86a2cb23d Mon Sep 17 00:00:00 2001 From: Faye Li Date: Fri, 24 Mar 2017 10:46:52 -0700 Subject: [PATCH 014/128] naming --- .../developer/utilities/render/photobooth/photoboothApp.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/developer/utilities/render/photobooth/photoboothApp.js b/scripts/developer/utilities/render/photobooth/photoboothApp.js index 4e1ed6a1ae..c193513b35 100644 --- a/scripts/developer/utilities/render/photobooth/photoboothApp.js +++ b/scripts/developer/utilities/render/photobooth/photoboothApp.js @@ -19,7 +19,7 @@ var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ icon: "icons/tablet-icons/snap-i.svg", - text: "TOP MODEL" + text: "PHOTOBOOTH" }); function onClicked() { @@ -89,7 +89,8 @@ PhotoBooth.init = function () { var success = Clipboard.importEntities(PHOTOBOOTH_SETUP_JSON_URL); var frontFactor = 10; - var frontUnitVec = Vec3.normalize(Quat.getFront(MyAvatar.orientation)); + // getForward is preffered as getFront function is deprecated + var frontUnitVec = (typeof Quat.getForward === "undefined") ? Vec3.normalize(Quat.getFront(MyAvatar.orientation)) : Vec3.normalize(Quat.getForward(MyAvatar.orientation)); var frontOffset = Vec3.multiply(frontUnitVec,frontFactor); var rightFactor = 3; var rightUnitVec = Vec3.normalize(Quat.getRight(MyAvatar.orientation)); From 405be471c32e8dbd8448329af0fcb5b070514c5a Mon Sep 17 00:00:00 2001 From: Faye Li Date: Fri, 24 Mar 2017 13:47:19 -0700 Subject: [PATCH 015/128] button state change --- .../render/photobooth/photoboothApp.js | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/scripts/developer/utilities/render/photobooth/photoboothApp.js b/scripts/developer/utilities/render/photobooth/photoboothApp.js index c193513b35..675db14be3 100644 --- a/scripts/developer/utilities/render/photobooth/photoboothApp.js +++ b/scripts/developer/utilities/render/photobooth/photoboothApp.js @@ -23,14 +23,25 @@ }); function onClicked() { - tablet.gotoWebScreen(PHOTOBOOTH_WINDOW_HTML_URL); - // Initialise the photobooth if it wasn't created already - if (!photoboothCreated) { + if (photoboothCreated) { + tablet.gotoHomeScreen(); + PhotoBooth.destroy(); + } else { + tablet.gotoWebScreen(PHOTOBOOTH_WINDOW_HTML_URL); PhotoBooth.init(); - photoboothCreated = true; } - } + + function onScreenChanged() { + if (photoboothCreated) { + tablet.gotoHomeScreen(); + PhotoBooth.destroy(); + button.editProperties({isActive: false}); + } else { + button.editProperties({isActive: true}); + } + } + tablet.screenChanged.connect(onScreenChanged); button.clicked.connect(onClicked); tablet.webEventReceived.connect(onWebEventReceived); @@ -87,6 +98,7 @@ } PhotoBooth.init = function () { + photoboothCreated = true; var success = Clipboard.importEntities(PHOTOBOOTH_SETUP_JSON_URL); var frontFactor = 10; // getForward is preffered as getFront function is deprecated From 2d0fac794e739150d91edd30d7428d15f8ea80fc Mon Sep 17 00:00:00 2001 From: trent Date: Tue, 28 Mar 2017 18:41:38 -0400 Subject: [PATCH 016/128] Committing this work-in-progress loader as an example of how not to do this. --- libraries/fbx/src/OBJReader.cpp | 198 +++++++++++++++++--------------- libraries/fbx/src/OBJReader.h | 2 +- 2 files changed, 104 insertions(+), 96 deletions(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index c1bb72dff8..6d23be0a9f 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -302,9 +302,10 @@ QNetworkReply* OBJReader::request(QUrl& url, bool isTest) { } -bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, FBXGeometry& geometry, float& scaleGuess) { +bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, FBXGeometry& geometry, float& scaleGuess, int index) { FaceGroup faces; - FBXMesh& mesh = geometry.meshes[0]; + geometry.meshes.append(FBXMesh()); + FBXMesh& mesh = geometry.meshes.last(); mesh.parts.append(FBXMeshPart()); FBXMeshPart& meshPart = mesh.parts.last(); bool sawG = false; @@ -433,111 +434,118 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, _url = url; geometry.meshExtents.reset(); - geometry.meshes.append(FBXMesh()); +// geometry.meshes.append(FBXMesh()); try { // call parseOBJGroup as long as it's returning true. Each successful call will // add a new meshPart to the geometry's single mesh. - while (parseOBJGroup(tokenizer, mapping, geometry, scaleGuess)) {} + int i = 0; + while (parseOBJGroup(tokenizer, mapping, geometry, scaleGuess, i)) { + ++i; + } - FBXMesh& mesh = geometry.meshes[0]; - mesh.meshIndex = 0; + geometry.joints.resize(1); + geometry.joints[0].isFree = false; + geometry.joints[0].parentIndex = -1; + geometry.joints[0].distanceToParent = 0; + geometry.joints[0].translation = glm::vec3(0, 0, 0); + geometry.joints[0].rotationMin = glm::vec3(0, 0, 0); + geometry.joints[0].rotationMax = glm::vec3(0, 0, 0); + geometry.joints[0].name = "OBJ"; + geometry.joints[0].isSkeletonJoint = true; - geometry.joints.resize(1); - geometry.joints[0].isFree = false; - geometry.joints[0].parentIndex = -1; - geometry.joints[0].distanceToParent = 0; - geometry.joints[0].translation = glm::vec3(0, 0, 0); - geometry.joints[0].rotationMin = glm::vec3(0, 0, 0); - geometry.joints[0].rotationMax = glm::vec3(0, 0, 0); - geometry.joints[0].name = "OBJ"; - geometry.joints[0].isSkeletonJoint = true; + geometry.jointIndices["x"] = 1; - geometry.jointIndices["x"] = 1; + for (int i = 0; i < geometry.meshes.count(); i++) { + FBXMesh& mesh = geometry.meshes[i]; + mesh.meshIndex = i; - FBXCluster cluster; - cluster.jointIndex = 0; - cluster.inverseBindMatrix = glm::mat4(1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - mesh.clusters.append(cluster); + FBXCluster cluster; + cluster.jointIndex = 0; + cluster.inverseBindMatrix = glm::mat4(1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1); + mesh.clusters.append(cluster); - for (int i = 0, meshPartCount = 0; i < mesh.parts.count(); i++, meshPartCount++) { - FBXMeshPart& meshPart = mesh.parts[i]; - FaceGroup faceGroup = faceGroups[meshPartCount]; - bool specifiesUV = false; - foreach(OBJFace face, faceGroup) { - glm::vec3 v0 = checked_at(vertices, face.vertexIndices[0]); - glm::vec3 v1 = checked_at(vertices, face.vertexIndices[1]); - glm::vec3 v2 = checked_at(vertices, face.vertexIndices[2]); - meshPart.triangleIndices.append(mesh.vertices.count()); // not face.vertexIndices into vertices - mesh.vertices << v0; - meshPart.triangleIndices.append(mesh.vertices.count()); - mesh.vertices << v1; - meshPart.triangleIndices.append(mesh.vertices.count()); - mesh.vertices << v2; + for (int meshPartCount = 0; meshPartCount < mesh.parts.count( ); ++meshPartCount) { + FBXMeshPart& meshPart = mesh.parts[meshPartCount]; + FaceGroup faceGroup = faceGroups[meshPartCount]; + bool specifiesUV = false; - glm::vec3 n0, n1, n2; - if (face.normalIndices.count()) { - n0 = checked_at(normals, face.normalIndices[0]); - n1 = checked_at(normals, face.normalIndices[1]); - n2 = checked_at(normals, face.normalIndices[2]); - } else { // generate normals from triangle plane if not provided - n0 = n1 = n2 = glm::cross(v1 - v0, v2 - v0); - } - mesh.normals << n0 << n1 << n2; - if (face.textureUVIndices.count()) { - specifiesUV = true; - mesh.texCoords << - checked_at(textureUVs, face.textureUVIndices[0]) << - checked_at(textureUVs, face.textureUVIndices[1]) << - checked_at(textureUVs, face.textureUVIndices[2]); - } else { - glm::vec2 corner(0.0f, 1.0f); - mesh.texCoords << corner << corner << corner; - } - } - // All the faces in the same group will have the same name and material. - OBJFace leadFace = faceGroup[0]; - QString groupMaterialName = leadFace.materialName; - if (groupMaterialName.isEmpty() && specifiesUV) { - #ifdef WANT_DEBUG - qCDebug(modelformat) << "OBJ Reader WARNING: " << url - << " needs a texture that isn't specified. Using default mechanism."; - #endif - groupMaterialName = SMART_DEFAULT_MATERIAL_NAME; - } - if (!groupMaterialName.isEmpty()) { - OBJMaterial& material = materials[groupMaterialName]; - if (specifiesUV) { - material.userSpecifiesUV = true; // Note might not be true in a later usage. - } - if (specifiesUV || (0 != groupMaterialName.compare("none", Qt::CaseInsensitive))) { - // Blender has a convention that a material named "None" isn't really used (or defined). - material.used = true; - needsMaterialLibrary = groupMaterialName != SMART_DEFAULT_MATERIAL_NAME; - } - materials[groupMaterialName] = material; - meshPart.materialID = groupMaterialName; - } + foreach(OBJFace face, faceGroup) { + glm::vec3 v0 = checked_at(vertices, face.vertexIndices[0]); + glm::vec3 v1 = checked_at(vertices, face.vertexIndices[1]); + glm::vec3 v2 = checked_at(vertices, face.vertexIndices[2]); + meshPart.triangleIndices.append(mesh.vertices.count()); // not face.vertexIndices into vertices + mesh.vertices << v0; + meshPart.triangleIndices.append(mesh.vertices.count()); + mesh.vertices << v1; + meshPart.triangleIndices.append(mesh.vertices.count()); + mesh.vertices << v2; + glm::vec3 n0, n1, n2; + if (face.normalIndices.count()) { + n0 = checked_at(normals, face.normalIndices[0]); + n1 = checked_at(normals, face.normalIndices[1]); + n2 = checked_at(normals, face.normalIndices[2]); + } + else { // generate normals from triangle plane if not provided + n0 = n1 = n2 = glm::cross(v1 - v0, v2 - v0); + } + mesh.normals << n0 << n1 << n2; + if (face.textureUVIndices.count()) { + specifiesUV = true; + mesh.texCoords << + checked_at(textureUVs, face.textureUVIndices[0]) << + checked_at(textureUVs, face.textureUVIndices[1]) << + checked_at(textureUVs, face.textureUVIndices[2]); + } + else { + glm::vec2 corner(0.0f, 1.0f); + mesh.texCoords << corner << corner << corner; + } + } + // All the faces in the same group will have the same name and material. + OBJFace leadFace = faceGroup[0]; + QString groupMaterialName = leadFace.materialName; + if (groupMaterialName.isEmpty() && specifiesUV) { +#ifdef WANT_DEBUG + qCDebug(modelformat) << "OBJ Reader WARNING: " << url + << " needs a texture that isn't specified. Using default mechanism."; +#endif + groupMaterialName = SMART_DEFAULT_MATERIAL_NAME; + } + if (!groupMaterialName.isEmpty()) { + OBJMaterial& material = materials[groupMaterialName]; + if (specifiesUV) { + material.userSpecifiesUV = true; // Note might not be true in a later usage. + } + if (specifiesUV || (0 != groupMaterialName.compare("none", Qt::CaseInsensitive))) { + // Blender has a convention that a material named "None" isn't really used (or defined). + material.used = true; + needsMaterialLibrary = groupMaterialName != SMART_DEFAULT_MATERIAL_NAME; + } + materials[groupMaterialName] = material; + meshPart.materialID = groupMaterialName; + } + } + + // if we got a hint about units, scale all the points + if (scaleGuess != 1.0f) { + for (int i = 0; i < mesh.vertices.size(); i++) { + mesh.vertices[i] *= scaleGuess; + } + } + + mesh.meshExtents.reset(); + foreach(const glm::vec3& vertex, mesh.vertices) { + mesh.meshExtents.addPoint(vertex); + geometry.meshExtents.addPoint(vertex); + } + + FBXReader::buildModelMesh(mesh, url.toString()); } - - // if we got a hint about units, scale all the points - if (scaleGuess != 1.0f) { - for (int i = 0; i < mesh.vertices.size(); i++) { - mesh.vertices[i] *= scaleGuess; - } - } - - mesh.meshExtents.reset(); - foreach (const glm::vec3& vertex, mesh.vertices) { - mesh.meshExtents.addPoint(vertex); - geometry.meshExtents.addPoint(vertex); - } - - FBXReader::buildModelMesh(mesh, url.toString()); // fbxDebugDump(geometry); } catch(const std::exception& e) { qCDebug(modelformat) << "OBJ reader fail: " << e.what(); diff --git a/libraries/fbx/src/OBJReader.h b/libraries/fbx/src/OBJReader.h index b4a48c570e..e75b1900e9 100644 --- a/libraries/fbx/src/OBJReader.h +++ b/libraries/fbx/src/OBJReader.h @@ -79,7 +79,7 @@ private: QUrl _url; QHash librariesSeen; - bool parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, FBXGeometry& geometry, float& scaleGuess); + bool parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, FBXGeometry& geometry, float& scaleGuess, int index); void parseMaterialLibrary(QIODevice* device); bool isValidTexture(const QByteArray &filename); // true if the file exists. TODO?: check content-type header and that it is a supported format. }; From 98221936448cdcf757576acbb257049eca826331 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Wed, 29 Mar 2017 14:41:18 +0200 Subject: [PATCH 017/128] Set z-order of comboboxes to make sure lowest will no overlap higher ones --- .../tablet/tabletWindows/preferences/Section.qml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/tabletWindows/preferences/Section.qml b/interface/resources/qml/hifi/tablet/tabletWindows/preferences/Section.qml index 3d6dfa10ce..9dd0956000 100644 --- a/interface/resources/qml/hifi/tablet/tabletWindows/preferences/Section.qml +++ b/interface/resources/qml/hifi/tablet/tabletWindows/preferences/Section.qml @@ -89,14 +89,17 @@ Preference { if (categoryPreferences) { console.log("Category " + root.name + " with " + categoryPreferences.length + " preferences"); for (var j = 0; j < categoryPreferences.length; ++j) { - buildPreference(categoryPreferences[j]); + //provide component position within column + //lowest numbers on top + buildPreference(categoryPreferences[j], j); } } } - function buildPreference(preference) { + function buildPreference(preference, itemNum) { console.log("\tPreference type " + preference.type + " name " + preference.name) var builder; + var zpos; switch (preference.type) { case Preference.Editable: checkBoxCount = 0; @@ -136,11 +139,14 @@ Preference { case Preference.ComboBox: checkBoxCount = 0; builder = comboBoxBuilder; + //make sure that combo boxes sitting higher will have higher z coordinate + //to be not overlapped when drop down is active + zpos = root.z + 1000 - itemNum break; }; if (builder) { - preferences.push(builder.createObject(contentContainer, { preference: preference, isFirstCheckBox: (checkBoxCount === 1) })); + preferences.push(builder.createObject(contentContainer, { preference: preference, isFirstCheckBox: (checkBoxCount === 1) , z: zpos})); } } } From d47c040768f0faaaf7590515eb8a18e0e31d7771 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 29 Mar 2017 18:15:29 -0700 Subject: [PATCH 018/128] Vive: Expose all 16 tracked poses to the controller system. This is in preparation for the Vive hockey puck trackers... --- .../src/controllers/StandardControls.h | 16 ++ plugins/openvr/src/ViveControllerManager.cpp | 164 +++++------------- plugins/openvr/src/ViveControllerManager.h | 3 +- 3 files changed, 64 insertions(+), 119 deletions(-) diff --git a/libraries/controllers/src/controllers/StandardControls.h b/libraries/controllers/src/controllers/StandardControls.h index c21d8a2f6e..f521ab81cf 100644 --- a/libraries/controllers/src/controllers/StandardControls.h +++ b/libraries/controllers/src/controllers/StandardControls.h @@ -158,6 +158,22 @@ namespace controller { LEFT_HAND_PINKY2, LEFT_HAND_PINKY3, LEFT_HAND_PINKY4, + TRACKED_OBJECT_00, + TRACKED_OBJECT_01, + TRACKED_OBJECT_02, + TRACKED_OBJECT_03, + TRACKED_OBJECT_04, + TRACKED_OBJECT_05, + TRACKED_OBJECT_06, + TRACKED_OBJECT_07, + TRACKED_OBJECT_08, + TRACKED_OBJECT_09, + TRACKED_OBJECT_10, + TRACKED_OBJECT_11, + TRACKED_OBJECT_12, + TRACKED_OBJECT_13, + TRACKED_OBJECT_14, + TRACKED_OBJECT_15, NUM_STANDARD_POSES }; diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 2e930c0fdc..8cedee2d8f 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -63,59 +63,6 @@ bool ViveControllerManager::activate() { enableOpenVrKeyboard(_container); - // OpenVR provides 3d mesh representations of the controllers - // Disabled controller rendering code - /* - auto renderModels = vr::VRRenderModels(); - - vr::RenderModel_t model; - if (!_system->LoadRenderModel(CONTROLLER_MODEL_STRING, &model)) { - qDebug() << QString("Unable to load render model %1\n").arg(CONTROLLER_MODEL_STRING); - } else { - model::Mesh* mesh = new model::Mesh(); - model::MeshPointer meshPtr(mesh); - _modelGeometry.setMesh(meshPtr); - - auto indexBuffer = new gpu::Buffer(3 * model.unTriangleCount * sizeof(uint16_t), (gpu::Byte*)model.rIndexData); - auto indexBufferPtr = gpu::BufferPointer(indexBuffer); - auto indexBufferView = new gpu::BufferView(indexBufferPtr, gpu::Element(gpu::SCALAR, gpu::UINT16, gpu::RAW)); - mesh->setIndexBuffer(*indexBufferView); - - auto vertexBuffer = new gpu::Buffer(model.unVertexCount * sizeof(vr::RenderModel_Vertex_t), - (gpu::Byte*)model.rVertexData); - auto vertexBufferPtr = gpu::BufferPointer(vertexBuffer); - auto vertexBufferView = new gpu::BufferView(vertexBufferPtr, - 0, - vertexBufferPtr->getSize() - sizeof(float) * 3, - sizeof(vr::RenderModel_Vertex_t), - gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW)); - mesh->setVertexBuffer(*vertexBufferView); - mesh->addAttribute(gpu::Stream::NORMAL, - gpu::BufferView(vertexBufferPtr, - sizeof(float) * 3, - vertexBufferPtr->getSize() - sizeof(float) * 3, - sizeof(vr::RenderModel_Vertex_t), - gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW))); - //mesh->addAttribute(gpu::Stream::TEXCOORD, - // gpu::BufferView(vertexBufferPtr, - // 2 * sizeof(float) * 3, - // vertexBufferPtr->getSize() - sizeof(float) * 2, - // sizeof(vr::RenderModel_Vertex_t), - // gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::RAW))); - - gpu::Element formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); - gpu::Element formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); - _texture = gpu::TexturePointer( - gpu::Texture::create2D(formatGPU, model.diffuseTexture.unWidth, model.diffuseTexture.unHeight, - gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); - _texture->assignStoredMip(0, formatMip, model.diffuseTexture.unWidth * model.diffuseTexture.unHeight * 4 * sizeof(uint8_t), model.diffuseTexture.rubTextureMapData); - _texture->autoGenerateMips(-1); - - _modelLoaded = true; - _renderControllers = true; - } - */ - // register with UserInputMapper auto userInputMapper = DependencyManager::get(); userInputMapper->registerDevice(_inputDevice); @@ -145,70 +92,6 @@ void ViveControllerManager::deactivate() { _registeredWithInputMapper = false; } -void ViveControllerManager::updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges) { - PerformanceTimer perfTimer("ViveControllerManager::updateRendering"); - - /* - if (_modelLoaded) { - //auto controllerPayload = new render::Payload(this); - //auto controllerPayloadPointer = ViveControllerManager::PayloadPointer(controllerPayload); - //if (_leftHandRenderID == 0) { - // _leftHandRenderID = scene->allocateID(); - // pendingChanges.resetItem(_leftHandRenderID, controllerPayloadPointer); - //} - //pendingChanges.updateItem(_leftHandRenderID, ); - - - controller::Pose leftHand = _inputDevice->_poseStateMap[controller::StandardPoseChannel::LEFT_HAND]; - controller::Pose rightHand = _inputDevice->_poseStateMap[controller::StandardPoseChannel::RIGHT_HAND]; - - gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { - auto geometryCache = DependencyManager::get(); - geometryCache->useSimpleDrawPipeline(batch); - DependencyManager::get()->bindSimpleProgram(batch, true); - - auto mesh = _modelGeometry.getMesh(); - batch.setInputFormat(mesh->getVertexFormat()); - //batch._glBindTexture(GL_TEXTURE_2D, _uexture); - - if (leftHand.isValid()) { - renderHand(leftHand, batch, 1); - } - if (rightHand.isValid()) { - renderHand(rightHand, batch, -1); - } - }); - } - */ -} - -void ViveControllerManager::renderHand(const controller::Pose& pose, gpu::Batch& batch, int sign) { - /* - auto userInputMapper = DependencyManager::get(); - Transform transform(userInputMapper->getSensorToWorldMat()); - transform.postTranslate(pose.getTranslation() + pose.getRotation() * glm::vec3(0, 0, CONTROLLER_LENGTH_OFFSET)); - - glm::quat rotation = pose.getRotation() * glm::angleAxis(PI, glm::vec3(1.0f, 0.0f, 0.0f)) * glm::angleAxis(sign * PI_OVER_TWO, glm::vec3(0.0f, 0.0f, 1.0f)); - transform.postRotate(rotation); - - batch.setModelTransform(transform); - - auto mesh = _modelGeometry.getMesh(); - batch.setInputBuffer(gpu::Stream::POSITION, mesh->getVertexBuffer()); - batch.setInputBuffer(gpu::Stream::NORMAL, - mesh->getVertexBuffer()._buffer, - sizeof(float) * 3, - mesh->getVertexBuffer()._stride); - //batch.setInputBuffer(gpu::Stream::TEXCOORD, - // mesh->getVertexBuffer()._buffer, - // 2 * 3 * sizeof(float), - // mesh->getVertexBuffer()._stride); - batch.setIndexBuffer(gpu::UINT16, mesh->getIndexBuffer()._buffer, 0); - batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0); - */ -} - - void ViveControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { if (!_system) { @@ -257,6 +140,11 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle handleHandController(deltaTime, leftHandDeviceIndex, inputCalibrationData, true); handleHandController(deltaTime, rightHandDeviceIndex, inputCalibrationData, false); + // collect raw poses + for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) { + handleTrackedObject(i, inputCalibrationData); + } + // handle haptics { Locker locker(_lock); @@ -278,6 +166,30 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle _trackedControllers = numTrackedControllers; } +void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData) { + + uint32_t poseIndex = controller::TRACKED_OBJECT_00 + deviceIndex; + + if (_system->IsTrackedDeviceConnected(deviceIndex) && + _nextSimPoseData.vrPoses[deviceIndex].bPoseIsValid && + poseIndex <= controller::TRACKED_OBJECT_15) { + + // process pose + const mat4& mat = _nextSimPoseData.poses[deviceIndex]; + const vec3 linearVelocity = _nextSimPoseData.linearVelocities[deviceIndex]; + const vec3 angularVelocity = _nextSimPoseData.angularVelocities[deviceIndex]; + + controller::Pose pose(extractTranslation(mat), glmExtractRotation(mat), linearVelocity, angularVelocity); + + // transform into avatar frame + glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; + _poseStateMap[poseIndex] = pose.transform(controllerToAvatar); + } else { + controller::Pose invalidPose; + _poseStateMap[poseIndex] = invalidPose; + } +} + void ViveControllerManager::InputDevice::handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand) { if (_system->IsTrackedDeviceConnected(deviceIndex) && @@ -492,6 +404,24 @@ controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableI makePair(LEFT_HAND, "LeftHand"), makePair(RIGHT_HAND, "RightHand"), + // 16 tracked poses + makePair(TRACKED_OBJECT_00, "TrackedObject00"), + makePair(TRACKED_OBJECT_01, "TrackedObject01"), + makePair(TRACKED_OBJECT_02, "TrackedObject02"), + makePair(TRACKED_OBJECT_03, "TrackedObject03"), + makePair(TRACKED_OBJECT_04, "TrackedObject04"), + makePair(TRACKED_OBJECT_05, "TrackedObject05"), + makePair(TRACKED_OBJECT_06, "TrackedObject06"), + makePair(TRACKED_OBJECT_07, "TrackedObject07"), + makePair(TRACKED_OBJECT_08, "TrackedObject08"), + makePair(TRACKED_OBJECT_09, "TrackedObject09"), + makePair(TRACKED_OBJECT_10, "TrackedObject10"), + makePair(TRACKED_OBJECT_11, "TrackedObject11"), + makePair(TRACKED_OBJECT_12, "TrackedObject12"), + makePair(TRACKED_OBJECT_13, "TrackedObject13"), + makePair(TRACKED_OBJECT_14, "TrackedObject14"), + makePair(TRACKED_OBJECT_15, "TrackedObject15"), + // app button above trackpad. Input::NamedPair(Input(_deviceID, LEFT_APP_MENU, ChannelType::BUTTON), "LeftApplicationMenu"), Input::NamedPair(Input(_deviceID, RIGHT_APP_MENU, ChannelType::BUTTON), "RightApplicationMenu"), diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 3fb166c842..dc1883d5e4 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -43,8 +43,6 @@ public: void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); } void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; - void updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges); - void setRenderControllers(bool renderControllers) { _renderControllers = renderControllers; } private: @@ -62,6 +60,7 @@ private: void hapticsHelper(float deltaTime, bool leftHand); void handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand); + void handleTrackedObject(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData); void handleButtonEvent(float deltaTime, uint32_t button, bool pressed, bool touched, bool isLeftHand); void handleAxisEvent(float deltaTime, uint32_t axis, float x, float y, bool isLeftHand); void handlePoseEvent(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, const mat4& mat, From 0e63f97f7747f7d0eab4d6c551ff14feefd00f3b Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 29 Mar 2017 18:17:32 -0700 Subject: [PATCH 019/128] Test script that displays tracking data from Vive.TrackedObjects --- scripts/developer/tests/viveTrackedObjects.js | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 scripts/developer/tests/viveTrackedObjects.js diff --git a/scripts/developer/tests/viveTrackedObjects.js b/scripts/developer/tests/viveTrackedObjects.js new file mode 100644 index 0000000000..78911538e4 --- /dev/null +++ b/scripts/developer/tests/viveTrackedObjects.js @@ -0,0 +1,36 @@ + +var TRACKED_OBJECT_POSES = [ + "TrackedObject00", "TrackedObject01", "TrackedObject02", "TrackedObject03", + "TrackedObject04", "TrackedObject05", "TrackedObject06", "TrackedObject07", + "TrackedObject08", "TrackedObject09", "TrackedObject10", "TrackedObject11", + "TrackedObject12", "TrackedObject13", "TrackedObject14", "TrackedObject15" +]; + +function init() { + Script.update.connect(update); +} + +function shutdown() { + Script.update.disconnect(update); + + TRACKED_OBJECT_POSES.forEach(function (key) { + DebugDraw.removeMyAvatarMarker(key); + }); +} + +var WHITE = {x: 1, y: 1, z: 1, w: 1}; + +function update(dt) { + if (Controller.Hardware.Vive) { + TRACKED_OBJECT_POSES.forEach(function (key) { + var pose = Controller.getPoseValue(Controller.Hardware.Vive[key]); + if (pose.valid) { + DebugDraw.addMyAvatarMarker(key, pose.rotation, pose.translation, WHITE); + } else { + DebugDraw.removeMyAvatarMarker(key); + } + }); + } +} + +init(); From 5bf3da9a7f438b74c2acaf6b65acd41cb39e12f6 Mon Sep 17 00:00:00 2001 From: trent Date: Thu, 30 Mar 2017 16:14:42 -0400 Subject: [PATCH 020/128] Restoring hifi version of the OBJ files to get rid of my debug nonsense. --- libraries/fbx/src/OBJReader.cpp | 198 +++++++++++++++----------------- libraries/fbx/src/OBJReader.h | 2 +- 2 files changed, 96 insertions(+), 104 deletions(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 6d23be0a9f..c1bb72dff8 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -302,10 +302,9 @@ QNetworkReply* OBJReader::request(QUrl& url, bool isTest) { } -bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, FBXGeometry& geometry, float& scaleGuess, int index) { +bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, FBXGeometry& geometry, float& scaleGuess) { FaceGroup faces; - geometry.meshes.append(FBXMesh()); - FBXMesh& mesh = geometry.meshes.last(); + FBXMesh& mesh = geometry.meshes[0]; mesh.parts.append(FBXMeshPart()); FBXMeshPart& meshPart = mesh.parts.last(); bool sawG = false; @@ -434,118 +433,111 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, _url = url; geometry.meshExtents.reset(); -// geometry.meshes.append(FBXMesh()); + geometry.meshes.append(FBXMesh()); try { // call parseOBJGroup as long as it's returning true. Each successful call will // add a new meshPart to the geometry's single mesh. - int i = 0; - while (parseOBJGroup(tokenizer, mapping, geometry, scaleGuess, i)) { - ++i; - } + while (parseOBJGroup(tokenizer, mapping, geometry, scaleGuess)) {} - geometry.joints.resize(1); - geometry.joints[0].isFree = false; - geometry.joints[0].parentIndex = -1; - geometry.joints[0].distanceToParent = 0; - geometry.joints[0].translation = glm::vec3(0, 0, 0); - geometry.joints[0].rotationMin = glm::vec3(0, 0, 0); - geometry.joints[0].rotationMax = glm::vec3(0, 0, 0); - geometry.joints[0].name = "OBJ"; - geometry.joints[0].isSkeletonJoint = true; + FBXMesh& mesh = geometry.meshes[0]; + mesh.meshIndex = 0; - geometry.jointIndices["x"] = 1; + geometry.joints.resize(1); + geometry.joints[0].isFree = false; + geometry.joints[0].parentIndex = -1; + geometry.joints[0].distanceToParent = 0; + geometry.joints[0].translation = glm::vec3(0, 0, 0); + geometry.joints[0].rotationMin = glm::vec3(0, 0, 0); + geometry.joints[0].rotationMax = glm::vec3(0, 0, 0); + geometry.joints[0].name = "OBJ"; + geometry.joints[0].isSkeletonJoint = true; - for (int i = 0; i < geometry.meshes.count(); i++) { - FBXMesh& mesh = geometry.meshes[i]; - mesh.meshIndex = i; + geometry.jointIndices["x"] = 1; - FBXCluster cluster; - cluster.jointIndex = 0; - cluster.inverseBindMatrix = glm::mat4(1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - mesh.clusters.append(cluster); + FBXCluster cluster; + cluster.jointIndex = 0; + cluster.inverseBindMatrix = glm::mat4(1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1); + mesh.clusters.append(cluster); - for (int meshPartCount = 0; meshPartCount < mesh.parts.count( ); ++meshPartCount) { - FBXMeshPart& meshPart = mesh.parts[meshPartCount]; - FaceGroup faceGroup = faceGroups[meshPartCount]; - bool specifiesUV = false; + for (int i = 0, meshPartCount = 0; i < mesh.parts.count(); i++, meshPartCount++) { + FBXMeshPart& meshPart = mesh.parts[i]; + FaceGroup faceGroup = faceGroups[meshPartCount]; + bool specifiesUV = false; + foreach(OBJFace face, faceGroup) { + glm::vec3 v0 = checked_at(vertices, face.vertexIndices[0]); + glm::vec3 v1 = checked_at(vertices, face.vertexIndices[1]); + glm::vec3 v2 = checked_at(vertices, face.vertexIndices[2]); + meshPart.triangleIndices.append(mesh.vertices.count()); // not face.vertexIndices into vertices + mesh.vertices << v0; + meshPart.triangleIndices.append(mesh.vertices.count()); + mesh.vertices << v1; + meshPart.triangleIndices.append(mesh.vertices.count()); + mesh.vertices << v2; - foreach(OBJFace face, faceGroup) { - glm::vec3 v0 = checked_at(vertices, face.vertexIndices[0]); - glm::vec3 v1 = checked_at(vertices, face.vertexIndices[1]); - glm::vec3 v2 = checked_at(vertices, face.vertexIndices[2]); - meshPart.triangleIndices.append(mesh.vertices.count()); // not face.vertexIndices into vertices - mesh.vertices << v0; - meshPart.triangleIndices.append(mesh.vertices.count()); - mesh.vertices << v1; - meshPart.triangleIndices.append(mesh.vertices.count()); - mesh.vertices << v2; + glm::vec3 n0, n1, n2; + if (face.normalIndices.count()) { + n0 = checked_at(normals, face.normalIndices[0]); + n1 = checked_at(normals, face.normalIndices[1]); + n2 = checked_at(normals, face.normalIndices[2]); + } else { // generate normals from triangle plane if not provided + n0 = n1 = n2 = glm::cross(v1 - v0, v2 - v0); + } + mesh.normals << n0 << n1 << n2; + if (face.textureUVIndices.count()) { + specifiesUV = true; + mesh.texCoords << + checked_at(textureUVs, face.textureUVIndices[0]) << + checked_at(textureUVs, face.textureUVIndices[1]) << + checked_at(textureUVs, face.textureUVIndices[2]); + } else { + glm::vec2 corner(0.0f, 1.0f); + mesh.texCoords << corner << corner << corner; + } + } + // All the faces in the same group will have the same name and material. + OBJFace leadFace = faceGroup[0]; + QString groupMaterialName = leadFace.materialName; + if (groupMaterialName.isEmpty() && specifiesUV) { + #ifdef WANT_DEBUG + qCDebug(modelformat) << "OBJ Reader WARNING: " << url + << " needs a texture that isn't specified. Using default mechanism."; + #endif + groupMaterialName = SMART_DEFAULT_MATERIAL_NAME; + } + if (!groupMaterialName.isEmpty()) { + OBJMaterial& material = materials[groupMaterialName]; + if (specifiesUV) { + material.userSpecifiesUV = true; // Note might not be true in a later usage. + } + if (specifiesUV || (0 != groupMaterialName.compare("none", Qt::CaseInsensitive))) { + // Blender has a convention that a material named "None" isn't really used (or defined). + material.used = true; + needsMaterialLibrary = groupMaterialName != SMART_DEFAULT_MATERIAL_NAME; + } + materials[groupMaterialName] = material; + meshPart.materialID = groupMaterialName; + } - glm::vec3 n0, n1, n2; - if (face.normalIndices.count()) { - n0 = checked_at(normals, face.normalIndices[0]); - n1 = checked_at(normals, face.normalIndices[1]); - n2 = checked_at(normals, face.normalIndices[2]); - } - else { // generate normals from triangle plane if not provided - n0 = n1 = n2 = glm::cross(v1 - v0, v2 - v0); - } - mesh.normals << n0 << n1 << n2; - if (face.textureUVIndices.count()) { - specifiesUV = true; - mesh.texCoords << - checked_at(textureUVs, face.textureUVIndices[0]) << - checked_at(textureUVs, face.textureUVIndices[1]) << - checked_at(textureUVs, face.textureUVIndices[2]); - } - else { - glm::vec2 corner(0.0f, 1.0f); - mesh.texCoords << corner << corner << corner; - } - } - // All the faces in the same group will have the same name and material. - OBJFace leadFace = faceGroup[0]; - QString groupMaterialName = leadFace.materialName; - if (groupMaterialName.isEmpty() && specifiesUV) { -#ifdef WANT_DEBUG - qCDebug(modelformat) << "OBJ Reader WARNING: " << url - << " needs a texture that isn't specified. Using default mechanism."; -#endif - groupMaterialName = SMART_DEFAULT_MATERIAL_NAME; - } - if (!groupMaterialName.isEmpty()) { - OBJMaterial& material = materials[groupMaterialName]; - if (specifiesUV) { - material.userSpecifiesUV = true; // Note might not be true in a later usage. - } - if (specifiesUV || (0 != groupMaterialName.compare("none", Qt::CaseInsensitive))) { - // Blender has a convention that a material named "None" isn't really used (or defined). - material.used = true; - needsMaterialLibrary = groupMaterialName != SMART_DEFAULT_MATERIAL_NAME; - } - materials[groupMaterialName] = material; - meshPart.materialID = groupMaterialName; - } - } - - // if we got a hint about units, scale all the points - if (scaleGuess != 1.0f) { - for (int i = 0; i < mesh.vertices.size(); i++) { - mesh.vertices[i] *= scaleGuess; - } - } - - mesh.meshExtents.reset(); - foreach(const glm::vec3& vertex, mesh.vertices) { - mesh.meshExtents.addPoint(vertex); - geometry.meshExtents.addPoint(vertex); - } - - FBXReader::buildModelMesh(mesh, url.toString()); } + + // if we got a hint about units, scale all the points + if (scaleGuess != 1.0f) { + for (int i = 0; i < mesh.vertices.size(); i++) { + mesh.vertices[i] *= scaleGuess; + } + } + + mesh.meshExtents.reset(); + foreach (const glm::vec3& vertex, mesh.vertices) { + mesh.meshExtents.addPoint(vertex); + geometry.meshExtents.addPoint(vertex); + } + + FBXReader::buildModelMesh(mesh, url.toString()); // fbxDebugDump(geometry); } catch(const std::exception& e) { qCDebug(modelformat) << "OBJ reader fail: " << e.what(); diff --git a/libraries/fbx/src/OBJReader.h b/libraries/fbx/src/OBJReader.h index e75b1900e9..b4a48c570e 100644 --- a/libraries/fbx/src/OBJReader.h +++ b/libraries/fbx/src/OBJReader.h @@ -79,7 +79,7 @@ private: QUrl _url; QHash librariesSeen; - bool parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, FBXGeometry& geometry, float& scaleGuess, int index); + bool parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, FBXGeometry& geometry, float& scaleGuess); void parseMaterialLibrary(QIODevice* device); bool isValidTexture(const QByteArray &filename); // true if the file exists. TODO?: check content-type header and that it is a supported format. }; From 864184a107c8b063e1d13fb8a6bc520a4ffaea98 Mon Sep 17 00:00:00 2001 From: trent Date: Thu, 30 Mar 2017 17:11:40 -0400 Subject: [PATCH 021/128] wip OBJ loader rewrite; wip because it crashes. --- libraries/fbx/src/OBJReader.cpp | 209 ++++++++++++++++++-------------- 1 file changed, 121 insertions(+), 88 deletions(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index c1bb72dff8..16562c4fdb 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -440,105 +440,138 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, // add a new meshPart to the geometry's single mesh. while (parseOBJGroup(tokenizer, mapping, geometry, scaleGuess)) {} - FBXMesh& mesh = geometry.meshes[0]; - mesh.meshIndex = 0; +// FBXMesh& mesh = geometry.meshes[0]; + geometry.joints.resize(1); + geometry.joints[0].isFree = false; + geometry.joints[0].parentIndex = -1; + geometry.joints[0].distanceToParent = 0; + geometry.joints[0].translation = glm::vec3(0, 0, 0); + geometry.joints[0].rotationMin = glm::vec3(0, 0, 0); + geometry.joints[0].rotationMax = glm::vec3(0, 0, 0); + geometry.joints[0].name = "OBJ"; + geometry.joints[0].isSkeletonJoint = true; - geometry.joints.resize(1); - geometry.joints[0].isFree = false; - geometry.joints[0].parentIndex = -1; - geometry.joints[0].distanceToParent = 0; - geometry.joints[0].translation = glm::vec3(0, 0, 0); - geometry.joints[0].rotationMin = glm::vec3(0, 0, 0); - geometry.joints[0].rotationMax = glm::vec3(0, 0, 0); - geometry.joints[0].name = "OBJ"; - geometry.joints[0].isSkeletonJoint = true; + geometry.jointIndices["x"] = 1; - geometry.jointIndices["x"] = 1; + FBXCluster cluster; + cluster.jointIndex = 0; + cluster.inverseBindMatrix = glm::mat4(1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1); - FBXCluster cluster; - cluster.jointIndex = 0; - cluster.inverseBindMatrix = glm::mat4(1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - mesh.clusters.append(cluster); - - for (int i = 0, meshPartCount = 0; i < mesh.parts.count(); i++, meshPartCount++) { - FBXMeshPart& meshPart = mesh.parts[i]; + QMap materialMeshIdMap; + QVector fbxMeshes; + for (int i = 0, meshPartCount = 0; i < geometry.meshes[0].parts.count(); i++, meshPartCount++) { + FBXMeshPart& meshPart = geometry.meshes[0].parts[i]; FaceGroup faceGroup = faceGroups[meshPartCount]; bool specifiesUV = false; - foreach(OBJFace face, faceGroup) { - glm::vec3 v0 = checked_at(vertices, face.vertexIndices[0]); - glm::vec3 v1 = checked_at(vertices, face.vertexIndices[1]); - glm::vec3 v2 = checked_at(vertices, face.vertexIndices[2]); - meshPart.triangleIndices.append(mesh.vertices.count()); // not face.vertexIndices into vertices - mesh.vertices << v0; - meshPart.triangleIndices.append(mesh.vertices.count()); - mesh.vertices << v1; - meshPart.triangleIndices.append(mesh.vertices.count()); - mesh.vertices << v2; + foreach(OBJFace face, faceGroup) { + // Go through all of the OBJ faces and determine the number of different materials necessary (each different material will be a unique mesh). + // NOTE (trent/mittens 3/30/17): this seems hardcore wasteful and is slowed down a bit by iterating through the face group twice, but it's the best way I've thought of to hack multi-material support in an OBJ into this pipeline. + if (!materialMeshIdMap.contains(face.materialName)) { + // Create a new FBXMesh for this material mapping. + materialMeshIdMap.insert(face.materialName, materialMeshIdMap.count()); - glm::vec3 n0, n1, n2; - if (face.normalIndices.count()) { - n0 = checked_at(normals, face.normalIndices[0]); - n1 = checked_at(normals, face.normalIndices[1]); - n2 = checked_at(normals, face.normalIndices[2]); - } else { // generate normals from triangle plane if not provided - n0 = n1 = n2 = glm::cross(v1 - v0, v2 - v0); - } - mesh.normals << n0 << n1 << n2; - if (face.textureUVIndices.count()) { - specifiesUV = true; - mesh.texCoords << - checked_at(textureUVs, face.textureUVIndices[0]) << - checked_at(textureUVs, face.textureUVIndices[1]) << - checked_at(textureUVs, face.textureUVIndices[2]); - } else { - glm::vec2 corner(0.0f, 1.0f); - mesh.texCoords << corner << corner << corner; - } - } - // All the faces in the same group will have the same name and material. - OBJFace leadFace = faceGroup[0]; - QString groupMaterialName = leadFace.materialName; - if (groupMaterialName.isEmpty() && specifiesUV) { - #ifdef WANT_DEBUG - qCDebug(modelformat) << "OBJ Reader WARNING: " << url - << " needs a texture that isn't specified. Using default mechanism."; - #endif - groupMaterialName = SMART_DEFAULT_MATERIAL_NAME; - } - if (!groupMaterialName.isEmpty()) { - OBJMaterial& material = materials[groupMaterialName]; - if (specifiesUV) { - material.userSpecifiesUV = true; // Note might not be true in a later usage. - } - if (specifiesUV || (0 != groupMaterialName.compare("none", Qt::CaseInsensitive))) { - // Blender has a convention that a material named "None" isn't really used (or defined). - material.used = true; - needsMaterialLibrary = groupMaterialName != SMART_DEFAULT_MATERIAL_NAME; - } - materials[groupMaterialName] = material; - meshPart.materialID = groupMaterialName; - } + FBXMesh& meshNew = geometry.meshes[0]; + meshNew.meshIndex = 0; + meshNew.clusters.append(cluster); + // Add this mesh part to the mesh. + meshNew.parts.append(meshPart); + + // Add it to the mesh vector. + fbxMeshes.append(meshNew); + + // Do some of the material logic (which previously lived below) now. + // All the faces in the same group will have the same name and material. + OBJFace leadFace = faceGroup[0]; + QString groupMaterialName = leadFace.materialName; + if (groupMaterialName.isEmpty() && specifiesUV) { +#ifdef WANT_DEBUG + qCDebug(modelformat) << "OBJ Reader WARNING: " << url + << " needs a texture that isn't specified. Using default mechanism."; +#endif + groupMaterialName = SMART_DEFAULT_MATERIAL_NAME; + } + if (!groupMaterialName.isEmpty()) { + OBJMaterial& material = materials[groupMaterialName]; + if (specifiesUV) { + material.userSpecifiesUV = true; // Note might not be true in a later usage. + } + if (specifiesUV || (0 != groupMaterialName.compare("none", Qt::CaseInsensitive))) { + // Blender has a convention that a material named "None" isn't really used (or defined). + material.used = true; + needsMaterialLibrary = groupMaterialName != SMART_DEFAULT_MATERIAL_NAME; + } + materials[groupMaterialName] = material; + meshPart.materialID = groupMaterialName; + } + } + } + + // Now that each mesh has been created with its own unique material mappings, fill them with data (vertex data is duplicated, face data is not). + foreach(OBJFace face, faceGroup) { + FBXMesh& mesh = fbxMeshes[materialMeshIdMap[face.materialName]]; + + glm::vec3 v0 = checked_at(vertices, face.vertexIndices[0]); + glm::vec3 v1 = checked_at(vertices, face.vertexIndices[1]); + glm::vec3 v2 = checked_at(vertices, face.vertexIndices[2]); + + // Scale the vertices if the OBJ file scale is specified as non-one. + if (scaleGuess != 1.0f) { + v0 *= scaleGuess; + v1 *= scaleGuess; + v2 *= scaleGuess; + } + + // Add the vertices. + meshPart.triangleIndices.append(mesh.vertices.count()); // not face.vertexIndices into vertices + mesh.vertices << v0; + meshPart.triangleIndices.append(mesh.vertices.count()); + mesh.vertices << v1; + meshPart.triangleIndices.append(mesh.vertices.count()); + mesh.vertices << v2; + + glm::vec3 n0, n1, n2; + if (face.normalIndices.count()) { + n0 = checked_at(normals, face.normalIndices[0]); + n1 = checked_at(normals, face.normalIndices[1]); + n2 = checked_at(normals, face.normalIndices[2]); + } + else { + // generate normals from triangle plane if not provided + n0 = n1 = n2 = glm::cross(v1 - v0, v2 - v0); + } + mesh.normals << n0 << n1 << n2; + if (face.textureUVIndices.count()) { + specifiesUV = true; + mesh.texCoords << + checked_at(textureUVs, face.textureUVIndices[0]) << + checked_at(textureUVs, face.textureUVIndices[1]) << + checked_at(textureUVs, face.textureUVIndices[2]); + } + else { + glm::vec2 corner(0.0f, 1.0f); + mesh.texCoords << corner << corner << corner; + } + } } - // if we got a hint about units, scale all the points - if (scaleGuess != 1.0f) { - for (int i = 0; i < mesh.vertices.size(); i++) { - mesh.vertices[i] *= scaleGuess; - } - } + geometry.meshes.clear(); + foreach(FBXMesh mesh, fbxMeshes) { + geometry.meshes.append(mesh); - mesh.meshExtents.reset(); - foreach (const glm::vec3& vertex, mesh.vertices) { - mesh.meshExtents.addPoint(vertex); - geometry.meshExtents.addPoint(vertex); - } + mesh.meshExtents.reset(); + foreach(const glm::vec3& vertex, mesh.vertices) { + mesh.meshExtents.addPoint(vertex); + geometry.meshExtents.addPoint(vertex); + } + + FBXReader::buildModelMesh(mesh, url.toString()); + } - FBXReader::buildModelMesh(mesh, url.toString()); - // fbxDebugDump(geometry); + // fbxDebugDump(geometry); } catch(const std::exception& e) { qCDebug(modelformat) << "OBJ reader fail: " << e.what(); } From c5bb419bd1559164b4e477216b1c6c1b16310baf Mon Sep 17 00:00:00 2001 From: trent Date: Thu, 30 Mar 2017 18:16:55 -0400 Subject: [PATCH 022/128] Fixed OBJ reader crash, did not fix OBJ reader not working properly. --- libraries/fbx/src/OBJReader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 16562c4fdb..18450403c1 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -473,8 +473,8 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, // Create a new FBXMesh for this material mapping. materialMeshIdMap.insert(face.materialName, materialMeshIdMap.count()); - FBXMesh& meshNew = geometry.meshes[0]; - meshNew.meshIndex = 0; + FBXMesh meshNew = geometry.meshes[0]; + meshNew.meshIndex = fbxMeshes.count(); meshNew.clusters.append(cluster); // Add this mesh part to the mesh. From e9035a1efba097575c48afafd026a0eaf2b486d3 Mon Sep 17 00:00:00 2001 From: trent Date: Thu, 30 Mar 2017 19:10:15 -0400 Subject: [PATCH 023/128] More fixes for the OBJ reader. The data seems to be fine. The rendering seems not so fine. --- libraries/fbx/src/OBJReader.cpp | 46 ++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 18450403c1..7f6f6a210a 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -463,7 +463,6 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, QMap materialMeshIdMap; QVector fbxMeshes; for (int i = 0, meshPartCount = 0; i < geometry.meshes[0].parts.count(); i++, meshPartCount++) { - FBXMeshPart& meshPart = geometry.meshes[0].parts[i]; FaceGroup faceGroup = faceGroups[meshPartCount]; bool specifiesUV = false; foreach(OBJFace face, faceGroup) { @@ -473,20 +472,15 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, // Create a new FBXMesh for this material mapping. materialMeshIdMap.insert(face.materialName, materialMeshIdMap.count()); - FBXMesh meshNew = geometry.meshes[0]; - meshNew.meshIndex = fbxMeshes.count(); + FBXMesh meshNew; + meshNew.modelTransform = geometry.meshes[0].modelTransform; + meshNew.meshExtents = geometry.meshes[0].meshExtents; + meshNew.meshIndex = 0;// fbxMeshes.count(); meshNew.clusters.append(cluster); - // Add this mesh part to the mesh. - meshNew.parts.append(meshPart); - - // Add it to the mesh vector. - fbxMeshes.append(meshNew); - // Do some of the material logic (which previously lived below) now. // All the faces in the same group will have the same name and material. - OBJFace leadFace = faceGroup[0]; - QString groupMaterialName = leadFace.materialName; + QString groupMaterialName = face.materialName; if (groupMaterialName.isEmpty() && specifiesUV) { #ifdef WANT_DEBUG qCDebug(modelformat) << "OBJ Reader WARNING: " << url @@ -505,14 +499,21 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, needsMaterialLibrary = groupMaterialName != SMART_DEFAULT_MATERIAL_NAME; } materials[groupMaterialName] = material; - meshPart.materialID = groupMaterialName; + geometry.meshes[0].parts[i].materialID = groupMaterialName; } + + // Add this mesh part. + meshNew.parts.append(FBXMeshPart(geometry.meshes[0].parts[i])); + + // Add it to the mesh vector. + fbxMeshes.append(meshNew); } } // Now that each mesh has been created with its own unique material mappings, fill them with data (vertex data is duplicated, face data is not). foreach(OBJFace face, faceGroup) { FBXMesh& mesh = fbxMeshes[materialMeshIdMap[face.materialName]]; + FBXMeshPart& meshPart = mesh.parts.last(); glm::vec3 v0 = checked_at(vertices, face.vertexIndices[0]); glm::vec3 v1 = checked_at(vertices, face.vertexIndices[1]); @@ -527,11 +528,11 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, // Add the vertices. meshPart.triangleIndices.append(mesh.vertices.count()); // not face.vertexIndices into vertices - mesh.vertices << v0; + mesh.vertices.append(v0); meshPart.triangleIndices.append(mesh.vertices.count()); - mesh.vertices << v1; + mesh.vertices.append(v1); meshPart.triangleIndices.append(mesh.vertices.count()); - mesh.vertices << v2; + mesh.vertices.append(v2); glm::vec3 n0, n1, n2; if (face.normalIndices.count()) { @@ -543,17 +544,20 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, // generate normals from triangle plane if not provided n0 = n1 = n2 = glm::cross(v1 - v0, v2 - v0); } - mesh.normals << n0 << n1 << n2; + mesh.normals.append(n0); + mesh.normals.append(n1); + mesh.normals.append(n2); if (face.textureUVIndices.count()) { specifiesUV = true; - mesh.texCoords << - checked_at(textureUVs, face.textureUVIndices[0]) << - checked_at(textureUVs, face.textureUVIndices[1]) << - checked_at(textureUVs, face.textureUVIndices[2]); + mesh.texCoords.append(checked_at(textureUVs, face.textureUVIndices[0])); + mesh.texCoords.append(checked_at(textureUVs, face.textureUVIndices[1])); + mesh.texCoords.append(checked_at(textureUVs, face.textureUVIndices[2])); } else { glm::vec2 corner(0.0f, 1.0f); - mesh.texCoords << corner << corner << corner; + mesh.texCoords.append(corner); + mesh.texCoords.append(corner); + mesh.texCoords.append(corner); } } } From 53c439ffba3e4cc105d011b42ed207a4b6fb68c3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 30 Mar 2017 19:11:16 -0700 Subject: [PATCH 024/128] add foot IK targets as actions --- interface/resources/controllers/kinect.json | 4 +- interface/resources/controllers/standard.json | 5 +- interface/src/Application.cpp | 4 + interface/src/avatar/MyAvatar.cpp | 39 +++++++++ interface/src/avatar/MyAvatar.h | 11 +++ interface/src/avatar/SkeletonModel.cpp | 44 +++++++--- libraries/animation/src/Rig.cpp | 24 +++++- libraries/animation/src/Rig.h | 11 ++- .../controllers/src/controllers/Actions.cpp | 2 + .../controllers/src/controllers/Actions.h | 2 + .../src/controllers/StandardController.cpp | 2 + .../controllers/proceduralFootPoseExample.js | 81 +++++++++++++++++++ script-archive/controllers/puppetFeet2.js | 35 ++++++++ 13 files changed, 245 insertions(+), 19 deletions(-) create mode 100644 script-archive/controllers/proceduralFootPoseExample.js create mode 100644 script-archive/controllers/puppetFeet2.js diff --git a/interface/resources/controllers/kinect.json b/interface/resources/controllers/kinect.json index 96a504030c..eb1d301af9 100644 --- a/interface/resources/controllers/kinect.json +++ b/interface/resources/controllers/kinect.json @@ -2,6 +2,8 @@ "name": "Kinect to Standard", "channels": [ { "from": "Kinect.LeftHand", "to": "Standard.LeftHand" }, - { "from": "Kinect.RightHand", "to": "Standard.RightHand" } + { "from": "Kinect.RightHand", "to": "Standard.RightHand" }, + { "from": "Kinect.LeftFoot", "to": "Standard.LeftFoot" }, + { "from": "Kinect.RightFoot", "to": "Standard.RightFoot" } ] } diff --git a/interface/resources/controllers/standard.json b/interface/resources/controllers/standard.json index 9e3b2f4d13..53285ea974 100644 --- a/interface/resources/controllers/standard.json +++ b/interface/resources/controllers/standard.json @@ -58,6 +58,9 @@ { "from": "Standard.RT", "to": "Actions.RightHandClick" }, { "from": "Standard.LeftHand", "to": "Actions.LeftHand" }, - { "from": "Standard.RightHand", "to": "Actions.RightHand" } + { "from": "Standard.RightHand", "to": "Actions.RightHand" }, + + { "from": "Standard.LeftFoot", "to": "Actions.LeftFoot" }, + { "from": "Standard.RightFoot", "to": "Actions.RightFoot" } ] } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 25a585ea34..a1a4a63e5b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4386,6 +4386,10 @@ void Application::update(float deltaTime) { auto avatarToSensorMatrix = worldToSensorMatrix * myAvatarMatrix; myAvatar->setHandControllerPosesInSensorFrame(leftHandPose.transform(avatarToSensorMatrix), rightHandPose.transform(avatarToSensorMatrix)); + controller::Pose leftFootPose = userInputMapper->getPoseState(controller::Action::LEFT_FOOT); + controller::Pose rightFootPose = userInputMapper->getPoseState(controller::Action::RIGHT_FOOT); + myAvatar->setFootControllerPosesInSensorFrame(leftFootPose.transform(avatarToSensorMatrix), rightFootPose.transform(avatarToSensorMatrix)); + updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process... updateDialogs(deltaTime); // update various stats dialogs if present diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0d0390a365..d1edf9d44e 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1345,6 +1345,45 @@ controller::Pose MyAvatar::getRightHandControllerPoseInAvatarFrame() const { return getRightHandControllerPoseInWorldFrame().transform(invAvatarMatrix); } +void MyAvatar::setFootControllerPosesInSensorFrame(const controller::Pose& left, const controller::Pose& right) { + if (controller::InputDevice::getLowVelocityFilter()) { + auto oldLeftPose = getLeftFootControllerPoseInSensorFrame(); + auto oldRightPose = getRightFootControllerPoseInSensorFrame(); + _leftFootControllerPoseInSensorFrameCache.set(applyLowVelocityFilter(oldLeftPose, left)); + _rightFootControllerPoseInSensorFrameCache.set(applyLowVelocityFilter(oldRightPose, right)); + } else { + _leftFootControllerPoseInSensorFrameCache.set(left); + _rightFootControllerPoseInSensorFrameCache.set(right); + } +} + +controller::Pose MyAvatar::getLeftFootControllerPoseInSensorFrame() const { + return _leftFootControllerPoseInSensorFrameCache.get(); +} + +controller::Pose MyAvatar::getRightFootControllerPoseInSensorFrame() const { + return _rightFootControllerPoseInSensorFrameCache.get(); +} + +controller::Pose MyAvatar::getLeftFootControllerPoseInWorldFrame() const { + return _leftFootControllerPoseInSensorFrameCache.get().transform(getSensorToWorldMatrix()); +} + +controller::Pose MyAvatar::getRightFootControllerPoseInWorldFrame() const { + return _rightFootControllerPoseInSensorFrameCache.get().transform(getSensorToWorldMatrix()); +} + +controller::Pose MyAvatar::getLeftFootControllerPoseInAvatarFrame() const { + glm::mat4 invAvatarMatrix = glm::inverse(createMatFromQuatAndPos(getOrientation(), getPosition())); + return getLeftFootControllerPoseInWorldFrame().transform(invAvatarMatrix); +} + +controller::Pose MyAvatar::getRightFootControllerPoseInAvatarFrame() const { + glm::mat4 invAvatarMatrix = glm::inverse(createMatFromQuatAndPos(getOrientation(), getPosition())); + return getRightFootControllerPoseInWorldFrame().transform(invAvatarMatrix); +} + + void MyAvatar::updateMotors() { _characterController.clearMotors(); glm::quat motorRotation; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index add57cf5be..097d3a1059 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -445,6 +445,14 @@ public: controller::Pose getLeftHandControllerPoseInAvatarFrame() const; controller::Pose getRightHandControllerPoseInAvatarFrame() const; + void setFootControllerPosesInSensorFrame(const controller::Pose& left, const controller::Pose& right); + controller::Pose getLeftFootControllerPoseInSensorFrame() const; + controller::Pose getRightFootControllerPoseInSensorFrame() const; + controller::Pose getLeftFootControllerPoseInWorldFrame() const; + controller::Pose getRightFootControllerPoseInWorldFrame() const; + controller::Pose getLeftFootControllerPoseInAvatarFrame() const; + controller::Pose getRightFootControllerPoseInAvatarFrame() const; + bool hasDriveInput() const; Q_INVOKABLE void setCharacterControllerEnabled(bool enabled); @@ -684,6 +692,9 @@ private: ThreadSafeValueCache _leftHandControllerPoseInSensorFrameCache { controller::Pose() }; ThreadSafeValueCache _rightHandControllerPoseInSensorFrameCache { controller::Pose() }; + ThreadSafeValueCache _leftFootControllerPoseInSensorFrameCache{ controller::Pose() }; + ThreadSafeValueCache _rightFootControllerPoseInSensorFrameCache{ controller::Pose() }; + bool _hmdLeanRecenterEnabled = true; AnimPose _prePhysicsRoomPose; diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 476abf8d4b..d7dd93cedf 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -132,31 +132,49 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { _rig->updateFromHeadParameters(headParams, deltaTime); - Rig::HandParameters handParams; + Rig::HandAndFeetParameters handAndFeetParams; auto leftPose = myAvatar->getLeftHandControllerPoseInAvatarFrame(); if (leftPose.isValid()) { - handParams.isLeftEnabled = true; - handParams.leftPosition = Quaternions::Y_180 * leftPose.getTranslation(); - handParams.leftOrientation = Quaternions::Y_180 * leftPose.getRotation(); + handAndFeetParams.isLeftEnabled = true; + handAndFeetParams.leftPosition = Quaternions::Y_180 * leftPose.getTranslation(); + handAndFeetParams.leftOrientation = Quaternions::Y_180 * leftPose.getRotation(); } else { - handParams.isLeftEnabled = false; + handAndFeetParams.isLeftEnabled = false; } auto rightPose = myAvatar->getRightHandControllerPoseInAvatarFrame(); if (rightPose.isValid()) { - handParams.isRightEnabled = true; - handParams.rightPosition = Quaternions::Y_180 * rightPose.getTranslation(); - handParams.rightOrientation = Quaternions::Y_180 * rightPose.getRotation(); + handAndFeetParams.isRightEnabled = true; + handAndFeetParams.rightPosition = Quaternions::Y_180 * rightPose.getTranslation(); + handAndFeetParams.rightOrientation = Quaternions::Y_180 * rightPose.getRotation(); } else { - handParams.isRightEnabled = false; + handAndFeetParams.isRightEnabled = false; } - handParams.bodyCapsuleRadius = myAvatar->getCharacterController()->getCapsuleRadius(); - handParams.bodyCapsuleHalfHeight = myAvatar->getCharacterController()->getCapsuleHalfHeight(); - handParams.bodyCapsuleLocalOffset = myAvatar->getCharacterController()->getCapsuleLocalOffset(); + auto leftFootPose = myAvatar->getLeftFootControllerPoseInAvatarFrame(); + if (leftFootPose.isValid()) { + handAndFeetParams.isLeftFootEnabled = true; + handAndFeetParams.leftFootPosition = Quaternions::Y_180 * leftFootPose.getTranslation(); + handAndFeetParams.leftFootOrientation = Quaternions::Y_180 * leftFootPose.getRotation(); + } else { + handAndFeetParams.isLeftFootEnabled = false; + } - _rig->updateFromHandParameters(handParams, deltaTime); + auto rightFootPose = myAvatar->getRightFootControllerPoseInAvatarFrame(); + if (rightFootPose.isValid()) { + handAndFeetParams.isRightFootEnabled = true; + handAndFeetParams.rightFootPosition = Quaternions::Y_180 * rightFootPose.getTranslation(); + handAndFeetParams.rightFootOrientation = Quaternions::Y_180 * rightFootPose.getRotation(); + } else { + handAndFeetParams.isRightFootEnabled = false; + } + + handAndFeetParams.bodyCapsuleRadius = myAvatar->getCharacterController()->getCapsuleRadius(); + handAndFeetParams.bodyCapsuleHalfHeight = myAvatar->getCharacterController()->getCapsuleHalfHeight(); + handAndFeetParams.bodyCapsuleLocalOffset = myAvatar->getCharacterController()->getCapsuleLocalOffset(); + + _rig->updateFromHandAndFeetParameters(handAndFeetParams, deltaTime); Rig::CharacterControllerState ccState = convertCharacterControllerState(myAvatar->getCharacterController()->getState()); diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 8b54f0ee92..020ea1d657 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1146,9 +1146,8 @@ void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm } } -void Rig::updateFromHandParameters(const HandParameters& params, float dt) { +void Rig::updateFromHandAndFeetParameters(const HandAndFeetParameters& params, float dt) { if (_animSkeleton && _animNode) { - const float HAND_RADIUS = 0.05f; int hipsIndex = indexOfJoint("Hips"); glm::vec3 hipsTrans; @@ -1197,6 +1196,27 @@ void Rig::updateFromHandParameters(const HandParameters& params, float dt) { _animVars.unset("rightHandRotation"); _animVars.set("rightHandType", (int)IKTarget::Type::HipsRelativeRotationAndPosition); } + + if (params.isLeftFootEnabled) { + _animVars.set("leftFootPosition", params.leftFootPosition); + _animVars.set("leftFootRotation", params.leftFootOrientation); + _animVars.set("leftFootType", (int)IKTarget::Type::RotationAndPosition); + } else { + _animVars.unset("leftFootPosition"); + _animVars.unset("leftFootRotation"); + _animVars.set("leftFootType", (int)IKTarget::Type::HipsRelativeRotationAndPosition); + } + + if (params.isRightFootEnabled) { + _animVars.set("rightFootPosition", params.rightFootPosition); + _animVars.set("rightFootRotation", params.rightFootOrientation); + _animVars.set("rightFootType", (int)IKTarget::Type::RotationAndPosition); + } else { + _animVars.unset("rightFootPosition"); + _animVars.unset("rightFootRotation"); + _animVars.set("rightFootType", (int)IKTarget::Type::HipsRelativeRotationAndPosition); + } + } } diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index ea498e6a69..2cd20c2704 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -60,7 +60,7 @@ public: int rightEyeJointIndex = -1; }; - struct HandParameters { + struct HandAndFeetParameters { bool isLeftEnabled; bool isRightEnabled; float bodyCapsuleRadius; @@ -70,6 +70,13 @@ public: glm::quat leftOrientation = glm::quat(); // rig space (z forward) glm::vec3 rightPosition = glm::vec3(); // rig space glm::quat rightOrientation = glm::quat(); // rig space (z forward) + + bool isLeftFootEnabled; + bool isRightFootEnabled; + glm::vec3 leftFootPosition = glm::vec3(); // rig space + glm::quat leftFootOrientation = glm::quat(); // rig space (z forward) + glm::vec3 rightFootPosition = glm::vec3(); // rig space + glm::quat rightFootOrientation = glm::quat(); // rig space (z forward) }; enum class CharacterControllerState { @@ -185,7 +192,7 @@ public: void updateFromHeadParameters(const HeadParameters& params, float dt); void updateFromEyeParameters(const EyeParameters& params); - void updateFromHandParameters(const HandParameters& params, float dt); + void updateFromHandAndFeetParameters(const HandAndFeetParameters& params, float dt); void initAnimGraph(const QUrl& url); diff --git a/libraries/controllers/src/controllers/Actions.cpp b/libraries/controllers/src/controllers/Actions.cpp index 79ff4ecbf8..300fa684d9 100644 --- a/libraries/controllers/src/controllers/Actions.cpp +++ b/libraries/controllers/src/controllers/Actions.cpp @@ -51,6 +51,8 @@ namespace controller { makePosePair(Action::LEFT_HAND, "LeftHand"), makePosePair(Action::RIGHT_HAND, "RightHand"), + makePosePair(Action::LEFT_FOOT, "LeftFoot"), + makePosePair(Action::RIGHT_FOOT, "RightFoot"), makeButtonPair(Action::LEFT_HAND_CLICK, "LeftHandClick"), makeButtonPair(Action::RIGHT_HAND_CLICK, "RightHandClick"), diff --git a/libraries/controllers/src/controllers/Actions.h b/libraries/controllers/src/controllers/Actions.h index 724d17d951..edf3dee07a 100644 --- a/libraries/controllers/src/controllers/Actions.h +++ b/libraries/controllers/src/controllers/Actions.h @@ -42,6 +42,8 @@ enum class Action { LEFT_HAND = NUM_COMBINED_AXES, RIGHT_HAND, + LEFT_FOOT, + RIGHT_FOOT, LEFT_HAND_CLICK, RIGHT_HAND_CLICK, diff --git a/libraries/controllers/src/controllers/StandardController.cpp b/libraries/controllers/src/controllers/StandardController.cpp index 02ae5706b7..cc90ee7b49 100644 --- a/libraries/controllers/src/controllers/StandardController.cpp +++ b/libraries/controllers/src/controllers/StandardController.cpp @@ -102,6 +102,8 @@ Input::NamedVector StandardController::getAvailableInputs() const { // Poses makePair(LEFT_HAND, "LeftHand"), makePair(RIGHT_HAND, "RightHand"), + makePair(LEFT_FOOT, "LeftFoot"), + makePair(RIGHT_FOOT, "RightFoot"), // Aliases, PlayStation style names makePair(LB, "L1"), diff --git a/script-archive/controllers/proceduralFootPoseExample.js b/script-archive/controllers/proceduralFootPoseExample.js new file mode 100644 index 0000000000..e2504de04d --- /dev/null +++ b/script-archive/controllers/proceduralFootPoseExample.js @@ -0,0 +1,81 @@ +// +// proceduralFootPoseExample.js +// examples/controllers +// +// Created by Brad Hefta-Gaub on 2015/12/15 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +var MAPPING_NAME = "com.highfidelity.examples.proceduralFootPose"; +var mapping = Controller.newMapping(MAPPING_NAME); +var translation = { x: 0, y: 0.1, z: 0 }; +var translationDx = 0.01; +var translationDy = 0.01; +var translationDz = -0.01; +var TRANSLATION_LIMIT = 0.5; + +var pitch = 45; +var yaw = 0; +var roll = 45; +var pitchDelta = 1; +var yawDelta = -1; +var rollDelta = 1; +var ROTATION_MIN = -90; +var ROTATION_MAX = 90; + +mapping.from(function() { + + // adjust the hand translation in a periodic back and forth motion for each of the 3 axes + translation.x = translation.x + translationDx; + translation.y = translation.y + translationDy; + translation.z = translation.z + translationDz; + if ((translation.x > TRANSLATION_LIMIT) || (translation.x < (-1 * TRANSLATION_LIMIT))) { + translationDx = translationDx * -1; + } + if ((translation.y > TRANSLATION_LIMIT) || (translation.y < (-1 * TRANSLATION_LIMIT))) { + translationDy = translationDy * -1; + } + if ((translation.z > TRANSLATION_LIMIT) || (translation.z < (-1 * TRANSLATION_LIMIT))) { + translationDz = translationDz * -1; + } + + // adjust the hand rotation in a periodic back and forth motion for each of pitch/yaw/roll + pitch = pitch + pitchDelta; + yaw = yaw + yawDelta; + roll = roll + rollDelta; + if ((pitch > ROTATION_MAX) || (pitch < ROTATION_MIN)) { + pitchDelta = pitchDelta * -1; + } + if ((yaw > ROTATION_MAX) || (yaw < ROTATION_MIN)) { + yawDelta = yawDelta * -1; + } + if ((roll > ROTATION_MAX) || (roll < ROTATION_MIN)) { + rollDelta = rollDelta * -1; + } + + var rotation = Quat.fromPitchYawRollDegrees(pitch, yaw, roll); + + var pose = { + translation: translation, + rotation: rotation, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }; + + Vec3.print("foot translation:", translation); + return pose; +}).debug(true).to(Controller.Standard.LeftFoot); + +//mapping.from(Controller.Standard.LeftFoot).debug(true).to(Controller.Actions.LeftFoot); + + +Controller.enableMapping(MAPPING_NAME); + + +Script.scriptEnding.connect(function(){ + mapping.disable(); +}); diff --git a/script-archive/controllers/puppetFeet2.js b/script-archive/controllers/puppetFeet2.js new file mode 100644 index 0000000000..754f3c4270 --- /dev/null +++ b/script-archive/controllers/puppetFeet2.js @@ -0,0 +1,35 @@ +// +// proceduralFootPoseExample.js +// examples/controllers +// +// Created by Brad Hefta-Gaub on 2015/12/15 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +var MAPPING_NAME = "com.highfidelity.examples.proceduralFootPose"; +var mapping = Controller.newMapping(MAPPING_NAME); +var puppetOffset = { x: 0, y: -1, z: 0 }; + +mapping.from(function() { + var leftHandPose = Controller.getPoseValue(Controller.Standard.LeftHand); + + var pose = { + translation: Vec3.sum(leftHandPose.translation, puppetOffset), + rotation: { x: 0, y: 0, z: 0, w: 0 }, //leftHandPose.rotation, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }; + return pose; +}).to(Controller.Standard.LeftFoot); + + +Controller.enableMapping(MAPPING_NAME); + + +Script.scriptEnding.connect(function(){ + mapping.disable(); +}); From 4da8e5e18f3d211637d508422d08dddf09b0d4ea Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 30 Mar 2017 20:01:59 -0700 Subject: [PATCH 025/128] fix left/right legs for kinect --- plugins/hifiKinect/src/KinectPlugin.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/plugins/hifiKinect/src/KinectPlugin.cpp b/plugins/hifiKinect/src/KinectPlugin.cpp index 72c7926ec1..6d29a261dd 100644 --- a/plugins/hifiKinect/src/KinectPlugin.cpp +++ b/plugins/hifiKinect/src/KinectPlugin.cpp @@ -113,16 +113,16 @@ static controller::StandardPoseChannel KinectJointIndexToPoseIndexMap[KinectJoin controller::RIGHT_FORE_ARM, controller::RIGHT_HAND, - controller::RIGHT_UP_LEG, // hip socket - controller::RIGHT_LEG, // knee? - controller::RIGHT_FOOT, // ankle? - UNKNOWN_JOINT, // ???? - controller::LEFT_UP_LEG, // hip socket controller::LEFT_LEG, // knee? controller::LEFT_FOOT, // ankle? UNKNOWN_JOINT, // ???? + controller::RIGHT_UP_LEG, // hip socket + controller::RIGHT_LEG, // knee? + controller::RIGHT_FOOT, // ankle? + UNKNOWN_JOINT, // ???? + UNKNOWN_JOINT, /* SpineShoulder */ controller::LEFT_HAND_INDEX4, @@ -130,7 +130,6 @@ static controller::StandardPoseChannel KinectJointIndexToPoseIndexMap[KinectJoin controller::RIGHT_HAND_INDEX4, controller::RIGHT_HAND_THUMB4, - }; // in rig frame From 7558765042014f03aa014d8d69d9e7a690b54d8e Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Fri, 31 Mar 2017 14:20:15 +0200 Subject: [PATCH 026/128] Script log now back to HUD --- interface/src/Application.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 25a585ea34..83c14457fb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5781,22 +5781,10 @@ void Application::toggleRunningScriptsWidget() const { } void Application::showScriptLogs() { - auto tabletScriptingInterface = DependencyManager::get(); - auto tablet = dynamic_cast(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system")); auto scriptEngines = DependencyManager::get(); QUrl defaultScriptsLoc = defaultScriptsLocation(); defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/debugging/debugWindow.js"); - - if (tablet->getToolbarMode()) { - scriptEngines->loadScript(defaultScriptsLoc.toString()); - } else { - QQuickItem* tabletRoot = tablet->getTabletRoot(); - if (!tabletRoot && !isHMDMode()) { - scriptEngines->loadScript(defaultScriptsLoc.toString()); - } else { - tablet->pushOntoStack("../../hifi/dialogs/TabletDebugWindow.qml"); - } - } + scriptEngines->loadScript(defaultScriptsLoc.toString()); } void Application::showAssetServerWidget(QString filePath) { From f148bca1c06f856c6505f5826f13f27a168a7d2e Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 31 Mar 2017 16:27:37 -0700 Subject: [PATCH 027/128] More progress on ComboDialog --- interface/resources/qml/hifi/ComboDialog.qml | 31 +++++++++------- interface/resources/qml/hifi/Pal.qml | 39 +++++++++++++++----- 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/interface/resources/qml/hifi/ComboDialog.qml b/interface/resources/qml/hifi/ComboDialog.qml index f5bb7dcfcc..7f50f37d54 100644 --- a/interface/resources/qml/hifi/ComboDialog.qml +++ b/interface/resources/qml/hifi/ComboDialog.qml @@ -19,6 +19,7 @@ Item { property var optionBodyText; property var optionValues; property var selectedOptionIndex; + property var callbackFunction; property int dialogWidth; property int dialogHeight; property int comboOptionTextSize: 18; @@ -31,6 +32,14 @@ Item { populateComboListViewModel(); } + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.LeftButton + onClicked: { + combo.visible = false; + } + } + Rectangle { id: dialogBackground; anchors.fill: parent; @@ -69,6 +78,7 @@ Item { anchors.bottom: parent.bottom; anchors.left: parent.left; anchors.right: parent.right; + clip: true; model: comboListViewModel; delegate: comboListViewDelegate; @@ -77,7 +87,7 @@ Item { Rectangle { id: comboListViewItemContainer; // Size - height: childrenRect.height + 10; + height: optionTitle.height + optionBody.height + 20; width: dialogContainer.width; color: selectedOptionIndex === index ? '#cee6ff' : 'white'; Rectangle { @@ -100,9 +110,11 @@ Item { id: optionTitle; text: titleText; anchors.top: parent.top; + anchors.topMargin: 7; anchors.left: comboOptionSelected.right; - anchors.leftMargin: 20; + anchors.leftMargin: 10; anchors.right: parent.right; + anchors.rightMargin: 10; height: 30; size: comboOptionTextSize; wrapMode: Text.WordWrap; @@ -112,10 +124,10 @@ Item { id: optionBody; text: bodyText; anchors.top: optionTitle.bottom; - anchors.bottom: parent.bottom; anchors.left: comboOptionSelected.right; anchors.leftMargin: 25; anchors.right: parent.right; + anchors.rightMargin: 10; size: comboOptionTextSize; wrapMode: Text.WordWrap; } @@ -127,9 +139,8 @@ Item { onEntered: comboListViewItemContainer.color = hifi.colors.blueHighlight onExited: comboListViewItemContainer.color = selectedOptionIndex === index ? '#cee6ff' : 'white'; onClicked: { - GlobalServices.findableBy = optionValue; - UserActivityLogger.palAction("set_availability", optionValue); - print('Setting availability:', optionValue); + callbackFunction(optionValue); + combo.visible = false; } } } @@ -137,14 +148,6 @@ Item { } } - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.LeftButton - onClicked: { - combo.visible = false; - } - } - function populateComboListViewModel() { comboListViewModel.clear(); optionTitleText.forEach(function(titleText, index) { diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 06360ce183..b7d31e06da 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -56,7 +56,7 @@ Rectangle { ComboDialog { id: comboDialog; z: 999; // Force the ComboDialog on top of everything else - dialogWidth: parent.width - 100; + dialogWidth: parent.width - 50; dialogHeight: parent.height - 100; } function letterbox(headerGlyph, headerText, message) { @@ -66,7 +66,13 @@ Rectangle { letterboxMessage.visible = true; letterboxMessage.popupRadius = 0; } + function popupComboDialogCallback(availability) { + GlobalServices.findableBy = availability; + UserActivityLogger.palAction("set_availability", availability); + print('Setting availability:', JSON.stringify(GlobalServices.findableBy)); + } function popupComboDialog(dialogTitleText, optionTitleText, optionBodyText, optionValues) { + comboDialog.callbackFunction = popupComboDialogCallback; comboDialog.dialogTitleText = dialogTitleText; comboDialog.optionTitleText = optionTitleText; comboDialog.optionBodyText = optionBodyText; @@ -961,29 +967,42 @@ Rectangle { horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignTop; } - /*Rectangle { + Rectangle { + property var availabilityStrings: ["Everyone", "Friends and Connections", "Friends Only", "Appear Offline"]; id: availabilityComboBox; + color: hifi.colors.textFieldLightBackground // Anchors anchors.top: parent.top; anchors.horizontalCenter: parent.horizontalCenter; // Size width: parent.width; height: 40; + RalewayRegular { + text: myData.userName === "Unknown user" ? "Login to Set" : availabilityStrings[GlobalServices.findableBy]; + anchors.fill: parent; + anchors.leftMargin: 10; + horizontalAlignment: Text.AlignLeft; + size: 16; + } MouseArea { - anchors.fill: parent + anchors.fill: parent; + enabled: myData.userName ==! "Unknown user"; + hoverEnabled: true; onClicked: { - popupComboDialog("Set your list visibility", - ["Everyone", "Friends and Connections", "Friends Only", "Appear Offline"], - ["You will be invisible in everyone's 'People' list.\nAnyone will be able to jump to your location if the domain allows.", + popupComboDialog("Set your availability:", + availabilityComboBox.availabilityStrings, + ["Your username will be visible in everyone's 'Nearby' list.\nAnyone will be able to jump to your location from within the 'Nearby' list.", "You will be visible in the 'People' list only for those with whom you are connected or friends.\nThey will be able to jump to your location if the domain allows.", "You will be visible in the 'People' list only for those with whom you are friends.\nThey will be able to jump to your location if the domain allows.", - "You will not be visible in the 'People' list of any other users."], + "You will not be visible in the 'People' list of any other users. Only domain admins will be able to see your username in the 'Nearby' list."], ["all", "connections", "friends", "none"]); } + onEntered: availabilityComboBox.color = hifi.colors.lightGrayText; + onExited: availabilityComboBox.color = hifi.colors.textFieldLightBackground; } - }*/ + } - HifiControlsUit.ComboBox { + /*HifiControlsUit.ComboBox { function determineAvailabilityIndex() { return ['all', 'connections', 'friends', 'none'].indexOf(GlobalServices.findableBy) } @@ -1007,7 +1026,7 @@ Rectangle { UserActivityLogger.palAction("set_availability", availabilityComboBoxListItems.get(currentIndex).value); print('Setting availability:', JSON.stringify(GlobalServices.findableBy)); } - } + }*/ } } From d207dae5b7bdf8b295e20a37da3cbc49d5606f26 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Sun, 2 Apr 2017 20:02:40 +0200 Subject: [PATCH 028/128] Put current address to location instead of inputfield --- .../qml/hifi/tablet/TabletAddressDialog.qml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index 623054f233..0373253ff3 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -38,7 +38,7 @@ StackView { root.currentItem.focus = true; root.currentItem.forceActiveFocus(); fillDestinations(); - updateLocationText(); + updateLocationText(false); root.parentChanged.connect(center); center(); } @@ -62,8 +62,8 @@ StackView { root.push(card); return; } - addressLine.text = targetString; - toggleOrGo(true); + location.text = targetString; + toggleOrGo(true, targetString); clearAddressLineTimer.start(); } @@ -539,7 +539,11 @@ StackView { } } - function toggleOrGo(fromSuggestions) { + function toggleOrGo(fromSuggestions, address) { + if (address !== undefined && address !== "") { + addressBarDialog.loadAddress(address, fromSuggestions) + } + if (addressLine.text !== "") { addressBarDialog.loadAddress(addressLine.text, fromSuggestions) } From 849d65f95f2e1fbd4bde1e3fdfda29988ae5f35e Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Fri, 31 Mar 2017 15:01:19 +0200 Subject: [PATCH 029/128] Fixed warning: Tablet.qml:205: TypeError: Cannot read property of null (cherry picked from commit b1dc14b355bc6053a0e264a057a799a4d446e347) --- interface/resources/qml/hifi/tablet/Tablet.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/tablet/Tablet.qml b/interface/resources/qml/hifi/tablet/Tablet.qml index 3fb70f9cca..8ad6339d88 100644 --- a/interface/resources/qml/hifi/tablet/Tablet.qml +++ b/interface/resources/qml/hifi/tablet/Tablet.qml @@ -202,7 +202,7 @@ Item { RalewaySemiBold { id: usernameText - text: tablet.parent.parent.username + text: tabletRoot.username anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right anchors.rightMargin: 20 From 6b7f3f7125994ed6a8f2c77a5ca6e4ce3f793c71 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Fri, 31 Mar 2017 15:09:39 +0200 Subject: [PATCH 030/128] Fixed warning: TabletAddressDialog.qml:282:13: QML ListView: Cannot specify top, bottom, and verticalCenter anchors at the same time. (cherry picked from commit b11e245cb1b19149ff00f16b718ff4088b856f3e) --- interface/resources/qml/hifi/tablet/TabletAddressDialog.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index a58177640d..e99332368e 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -291,8 +291,6 @@ StackView { left: parent.left right: parent.right leftMargin: 10 - verticalCenter: parent.verticalCenter; - horizontalCenter: parent.horizontalCenter; } model: suggestions orientation: ListView.Vertical From 9e96888534b703a67026bf16ed95b71c9bf0c600 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Fri, 31 Mar 2017 15:18:02 +0200 Subject: [PATCH 031/128] Fixed warning: TabletAddressDialog.qml:546: Error: Cannot assign to non-existent property 'shown' (cherry picked from commit e70c2cdcc74f9fd43273dca268433cdefd9ecf40) --- interface/resources/qml/hifi/tablet/TabletAddressDialog.qml | 6 +++--- interface/resources/qml/hifi/tablet/TabletRoot.qml | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index e99332368e..b3d56f02f2 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -107,7 +107,7 @@ StackView { imageURL: "../../../images/home.svg" onClicked: { addressBarDialog.loadHome(); - root.shown = false; + tabletRoot.shown = false; } anchors { left: parent.left @@ -541,14 +541,14 @@ StackView { if (addressLine.text !== "") { addressBarDialog.loadAddress(addressLine.text, fromSuggestions) } - root.shown = false; + tabletRoot.shown = false; } Keys.onPressed: { switch (event.key) { case Qt.Key_Escape: case Qt.Key_Back: - root.shown = false + tabletRoot.shown = false clearAddressLineTimer.start(); event.accepted = true break diff --git a/interface/resources/qml/hifi/tablet/TabletRoot.qml b/interface/resources/qml/hifi/tablet/TabletRoot.qml index 8037c1280e..f5144e698f 100644 --- a/interface/resources/qml/hifi/tablet/TabletRoot.qml +++ b/interface/resources/qml/hifi/tablet/TabletRoot.qml @@ -13,6 +13,7 @@ Item { property var openMessage: null; property string subMenu: "" signal showDesktop(); + property bool shown: true function setOption(value) { option = value; From 156166ce4a0b8dac8a40fb08b76835eca676eaa7 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Fri, 31 Mar 2017 15:25:53 +0200 Subject: [PATCH 032/128] Fixed another warning in TabletAddressDialog.qml (cherry picked from commit 73c923bb522ad711380a2fcdaa9babe9f01a639a) --- interface/resources/qml/hifi/tablet/TabletAddressDialog.qml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index b3d56f02f2..4699bfd66b 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -25,8 +25,8 @@ StackView { HifiConstants { id: hifi } HifiStyles.HifiConstants { id: hifiStyleConstants } initialItem: addressBarDialog - width: parent.width - height: parent.height + width: parent !== null ? parent.width : undefined + height: parent !== null ? parent.height : undefined property var eventBridge; property var allStories: []; property int cardWidth: 460; @@ -142,7 +142,9 @@ StackView { anchors { top: navBar.bottom right: parent.right + rightMargin: 16 left: parent.left + leftMargin: 16 } property int inputAreaHeight: 70 From 7318ec468b7d1e5880a3f24910ad5afea239d0c6 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Fri, 31 Mar 2017 16:01:43 +0200 Subject: [PATCH 033/128] Fixed warning QObject::connect: No such signal Desktop_QMLTYPE_217::sendToScript(QVariant) (cherry picked from commit ef4bea2cd4811364e65baec2c48ce2205a0e2cb3) --- libraries/gl/src/gl/OffscreenGLCanvas.cpp | 3 ++- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libraries/gl/src/gl/OffscreenGLCanvas.cpp b/libraries/gl/src/gl/OffscreenGLCanvas.cpp index e54846196b..fcb3195741 100644 --- a/libraries/gl/src/gl/OffscreenGLCanvas.cpp +++ b/libraries/gl/src/gl/OffscreenGLCanvas.cpp @@ -59,7 +59,8 @@ bool OffscreenGLCanvas::create(QOpenGLContext* sharedContext) { bool OffscreenGLCanvas::makeCurrent() { bool result = _context->makeCurrent(_offscreenSurface); - Q_ASSERT(result); + //Q_ASSERT(result); + std::call_once(_reportOnce, [this]{ qCDebug(glLogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION)); qCDebug(glLogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION)); diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index de0caf56a9..4842faa3ef 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -607,7 +607,11 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::functionmetaObject()->indexOfSignal("sendToScript"); + if (sendToScriptIndex != -1) { + connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant))); + } // The root item is ready. Associate it with the window. _rootItem = newItem; From 990e1379e3cc66e04e36c2f372b57713c65fb2a4 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Sat, 1 Apr 2017 20:33:46 +0200 Subject: [PATCH 034/128] Fix warning in Audio page. Revert commented out assert in OffscreenGLCanvas: move to separate task (cherry picked from commit d966979c2368b159cf5b96c5fd535411cda019b8) --- interface/resources/qml/hifi/Audio.qml | 4 ++-- libraries/gl/src/gl/OffscreenGLCanvas.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/Audio.qml b/interface/resources/qml/hifi/Audio.qml index deb44b9bd5..d0c3122100 100644 --- a/interface/resources/qml/hifi/Audio.qml +++ b/interface/resources/qml/hifi/Audio.qml @@ -127,7 +127,7 @@ Rectangle { text: hifi.glyphs.mic color: hifi.colors.primaryHighlight anchors.verticalCenter: parent.verticalCenter - font.pointSize: 27 + size: 32 } RalewayRegular { anchors.verticalCenter: parent.verticalCenter @@ -182,7 +182,7 @@ Rectangle { text: hifi.glyphs.unmuted color: hifi.colors.primaryHighlight anchors.verticalCenter: parent.verticalCenter - font.pointSize: 27 + size: 32 } RalewayRegular { anchors.verticalCenter: parent.verticalCenter diff --git a/libraries/gl/src/gl/OffscreenGLCanvas.cpp b/libraries/gl/src/gl/OffscreenGLCanvas.cpp index fcb3195741..e5c630d97e 100644 --- a/libraries/gl/src/gl/OffscreenGLCanvas.cpp +++ b/libraries/gl/src/gl/OffscreenGLCanvas.cpp @@ -59,7 +59,7 @@ bool OffscreenGLCanvas::create(QOpenGLContext* sharedContext) { bool OffscreenGLCanvas::makeCurrent() { bool result = _context->makeCurrent(_offscreenSurface); - //Q_ASSERT(result); + Q_ASSERT(result); std::call_once(_reportOnce, [this]{ qCDebug(glLogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION)); From 3090629f77fc43b18e1702356db5a1cdcabbb8c1 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 3 Apr 2017 18:51:39 +0100 Subject: [PATCH 035/128] clean up code --- interface/resources/qml/TabletBrowser.qml | 40 +++++++------------ .../resources/qml/controls/TabletWebView.qml | 34 ++++++---------- 2 files changed, 26 insertions(+), 48 deletions(-) diff --git a/interface/resources/qml/TabletBrowser.qml b/interface/resources/qml/TabletBrowser.qml index 312b811928..85fff59207 100644 --- a/interface/resources/qml/TabletBrowser.qml +++ b/interface/resources/qml/TabletBrowser.qml @@ -110,7 +110,6 @@ Item { Component.onCompleted: { // Ensure the JS from the web-engine makes it to our logging webview.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) { - console.log("TabletBrowser"); console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message); }); @@ -138,33 +137,22 @@ Item { } } - onActiveFocusOnPressChanged: { - console.log("on active focus changed"); - setActiveFocusOnPress(true); - } - - onNewViewRequested:{ - // desktop is not defined for web-entities - if (stackRoot.isDesktop) { - var component = Qt.createComponent("./Browser.qml"); - var newWindow = component.createObject(desktop); - request.openIn(newWindow.webView); - } else { - var component = Qt.createComponent("./TabletBrowser.qml"); - - if (component.status != Component.Ready) { - if (component.status == Component.Error) { - console.log("Error: " + component.errorString()); - } - return; + onNewViewRequested: { + var component = Qt.createComponent("./TabletBrowser.qml"); + + if (component.status != Component.Ready) { + if (component.status == Component.Error) { + console.log("Error: " + component.errorString()); } - var newWindow = component.createObject(); - newWindow.setProfile(webview.profile); - request.openIn(newWindow.webView); - newWindow.eventBridge = web.eventBridge; - stackRoot.push(newWindow); - newWindow.webView.forceActiveFocus(); + return; } + var newWindow = component.createObject(); + newWindow.setProfile(webview.profile); + request.openIn(newWindow.webView); + newWindow.eventBridge = web.eventBridge; + stackRoot.push(newWindow); + newWindow.webView.forceActiveFocus(); + } } diff --git a/interface/resources/qml/controls/TabletWebView.qml b/interface/resources/qml/controls/TabletWebView.qml index 890215a714..742ab2d333 100644 --- a/interface/resources/qml/controls/TabletWebView.qml +++ b/interface/resources/qml/controls/TabletWebView.qml @@ -112,6 +112,7 @@ Item { currentItem.goBack(); } else { stackRoot.pop(); + currentItem.webView.focus = true; currentItem.webView.forceActiveFocus(); web.address = currentItem.webView.url; } @@ -186,7 +187,6 @@ Item { Component.onCompleted: { // Ensure the JS from the web-engine makes it to our logging root.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) { - console.log("WebView.qml"); console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message); }); @@ -202,7 +202,6 @@ Item { keyboardRaised = false; punctuationMode = false; keyboard.resetShiftMode(false); - console.log("[DR] -> printing user string " + root.profile.httpUserAgent); // Required to support clicking on "hifi://" links if (WebEngineView.LoadStartedStatus == loadRequest.status) { var url = loadRequest.url.toString(); @@ -215,30 +214,21 @@ Item { } onNewViewRequested:{ - // desktop is not defined for web-entities - if (web.isDesktop) { - var component = Qt.createComponent("../Browser.qml"); - var newWindow = component.createObject(desktop); - newWindow.setProfile(root.profile); - request.openIn(newWindow.webView); - } else { - var component = Qt.createComponent("../TabletBrowser.qml"); - - if (component.status != Component.Ready) { - if (component.status == Component.Error) { - console.log("Error: " + component.errorString()); - } - return; + var component = Qt.createComponent("../TabletBrowser.qml"); + if (component.status != Component.Ready) { + if (component.status == Component.Error) { + console.log("Error: " + component.errorString()); } - var newWindow = component.createObject(); - newWindow.setProfile(root.profile); - request.openIn(newWindow.webView); - newWindow.eventBridge = web.eventBridge; - stackRoot.push(newWindow); + return; } + var newWindow = component.createObject(); + newWindow.setProfile(root.profile); + request.openIn(newWindow.webView); + newWindow.eventBridge = web.eventBridge; + stackRoot.push(newWindow); } } - + HiFiControls.Keyboard { id: keyboard raised: web.keyboardEnabled && web.keyboardRaised From 9e08925d7e5f2f7c58df1f222ba5a7c30bc17544 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 3 Apr 2017 11:34:29 -0700 Subject: [PATCH 036/128] involve clock time in _mouthTime calculation --- interface/src/avatar/Head.cpp | 16 +++++++++++++--- interface/src/avatar/Head.h | 2 ++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index f4fb844d9b..1e075fa0c8 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -235,6 +235,7 @@ void Head::calculateMouthShapes() { const float JAW_OPEN_RATE = 0.9f; const float JAW_CLOSE_RATE = 0.90f; const float TIMESTEP_CONSTANT = 0.0032f; + const float USECS_IN_SIXTIETH_SEC = (1.0f / 60.0f) * USECS_PER_SECOND; const float MMMM_POWER = 0.10f; const float SMILE_POWER = 0.10f; const float FUNNEL_POWER = 0.35f; @@ -251,11 +252,20 @@ void Head::calculateMouthShapes() { _audioJawOpen *= JAW_CLOSE_RATE; } _audioJawOpen = glm::clamp(_audioJawOpen, 0.0f, 1.0f); - _trailingAudioJawOpen = glm::mix(_trailingAudioJawOpen, _audioJawOpen, 0.99f); + _trailingAudioJawOpen = glm::mix(_trailingAudioJawOpen, _audioJawOpen, 0.99f); - // Advance time at a rate proportional to loudness, and move the mouth shapes through + // Advance time at a rate proportional to loudness, and move the mouth shapes through // a cycle at differing speeds to create a continuous random blend of shapes. - _mouthTime += sqrtf(_averageLoudness) * TIMESTEP_CONSTANT; + + quint64 now = usecTimestampNow(); + float timeRatio = 1.0f; + if (_calculateMouthShapesTime > 0) { + quint64 timeDelta = now - _calculateMouthShapesTime; + timeRatio = (float)timeDelta / USECS_IN_SIXTIETH_SEC; + } + _calculateMouthShapesTime = now; + + _mouthTime += sqrtf(_averageLoudness) * TIMESTEP_CONSTANT * timeRatio; _mouth2 = (sinf(_mouthTime * MMMM_SPEED) + 1.0f) * MMMM_POWER * glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN); _mouth3 = (sinf(_mouthTime * FUNNEL_SPEED) + 1.0f) * FUNNEL_POWER * glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN); _mouth4 = (sinf(_mouthTime * SMILE_SPEED) + 1.0f) * SMILE_POWER * glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN); diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index aa801e5eb5..609a1a039d 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -114,6 +114,8 @@ private: float _mouth2; float _mouth3; float _mouth4; + + quint64 _calculateMouthShapesTime { 0 }; float _mouthTime; glm::vec3 _saccade; From c3c73b209a51c4a3c31e0af2e2ef141c9c7856aa Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 3 Apr 2017 11:49:00 -0700 Subject: [PATCH 037/128] Fixing the bad rendering of the instanced primitives on 4.1 --- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 5 +++++ libraries/gl/src/gl/Config.h | 3 +++ libraries/gl/src/gl/OffscreenQmlSurface.cpp | 5 +++++ libraries/gpu-gl/src/gpu/gl41/GL41BackendTransform.cpp | 2 +- 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index a3cf91fcd5..f5d335adea 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -571,10 +571,15 @@ void OpenGLDisplayPlugin::compositeLayers() { compositeScene(); } + +#ifdef HIFI_ENABLE_NSIGHT_DEBUG + if (false) // do not compositeoverlay if running nsight debug +#endif { PROFILE_RANGE_EX(render_detail, "compositeOverlay", 0xff0077ff, (uint64_t)presentCount()) compositeOverlay(); } + auto compositorHelper = DependencyManager::get(); if (compositorHelper->getReticleVisible()) { PROFILE_RANGE_EX(render_detail, "compositePointer", 0xff0077ff, (uint64_t)presentCount()) diff --git a/libraries/gl/src/gl/Config.h b/libraries/gl/src/gl/Config.h index 7947bd45df..9efae96f2a 100644 --- a/libraries/gl/src/gl/Config.h +++ b/libraries/gl/src/gl/Config.h @@ -28,6 +28,9 @@ #include +// Uncomment this define and recompile to be able to avoid code path preventing to be able to run nsight graphics debug +//#define HIFI_ENABLE_NSIGHT_DEBUG 1 + #endif #endif // hifi_gpu_GPUConfig_h diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index de0caf56a9..07bc4179b7 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -278,6 +278,11 @@ void OffscreenQmlSurface::cleanup() { } void OffscreenQmlSurface::render() { + +#ifdef HIFI_ENABLE_NSIGHT_DEBUG + return; +#endif + if (_paused) { return; } diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTransform.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTransform.cpp index aa0a83689c..526bac9ec8 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTransform.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTransform.cpp @@ -95,7 +95,6 @@ void GL41Backend::updateTransform(const Batch& batch) { } else { if (!_transform._enabledDrawcallInfoBuffer) { glEnableVertexAttribArray(gpu::Stream::DRAW_CALL_INFO); // Make sure attrib array is enabled - glBindBuffer(GL_ARRAY_BUFFER, _transform._drawCallInfoBuffer); #ifdef GPU_STEREO_DRAWCALL_INSTANCED glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, (isStereo() ? 2 : 1)); #else @@ -103,6 +102,7 @@ void GL41Backend::updateTransform(const Batch& batch) { #endif _transform._enabledDrawcallInfoBuffer = true; } + glBindBuffer(GL_ARRAY_BUFFER, _transform._drawCallInfoBuffer); glVertexAttribIPointer(gpu::Stream::DRAW_CALL_INFO, 2, GL_UNSIGNED_SHORT, 0, _transform._drawCallInfoOffsets[batch._currentNamedCall]); } From 7f1095c590101893a1882dc9b35aea4992bd004f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 3 Apr 2017 11:55:08 -0700 Subject: [PATCH 038/128] use deltaTime rather than calling usecTimestampNow --- interface/src/avatar/Head.cpp | 65 +++++++++++++++++------------------ interface/src/avatar/Head.h | 2 +- 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 1e075fa0c8..2f4c717e39 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -71,6 +71,7 @@ void Head::reset() { } void Head::simulate(float deltaTime, bool isMine) { + // Update audio trailing average for rendering facial animations const float AUDIO_AVERAGING_SECS = 0.05f; const float AUDIO_LONG_TERM_AVERAGING_SECS = 30.0f; @@ -79,7 +80,8 @@ void Head::simulate(float deltaTime, bool isMine) { if (_longTermAverageLoudness == -1.0f) { _longTermAverageLoudness = _averageLoudness; } else { - _longTermAverageLoudness = glm::mix(_longTermAverageLoudness, _averageLoudness, glm::min(deltaTime / AUDIO_LONG_TERM_AVERAGING_SECS, 1.0f)); + _longTermAverageLoudness = glm::mix(_longTermAverageLoudness, _averageLoudness, + glm::min(deltaTime / AUDIO_LONG_TERM_AVERAGING_SECS, 1.0f)); } if (isMine) { @@ -94,7 +96,7 @@ void Head::simulate(float deltaTime, bool isMine) { if (typeid(*faceTracker) == typeid(DdeFaceTracker)) { if (Menu::getInstance()->isOptionChecked(MenuOption::UseAudioForMouth)) { - calculateMouthShapes(); + calculateMouthShapes(deltaTime); const int JAW_OPEN_BLENDSHAPE = 21; const int MMMM_BLENDSHAPE = 34; @@ -116,7 +118,7 @@ void Head::simulate(float deltaTime, bool isMine) { _isEyeTrackerConnected = eyeTracker->isTracking(); } } - + if (!_isFaceTrackerConnected) { if (!_isEyeTrackerConnected) { @@ -144,22 +146,23 @@ void Head::simulate(float deltaTime, bool isMine) { _timeWithoutTalking += deltaTime; if ((_averageLoudness - _longTermAverageLoudness) > TALKING_LOUDNESS) { _timeWithoutTalking = 0.0f; - + } else if (_timeWithoutTalking < BLINK_AFTER_TALKING && _timeWithoutTalking >= BLINK_AFTER_TALKING) { forceBlink = true; } - + // Update audio attack data for facial animation (eyebrows and mouth) const float AUDIO_ATTACK_AVERAGING_RATE = 0.9f; - _audioAttack = AUDIO_ATTACK_AVERAGING_RATE * _audioAttack + (1.0f - AUDIO_ATTACK_AVERAGING_RATE) * fabs((_audioLoudness - _longTermAverageLoudness) - _lastLoudness); + _audioAttack = AUDIO_ATTACK_AVERAGING_RATE * _audioAttack + + (1.0f - AUDIO_ATTACK_AVERAGING_RATE) * fabs((_audioLoudness - _longTermAverageLoudness) - _lastLoudness); _lastLoudness = (_audioLoudness - _longTermAverageLoudness); - + const float BROW_LIFT_THRESHOLD = 100.0f; if (_audioAttack > BROW_LIFT_THRESHOLD) { _browAudioLift += sqrtf(_audioAttack) * 0.01f; } _browAudioLift = glm::clamp(_browAudioLift *= 0.7f, 0.0f, 1.0f); - + const float BLINK_SPEED = 10.0f; const float BLINK_SPEED_VARIABILITY = 1.0f; const float BLINK_START_VARIABILITY = 0.25f; @@ -169,8 +172,9 @@ void Head::simulate(float deltaTime, bool isMine) { // no blinking when brows are raised; blink less with increasing loudness const float BASE_BLINK_RATE = 15.0f / 60.0f; const float ROOT_LOUDNESS_TO_BLINK_INTERVAL = 0.25f; - if (forceBlink || (_browAudioLift < EPSILON && shouldDo(glm::max(1.0f, sqrt(fabs(_averageLoudness - _longTermAverageLoudness)) * - ROOT_LOUDNESS_TO_BLINK_INTERVAL) / BASE_BLINK_RATE, deltaTime))) { + if (forceBlink || + (_browAudioLift < EPSILON && shouldDo(glm::max(1.0f, sqrt(fabs(_averageLoudness - _longTermAverageLoudness)) * + ROOT_LOUDNESS_TO_BLINK_INTERVAL) / BASE_BLINK_RATE, deltaTime))) { _leftEyeBlinkVelocity = BLINK_SPEED + randFloat() * BLINK_SPEED_VARIABILITY; _rightEyeBlinkVelocity = BLINK_SPEED + randFloat() * BLINK_SPEED_VARIABILITY; if (randFloat() < 0.5f) { @@ -182,23 +186,23 @@ void Head::simulate(float deltaTime, bool isMine) { } else { _leftEyeBlink = glm::clamp(_leftEyeBlink + _leftEyeBlinkVelocity * deltaTime, FULLY_OPEN, FULLY_CLOSED); _rightEyeBlink = glm::clamp(_rightEyeBlink + _rightEyeBlinkVelocity * deltaTime, FULLY_OPEN, FULLY_CLOSED); - + if (_leftEyeBlink == FULLY_CLOSED) { _leftEyeBlinkVelocity = -BLINK_SPEED; - + } else if (_leftEyeBlink == FULLY_OPEN) { _leftEyeBlinkVelocity = 0.0f; } if (_rightEyeBlink == FULLY_CLOSED) { _rightEyeBlinkVelocity = -BLINK_SPEED; - + } else if (_rightEyeBlink == FULLY_OPEN) { _rightEyeBlinkVelocity = 0.0f; } } - + // use data to update fake Faceshift blendshape coefficients - calculateMouthShapes(); + calculateMouthShapes(deltaTime); DependencyManager::get()->updateFakeCoefficients(_leftEyeBlink, _rightEyeBlink, _browAudioLift, @@ -216,7 +220,7 @@ void Head::simulate(float deltaTime, bool isMine) { if (Menu::getInstance()->isOptionChecked(MenuOption::FixGaze)) { // if debug menu turns off, use no saccade _saccade = glm::vec3(); } - + _leftEyePosition = _rightEyePosition = getPosition(); _eyePosition = getPosition(); @@ -230,12 +234,12 @@ void Head::simulate(float deltaTime, bool isMine) { _eyePosition = calculateAverageEyePosition(); } -void Head::calculateMouthShapes() { +void Head::calculateMouthShapes(float deltaTime) { const float JAW_OPEN_SCALE = 0.015f; const float JAW_OPEN_RATE = 0.9f; const float JAW_CLOSE_RATE = 0.90f; const float TIMESTEP_CONSTANT = 0.0032f; - const float USECS_IN_SIXTIETH_SEC = (1.0f / 60.0f) * USECS_PER_SECOND; + // const float USECS_IN_SIXTIETH_SEC = (1.0f / 60.0f) * USECS_PER_SECOND; const float MMMM_POWER = 0.10f; const float SMILE_POWER = 0.10f; const float FUNNEL_POWER = 0.35f; @@ -247,9 +251,9 @@ void Head::calculateMouthShapes() { // From the change in loudness, decide how much to open or close the jaw float audioDelta = sqrtf(glm::max(_averageLoudness - _longTermAverageLoudness, 0.0f)) * JAW_OPEN_SCALE; if (audioDelta > _audioJawOpen) { - _audioJawOpen += (audioDelta - _audioJawOpen) * JAW_OPEN_RATE; + _audioJawOpen += (audioDelta - _audioJawOpen) * JAW_OPEN_RATE * deltaTime; } else { - _audioJawOpen *= JAW_CLOSE_RATE; + _audioJawOpen *= JAW_CLOSE_RATE * deltaTime; } _audioJawOpen = glm::clamp(_audioJawOpen, 0.0f, 1.0f); _trailingAudioJawOpen = glm::mix(_trailingAudioJawOpen, _audioJawOpen, 0.99f); @@ -257,18 +261,13 @@ void Head::calculateMouthShapes() { // Advance time at a rate proportional to loudness, and move the mouth shapes through // a cycle at differing speeds to create a continuous random blend of shapes. - quint64 now = usecTimestampNow(); - float timeRatio = 1.0f; - if (_calculateMouthShapesTime > 0) { - quint64 timeDelta = now - _calculateMouthShapesTime; - timeRatio = (float)timeDelta / USECS_IN_SIXTIETH_SEC; - } - _calculateMouthShapesTime = now; - - _mouthTime += sqrtf(_averageLoudness) * TIMESTEP_CONSTANT * timeRatio; - _mouth2 = (sinf(_mouthTime * MMMM_SPEED) + 1.0f) * MMMM_POWER * glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN); - _mouth3 = (sinf(_mouthTime * FUNNEL_SPEED) + 1.0f) * FUNNEL_POWER * glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN); - _mouth4 = (sinf(_mouthTime * SMILE_SPEED) + 1.0f) * SMILE_POWER * glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN); + _mouthTime += sqrtf(_averageLoudness) * TIMESTEP_CONSTANT * deltaTime; + _mouth2 = (sinf(_mouthTime * MMMM_SPEED) + 1.0f) * MMMM_POWER * + glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN) * deltaTime; + _mouth3 = (sinf(_mouthTime * FUNNEL_SPEED) + 1.0f) * FUNNEL_POWER * + glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN) * deltaTime; + _mouth4 = (sinf(_mouthTime * SMILE_SPEED) + 1.0f) * SMILE_POWER * + glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN) * deltaTime; } void Head::applyEyelidOffset(glm::quat headOrientation) { @@ -331,7 +330,7 @@ glm::quat Head::getFinalOrientationInLocalFrame() const { // // Everyone else's head also keeps track of a correctedLookAtPosition that may be different for the same head within // different Interfaces. If that head is not looking at me, the correctedLookAtPosition is the same as the lookAtPosition. -// However, if that head is looking at me, then I will attempt to adjust the lookAtPosition by the difference between +// However, if that head is looking at me, then I will attempt to adjust the lookAtPosition by the difference between // my (singular) eye position and my actual camera position. This adjustment is used on their eyeballs during rendering // (and also on any lookAt vector display for that head, during rendering). Note that: // 1. this adjustment can be made directly to the other head's eyeball joints, because we won't be send their joint information to others. diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 609a1a039d..21eccfb7cd 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -140,7 +140,7 @@ private: int _rightEyeLookAtID; // private methods - void calculateMouthShapes(); + void calculateMouthShapes(float timeRatio); void applyEyelidOffset(glm::quat headOrientation); }; From d726bd352dc9ab67d73efa804d5ed4198f308944 Mon Sep 17 00:00:00 2001 From: Faye Li Date: Mon, 3 Apr 2017 12:14:29 -0700 Subject: [PATCH 039/128] fix for locked camera state issue --- scripts/developer/utilities/render/photobooth/photoboothApp.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/developer/utilities/render/photobooth/photoboothApp.js b/scripts/developer/utilities/render/photobooth/photoboothApp.js index 675db14be3..dcbf363c3d 100644 --- a/scripts/developer/utilities/render/photobooth/photoboothApp.js +++ b/scripts/developer/utilities/render/photobooth/photoboothApp.js @@ -188,11 +188,11 @@ }); Entities.deleteEntity(this.modelEntityID); photoboothCreated = false; + Camera.mode = "first person"; }; function cleanup() { tablet.removeButton(button); - Camera.mode = "first person"; PhotoBooth.destroy(); } Script.scriptEnding.connect(cleanup); From 2ca4203d85c9eece148743b7bc83ea2a9b0aa607 Mon Sep 17 00:00:00 2001 From: Faye Li Date: Mon, 3 Apr 2017 12:57:51 -0700 Subject: [PATCH 040/128] fix for submerge in floor issue --- .../utilities/render/photobooth/photoboothApp.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/developer/utilities/render/photobooth/photoboothApp.js b/scripts/developer/utilities/render/photobooth/photoboothApp.js index dcbf363c3d..154028f091 100644 --- a/scripts/developer/utilities/render/photobooth/photoboothApp.js +++ b/scripts/developer/utilities/render/photobooth/photoboothApp.js @@ -102,16 +102,16 @@ var success = Clipboard.importEntities(PHOTOBOOTH_SETUP_JSON_URL); var frontFactor = 10; // getForward is preffered as getFront function is deprecated - var frontUnitVec = (typeof Quat.getForward === "undefined") ? Vec3.normalize(Quat.getFront(MyAvatar.orientation)) : Vec3.normalize(Quat.getForward(MyAvatar.orientation)); + var frontUnitVec = Vec3.normalize(Quat.getFront(MyAvatar.orientation)); var frontOffset = Vec3.multiply(frontUnitVec,frontFactor); - var rightFactor = 3; - var rightUnitVec = Vec3.normalize(Quat.getRight(MyAvatar.orientation)); - var rightOffset = Vec3.multiply(rightUnitVec,rightFactor); - var spawnLocation = Vec3.sum(Vec3.sum(MyAvatar.position,frontOffset),rightOffset); + var upFactor = 3; + var upUnitVec = Vec3.normalize(Quat.getUp(MyAvatar.orientation)); + var upOffset = Vec3.multiply(upUnitVec, upFactor); + var spawnLocation = Vec3.sum(MyAvatar.position,frontOffset); + spawnLocation = Vec3.sum(spawnLocation, upOffset); if (success) { this.pastedEntityIDs = Clipboard.pasteEntities(spawnLocation); this.processPastedEntities(); - } }; From 29913326523622fb7a39b5b8e64afa917641c331 Mon Sep 17 00:00:00 2001 From: trent Date: Mon, 3 Apr 2017 16:46:22 -0400 Subject: [PATCH 041/128] Rewrote the OBJ reader (again) to use FBXMeshPart instead of separate meshes. Works now! Multi-material support win. --- libraries/fbx/src/OBJReader.cpp | 81 +++++++++++++++++---------------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 7f6f6a210a..af58cef6ad 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -440,7 +440,9 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, // add a new meshPart to the geometry's single mesh. while (parseOBJGroup(tokenizer, mapping, geometry, scaleGuess)) {} -// FBXMesh& mesh = geometry.meshes[0]; + FBXMesh& mesh = geometry.meshes[0]; + mesh.meshIndex = 0; + geometry.joints.resize(1); geometry.joints[0].isFree = false; geometry.joints[0].parentIndex = -1; @@ -459,11 +461,14 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); + mesh.clusters.append(cluster); QMap materialMeshIdMap; - QVector fbxMeshes; - for (int i = 0, meshPartCount = 0; i < geometry.meshes[0].parts.count(); i++, meshPartCount++) { - FaceGroup faceGroup = faceGroups[meshPartCount]; + QVector fbxMeshParts; + int meshPartCount = 0; + for (int i = 0, meshPartCount = 0; i < mesh.parts.count(); i++, meshPartCount++) { + FBXMeshPart& meshPart = mesh.parts[i]; + FaceGroup faceGroup = faceGroups[meshPartCount]; bool specifiesUV = false; foreach(OBJFace face, faceGroup) { // Go through all of the OBJ faces and determine the number of different materials necessary (each different material will be a unique mesh). @@ -472,11 +477,11 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, // Create a new FBXMesh for this material mapping. materialMeshIdMap.insert(face.materialName, materialMeshIdMap.count()); - FBXMesh meshNew; - meshNew.modelTransform = geometry.meshes[0].modelTransform; - meshNew.meshExtents = geometry.meshes[0].meshExtents; - meshNew.meshIndex = 0;// fbxMeshes.count(); - meshNew.clusters.append(cluster); + fbxMeshParts.append(FBXMeshPart()); + FBXMeshPart& meshPartNew = fbxMeshParts.last(); + meshPartNew.quadIndices = QVector(meshPart.quadIndices); // Copy over quad indices [NOTE (trent/mittens, 4/3/17): Likely unnecessary since they go unused anyway]. + meshPartNew.quadTrianglesIndices = QVector(meshPart.quadTrianglesIndices); // Copy over quad triangulated indices [NOTE (trent/mittens, 4/3/17): Likely unnecessary since they go unused anyway]. + meshPartNew.triangleIndices = QVector(meshPart.triangleIndices); // Copy over triangle indices. // Do some of the material logic (which previously lived below) now. // All the faces in the same group will have the same name and material. @@ -499,21 +504,23 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, needsMaterialLibrary = groupMaterialName != SMART_DEFAULT_MATERIAL_NAME; } materials[groupMaterialName] = material; - geometry.meshes[0].parts[i].materialID = groupMaterialName; + meshPartNew.materialID = groupMaterialName; } - - // Add this mesh part. - meshNew.parts.append(FBXMeshPart(geometry.meshes[0].parts[i])); - - // Add it to the mesh vector. - fbxMeshes.append(meshNew); } } + } + + // clean up old mesh parts. + int unmodifiedMeshPartCount = mesh.parts.count(); + mesh.parts.clear(); + mesh.parts = QVector(fbxMeshParts); + + for (int i = 0, meshPartCount = 0; i < unmodifiedMeshPartCount; i++, meshPartCount++) { + FaceGroup faceGroup = faceGroups[meshPartCount]; // Now that each mesh has been created with its own unique material mappings, fill them with data (vertex data is duplicated, face data is not). foreach(OBJFace face, faceGroup) { - FBXMesh& mesh = fbxMeshes[materialMeshIdMap[face.materialName]]; - FBXMeshPart& meshPart = mesh.parts.last(); + FBXMeshPart& meshPart = mesh.parts[materialMeshIdMap[face.materialName]]; glm::vec3 v0 = checked_at(vertices, face.vertexIndices[0]); glm::vec3 v1 = checked_at(vertices, face.vertexIndices[1]); @@ -528,11 +535,11 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, // Add the vertices. meshPart.triangleIndices.append(mesh.vertices.count()); // not face.vertexIndices into vertices - mesh.vertices.append(v0); + mesh.vertices << v0; meshPart.triangleIndices.append(mesh.vertices.count()); - mesh.vertices.append(v1); + mesh.vertices << v1; meshPart.triangleIndices.append(mesh.vertices.count()); - mesh.vertices.append(v2); + mesh.vertices << v2; glm::vec3 n0, n1, n2; if (face.normalIndices.count()) { @@ -548,39 +555,33 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, mesh.normals.append(n1); mesh.normals.append(n2); if (face.textureUVIndices.count()) { - specifiesUV = true; - mesh.texCoords.append(checked_at(textureUVs, face.textureUVIndices[0])); - mesh.texCoords.append(checked_at(textureUVs, face.textureUVIndices[1])); - mesh.texCoords.append(checked_at(textureUVs, face.textureUVIndices[2])); + mesh.texCoords << + checked_at(textureUVs, face.textureUVIndices[0]) << + checked_at(textureUVs, face.textureUVIndices[1]) << + checked_at(textureUVs, face.textureUVIndices[2]); } else { glm::vec2 corner(0.0f, 1.0f); - mesh.texCoords.append(corner); - mesh.texCoords.append(corner); - mesh.texCoords.append(corner); + mesh.texCoords << corner << corner << corner; } } } - geometry.meshes.clear(); - foreach(FBXMesh mesh, fbxMeshes) { - geometry.meshes.append(mesh); - - mesh.meshExtents.reset(); - foreach(const glm::vec3& vertex, mesh.vertices) { - mesh.meshExtents.addPoint(vertex); - geometry.meshExtents.addPoint(vertex); - } - - FBXReader::buildModelMesh(mesh, url.toString()); + mesh.meshExtents.reset(); + foreach(const glm::vec3& vertex, mesh.vertices) { + mesh.meshExtents.addPoint(vertex); + geometry.meshExtents.addPoint(vertex); } + // Build the single mesh. + FBXReader::buildModelMesh(mesh, url.toString()); + // fbxDebugDump(geometry); } catch(const std::exception& e) { qCDebug(modelformat) << "OBJ reader fail: " << e.what(); } - QString queryPart = _url.query(); + QString queryPart = _url.query(); bool suppressMaterialsHack = queryPart.contains("hifiusemat"); // If this appears in query string, don't fetch mtl even if used. OBJMaterial& preDefinedMaterial = materials[SMART_DEFAULT_MATERIAL_NAME]; preDefinedMaterial.used = true; From 6ed4295b8bb9d102af401ef4c07c0652bad7c9a0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 3 Apr 2017 13:55:11 -0700 Subject: [PATCH 042/128] make sure HeadData is present before processing recording frames --- assignment-client/src/Agent.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 4cf4049824..e28c04379f 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -336,6 +336,10 @@ void Agent::executeScript() { // call model URL setters with empty URLs so our avatar, if user, will have the default models scriptedAvatar->setSkeletonModelURL(QUrl()); + // force lazy initialization of the head data for the scripted avatar + // since it is referenced below by computeLoudness and getAudioLoudness + scriptedAvatar->getHeadOrientation(); + // give this AvatarData object to the script engine _scriptEngine->registerGlobalObject("Avatar", scriptedAvatar.data()); From 7ac09398bec8a0c3d85a20b42942176de460b50f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 3 Apr 2017 14:44:05 -0700 Subject: [PATCH 043/128] include deltaTime in audioAttack running average --- interface/src/avatar/Head.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 2f4c717e39..279aa4c73b 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -152,9 +152,9 @@ void Head::simulate(float deltaTime, bool isMine) { } // Update audio attack data for facial animation (eyebrows and mouth) - const float AUDIO_ATTACK_AVERAGING_RATE = 0.9f; - _audioAttack = AUDIO_ATTACK_AVERAGING_RATE * _audioAttack + - (1.0f - AUDIO_ATTACK_AVERAGING_RATE) * fabs((_audioLoudness - _longTermAverageLoudness) - _lastLoudness); + const float audioAttackAveragingRate = (10.0f - deltaTime * 90.0f) / 10.0f; // --> 0.9 at 90 Hz + _audioAttack = audioAttackAveragingRate * _audioAttack + + (1.0f - audioAttackAveragingRate) * fabs((_audioLoudness - _longTermAverageLoudness) - _lastLoudness); _lastLoudness = (_audioLoudness - _longTermAverageLoudness); const float BROW_LIFT_THRESHOLD = 100.0f; @@ -238,8 +238,7 @@ void Head::calculateMouthShapes(float deltaTime) { const float JAW_OPEN_SCALE = 0.015f; const float JAW_OPEN_RATE = 0.9f; const float JAW_CLOSE_RATE = 0.90f; - const float TIMESTEP_CONSTANT = 0.0032f; - // const float USECS_IN_SIXTIETH_SEC = (1.0f / 60.0f) * USECS_PER_SECOND; + const float TIMESTEP_CONSTANT = 0.288f; const float MMMM_POWER = 0.10f; const float SMILE_POWER = 0.10f; const float FUNNEL_POWER = 0.35f; @@ -262,12 +261,9 @@ void Head::calculateMouthShapes(float deltaTime) { // a cycle at differing speeds to create a continuous random blend of shapes. _mouthTime += sqrtf(_averageLoudness) * TIMESTEP_CONSTANT * deltaTime; - _mouth2 = (sinf(_mouthTime * MMMM_SPEED) + 1.0f) * MMMM_POWER * - glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN) * deltaTime; - _mouth3 = (sinf(_mouthTime * FUNNEL_SPEED) + 1.0f) * FUNNEL_POWER * - glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN) * deltaTime; - _mouth4 = (sinf(_mouthTime * SMILE_SPEED) + 1.0f) * SMILE_POWER * - glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN) * deltaTime; + _mouth2 = (sinf(_mouthTime * MMMM_SPEED) + 1.0f) * MMMM_POWER * glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN); + _mouth3 = (sinf(_mouthTime * FUNNEL_SPEED) + 1.0f) * FUNNEL_POWER * glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN); + _mouth4 = (sinf(_mouthTime * SMILE_SPEED) + 1.0f) * SMILE_POWER * glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN); } void Head::applyEyelidOffset(glm::quat headOrientation) { From d4112f0e3691f2a7a56ea3124083050e0c928b74 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 3 Apr 2017 14:57:02 -0700 Subject: [PATCH 044/128] use full relative filepath for texture caching/referencing --- libraries/fbx/src/FBXReader.cpp | 17 ++++++++--------- libraries/fbx/src/FBXReader.h | 2 -- libraries/fbx/src/FBXReader_Material.cpp | 9 ++------- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 64ee0bc869..7bab0415f8 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -376,10 +376,10 @@ public: }; bool checkMaterialsHaveTextures(const QHash& materials, - const QHash& textureFilenames, const QMultiMap& _connectionChildMap) { + const QHash& textureFilepaths, const QMultiMap& _connectionChildMap) { foreach (const QString& materialID, materials.keys()) { foreach (const QString& childID, _connectionChildMap.values(materialID)) { - if (textureFilenames.contains(childID)) { + if (textureFilepaths.contains(childID)) { return true; } } @@ -833,11 +833,10 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS const int MODEL_UV_SCALING_MIN_SIZE = 2; const int CROPPING_MIN_SIZE = 4; if (subobject.name == "RelativeFilename" && subobject.properties.length() >= RELATIVE_FILENAME_MIN_SIZE) { - QByteArray filename = subobject.properties.at(0).toByteArray(); - QByteArray filepath = filename.replace('\\', '/'); - filename = fileOnUrl(filepath, url); + QByteArray filepath = subobject.properties.at(0).toByteArray(); + filepath = filepath.replace('\\', '/'); + _textureFilepaths.insert(getID(object.properties), filepath); - _textureFilenames.insert(getID(object.properties), filename); } else if (subobject.name == "TextureName" && subobject.properties.length() >= TEXTURE_NAME_MIN_SIZE) { // trim the name from the timestamp QString name = QString(subobject.properties.at(0).toByteArray()); @@ -930,7 +929,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS QByteArray content; foreach (const FBXNode& subobject, object.children) { if (subobject.name == "RelativeFilename") { - filepath= subobject.properties.at(0).toByteArray(); + filepath = subobject.properties.at(0).toByteArray(); filepath = filepath.replace('\\', '/'); } else if (subobject.name == "Content" && !subobject.properties.isEmpty()) { @@ -1502,7 +1501,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS geometry.materials = _fbxMaterials; // see if any materials have texture children - bool materialsHaveTextures = checkMaterialsHaveTextures(_fbxMaterials, _textureFilenames, _connectionChildMap); + bool materialsHaveTextures = checkMaterialsHaveTextures(_fbxMaterials, _textureFilepaths, _connectionChildMap); for (QMap::iterator it = meshes.begin(); it != meshes.end(); it++) { ExtractedMesh& extracted = it.value(); @@ -1547,7 +1546,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS materialIndex++; - } else if (_textureFilenames.contains(childID)) { + } else if (_textureFilepaths.contains(childID)) { FBXTexture texture = getTexture(childID); for (int j = 0; j < extracted.partMaterialTextures.size(); j++) { int partTexture = extracted.partMaterialTextures.at(j).second; diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index f73088e7a1..79133c4c4a 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -413,8 +413,6 @@ public: QHash _textureNames; // Hashes the original RelativeFilename of textures QHash _textureFilepaths; - // Hashes the place to look for textures, in case they are not inlined - QHash _textureFilenames; // Hashes texture content by filepath, in case they are inlined QHash _textureContent; QHash _textureParams; diff --git a/libraries/fbx/src/FBXReader_Material.cpp b/libraries/fbx/src/FBXReader_Material.cpp index ca2ec557b4..2f63d894fd 100644 --- a/libraries/fbx/src/FBXReader_Material.cpp +++ b/libraries/fbx/src/FBXReader_Material.cpp @@ -85,12 +85,7 @@ FBXTexture FBXReader::getTexture(const QString& textureID) { FBXTexture texture; const QByteArray& filepath = _textureFilepaths.value(textureID); texture.content = _textureContent.value(filepath); - - if (texture.content.isEmpty()) { // the content is not inlined - texture.filename = _textureFilenames.value(textureID); - } else { // use supplied filepath for inlined content - texture.filename = filepath; - } + texture.filename = filepath; texture.name = _textureNames.value(textureID); texture.transform.setIdentity(); @@ -155,7 +150,7 @@ void FBXReader::consolidateFBXMaterials(const QVariantHash& mapping) { // FBX files generated by 3DSMax have an intermediate texture parent, apparently foreach(const QString& childTextureID, _connectionChildMap.values(diffuseTextureID)) { - if (_textureFilenames.contains(childTextureID)) { + if (_textureFilepaths.contains(childTextureID)) { diffuseTexture = getTexture(diffuseTextureID); } } From 55c2d367527ab76bd3cdbefbdbd9a161d9233b87 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 3 Apr 2017 15:30:06 -0700 Subject: [PATCH 045/128] math fixes, cleanups --- interface/src/avatar/Head.cpp | 26 ++++++++++++++------------ interface/src/avatar/Head.h | 2 -- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 279aa4c73b..4e748037a4 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -71,6 +71,7 @@ void Head::reset() { } void Head::simulate(float deltaTime, bool isMine) { + const float NORMAL_HZ = 60.0f; // the update rate the constant values were tuned for // Update audio trailing average for rendering facial animations const float AUDIO_AVERAGING_SECS = 0.05f; @@ -80,8 +81,7 @@ void Head::simulate(float deltaTime, bool isMine) { if (_longTermAverageLoudness == -1.0f) { _longTermAverageLoudness = _averageLoudness; } else { - _longTermAverageLoudness = glm::mix(_longTermAverageLoudness, _averageLoudness, - glm::min(deltaTime / AUDIO_LONG_TERM_AVERAGING_SECS, 1.0f)); + _longTermAverageLoudness = glm::mix(_longTermAverageLoudness, _averageLoudness, glm::min(deltaTime / AUDIO_LONG_TERM_AVERAGING_SECS, 1.0f)); } if (isMine) { @@ -152,7 +152,7 @@ void Head::simulate(float deltaTime, bool isMine) { } // Update audio attack data for facial animation (eyebrows and mouth) - const float audioAttackAveragingRate = (10.0f - deltaTime * 90.0f) / 10.0f; // --> 0.9 at 90 Hz + float audioAttackAveragingRate = (10.0f - deltaTime * NORMAL_HZ) / 10.0f; // --> 0.9 at 60 Hz _audioAttack = audioAttackAveragingRate * _audioAttack + (1.0f - audioAttackAveragingRate) * fabs((_audioLoudness - _longTermAverageLoudness) - _lastLoudness); _lastLoudness = (_audioLoudness - _longTermAverageLoudness); @@ -172,9 +172,8 @@ void Head::simulate(float deltaTime, bool isMine) { // no blinking when brows are raised; blink less with increasing loudness const float BASE_BLINK_RATE = 15.0f / 60.0f; const float ROOT_LOUDNESS_TO_BLINK_INTERVAL = 0.25f; - if (forceBlink || - (_browAudioLift < EPSILON && shouldDo(glm::max(1.0f, sqrt(fabs(_averageLoudness - _longTermAverageLoudness)) * - ROOT_LOUDNESS_TO_BLINK_INTERVAL) / BASE_BLINK_RATE, deltaTime))) { + if (forceBlink || (_browAudioLift < EPSILON && shouldDo(glm::max(1.0f, sqrt(fabs(_averageLoudness - _longTermAverageLoudness)) * + ROOT_LOUDNESS_TO_BLINK_INTERVAL) / BASE_BLINK_RATE, deltaTime))) { _leftEyeBlinkVelocity = BLINK_SPEED + randFloat() * BLINK_SPEED_VARIABILITY; _rightEyeBlinkVelocity = BLINK_SPEED + randFloat() * BLINK_SPEED_VARIABILITY; if (randFloat() < 0.5f) { @@ -238,7 +237,7 @@ void Head::calculateMouthShapes(float deltaTime) { const float JAW_OPEN_SCALE = 0.015f; const float JAW_OPEN_RATE = 0.9f; const float JAW_CLOSE_RATE = 0.90f; - const float TIMESTEP_CONSTANT = 0.288f; + const float TIMESTEP_CONSTANT = 0.0032f; const float MMMM_POWER = 0.10f; const float SMILE_POWER = 0.10f; const float FUNNEL_POWER = 0.35f; @@ -246,21 +245,24 @@ void Head::calculateMouthShapes(float deltaTime) { const float SMILE_SPEED = 1.0f; const float FUNNEL_SPEED = 2.335f; const float STOP_GAIN = 5.0f; + const float NORMAL_HZ = 60.0f; // the update rate the constant values were tuned for + + float deltaTimeRatio = deltaTime / (1.0f / NORMAL_HZ); // From the change in loudness, decide how much to open or close the jaw float audioDelta = sqrtf(glm::max(_averageLoudness - _longTermAverageLoudness, 0.0f)) * JAW_OPEN_SCALE; if (audioDelta > _audioJawOpen) { - _audioJawOpen += (audioDelta - _audioJawOpen) * JAW_OPEN_RATE * deltaTime; + _audioJawOpen += (audioDelta - _audioJawOpen) * JAW_OPEN_RATE * deltaTimeRatio; } else { - _audioJawOpen *= JAW_CLOSE_RATE * deltaTime; + _audioJawOpen *= powf(JAW_CLOSE_RATE, deltaTimeRatio); } _audioJawOpen = glm::clamp(_audioJawOpen, 0.0f, 1.0f); - _trailingAudioJawOpen = glm::mix(_trailingAudioJawOpen, _audioJawOpen, 0.99f); + float trailingAudioJawOpenRatio = (100.0f - deltaTime * NORMAL_HZ) / 100.0f; // --> 0.99 at 60 Hz + _trailingAudioJawOpen = glm::mix(_trailingAudioJawOpen, _audioJawOpen, trailingAudioJawOpenRatio); // Advance time at a rate proportional to loudness, and move the mouth shapes through // a cycle at differing speeds to create a continuous random blend of shapes. - - _mouthTime += sqrtf(_averageLoudness) * TIMESTEP_CONSTANT * deltaTime; + _mouthTime += sqrtf(_averageLoudness) * TIMESTEP_CONSTANT * deltaTimeRatio; _mouth2 = (sinf(_mouthTime * MMMM_SPEED) + 1.0f) * MMMM_POWER * glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN); _mouth3 = (sinf(_mouthTime * FUNNEL_SPEED) + 1.0f) * FUNNEL_POWER * glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN); _mouth4 = (sinf(_mouthTime * SMILE_SPEED) + 1.0f) * SMILE_POWER * glm::min(1.0f, _trailingAudioJawOpen * STOP_GAIN); diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 21eccfb7cd..fd20e709f5 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -114,8 +114,6 @@ private: float _mouth2; float _mouth3; float _mouth4; - - quint64 _calculateMouthShapesTime { 0 }; float _mouthTime; glm::vec3 _saccade; From 4629accc9c39607801820547e113e65c5ea833ec Mon Sep 17 00:00:00 2001 From: David Kelly Date: Mon, 3 Apr 2017 15:35:53 -0700 Subject: [PATCH 046/128] style updates --- .../resources/qml/controls-uit/CheckBox.qml | 8 ++-- interface/resources/qml/hifi/ComboDialog.qml | 18 ++++---- interface/resources/qml/hifi/Pal.qml | 46 ++++++------------- 3 files changed, 27 insertions(+), 45 deletions(-) diff --git a/interface/resources/qml/controls-uit/CheckBox.qml b/interface/resources/qml/controls-uit/CheckBox.qml index 60e136d13a..bb138e07c6 100644 --- a/interface/resources/qml/controls-uit/CheckBox.qml +++ b/interface/resources/qml/controls-uit/CheckBox.qml @@ -19,12 +19,11 @@ Original.CheckBox { property int colorScheme: hifi.colorSchemes.light readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light - + property bool isRedCheck: false property int boxSize: 14 readonly property int boxRadius: 3 readonly property int checkSize: Math.max(boxSize - 8, 10) readonly property int checkRadius: 2 - activeFocusOnPress: true style: CheckBoxStyle { @@ -37,6 +36,7 @@ Original.CheckBox { border.color: pressed || hovered ? hifi.colors.checkboxCheckedBorder : (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish) + gradient: Gradient { GradientStop { position: 0.2 @@ -68,9 +68,9 @@ Original.CheckBox { height: checkSize radius: checkRadius anchors.centerIn: parent - color: hifi.colors.checkboxChecked + color: isRedCheck ? "#FF0000" : hifi.colors.checkboxChecked border.width: 2 - border.color: hifi.colors.checkboxCheckedBorder + border.color: isRedCheck? "#D00000" : hifi.colors.checkboxCheckedBorder visible: checked && !pressed || !checked && pressed } diff --git a/interface/resources/qml/hifi/ComboDialog.qml b/interface/resources/qml/hifi/ComboDialog.qml index 7f50f37d54..8905ed9c17 100644 --- a/interface/resources/qml/hifi/ComboDialog.qml +++ b/interface/resources/qml/hifi/ComboDialog.qml @@ -14,11 +14,11 @@ import QtQuick.Controls 1.4 import "../styles-uit" Item { - property var dialogTitleText; - property var optionTitleText; - property var optionBodyText; - property var optionValues; - property var selectedOptionIndex; + property var dialogTitleText : ""; + property var optionTitleText: ""; + property var optionBodyText: ""; + property var optionValues: []; + property var selectedOptionIndex: 0; property var callbackFunction; property int dialogWidth; property int dialogHeight; @@ -51,12 +51,12 @@ Item { id: dialogContainer; color: "white"; anchors.centerIn: dialogBackground; - width: dialogWidth; - height: dialogHeight; + width: combo.dialogWidth; + height: combo.dialogHeight; RalewayRegular { id: dialogTitle; - text: dialogTitleText; + text: combo.dialogTitleText; anchors.top: parent.top; anchors.topMargin: 20; anchors.left: parent.left; @@ -154,4 +154,4 @@ Item { comboListViewModel.insert(index, {"titleText": titleText, "bodyText": optionBodyText[index], "optionValue": optionValues[index]}); }); } -} \ No newline at end of file +} diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index b7d31e06da..807a315693 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -512,6 +512,7 @@ Rectangle { // If this is an "Ignore" checkbox, disable the checkbox if user isn't present. enabled: styleData.role === "ignore" ? (model ? model["isPresent"] : true) : true; boxSize: 24; + isRedCheck: true onClicked: { var newValue = !model[styleData.role]; nearbyUserModel.setProperty(model.userIndex, styleData.role, newValue); @@ -611,7 +612,7 @@ Rectangle { "Bold names in the list are avatar display names.
" + "Purple borders around profile pictures are connections.
" + "Green borders around profile pictures are friends.
" + - "(TEMPORARY LANGUAGE) In some situations, you can also see others' usernames.
" + + "In some situations, you can also see others' usernames.
" + "If you can see someone's username, you can GoTo them by selecting them in the PAL, then clicking their name.
" + "
If someone's display name isn't set, a unique session display name is assigned to them.
" + "
Administrators of this domain can also see the username or machine ID associated with each avatar present."); @@ -948,7 +949,7 @@ Rectangle { } Item { id: upperRightInfoContainer; - width: 160; + width: 200; height: parent.height; anchors.top: parent.top; anchors.right: parent.right; @@ -959,7 +960,7 @@ Rectangle { // Text size size: hifi.fontSizes.tabularData; // Anchors - anchors.top: availabilityComboBox.bottom; + anchors.top: myCard.top; anchors.horizontalCenter: parent.horizontalCenter; // Style color: hifi.colors.baseGrayHighlight; @@ -972,13 +973,20 @@ Rectangle { id: availabilityComboBox; color: hifi.colors.textFieldLightBackground // Anchors - anchors.top: parent.top; + anchors.top: availabilityText.bottom; anchors.horizontalCenter: parent.horizontalCenter; // Size width: parent.width; height: 40; + function determineAvailabilityIndex() { + return ['all', 'connections', 'friends', 'none'].indexOf(GlobalServices.findableBy); + } + + function determineAvailabilityString() { + return availabilityStrings[determineAvailabilityIndex()]; + } RalewayRegular { - text: myData.userName === "Unknown user" ? "Login to Set" : availabilityStrings[GlobalServices.findableBy]; + text: myData.userName === "Unknown user" ? "Login to Set" : availabilityComboBox.determineAvailabilityString(); anchors.fill: parent; anchors.leftMargin: 10; horizontalAlignment: Text.AlignLeft; @@ -986,7 +994,7 @@ Rectangle { } MouseArea { anchors.fill: parent; - enabled: myData.userName ==! "Unknown user"; + enabled: myData.userName !== "Unknown user"; hoverEnabled: true; onClicked: { popupComboDialog("Set your availability:", @@ -1001,32 +1009,6 @@ Rectangle { onExited: availabilityComboBox.color = hifi.colors.textFieldLightBackground; } } - - /*HifiControlsUit.ComboBox { - function determineAvailabilityIndex() { - return ['all', 'connections', 'friends', 'none'].indexOf(GlobalServices.findableBy) - } - id: availabilityComboBox; - // Anchors - anchors.top: parent.top; - anchors.horizontalCenter: parent.horizontalCenter; - // Size - width: parent.width; - height: 40; - currentIndex: determineAvailabilityIndex(); - model: ListModel { - id: availabilityComboBoxListItems - ListElement { text: "Everyone"; value: "all"; } - ListElement { text: "All Connections"; value: "connections"; } - ListElement { text: "Friends Only"; value: "friends"; } - ListElement { text: "Appear Offline"; value: "none" } - } - onCurrentIndexChanged: { - GlobalServices.findableBy = availabilityComboBoxListItems.get(currentIndex).value; - UserActivityLogger.palAction("set_availability", availabilityComboBoxListItems.get(currentIndex).value); - print('Setting availability:', JSON.stringify(GlobalServices.findableBy)); - } - }*/ } } From b9fffc10f8dca69f064fb688735002edb67d4dfc Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 3 Apr 2017 15:51:19 -0700 Subject: [PATCH 047/128] Fix entity "unlock" edits not being propagated to clients The lastEditedBy property was not being updated when changing the locked property of entities from true to false. --- libraries/entities/src/EntityTree.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index d7471474a6..f544a4e5c7 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -182,6 +182,7 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI if (!wantsLocked) { EntityItemProperties tempProperties; tempProperties.setLocked(wantsLocked); + tempProperties.setLastEdited(properties.getLastEdited()); bool success; AACube queryCube = entity->getQueryAACube(success); From 8ff457a1b62e8a63e651516d5f30cda105cb0087 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 3 Apr 2017 16:03:55 -0700 Subject: [PATCH 048/128] Fix broken eventBridge on tablet after Reload All Scripts. The main issue here was the "webEventReceived" connection between the OffscreenQMLSurface and the TabletProxy object. For whatever reason, if this is not a direct Signal to Slot connection, the webEventReceived event does not propagate. --- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 2 + libraries/script-engine/src/ScriptEngine.cpp | 2 + .../src/TabletScriptingInterface.cpp | 12 +- .../src/TabletScriptingInterface.h | 5 +- .../developer/tests/tabletEventBridgeTest.js | 114 +++++++++++------- scripts/system/tablet-ui/tabletUI.js | 7 ++ 6 files changed, 92 insertions(+), 50 deletions(-) diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index de0caf56a9..33d62a6a40 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -576,7 +576,9 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::functionsetObjectOwnership(this, QQmlEngine::CppOwnership); newObject->setProperty("eventBridge", QVariant::fromValue(this)); + newContext->setContextProperty("eventBridgeJavaScriptToInject", QVariant(javaScriptToInject)); f(newContext, newObject); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index a5c94c1bb4..caa42bea5e 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -974,6 +974,8 @@ void ScriptEngine::run() { return; // bail early - avoid setting state in init(), as evaluate() will bail too } + scriptInfoMessage("Script Engine starting:" + getFilename()); + if (!_isInitialized) { init(); } diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp index c287fbcfe7..02c2253fc6 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.cpp +++ b/libraries/script-engine/src/TabletScriptingInterface.cpp @@ -201,7 +201,7 @@ void TabletProxy::setToolbarMode(bool toolbarMode) { QObject::connect(quickItem, SIGNAL(windowClosed()), this, SLOT(desktopWindowClosed())); - QObject::connect(tabletRootWindow, SIGNAL(webEventReceived(QVariant)), this, SIGNAL(webEventReceived(QVariant))); + QObject::connect(tabletRootWindow, SIGNAL(webEventReceived(QVariant)), this, SLOT(emitWebEvent(QVariant)), Qt::DirectConnection); // forward qml surface events to interface js connect(tabletRootWindow, &QmlWindowClass::fromQml, this, &TabletProxy::fromQml); @@ -271,12 +271,17 @@ bool TabletProxy::isMessageDialogOpen() { return false; } +void TabletProxy::emitWebEvent(QVariant msg) { + emit webEventReceived(msg); +} + void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface) { std::lock_guard guard(_mutex); _qmlOffscreenSurface = qmlOffscreenSurface; _qmlTabletRoot = qmlTabletRoot; if (_qmlTabletRoot && _qmlOffscreenSurface) { - QObject::connect(_qmlOffscreenSurface, SIGNAL(webEventReceived(QVariant)), this, SIGNAL(webEventReceived(QVariant))); + + QObject::connect(_qmlOffscreenSurface, SIGNAL(webEventReceived(QVariant)), this, SLOT(emitWebEvent(QVariant)), Qt::DirectConnection); // forward qml surface events to interface js connect(dynamic_cast(_qmlOffscreenSurface), &OffscreenQmlSurface::fromQml, [this](QVariant message) { @@ -398,7 +403,7 @@ void TabletProxy::popFromStack() { auto stack = _desktopWindow->asQuickItem()->findChild("stack"); if (stack) { QMetaObject::invokeMethod(stack, "popSource"); - } else { + } else { qCDebug(scriptengine) << "tablet cannot pop QML because _desktopWindow doesn't have child stack"; } } else { @@ -705,4 +710,3 @@ void TabletButtonProxy::editProperties(QVariantMap properties) { } #include "TabletScriptingInterface.moc" - diff --git a/libraries/script-engine/src/TabletScriptingInterface.h b/libraries/script-engine/src/TabletScriptingInterface.h index 2e7b91fa4c..fa6b8fb56f 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.h +++ b/libraries/script-engine/src/TabletScriptingInterface.h @@ -63,7 +63,7 @@ signals: * @returns {Signal} */ void tabletNotification(); - + private: void processMenuEvents(QObject* object, const QKeyEvent* event); void processTabletEvents(QObject* object, const QKeyEvent* event); @@ -209,6 +209,7 @@ signals: protected slots: void addButtonsToHomeScreen(); void desktopWindowClosed(); + void emitWebEvent(QVariant msg); protected: void removeButtonsFromHomeScreen(); void loadHomeScreen(bool forceOntoHomeScreen); @@ -216,7 +217,7 @@ protected: void removeButtonsFromToolbar(); bool _initialScreen { false }; - QVariant _initialPath { "" }; + QVariant _initialPath { "" }; QString _name; std::mutex _mutex; std::vector> _tabletButtonProxies; diff --git a/scripts/developer/tests/tabletEventBridgeTest.js b/scripts/developer/tests/tabletEventBridgeTest.js index 1fa935bef2..83031741fc 100644 --- a/scripts/developer/tests/tabletEventBridgeTest.js +++ b/scripts/developer/tests/tabletEventBridgeTest.js @@ -16,66 +16,92 @@ var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var tabletButton = tablet.addButton({ - text: "SOUNDS" + text: "SOUNDS", + icon: "http://s3.amazonaws.com/hifi-public/tony/icons/trombone-i.png", + activeIcon: "http://s3.amazonaws.com/hifi-public/tony/icons/trombone-a.png" }); var WEB_BRIDGE_TEST_HTML = "https://s3.amazonaws.com/hifi-public/tony/webBridgeTest.html?2"; - var TROMBONE_URL = "https://s3.amazonaws.com/hifi-public/tony/audio/sad-trombone.wav"; -var tromboneSound = SoundCache.getSound(TROMBONE_URL); -var tromboneInjector; - var SCREAM_URL = "https://s3.amazonaws.com/hifi-public/tony/audio/wilhelm-scream.wav"; -var screamSound = SoundCache.getSound(SCREAM_URL); -var screamInjector; tabletButton.clicked.connect(function () { - tablet.gotoWebScreen(WEB_BRIDGE_TEST_HTML); + if (shown) { + tablet.gotoHomeScreen(); + } else { + tablet.gotoWebScreen(WEB_BRIDGE_TEST_HTML); + } }); -// hook up to the event bridge -tablet.webEventReceived.connect(function (msg) { +var shown = false; + +function onScreenChanged(type, url) { + if (type === "Web" && url === WEB_BRIDGE_TEST_HTML) { + tabletButton.editProperties({isActive: true}); + + if (!shown) { + // hook up to the event bridge + tablet.webEventReceived.connect(onWebEventReceived); + } + shown = true; + } else { + tabletButton.editProperties({isActive: false}); + + if (shown) { + // disconnect from the event bridge + tablet.webEventReceived.disconnect(onWebEventReceived); + } + shown = false; + } +} + +tablet.screenChanged.connect(onScreenChanged); + +// ctor +function SoundBuddy(url) { + this.sound = SoundCache.getSound(url); + this.injector = null; +} + +SoundBuddy.prototype.play = function (options, doneCallback) { + if (this.sound.downloaded) { + if (this.injector) { + this.injector.setOptions(options); + this.injector.restart(); + } else { + this.injector = Audio.playSound(this.sound, options); + this.injector.finished.connect(function () { + if (doneCallback) { + doneCallback(); + } + }); + } + } +}; + +var tromboneSound = new SoundBuddy(TROMBONE_URL); +var screamSound = new SoundBuddy(SCREAM_URL); +var soundOptions = { position: MyAvatar.position, volume: 1.0, loop: false, localOnly: true }; + +function onWebEventReceived(msg) { Script.print("HIFI: recv web event = " + JSON.stringify(msg)); if (msg === "button-1-play") { - - // play sad trombone - if (tromboneSound.downloaded) { - if (tromboneInjector) { - tromboneInjector.restart(); - } else { - tromboneInjector = Audio.playSound(tromboneSound, { position: MyAvatar.position, - volume: 1.0, - loop: false }); - } - } - - // wait until sound is finished then send a done event - Script.setTimeout(function () { + soundOptions.position = MyAvatar.position; + tromboneSound.play(soundOptions, function () { tablet.emitScriptEvent("button-1-done"); - }, 3500); - } - - if (msg === "button-2-play") { - - // play scream - if (screamSound.downloaded) { - if (screamInjector) { - screamInjector.restart(); - } else { - screamInjector = Audio.playSound(screamSound, { position: MyAvatar.position, - volume: 1.0, - loop: false }); - } - } - - // wait until sound is finished then send a done event - Script.setTimeout(function () { + }); + } else if (msg === "button-2-play") { + soundOptions.position = MyAvatar.position; + screamSound.play(soundOptions, function () { tablet.emitScriptEvent("button-2-done"); - }, 1000); + }); } -}); +} Script.scriptEnding.connect(function () { tablet.removeButton(tabletButton); + if (shown) { + tablet.webEventReceived.disconnect(onWebEventReceived); + } }); diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index a010cb0a9c..a3ccd34976 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -271,6 +271,13 @@ } Script.scriptEnding.connect(function () { + + // if we reload scripts in tablet mode make sure we close the currently open window, by calling gotoHomeScreen + var tabletProxy = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + if (tabletProxy && tabletProxy.toolbarMode) { + tabletProxy.gotoHomeScreen(); + } + var tabletID = HMD.tabletID; Entities.deleteEntity(tabletID); Overlays.deleteOverlay(tabletID) From 5cc87ccc4a3a42a9bc2bd9d16d07b07109c9d5db Mon Sep 17 00:00:00 2001 From: trent Date: Mon, 3 Apr 2017 19:38:34 -0400 Subject: [PATCH 049/128] Fixed warning for subtly-stupid unused variable. --- libraries/fbx/src/OBJReader.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 93b474db25..7ed1c9cc1d 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -465,7 +465,6 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, QMap materialMeshIdMap; QVector fbxMeshParts; - int meshPartCount = 0; for (int i = 0, meshPartCount = 0; i < mesh.parts.count(); i++, meshPartCount++) { FBXMeshPart& meshPart = mesh.parts[i]; FaceGroup faceGroup = faceGroups[meshPartCount]; From 4d6886d1f489772c4640872e5a8115520156d2f8 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Mon, 3 Apr 2017 17:03:14 -0700 Subject: [PATCH 050/128] cr feedback, plus changed 'People' to 'Connections' in a couple places --- interface/resources/qml/controls-uit/CheckBox.qml | 4 ++-- interface/resources/qml/hifi/Pal.qml | 12 ++++++------ interface/resources/qml/styles-uit/HifiConstants.qml | 3 +++ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/controls-uit/CheckBox.qml b/interface/resources/qml/controls-uit/CheckBox.qml index bb138e07c6..916a7d4889 100644 --- a/interface/resources/qml/controls-uit/CheckBox.qml +++ b/interface/resources/qml/controls-uit/CheckBox.qml @@ -68,9 +68,9 @@ Original.CheckBox { height: checkSize radius: checkRadius anchors.centerIn: parent - color: isRedCheck ? "#FF0000" : hifi.colors.checkboxChecked + color: isRedCheck ? hifi.colors.checkboxCheckedRed : hifi.colors.checkboxChecked border.width: 2 - border.color: isRedCheck? "#D00000" : hifi.colors.checkboxCheckedBorder + border.color: isRedCheck? hifi.colors.checkboxCheckedBorderRed : hifi.colors.checkboxCheckedBorder visible: checked && !pressed || !checked && pressed } diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 807a315693..a332712ce3 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -612,7 +612,7 @@ Rectangle { "Bold names in the list are avatar display names.
" + "Purple borders around profile pictures are connections.
" + "Green borders around profile pictures are friends.
" + - "In some situations, you can also see others' usernames.
" + + "Others can find you and see your username according to your availability settings.
" + "If you can see someone's username, you can GoTo them by selecting them in the PAL, then clicking their name.
" + "
If someone's display name isn't set, a unique session display name is assigned to them.
" + "
Administrators of this domain can also see the username or machine ID associated with each avatar present."); @@ -961,11 +961,11 @@ Rectangle { size: hifi.fontSizes.tabularData; // Anchors anchors.top: myCard.top; - anchors.horizontalCenter: parent.horizontalCenter; + anchors.left: parent.left; // Style color: hifi.colors.baseGrayHighlight; // Alignment - horizontalAlignment: Text.AlignHCenter; + horizontalAlignment: Text.AlignLeft; verticalAlignment: Text.AlignTop; } Rectangle { @@ -1000,9 +1000,9 @@ Rectangle { popupComboDialog("Set your availability:", availabilityComboBox.availabilityStrings, ["Your username will be visible in everyone's 'Nearby' list.\nAnyone will be able to jump to your location from within the 'Nearby' list.", - "You will be visible in the 'People' list only for those with whom you are connected or friends.\nThey will be able to jump to your location if the domain allows.", - "You will be visible in the 'People' list only for those with whom you are friends.\nThey will be able to jump to your location if the domain allows.", - "You will not be visible in the 'People' list of any other users. Only domain admins will be able to see your username in the 'Nearby' list."], + "You will be visible in the 'Connections' list only for those with whom you are connected or friends.\nThey will be able to jump to your location if the domain allows.", + "You will be visible in the 'Connections' list only for those with whom you are friends.\nThey will be able to jump to your location if the domain allows.", + "You will not be visible in the 'Connections' list of any other users. Only domain admins will be able to see your username in the 'Nearby' list."], ["all", "connections", "friends", "none"]); } onEntered: availabilityComboBox.color = hifi.colors.lightGrayText; diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index a9d5a0ed2f..386af206e1 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -70,6 +70,9 @@ Item { readonly property color indigoAccent: "#9495FF" readonly property color magentaHighlight: "#EF93D1" readonly property color magentaAccent: "#A2277C" + readonly property color checkboxCheckedRed: "#FF0000" + readonly property color checkboxCheckedBorderRed: "#D00000" + // Semitransparent readonly property color darkGray30: "#4d121212" readonly property color darkGray0: "#00121212" From a882beb2fd501b40aeb2ab04e8755bce040ca0f0 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 3 Apr 2017 17:35:28 -0700 Subject: [PATCH 051/128] Trying to fix the overlay Image3D shading pipeline used --- .../display-plugins/OpenGLDisplayPlugin.cpp | 2 +- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 1 + .../render-utils/src/RenderPipelines.cpp | 15 +++++--- .../src/simple_textured_unlit.slf | 16 +++++++-- .../src/simple_transparent_textured.slf | 36 +++++++++++++++++++ 5 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 libraries/render-utils/src/simple_transparent_textured.slf diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index a3cf91fcd5..e05d7c5bc9 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -573,7 +573,7 @@ void OpenGLDisplayPlugin::compositeLayers() { { PROFILE_RANGE_EX(render_detail, "compositeOverlay", 0xff0077ff, (uint64_t)presentCount()) - compositeOverlay(); + // compositeOverlay(); } auto compositorHelper = DependencyManager::get(); if (compositorHelper->getReticleVisible()) { diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index de0caf56a9..27f4f4f5dc 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -278,6 +278,7 @@ void OffscreenQmlSurface::cleanup() { } void OffscreenQmlSurface::render() { + return; if (_paused) { return; } diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 414bcf0d63..efbe09863b 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -28,6 +28,10 @@ #include "skin_model_shadow_vert.h" #include "skin_model_normal_map_vert.h" +#include "simple_vert.h" +#include "simple_textured_frag.h" +#include "simple_textured_unlit_frag.h" + #include "model_frag.h" #include "model_unlit_frag.h" #include "model_shadow_frag.h" @@ -135,6 +139,7 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { void initDeferredPipelines(render::ShapePlumber& plumber) { // Vertex shaders + auto simpleVertex = gpu::Shader::createVertex(std::string(simple_vert)); auto modelVertex = gpu::Shader::createVertex(std::string(model_vert)); auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert)); auto modelLightmapVertex = gpu::Shader::createVertex(std::string(model_lightmap_vert)); @@ -145,6 +150,8 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { auto skinModelShadowVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert)); // Pixel shaders + auto simplePixel = gpu::Shader::createPixel(std::string(simple_textured_frag)); + auto simpleUnlitPixel = gpu::Shader::createPixel(std::string(simple_textured_unlit_frag)); auto modelPixel = gpu::Shader::createPixel(std::string(model_frag)); auto modelUnlitPixel = gpu::Shader::createPixel(std::string(model_unlit_frag)); auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag)); @@ -167,13 +174,13 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { modelVertex, modelPixel); addPipeline( Key::Builder(), - modelVertex, modelPixel); + modelVertex, simplePixel); addPipeline( Key::Builder().withMaterial().withUnlit(), modelVertex, modelUnlitPixel); addPipeline( Key::Builder().withUnlit(), - modelVertex, modelUnlitPixel); + modelVertex, simpleUnlitPixel); addPipeline( Key::Builder().withMaterial().withTangents(), modelNormalMapVertex, modelNormalMapPixel); @@ -189,13 +196,13 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { modelVertex, modelTranslucentPixel); addPipeline( Key::Builder().withTranslucent(), - modelVertex, modelTranslucentPixel); + simpleVertex, simplePixel); addPipeline( Key::Builder().withMaterial().withTranslucent().withUnlit(), modelVertex, modelTranslucentUnlitPixel); addPipeline( Key::Builder().withTranslucent().withUnlit(), - modelVertex, modelTranslucentUnlitPixel); + simpleVertex, simpleUnlitPixel); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents(), modelNormalMapVertex, modelTranslucentPixel); diff --git a/libraries/render-utils/src/simple_textured_unlit.slf b/libraries/render-utils/src/simple_textured_unlit.slf index 4f02140825..1ee2011972 100644 --- a/libraries/render-utils/src/simple_textured_unlit.slf +++ b/libraries/render-utils/src/simple_textured_unlit.slf @@ -2,7 +2,7 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// simple.frag +// simple_textured_unlit.frag // fragment shader // // Created by Clément Brisset on 5/29/15. @@ -31,12 +31,22 @@ void main(void) { const float ALPHA_THRESHOLD = 0.999; if (_color.a * texel.a < ALPHA_THRESHOLD) { - packDeferredFragmentTranslucent( + + _fragColor0 = vec4(_color.rgb * texel.rgb, _color.a * texel.a); + + if (_color.a * texel.a <= 0.0) { + _fragColor0 = vec4(_color.rgb * texel.rgb, _color.a * texel.a); + //discard; + } else { + _fragColor0 = vec4(_color.rgb * texel.rgb, _color.a * texel.a); + } + // _fragColor0 = vec4(albedo.rgb, alpha); + /* packDeferredFragmentTranslucent( normalize(_normal), _color.a * texel.a, _color.rgb * texel.rgb, DEFAULT_FRESNEL, - DEFAULT_ROUGHNESS); + DEFAULT_ROUGHNESS);*/ } else { packDeferredFragmentUnlit( normalize(_normal), diff --git a/libraries/render-utils/src/simple_transparent_textured.slf b/libraries/render-utils/src/simple_transparent_textured.slf new file mode 100644 index 0000000000..0fda804129 --- /dev/null +++ b/libraries/render-utils/src/simple_transparent_textured.slf @@ -0,0 +1,36 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple_transparent_textured.slf +// fragment shader +// +// Created by Sam Gateau on 4/3/17. +// 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 +// + +<@include gpu/Color.slh@> +<@include DeferredBufferWrite.slh@> +<@include model/Material.slh@> + +// the albedo texture +uniform sampler2D originalTexture; + +// the interpolated normal +in vec3 _normal; +in vec4 _color; +in vec2 _texCoord0; + +void main(void) { + vec4 texel = texture(originalTexture, _texCoord0.st); + texel = colorToLinearRGBA(texel); + packDeferredFragmentTranslucent( + normalize(_normal), + _color.a, + _color.rgb * texel.rgb, + DEFAULT_FRESNEL, + DEFAULT_ROUGHNESS); +} \ No newline at end of file From 362ffba11718cb94b212923e2588ca3c8bbd2a5b Mon Sep 17 00:00:00 2001 From: trent Date: Mon, 3 Apr 2017 21:54:19 -0400 Subject: [PATCH 052/128] Fixes to OBJReader.cpp style inconsistencies. --- libraries/fbx/src/OBJReader.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 7ed1c9cc1d..c99b847722 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -497,7 +497,7 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, if (specifiesUV) { material.userSpecifiesUV = true; // Note might not be true in a later usage. } - if (specifiesUV || (0 != groupMaterialName.compare("none", Qt::CaseInsensitive))) { + if (specifiesUV || (groupMaterialName.compare("none", Qt::CaseInsensitive) != 0)) { // Blender has a convention that a material named "None" isn't really used (or defined). material.used = true; needsMaterialLibrary = groupMaterialName != SMART_DEFAULT_MATERIAL_NAME; @@ -545,21 +545,21 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, n0 = checked_at(normals, face.normalIndices[0]); n1 = checked_at(normals, face.normalIndices[1]); n2 = checked_at(normals, face.normalIndices[2]); - } - else { + } else { // generate normals from triangle plane if not provided n0 = n1 = n2 = glm::cross(v1 - v0, v2 - v0); } + mesh.normals.append(n0); mesh.normals.append(n1); mesh.normals.append(n2); + if (face.textureUVIndices.count()) { mesh.texCoords << checked_at(textureUVs, face.textureUVIndices[0]) << checked_at(textureUVs, face.textureUVIndices[1]) << checked_at(textureUVs, face.textureUVIndices[2]); - } - else { + } else { glm::vec2 corner(0.0f, 1.0f); mesh.texCoords << corner << corner << corner; } @@ -580,7 +580,7 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, qCDebug(modelformat) << "OBJ reader fail: " << e.what(); } - QString queryPart = _url.query(); + QString queryPart = _url.query(); bool suppressMaterialsHack = queryPart.contains("hifiusemat"); // If this appears in query string, don't fetch mtl even if used. OBJMaterial& preDefinedMaterial = materials[SMART_DEFAULT_MATERIAL_NAME]; preDefinedMaterial.used = true; From 072e024d9ad29723f384dcb811b56bd59e9f55f1 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Tue, 4 Apr 2017 16:10:37 +0200 Subject: [PATCH 053/128] Fixed warning in JSConsole --- interface/src/ui/JSConsole.cpp | 14 ++++++++------ interface/src/ui/JSConsole.h | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index 5d197f5ddc..7700874d9a 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -76,8 +76,8 @@ void JSConsole::setScriptEngine(ScriptEngine* scriptEngine) { return; } if (_scriptEngine != NULL) { - disconnect(_scriptEngine, SIGNAL(printedMessage(const QString&)), this, SLOT(handlePrint(const QString&))); - disconnect(_scriptEngine, SIGNAL(errorMessage(const QString&)), this, SLOT(handleError(const QString&))); + disconnect(_scriptEngine, &ScriptEngine::printedMessage, this, &JSConsole::handlePrint); + disconnect(_scriptEngine, &ScriptEngine::errorMessage, this, &JSConsole::handleError); if (_ownScriptEngine) { _scriptEngine->deleteLater(); } @@ -87,8 +87,8 @@ void JSConsole::setScriptEngine(ScriptEngine* scriptEngine) { _ownScriptEngine = scriptEngine == NULL; _scriptEngine = _ownScriptEngine ? DependencyManager::get()->loadScript(QString(), false) : scriptEngine; - connect(_scriptEngine, SIGNAL(printedMessage(const QString&)), this, SLOT(handlePrint(const QString&))); - connect(_scriptEngine, SIGNAL(errorMessage(const QString&)), this, SLOT(handleError(const QString&))); + connect(_scriptEngine, &ScriptEngine::printedMessage, this, &JSConsole::handlePrint); + connect(_scriptEngine, &ScriptEngine::errorMessage, this, &JSConsole::handleError); } void JSConsole::executeCommand(const QString& command) { @@ -134,11 +134,13 @@ void JSConsole::commandFinished() { resetCurrentCommandHistory(); } -void JSConsole::handleError(const QString& message) { +void JSConsole::handleError(const QString& scriptName, const QString& message) { + Q_UNUSED(scriptName); appendMessage(GUTTER_ERROR, "" + message.toHtmlEscaped() + ""); } -void JSConsole::handlePrint(const QString& message) { +void JSConsole::handlePrint(const QString& scriptName, const QString& message) { + Q_UNUSED(scriptName); appendMessage("", message); } diff --git a/interface/src/ui/JSConsole.h b/interface/src/ui/JSConsole.h index 47878fea99..d5f5aff301 100644 --- a/interface/src/ui/JSConsole.h +++ b/interface/src/ui/JSConsole.h @@ -47,8 +47,8 @@ protected: protected slots: void scrollToBottom(); void resizeTextInput(); - void handlePrint(const QString& message); - void handleError(const QString& message); + void handlePrint(const QString& scriptName, const QString& message); + void handleError(const QString& scriptName, const QString& message); void commandFinished(); private: From 332f9bb28354f6f6bf509939c72813769f5d3bc2 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Tue, 4 Apr 2017 16:22:40 +0200 Subject: [PATCH 054/128] Fixed TabletMenuStack.qml:56: Error: Cannot assign [undefined] to QString. Fixed keyboardRaised undefined error --- interface/resources/qml/hifi/dialogs/TabletAssetServer.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml b/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml index 2460fc39d5..85f8a2f59e 100644 --- a/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml +++ b/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml @@ -21,6 +21,9 @@ Rectangle { id: root objectName: "AssetServer" + property string title: "Asset Browser" + property bool keyboardRaised: false + property var eventBridge; signal sendToScript(var message); property bool isHMD: false @@ -415,7 +418,6 @@ Rectangle { Column { width: parent.width - y: hifi.dimensions.tabletMenuHeader //-bgNavBar spacing: 10 HifiControls.TabletContentSection { From 367555acdbdbe184ebd6945cef1876057fe55508 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Tue, 4 Apr 2017 16:35:21 +0200 Subject: [PATCH 055/128] Fixed BasicTableView.qml:610:17: QML Item: Binding loop detected for property width. width must be explicitly set --- .../resources/qml/hifi/dialogs/TabletRunningScripts.qml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/TabletRunningScripts.qml b/interface/resources/qml/hifi/dialogs/TabletRunningScripts.qml index dee0d0e21f..d826b40ad1 100644 --- a/interface/resources/qml/hifi/dialogs/TabletRunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/TabletRunningScripts.qml @@ -20,7 +20,7 @@ import "../../windows" Rectangle { id: root objectName: "RunningScripts" - property var title: "Running Scripts" + property string title: "Running Scripts" HifiConstants { id: hifi } signal sendToScript(var message); property var eventBridge; @@ -81,9 +81,9 @@ Rectangle { Flickable { id: flickable - width: parent.width + width: tabletRoot.width height: parent.height - (keyboard.raised ? keyboard.raisedHeight : 0) - contentWidth: parent.width + contentWidth: column.width contentHeight: column.childrenRect.height clip: true @@ -121,9 +121,8 @@ Rectangle { model: runningScriptsModel id: table height: 185 + width: parent.width colorScheme: hifi.colorSchemes.dark - anchors.left: parent.left - anchors.right: parent.right expandSelectedRow: true itemDelegate: Item { From aa487faad17d10b222e84b83011ffe43390f0088 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Tue, 4 Apr 2017 16:59:09 +0200 Subject: [PATCH 056/128] Fixed No such signal QmlWindow_QMLTYPE_490::resized(QSizeF) and No such signal QmlWindow_QMLTYPE_490::moved(QVector2D) warnings --- libraries/ui/src/QmlWindowClass.cpp | 7 +++++-- scripts/developer/debugging/debugWindow.qml | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp index c60e4fa698..c0e94058ae 100644 --- a/libraries/ui/src/QmlWindowClass.cpp +++ b/libraries/ui/src/QmlWindowClass.cpp @@ -122,12 +122,15 @@ void QmlWindowClass::initQml(QVariantMap properties) { object->setProperty(OFFSCREEN_VISIBILITY_PROPERTY, visible); object->setProperty(SOURCE_PROPERTY, _source); + const QMetaObject *metaObject = _qmlWindow->metaObject(); // Forward messages received from QML on to the script connect(_qmlWindow, SIGNAL(sendToScript(QVariant)), this, SLOT(qmlToScript(const QVariant&)), Qt::QueuedConnection); connect(_qmlWindow, SIGNAL(visibleChanged()), this, SIGNAL(visibleChanged()), Qt::QueuedConnection); - connect(_qmlWindow, SIGNAL(resized(QSizeF)), this, SIGNAL(resized(QSizeF)), Qt::QueuedConnection); - connect(_qmlWindow, SIGNAL(moved(QVector2D)), this, SLOT(hasMoved(QVector2D)), Qt::QueuedConnection); + if (metaObject->indexOfSignal("resized") >= 0) + connect(_qmlWindow, SIGNAL(resized(QSizeF)), this, SIGNAL(resized(QSizeF)), Qt::QueuedConnection); + if (metaObject->indexOfSignal("moved") >= 0) + connect(_qmlWindow, SIGNAL(moved(QVector2D)), this, SLOT(hasMoved(QVector2D)), Qt::QueuedConnection); connect(_qmlWindow, SIGNAL(windowClosed()), this, SLOT(hasClosed()), Qt::QueuedConnection); }); } diff --git a/scripts/developer/debugging/debugWindow.qml b/scripts/developer/debugging/debugWindow.qml index f046a949ef..20fa24358d 100644 --- a/scripts/developer/debugging/debugWindow.qml +++ b/scripts/developer/debugging/debugWindow.qml @@ -18,6 +18,9 @@ Rectangle { width: parent ? parent.width : 100 height: parent ? parent.height : 100 + signal moved(vector2d position); + signal resized(size size); + property var channel; TextArea { From 08ac25473fa27ab4927a16f26c99727213fc75a0 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Tue, 4 Apr 2017 09:53:09 -0700 Subject: [PATCH 057/128] wording change --- interface/resources/qml/hifi/Pal.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index a332712ce3..66803621ec 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -1000,9 +1000,9 @@ Rectangle { popupComboDialog("Set your availability:", availabilityComboBox.availabilityStrings, ["Your username will be visible in everyone's 'Nearby' list.\nAnyone will be able to jump to your location from within the 'Nearby' list.", - "You will be visible in the 'Connections' list only for those with whom you are connected or friends.\nThey will be able to jump to your location if the domain allows.", - "You will be visible in the 'Connections' list only for those with whom you are friends.\nThey will be able to jump to your location if the domain allows.", - "You will not be visible in the 'Connections' list of any other users. Only domain admins will be able to see your username in the 'Nearby' list."], + "Your location will be visible in the 'Connections' list only for those with whom you are connected or friends.\nThey will be able to jump to your location if the domain allows.", + "Your location will be visible in the 'Connections' list only for those with whom you are friends.\nThey will be able to jump to your location if the domain allows.", + "Your location will not be visible in the 'Connections' list of any other users. Only domain admins will be able to see your username in the 'Nearby' list."], ["all", "connections", "friends", "none"]); } onEntered: availabilityComboBox.color = hifi.colors.lightGrayText; From 172fab6789d6caba4d8ae1c8e080d8897f3e7435 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 30 Mar 2017 17:53:54 -0700 Subject: [PATCH 058/128] Thread safety for property getter/setters on entities --- libraries/entities/src/EntityItem.cpp | 543 ++++++++++++++++++++-- libraries/entities/src/EntityItem.h | 139 +++--- libraries/entities/src/TextEntityItem.cpp | 95 ++++ libraries/entities/src/TextEntityItem.h | 38 +- 4 files changed, 682 insertions(+), 133 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 0bb085459e..9ba740728b 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -909,19 +909,23 @@ void EntityItem::adjustEditPacketForClockSkew(QByteArray& buffer, qint64 clockSk float EntityItem::computeMass() const { glm::vec3 dimensions = getDimensions(); - return _density * _volumeMultiplier * dimensions.x * dimensions.y * dimensions.z; + return getDensity() * _volumeMultiplier * dimensions.x * dimensions.y * dimensions.z; } void EntityItem::setDensity(float density) { - _density = glm::max(glm::min(density, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY); + withWriteLock([&] { + _density = glm::max(glm::min(density, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY); + }); } void EntityItem::updateDensity(float density) { float clampedDensity = glm::max(glm::min(density, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY); - if (_density != clampedDensity) { - _density = clampedDensity; - _dirtyFlags |= Simulation::DIRTY_MASS; - } + withWriteLock([&] { + if (_density != clampedDensity) { + _density = clampedDensity; + _dirtyFlags |= Simulation::DIRTY_MASS; + } + }); } void EntityItem::setMass(float mass) { @@ -941,10 +945,12 @@ void EntityItem::setMass(float mass) { } else { newDensity = glm::max(glm::min(mass / volume, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY); } - if (_density != newDensity) { - _density = newDensity; - _dirtyFlags |= Simulation::DIRTY_MASS; - } + withWriteLock([&] { + if (_density != newDensity) { + _density = newDensity; + _dirtyFlags |= Simulation::DIRTY_MASS; + } + }); } void EntityItem::setHref(QString value) { @@ -952,32 +958,47 @@ void EntityItem::setHref(QString value) { if (! (value.toLower().startsWith("hifi://")) ) { return; } - _href = value; + withWriteLock([&] { + _href = value; + }); } void EntityItem::setCollisionSoundURL(const QString& value) { - if (_collisionSoundURL != value) { - _collisionSoundURL = value; - + bool modified = false; + withWriteLock([&] { + if (_collisionSoundURL != value) { + _collisionSoundURL = value; + modified = true; + } + }); + if (modified) { if (auto myTree = getTree()) { - myTree->notifyNewCollisionSoundURL(_collisionSoundURL, getEntityItemID()); + myTree->notifyNewCollisionSoundURL(value, getEntityItemID()); } } } SharedSoundPointer EntityItem::getCollisionSound() { - if (!_collisionSound) { - _collisionSound = DependencyManager::get()->getSound(_collisionSoundURL); + SharedSoundPointer result; + withReadLock([&] { + result = _collisionSound; + }); + + if (!result) { + result = DependencyManager::get()->getSound(_collisionSoundURL); + withWriteLock([&] { + _collisionSound = result; + }); } - return _collisionSound; + return result; } void EntityItem::simulate(const quint64& now) { - if (_lastSimulated == 0) { - _lastSimulated = now; + if (0 == getLastSimulated()) { + setLastSimulated(now); } - float timeElapsed = (float)(now - _lastSimulated) / (float)(USECS_PER_SECOND); + float timeElapsed = (float)(now - getLastSimulated()) / (float)(USECS_PER_SECOND); #ifdef WANT_DEBUG qCDebug(entities) << "********** EntityItem::simulate()"; @@ -1024,7 +1045,7 @@ void EntityItem::simulate(const quint64& now) { _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; setAcceleration(Vectors::ZERO); } - _lastSimulated = now; + setLastSimulated(now); } bool EntityItem::stepKinematicMotion(float timeElapsed) { @@ -1056,9 +1077,10 @@ bool EntityItem::stepKinematicMotion(float timeElapsed) { timeElapsed = glm::min(timeElapsed, MAX_TIME_ELAPSED); if (isSpinning) { + float angularDamping = getAngularDamping(); // angular damping - if (_angularDamping > 0.0f) { - angularVelocity *= powf(1.0f - _angularDamping, timeElapsed); + if (angularDamping > 0.0f) { + angularVelocity *= powf(1.0f - angularDamping, timeElapsed); } const float MIN_KINEMATIC_ANGULAR_SPEED_SQUARED = @@ -1086,15 +1108,17 @@ bool EntityItem::stepKinematicMotion(float timeElapsed) { glm::vec3 deltaVelocity = Vectors::ZERO; // linear damping - if (_damping > 0.0f) { - deltaVelocity = (powf(1.0f - _damping, timeElapsed) - 1.0f) * linearVelocity; + float damping = getDamping(); + if (damping > 0.0f) { + deltaVelocity = (powf(1.0f - damping, timeElapsed) - 1.0f) * linearVelocity; } const float MIN_KINEMATIC_LINEAR_ACCELERATION_SQUARED = 1.0e-4f; // 0.01 m/sec^2 - if (glm::length2(_acceleration) > MIN_KINEMATIC_LINEAR_ACCELERATION_SQUARED) { + vec3 acceleration = getAcceleration(); + if (glm::length2(acceleration) > MIN_KINEMATIC_LINEAR_ACCELERATION_SQUARED) { // yes acceleration // acceleration is in world-frame but we need it in local-frame - glm::vec3 linearAcceleration = _acceleration; + glm::vec3 linearAcceleration = acceleration; bool success; Transform parentTransform = getParentTransform(success); if (success) { @@ -1180,7 +1204,7 @@ bool EntityItem::lifetimeHasExpired() const { } quint64 EntityItem::getExpiry() const { - return _created + (quint64)(_lifetime * (float)USECS_PER_SECOND); + return getCreated() + (quint64)(getLifetime() * (float)USECS_PER_SECOND); } EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProperties) const { @@ -1189,10 +1213,10 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper EntityItemProperties properties(propertyFlags); properties._id = getID(); properties._idSet = true; - properties._created = _created; - properties._lastEdited = _lastEdited; - properties.setClientOnly(_clientOnly); - properties.setOwningAvatarID(_owningAvatarID); + properties._created = getCreated(); + properties._lastEdited = getLastEdited(); + properties.setClientOnly(getClientOnly()); + properties.setOwningAvatarID(getOwningAvatarID()); properties._type = getType(); @@ -1259,7 +1283,7 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c properties._angularVelocity = getLocalAngularVelocity(); } if (!properties._accelerationChanged) { - properties._acceleration = _acceleration; + properties._acceleration = getAcceleration(); } properties._positionChanged = true; @@ -1777,20 +1801,26 @@ void EntityItem::updateRestitution(float value) { void EntityItem::updateFriction(float value) { float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_FRICTION, value), ENTITY_ITEM_MIN_FRICTION); - if (_friction != clampedValue) { - _friction = clampedValue; - _dirtyFlags |= Simulation::DIRTY_MATERIAL; - } + withWriteLock([&] { + if (_friction != clampedValue) { + _friction = clampedValue; + _dirtyFlags |= Simulation::DIRTY_MATERIAL; + } + }); } void EntityItem::setRestitution(float value) { float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_RESTITUTION, value), ENTITY_ITEM_MIN_RESTITUTION); - _restitution = clampedValue; + withWriteLock([&] { + _restitution = clampedValue; + }); } void EntityItem::setFriction(float value) { float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_FRICTION, value), ENTITY_ITEM_MIN_FRICTION); - _friction = clampedValue; + withWriteLock([&] { + _friction = clampedValue; + }); } void EntityItem::updateLifetime(float value) { @@ -2327,3 +2357,436 @@ bool EntityItem::matchesJSONFilters(const QJsonObject& jsonFilters) const { // the json filter syntax did not match what we expected, return a match return true; } + +quint64 EntityItem::getLastSimulated() const { + quint64 result; + withReadLock([&] { + result = _lastSimulated; + }); + return result; +} + +void EntityItem::setLastSimulated(quint64 now) { + withWriteLock([&] { + _lastSimulated = now; + }); +} + +quint64 EntityItem::getLastEdited() const { + quint64 result; + withReadLock([&] { + result = _lastEdited; + }); + return result; +} + +void EntityItem::setLastEdited(quint64 lastEdited) { + withWriteLock([&] { + _lastEdited = _lastUpdated = lastEdited; + _changedOnServer = glm::max(lastEdited, _changedOnServer); + }); +} + +quint64 EntityItem::getLastBroadcast() const { + quint64 result; + withReadLock([&] { + result = _lastBroadcast; + }); + return result; +} + +void EntityItem::setLastBroadcast(quint64 lastBroadcast) { + withWriteLock([&] { + _lastBroadcast = lastBroadcast; + }); +} + +void EntityItem::markAsChangedOnServer() { + withWriteLock([&] { + _changedOnServer = usecTimestampNow(); + }); +} + +quint64 EntityItem::getLastChangedOnServer() const { + quint64 result; + withReadLock([&] { + result = _changedOnServer; + }); + return result; +} + +void EntityItem::update(const quint64& now) { + withWriteLock([&] { + _lastUpdated = now; + }); +} + +quint64 EntityItem::getLastUpdated() const { + quint64 result; + withReadLock([&] { + result = _lastUpdated; + }); + return result; +} + +void EntityItem::requiresRecalcBoxes() { + withWriteLock([&] { + _recalcAABox = true; + _recalcMinAACube = true; + _recalcMaxAACube = true; + }); +} + +QString EntityItem::getHref() const { + QString result; + withReadLock([&] { + result = _href; + }); + return result; +} + +QString EntityItem::getDescription() const { + QString result; + withReadLock([&] { + result = _description; + }); + return result; +} + +void EntityItem::setDescription(const QString& value) { + withWriteLock([&] { + _description = value; + }); +} + +float EntityItem::getLocalRenderAlpha() const { + float result; + withReadLock([&] { + result = _localRenderAlpha; + }); + return result; +} + +void EntityItem::setLocalRenderAlpha(float localRenderAlpha) { + withWriteLock([&] { + _localRenderAlpha = localRenderAlpha; + }); +} + +glm::vec3 EntityItem::getGravity() const { + glm::vec3 result; + withReadLock([&] { + result = _gravity; + }); + return result; +} + +void EntityItem::setGravity(const glm::vec3& value) { + withWriteLock([&] { + _gravity = value; + }); +} + +glm::vec3 EntityItem::getAcceleration() const { + glm::vec3 result; + withReadLock([&] { + result = _acceleration; + }); + return result; +} + +void EntityItem::setAcceleration(const glm::vec3& value) { + withWriteLock([&] { + _acceleration = value; + }); +} + +float EntityItem::getDamping() const { + float result; + withReadLock([&] { + result = _damping; + }); + return result; +} +void EntityItem::setDamping(float value) { + withWriteLock([&] { + _damping = value; + }); +} + +float EntityItem::getRestitution() const { + float result; + withReadLock([&] { + result = _restitution; + }); + return result; +} + +float EntityItem::getFriction() const { + float result; + withReadLock([&] { + result = _friction; + }); + return result; +} + +// lifetime related properties. +float EntityItem::getLifetime() const { + float result; + withReadLock([&] { + result = _lifetime; + }); + return result; +} + +void EntityItem::setLifetime(float value) { + withWriteLock([&] { + _lifetime = value; + }); +} + +quint64 EntityItem::getCreated() const { + quint64 result; + withReadLock([&] { + result = _created; + }); + return result; +} + +void EntityItem::setCreated(quint64 value) { + withWriteLock([&] { + _created = value; + }); +} + +QString EntityItem::getScript() const { + QString result; + withReadLock([&] { + result = _script; + }); + return result; +} + +void EntityItem::setScript(const QString& value) { + withWriteLock([&] { + _script = value; + }); +} + +quint64 EntityItem::getScriptTimestamp() const { + quint64 result; + withReadLock([&] { + result = _scriptTimestamp; + }); + return result; +} + +void EntityItem::setScriptTimestamp(const quint64 value) { + withWriteLock([&] { + _scriptTimestamp = value; + }); +} + +QString EntityItem::getServerScripts() const { + QString result; + withReadLock([&] { + result = _serverScripts; + }); + return result; +} + +void EntityItem::setServerScripts(const QString& serverScripts) { + withWriteLock([&] { + _serverScripts = serverScripts; + _serverScriptsChangedTimestamp = usecTimestampNow(); + }); +} + +QString EntityItem::getCollisionSoundURL() const { + QString result; + withReadLock([&] { + result = _collisionSoundURL; + }); + return result; +} + +void EntityItem::setCollisionSound(SharedSoundPointer sound) { + withWriteLock([&] { + _collisionSound = sound; + }); +} + +glm::vec3 EntityItem::getRegistrationPoint() const { + glm::vec3 result; + withReadLock([&] { + result = _registrationPoint; + }); + return result; +} + +void EntityItem::setRegistrationPoint(const glm::vec3& value) { + withWriteLock([&] { + _registrationPoint = glm::clamp(value, 0.0f, 1.0f); + }); + dimensionsChanged(); // Registration Point affects the bounding box +} + +float EntityItem::getAngularDamping() const { + float result; + withReadLock([&] { + result = _angularDamping; + }); + return result; +} + +void EntityItem::setAngularDamping(float value) { + withWriteLock([&] { + _angularDamping = value; + }); +} + +QString EntityItem::getName() const { + QString result; + withReadLock([&] { + result = _name; + }); + return result; +} + +void EntityItem::setName(const QString& value) { + withWriteLock([&] { + _name = value; + }); +} + +QString EntityItem::getDebugName() { + QString result = getName(); + if (result.isEmpty()) { + result = getID().toString(); + } + return result; +} + +bool EntityItem::getVisible() const { + bool result; + withReadLock([&] { + result = _visible; + }); + return result; +} + +void EntityItem::setVisible(bool value) { + withWriteLock([&] { + _visible = value; + }); +} + +bool EntityItem::getCollisionless() const { + bool result; + withReadLock([&] { + result = _collisionless; + }); + return result; +} + +void EntityItem::setCollisionless(bool value) { + withWriteLock([&] { + _collisionless = value; + }); +} + +uint8_t EntityItem::getCollisionMask() const { + uint8_t result; + withReadLock([&] { + result = _collisionMask; + }); + return result; +} + +void EntityItem::setCollisionMask(uint8_t value) { + withWriteLock([&] { + _collisionMask = value; + }); +} + +bool EntityItem::getDynamic() const { + if (SHAPE_TYPE_STATIC_MESH == getShapeType()) { + return false; + } + bool result; + withReadLock([&] { + result = _dynamic; + }); + return result; +} + +void EntityItem::setDynamic(bool value) { + withWriteLock([&] { + _dynamic = value; + }); +} + +bool EntityItem::getLocked() const { + bool result; + withReadLock([&] { + result = _locked; + }); + return result; +} + +void EntityItem::setLocked(bool value) { + withWriteLock([&] { + _locked = value; + }); +} + +QString EntityItem::getUserData() const { + QString result; + withReadLock([&] { + result = _userData; + }); + return result; +} + +void EntityItem::setUserData(const QString& value) { + withWriteLock([&] { + _userData = value; + }); +} + +QString EntityItem::getMarketplaceID() const { + QString result; + withReadLock([&] { + result = _marketplaceID; + }); + return result; +} + +void EntityItem::setMarketplaceID(const QString& value) { + withWriteLock([&] { + _marketplaceID = value; + }); +} + +uint32_t EntityItem::getDirtyFlags() const { + uint32_t result; + withReadLock([&] { + result = _dirtyFlags; + }); + return result; +} + +void EntityItem::clearDirtyFlags(uint32_t mask) { + withWriteLock([&] { + _dirtyFlags &= ~mask; + }); +} + +float EntityItem::getDensity() const { + float result; + withReadLock([&] { + result = _density; + }); + return result; +} + diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index b973d916e6..929fe8a698 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -110,22 +110,21 @@ public: virtual void somethingChangedNotification() { } void recordCreationTime(); // set _created to 'now' - quint64 getLastSimulated() const { return _lastSimulated; } /// Last simulated time of this entity universal usecs - void setLastSimulated(quint64 now) { _lastSimulated = now; } + quint64 getLastSimulated() const; /// Last simulated time of this entity universal usecs + void setLastSimulated(quint64 now); /// Last edited time of this entity universal usecs - quint64 getLastEdited() const { return _lastEdited; } - void setLastEdited(quint64 lastEdited) - { _lastEdited = _lastUpdated = lastEdited; _changedOnServer = glm::max(lastEdited, _changedOnServer); } + quint64 getLastEdited() const; + void setLastEdited(quint64 lastEdited); float getEditedAgo() const /// Elapsed seconds since this entity was last edited { return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; } /// Last time we sent out an edit packet for this entity - quint64 getLastBroadcast() const { return _lastBroadcast; } - void setLastBroadcast(quint64 lastBroadcast) { _lastBroadcast = lastBroadcast; } + quint64 getLastBroadcast() const; + void setLastBroadcast(quint64 lastBroadcast); - void markAsChangedOnServer() { _changedOnServer = usecTimestampNow(); } - quint64 getLastChangedOnServer() const { return _changedOnServer; } + void markAsChangedOnServer(); + quint64 getLastChangedOnServer() const; // TODO: eventually only include properties changed since the params.lastQuerySent time virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; @@ -163,8 +162,8 @@ public: static void adjustEditPacketForClockSkew(QByteArray& buffer, qint64 clockSkew); // perform update - virtual void update(const quint64& now) { _lastUpdated = now; } - quint64 getLastUpdated() const { return _lastUpdated; } + virtual void update(const quint64& now); + quint64 getLastUpdated() const; // perform linear extrapolation for SimpleEntitySimulation void simulate(const quint64& now); @@ -188,63 +187,63 @@ public: const Transform getTransformToCenter(bool& success) const; - inline void requiresRecalcBoxes() { _recalcAABox = true; _recalcMinAACube = true; _recalcMaxAACube = true; } + inline void requiresRecalcBoxes(); // Hyperlink related getters and setters - QString getHref() const { return _href; } + QString getHref() const; void setHref(QString value); - QString getDescription() const { return _description; } - void setDescription(QString value) { _description = value; } + QString getDescription() const; + void setDescription(const QString& value); /// Dimensions in meters (0.0 - TREE_SCALE) inline const glm::vec3 getDimensions() const { return getScale(); } virtual void setDimensions(const glm::vec3& value); - float getLocalRenderAlpha() const { return _localRenderAlpha; } - void setLocalRenderAlpha(float localRenderAlpha) { _localRenderAlpha = localRenderAlpha; } + float getLocalRenderAlpha() const; + void setLocalRenderAlpha(float localRenderAlpha); void setDensity(float density); float computeMass() const; void setMass(float mass); - float getDensity() const { return _density; } + float getDensity() const; bool hasVelocity() const { return getVelocity() != ENTITY_ITEM_ZERO_VEC3; } bool hasLocalVelocity() const { return getLocalVelocity() != ENTITY_ITEM_ZERO_VEC3; } - const glm::vec3& getGravity() const { return _gravity; } /// get gravity in meters - void setGravity(const glm::vec3& value) { _gravity = value; } /// gravity in meters - bool hasGravity() const { return _gravity != ENTITY_ITEM_ZERO_VEC3; } + glm::vec3 getGravity() const; /// get gravity in meters + void setGravity(const glm::vec3& value); /// gravity in meters + bool hasGravity() const { return getGravity() != ENTITY_ITEM_ZERO_VEC3; } - const glm::vec3& getAcceleration() const { return _acceleration; } /// get acceleration in meters/second/second - void setAcceleration(const glm::vec3& value) { _acceleration = value; } /// acceleration in meters/second/second - bool hasAcceleration() const { return _acceleration != ENTITY_ITEM_ZERO_VEC3; } + glm::vec3 getAcceleration() const; /// get acceleration in meters/second/second + void setAcceleration(const glm::vec3& value); /// acceleration in meters/second/second + bool hasAcceleration() const { return getAcceleration() != ENTITY_ITEM_ZERO_VEC3; } - float getDamping() const { return _damping; } - void setDamping(float value) { _damping = value; } + float getDamping() const; + void setDamping(float value); - float getRestitution() const { return _restitution; } + float getRestitution() const; void setRestitution(float value); - float getFriction() const { return _friction; } + float getFriction() const; void setFriction(float value); // lifetime related properties. - float getLifetime() const { return _lifetime; } /// get the lifetime in seconds for the entity - void setLifetime(float value) { _lifetime = value; } /// set the lifetime in seconds for the entity + float getLifetime() const; /// get the lifetime in seconds for the entity + void setLifetime(float value); /// set the lifetime in seconds for the entity - quint64 getCreated() const { return _created; } /// get the created-time in useconds for the entity - void setCreated(quint64 value) { _created = value; } /// set the created-time in useconds for the entity + quint64 getCreated() const; /// get the created-time in useconds for the entity + void setCreated(quint64 value); /// set the created-time in useconds for the entity /// is this entity immortal, in that it has no lifetime set, and will exist until manually deleted - bool isImmortal() const { return _lifetime == ENTITY_ITEM_IMMORTAL_LIFETIME; } + bool isImmortal() const { return getLifetime() == ENTITY_ITEM_IMMORTAL_LIFETIME; } /// is this entity mortal, in that it has a lifetime set, and will automatically be deleted when that lifetime expires - bool isMortal() const { return _lifetime != ENTITY_ITEM_IMMORTAL_LIFETIME; } + bool isMortal() const { return getLifetime() != ENTITY_ITEM_IMMORTAL_LIFETIME; } /// age of this entity in seconds - float getAge() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; } + float getAge() const { return (float)(usecTimestampNow() - getCreated()) / (float)USECS_PER_SECOND; } bool lifetimeHasExpired() const; quint64 getExpiry() const; @@ -256,63 +255,61 @@ public: using SpatiallyNestable::getQueryAACube; virtual AACube getQueryAACube(bool& success) const override; - QString getScript() const { return _script; } - void setScript(const QString& value) { _script = value; } + QString getScript() const; + void setScript(const QString& value); - quint64 getScriptTimestamp() const { return _scriptTimestamp; } - void setScriptTimestamp(const quint64 value) { _scriptTimestamp = value; } + quint64 getScriptTimestamp() const; + void setScriptTimestamp(const quint64 value); - QString getServerScripts() const { return _serverScripts; } - void setServerScripts(const QString& serverScripts) - { _serverScripts = serverScripts; _serverScriptsChangedTimestamp = usecTimestampNow(); } + QString getServerScripts() const; + void setServerScripts(const QString& serverScripts); - const QString& getCollisionSoundURL() const { return _collisionSoundURL; } + QString getCollisionSoundURL() const; void setCollisionSoundURL(const QString& value); SharedSoundPointer getCollisionSound(); - void setCollisionSound(SharedSoundPointer sound) { _collisionSound = sound; } + void setCollisionSound(SharedSoundPointer sound); - const glm::vec3& getRegistrationPoint() const { return _registrationPoint; } /// registration point as ratio of entity + glm::vec3 getRegistrationPoint() const; /// registration point as ratio of entity /// registration point as ratio of entity - void setRegistrationPoint(const glm::vec3& value) { - _registrationPoint = glm::clamp(value, 0.0f, 1.0f); dimensionsChanged(); // Registration Point affects the bounding box - } + void setRegistrationPoint(const glm::vec3& value); bool hasAngularVelocity() const { return getAngularVelocity() != ENTITY_ITEM_ZERO_VEC3; } bool hasLocalAngularVelocity() const { return getLocalAngularVelocity() != ENTITY_ITEM_ZERO_VEC3; } - float getAngularDamping() const { return _angularDamping; } - void setAngularDamping(float value) { _angularDamping = value; } + float getAngularDamping() const; + void setAngularDamping(float value); - QString getName() const { return _name; } - void setName(const QString& value) { _name = value; } - QString getDebugName() { return _name != "" ? _name : getID().toString(); } + QString getName() const; + void setName(const QString& value); + QString getDebugName(); - bool getVisible() const { return _visible; } - void setVisible(bool value) { _visible = value; } - bool isVisible() const { return _visible; } - bool isInvisible() const { return !_visible; } + bool getVisible() const; + void setVisible(bool value); + inline bool isVisible() const { return getVisible(); } + inline bool isInvisible() const { return !getVisible(); } - bool getCollisionless() const { return _collisionless; } - void setCollisionless(bool value) { _collisionless = value; } + bool getCollisionless() const; + void setCollisionless(bool value); - uint8_t getCollisionMask() const { return _collisionMask; } - void setCollisionMask(uint8_t value) { _collisionMask = value; } + uint8_t getCollisionMask() const; + void setCollisionMask(uint8_t value); void computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask) const; - bool getDynamic() const { return SHAPE_TYPE_STATIC_MESH == getShapeType() ? false : _dynamic; } - void setDynamic(bool value) { _dynamic = value; } + bool getDynamic() const; + void setDynamic(bool value); virtual bool shouldBePhysical() const { return false; } - bool getLocked() const { return _locked; } - void setLocked(bool value) { _locked = value; } + bool getLocked() const; + void setLocked(bool value); - const QString& getUserData() const { return _userData; } - virtual void setUserData(const QString& value) { _userData = value; } + QString getUserData() const; + virtual void setUserData(const QString& value); + // FIXME not thread safe? const SimulationOwner& getSimulationOwner() const { return _simulationOwner; } void setSimulationOwner(const QUuid& id, quint8 priority); void setSimulationOwner(const SimulationOwner& owner); @@ -325,8 +322,8 @@ public: void setPendingOwnershipPriority(quint8 priority, const quint64& timestamp); void rememberHasSimulationOwnershipBid() const; - const QString& getMarketplaceID() const { return _marketplaceID; } - void setMarketplaceID(const QString& value) { _marketplaceID = value; } + QString getMarketplaceID() const; + void setMarketplaceID(const QString& value); // TODO: get rid of users of getRadius()... float getRadius() const; @@ -369,8 +366,8 @@ public: void updateCreated(uint64_t value); virtual void setShapeType(ShapeType type) { /* do nothing */ } - uint32_t getDirtyFlags() const { return _dirtyFlags; } - void clearDirtyFlags(uint32_t mask = 0xffffffff) { _dirtyFlags &= ~mask; } + uint32_t getDirtyFlags() const; + void clearDirtyFlags(uint32_t mask = 0xffffffff); bool isMoving() const; bool isMovingRelativeToParent() const; diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index fbb0bdc9cf..c6b857f6e7 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -141,3 +141,98 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const // FIXME - should set face and surfaceNormal return findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance); } + +void TextEntityItem::setText(const QString& value) { + withWriteLock([&] { + _text = value; + }); +} + +QString TextEntityItem::getText() const { + QString result; + withReadLock([&] { + result = _text; + }); + return result; +} + +void TextEntityItem::setLineHeight(float value) { + withWriteLock([&] { + _lineHeight = value; + }); +} + +float TextEntityItem::getLineHeight() const { + float result; + withReadLock([&] { + result = _lineHeight; + }); + return result; +} + +const rgbColor& TextEntityItem::getTextColor() const { + return _textColor; +} + +const rgbColor& TextEntityItem::getBackgroundColor() const { + return _backgroundColor; +} + +xColor TextEntityItem::getTextColorX() const { + xColor result; + withReadLock([&] { + result = { _textColor[RED_INDEX], _textColor[GREEN_INDEX], _textColor[BLUE_INDEX] }; + }); + return result; +} + +void TextEntityItem::setTextColor(const rgbColor& value) { + withWriteLock([&] { + memcpy(_textColor, value, sizeof(_textColor)); + }); +} + +void TextEntityItem::setTextColor(const xColor& value) { + withWriteLock([&] { + _textColor[RED_INDEX] = value.red; + _textColor[GREEN_INDEX] = value.green; + _textColor[BLUE_INDEX] = value.blue; + }); +} + +xColor TextEntityItem::getBackgroundColorX() const { + xColor result; + withReadLock([&] { + result = { _backgroundColor[RED_INDEX], _backgroundColor[GREEN_INDEX], _backgroundColor[BLUE_INDEX] }; + }); + return result; +} + +void TextEntityItem::setBackgroundColor(const rgbColor& value) { + withWriteLock([&] { + memcpy(_backgroundColor, value, sizeof(_backgroundColor)); + }); +} + +void TextEntityItem::setBackgroundColor(const xColor& value) { + withWriteLock([&] { + _backgroundColor[RED_INDEX] = value.red; + _backgroundColor[GREEN_INDEX] = value.green; + _backgroundColor[BLUE_INDEX] = value.blue; + }); +} + +bool TextEntityItem::getFaceCamera() const { + bool result; + withReadLock([&] { + result = _faceCamera; + }); + return result; +} + +void TextEntityItem::setFaceCamera(bool value) { + withWriteLock([&] { + _faceCamera = value; + }); +} + diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 633aa96bfa..4e49bb8ef0 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -53,38 +53,32 @@ public: void** intersectedObject, bool precisionPicking) const override; static const QString DEFAULT_TEXT; - void setText(const QString& value) { _text = value; } - const QString& getText() const { return _text; } + void setText(const QString& value); + QString getText() const; static const float DEFAULT_LINE_HEIGHT; - void setLineHeight(float value) { _lineHeight = value; } - float getLineHeight() const { return _lineHeight; } + void setLineHeight(float value); + float getLineHeight() const; static const xColor DEFAULT_TEXT_COLOR; - const rgbColor& getTextColor() const { return _textColor; } - xColor getTextColorX() const { xColor color = { _textColor[RED_INDEX], _textColor[GREEN_INDEX], _textColor[BLUE_INDEX] }; return color; } + // FIXME should not return a reference because of thread safety, but can't return an array + const rgbColor& getTextColor() const; + xColor getTextColorX() const; - void setTextColor(const rgbColor& value) { memcpy(_textColor, value, sizeof(_textColor)); } - void setTextColor(const xColor& value) { - _textColor[RED_INDEX] = value.red; - _textColor[GREEN_INDEX] = value.green; - _textColor[BLUE_INDEX] = value.blue; - } + void setTextColor(const rgbColor& value); + void setTextColor(const xColor& value); static const xColor DEFAULT_BACKGROUND_COLOR; - const rgbColor& getBackgroundColor() const { return _backgroundColor; } - xColor getBackgroundColorX() const { xColor color = { _backgroundColor[RED_INDEX], _backgroundColor[GREEN_INDEX], _backgroundColor[BLUE_INDEX] }; return color; } + // FIXME should not return a reference because of thread safety, but can't return an array + const rgbColor& getBackgroundColor() const; + xColor getBackgroundColorX() const; - void setBackgroundColor(const rgbColor& value) { memcpy(_backgroundColor, value, sizeof(_backgroundColor)); } - void setBackgroundColor(const xColor& value) { - _backgroundColor[RED_INDEX] = value.red; - _backgroundColor[GREEN_INDEX] = value.green; - _backgroundColor[BLUE_INDEX] = value.blue; - } + void setBackgroundColor(const rgbColor& value); + void setBackgroundColor(const xColor& value); static const bool DEFAULT_FACE_CAMERA; - bool getFaceCamera() const { return _faceCamera; } - void setFaceCamera(bool value) { _faceCamera = value; } + bool getFaceCamera() const; + void setFaceCamera(bool value); protected: QString _text; From 03c6275268fa32e2806afad7f8356d035a61b241 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 3 Apr 2017 08:44:27 -0700 Subject: [PATCH 059/128] more thread safety --- libraries/entities/src/EntityItem.cpp | 43 ++++--- libraries/entities/src/EntityItem.h | 3 +- libraries/entities/src/LightEntityItem.cpp | 140 ++++++++++++++++++--- libraries/entities/src/LightEntityItem.h | 2 +- libraries/entities/src/LineEntityItem.cpp | 61 ++++++++- libraries/entities/src/LineEntityItem.h | 20 ++- libraries/entities/src/ModelEntityItem.h | 2 +- libraries/entities/src/TextEntityItem.h | 2 +- 8 files changed, 216 insertions(+), 57 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 9ba740728b..891196862a 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -683,7 +683,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef // However, for now, when the server uses a newer time than what we sent, listen to what we're told. if (overwriteLocalData) weOwnSimulation = false; } else if (_simulationOwner.set(newSimOwner)) { - _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); somethingChanged = true; // recompute weOwnSimulation for later weOwnSimulation = _simulationOwner.matchesValidID(myNodeID); @@ -695,19 +695,19 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef weOwnSimulation = true; if (!_simulationOwner.isNull()) { // someone else really did own it - _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); somethingChanged = true; _simulationOwner.clearCurrentOwner(); } } else if (newSimOwner.matchesValidID(myNodeID) && !_hasBidOnSimulation) { // entity-server tells us that we have simulation ownership while we never requested this for this EntityItem, // this could happen when the user reloads the cache and entity tree. - _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); somethingChanged = true; _simulationOwner.clearCurrentOwner(); weOwnSimulation = false; } else if (_simulationOwner.set(newSimOwner)) { - _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); somethingChanged = true; // recompute weOwnSimulation for later weOwnSimulation = _simulationOwner.matchesValidID(myNodeID); @@ -994,7 +994,7 @@ SharedSoundPointer EntityItem::getCollisionSound() { } void EntityItem::simulate(const quint64& now) { - if (0 == getLastSimulated()) { + if (getLastSimulated() == 0) { setLastSimulated(now); } @@ -1042,7 +1042,7 @@ void EntityItem::simulate(const quint64& now) { if (!stepKinematicMotion(timeElapsed)) { // this entity is no longer moving // flag it to transition from KINEMATIC to STATIC - _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; + markDirtyFlags(Simulation::DIRTY_MOTION_TYPE); setAcceleration(Vectors::ZERO); } setLastSimulated(now); @@ -1294,7 +1294,7 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c } void EntityItem::pokeSimulationOwnership() { - _dirtyFlags |= Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE; + markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE); auto nodeList = DependencyManager::get(); if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) { // we already own it @@ -1306,7 +1306,7 @@ void EntityItem::pokeSimulationOwnership() { } void EntityItem::grabSimulationOwnership() { - _dirtyFlags |= Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB; + markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB); auto nodeList = DependencyManager::get(); if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) { // we already own it @@ -1599,18 +1599,18 @@ float EntityItem::getVolumeEstimate() const { void EntityItem::updateRegistrationPoint(const glm::vec3& value) { if (value != _registrationPoint) { setRegistrationPoint(value); - _dirtyFlags |= Simulation::DIRTY_SHAPE; + markDirtyFlags(Simulation::DIRTY_SHAPE); } } void EntityItem::updatePosition(const glm::vec3& value) { if (getLocalPosition() != value) { setLocalPosition(value); - _dirtyFlags |= Simulation::DIRTY_POSITION; + markDirtyFlags(Simulation::DIRTY_POSITION); forEachDescendant([&](SpatiallyNestablePointer object) { if (object->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(object); - entity->_dirtyFlags |= Simulation::DIRTY_POSITION; + entity->markDirtyFlags(Simulation::DIRTY_POSITION); } }); } @@ -1619,8 +1619,9 @@ void EntityItem::updatePosition(const glm::vec3& value) { void EntityItem::updateParentID(const QUuid& value) { if (getParentID() != value) { setParentID(value); - _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; // children are forced to be kinematic - _dirtyFlags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar + // children are forced to be kinematic + // may need to not collide with own avatar + markDirtyFlags(Simulation::DIRTY_MOTION_TYPE | Simulation::DIRTY_COLLISION_GROUP); } } @@ -1634,7 +1635,7 @@ void EntityItem::updatePositionFromNetwork(const glm::vec3& value) { void EntityItem::updateDimensions(const glm::vec3& value) { if (getDimensions() != value) { setDimensions(value); - _dirtyFlags |= (Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS); + markDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS); } } @@ -1645,8 +1646,7 @@ void EntityItem::updateRotation(const glm::quat& rotation) { forEachDescendant([&](SpatiallyNestablePointer object) { if (object->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(object); - entity->_dirtyFlags |= Simulation::DIRTY_ROTATION; - entity->_dirtyFlags |= Simulation::DIRTY_POSITION; + entity->markDirtyFlags(Simulation::DIRTY_ROTATION | Simulation::DIRTY_POSITION); } }); } @@ -1913,7 +1913,7 @@ void EntityItem::updateSimulationOwner(const SimulationOwner& owner) { } if (_simulationOwner.set(owner)) { - _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); } } @@ -1926,7 +1926,7 @@ void EntityItem::clearSimulationOwnership() { // don't bother setting the DIRTY_SIMULATOR_ID flag because: // (a) when entity-server calls clearSimulationOwnership() the dirty-flags are meaningless (only used by interface) // (b) the interface only calls clearSimulationOwnership() in a context that already knows best about dirty flags - //_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + //markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); } @@ -2776,6 +2776,13 @@ uint32_t EntityItem::getDirtyFlags() const { return result; } + +void EntityItem::markDirtyFlags(uint32_t mask) { + withWriteLock([&] { + _dirtyFlags |= mask; + }); +} + void EntityItem::clearDirtyFlags(uint32_t mask) { withWriteLock([&] { _dirtyFlags &= ~mask; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 929fe8a698..e705fcbe2a 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -367,6 +367,7 @@ public: virtual void setShapeType(ShapeType type) { /* do nothing */ } uint32_t getDirtyFlags() const; + void markDirtyFlags(uint32_t mask); void clearDirtyFlags(uint32_t mask = 0xffffffff); bool isMoving() const; @@ -509,7 +510,7 @@ protected: // NOTE: _volumeMultiplier is used to allow some mass properties code exist in the EntityItem base class // rather than in all of the derived classes. If we ever collapse these classes to one we could do it a // different way. - float _volumeMultiplier { 1.0f }; + const float _volumeMultiplier { 1.0f }; glm::vec3 _gravity; glm::vec3 _acceleration; float _damping; diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index e09822f028..753ff1d3c8 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -69,38 +69,59 @@ EntityItemProperties LightEntityItem::getProperties(EntityPropertyFlags desiredP } void LightEntityItem::setFalloffRadius(float value) { - _falloffRadius = glm::max(value, 0.0f); - _lightPropertiesChanged = true; + value = glm::max(value, 0.0f); + if (value == getFalloffRadius()) { + return; + } + withWriteLock([&] { + _falloffRadius = value; + _lightPropertiesChanged = true; + }); } void LightEntityItem::setIsSpotlight(bool value) { - if (value != _isSpotlight) { - _isSpotlight = value; - - glm::vec3 dimensions = getDimensions(); - if (_isSpotlight) { - const float length = dimensions.z; - const float width = length * glm::sin(glm::radians(_cutoff)); - setDimensions(glm::vec3(width, width, length)); - } else { - float maxDimension = glm::compMax(dimensions); - setDimensions(glm::vec3(maxDimension, maxDimension, maxDimension)); - } - _lightPropertiesChanged = true; + if (value == getIsSpotlight()) { + return; } + + glm::vec3 dimensions = getDimensions(); + glm::vec3 newDimensions; + if (value) { + const float length = dimensions.z; + const float width = length * glm::sin(glm::radians(getCutoff())); + newDimensions = glm::vec3(width, width, length); + } else { + newDimensions = glm::vec3(glm::compMax(dimensions)); + } + + withWriteLock([&] { + _isSpotlight = value; + _lightPropertiesChanged = true; + }); + setDimensions(newDimensions); } void LightEntityItem::setCutoff(float value) { - _cutoff = glm::clamp(value, 0.0f, 90.0f); + value = glm::clamp(value, 0.0f, 90.0f); + if (value == getCutoff()) { + return; + } - if (_isSpotlight) { + withWriteLock([&] { + _cutoff = value; + }); + + if (getIsSpotlight()) { // If we are a spotlight, adjusting the cutoff will affect the area we encapsulate, // so update the dimensions to reflect this. const float length = getDimensions().z; const float width = length * glm::sin(glm::radians(_cutoff)); setDimensions(glm::vec3(width, width, length)); } - _lightPropertiesChanged = true; + + withWriteLock([&] { + _lightPropertiesChanged = true; + }); } bool LightEntityItem::setProperties(const EntityItemProperties& properties) { @@ -205,5 +226,86 @@ void LightEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit void LightEntityItem::somethingChangedNotification() { EntityItem::somethingChangedNotification(); - _lightPropertiesChanged = false; + withWriteLock([&] { + _lightPropertiesChanged = false; + }); } + +const rgbColor& LightEntityItem::getColor() const { + return _color; +} + +xColor LightEntityItem::getXColor() const { + xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; +} + +void LightEntityItem::setColor(const rgbColor& value) { + withWriteLock([&] { + memcpy(_color, value, sizeof(_color)); + _lightPropertiesChanged = true; + }); +} + +void LightEntityItem::setColor(const xColor& value) { + withWriteLock([&] { + _color[RED_INDEX] = value.red; + _color[GREEN_INDEX] = value.green; + _color[BLUE_INDEX] = value.blue; + _lightPropertiesChanged = true; + }); +} + +bool LightEntityItem::getIsSpotlight() const { + bool result; + withReadLock([&] { + result = _isSpotlight; + }); + return result; +} + +float LightEntityItem::getIntensity() const { + float result; + withReadLock([&] { + result = _intensity; + }); + return result; +} + +void LightEntityItem::setIntensity(float value) { + withWriteLock([&] { + _intensity = value; + _lightPropertiesChanged = true; + }); +} + +float LightEntityItem::getFalloffRadius() const { + float result; + withReadLock([&] { + result = _falloffRadius; + }); + return result; +} + +float LightEntityItem::getExponent() const { + float result; + withReadLock([&] { + result = _exponent; + }); + return result; +} + +void LightEntityItem::setExponent(float value) { + withWriteLock([&] { + _exponent = value; + _lightPropertiesChanged = true; + }); +} + +float LightEntityItem::getCutoff() const { + float result; + withReadLock([&] { + result = _cutoff; + }); + return result; +} + diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index 3444b11cae..f0ed58f47a 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -97,7 +97,7 @@ public: static bool getLightsArePickable() { return _lightsArePickable; } static void setLightsArePickable(bool value) { _lightsArePickable = value; } -protected: +private: // properties of a light diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index 8ace665616..fe2c803f43 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -88,8 +88,10 @@ bool LineEntityItem::appendPoint(const glm::vec3& point) { qCDebug(entities) << "Point is outside entity's bounding box"; return false; } - _points << point; - _pointsChanged = true; + withWriteLock([&] { + _points << point; + _pointsChanged = true; + }); return true; } @@ -105,8 +107,11 @@ bool LineEntityItem::setLinePoints(const QVector& points) { return false; } } - _points = points; - _pointsChanged = true; + + withWriteLock([&] { + _points = points; + _pointsChanged = true; + }); return true; } @@ -159,3 +164,51 @@ void LineEntityItem::debugDump() const { qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); } + +const rgbColor& LineEntityItem::getColor() const { + return _color; +} + +xColor LineEntityItem::getXColor() const { + xColor result; + withReadLock([&] { + result = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; + }); + return result; +} + +void LineEntityItem::setColor(const rgbColor& value) { + withWriteLock([&] { + memcpy(_color, value, sizeof(_color)); + }); +} + +void LineEntityItem::setColor(const xColor& value) { + withWriteLock([&] { + _color[RED_INDEX] = value.red; + _color[GREEN_INDEX] = value.green; + _color[BLUE_INDEX] = value.blue; + }); +} + +void LineEntityItem::setLineWidth(float lineWidth) { + withWriteLock([&] { + _lineWidth = lineWidth; + }); +} + +float LineEntityItem::getLineWidth() const { + float result; + withReadLock([&] { + result = _lineWidth; + }); + return result; +} + +QVector LineEntityItem::getLinePoints() const { + QVector result; + withReadLock([&] { + result = _points; + }); + return result; +} diff --git a/libraries/entities/src/LineEntityItem.h b/libraries/entities/src/LineEntityItem.h index 8629c94eb4..7a882f6b9d 100644 --- a/libraries/entities/src/LineEntityItem.h +++ b/libraries/entities/src/LineEntityItem.h @@ -42,23 +42,19 @@ class LineEntityItem : public EntityItem { EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - const rgbColor& getColor() const { return _color; } - xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; } + const rgbColor& getColor() const; + xColor getXColor() const; - void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); } - void setColor(const xColor& value) { - _color[RED_INDEX] = value.red; - _color[GREEN_INDEX] = value.green; - _color[BLUE_INDEX] = value.blue; - } + void setColor(const rgbColor& value); + void setColor(const xColor& value); - void setLineWidth(float lineWidth){ _lineWidth = lineWidth; } - float getLineWidth() const{ return _lineWidth; } + void setLineWidth(float lineWidth); + float getLineWidth() const; bool setLinePoints(const QVector& points); bool appendPoint(const glm::vec3& point); - const QVector& getLinePoints() const{ return _points; } + QVector getLinePoints() const; virtual ShapeType getShapeType() const override { return SHAPE_TYPE_NONE; } @@ -74,7 +70,7 @@ class LineEntityItem : public EntityItem { static const float DEFAULT_LINE_WIDTH; static const int MAX_POINTS_PER_LINE; - protected: + private: rgbColor _color; float _lineWidth; bool _pointsChanged; diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index e1cb5cd92c..972bf1e18d 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -130,7 +130,7 @@ private: void setAnimationSettings(const QString& value); // only called for old bitstream format ShapeType computeTrueShapeType() const; -protected: +private: // these are used: // - to bounce joint data from an animation into the model/rig. // - to relay changes from scripts to model/rig. diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 4e49bb8ef0..ee421d567a 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -80,7 +80,7 @@ public: bool getFaceCamera() const; void setFaceCamera(bool value); -protected: +private: QString _text; float _lineHeight; rgbColor _textColor; From d89104f69ca3f68ae44236f81f1ea126a0b5dfe4 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 3 Apr 2017 14:22:00 -0700 Subject: [PATCH 060/128] Use getters instead of direct member access --- .../src/RenderableModelEntityItem.cpp | 27 ++++++++++--------- .../src/RenderableTextEntityItem.cpp | 8 +++--- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 487a3e1e56..06b79bb6a2 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -277,10 +277,11 @@ bool RenderableModelEntityItem::getAnimationFrame() { return false; } - if (_animation && _animation->isLoaded()) { + auto animation = getAnimation(); + if (animation && animation->isLoaded()) { - const QVector& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy - auto& fbxJoints = _animation->getGeometry().joints; + const QVector& frames = animation->getFramesReference(); // NOTE: getFrames() is too heavy + auto& fbxJoints = animation->getGeometry().joints; int frameCount = frames.size(); if (frameCount > 0) { @@ -566,7 +567,7 @@ void RenderableModelEntityItem::update(const quint64& now) { } // make a copy of the animation properites - _renderAnimationProperties = _animationProperties; + _renderAnimationProperties = getAnimationProperties(); ModelEntityItem::update(now); } @@ -608,11 +609,11 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori void RenderableModelEntityItem::setShapeType(ShapeType type) { ModelEntityItem::setShapeType(type); - if (_shapeType == SHAPE_TYPE_COMPOUND) { - if (!_compoundShapeResource && !_compoundShapeURL.isEmpty()) { + if (getShapeType() == SHAPE_TYPE_COMPOUND) { + if (!_compoundShapeResource && !getCompoundShapeURL().isEmpty()) { _compoundShapeResource = DependencyManager::get()->getGeometryResource(getCompoundShapeURL()); } - } else if (_compoundShapeResource && !_compoundShapeURL.isEmpty()) { + } else if (_compoundShapeResource && !getCompoundShapeURL().isEmpty()) { // the compoundURL has been set but the shapeType does not agree _compoundShapeResource.reset(); } @@ -627,7 +628,7 @@ void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) { if (tree) { QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID())); } - if (_shapeType == SHAPE_TYPE_COMPOUND) { + if (getShapeType() == SHAPE_TYPE_COMPOUND) { _compoundShapeResource = DependencyManager::get()->getGeometryResource(url); } } @@ -637,7 +638,7 @@ bool RenderableModelEntityItem::isReadyToComputeShape() { ShapeType type = getShapeType(); if (type == SHAPE_TYPE_COMPOUND) { - if (!_model || _compoundShapeURL.isEmpty()) { + if (!_model || getCompoundShapeURL().isEmpty()) { EntityTreePointer tree = getTree(); if (tree) { QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID())); @@ -659,8 +660,8 @@ bool RenderableModelEntityItem::isReadyToComputeShape() { doInitialModelSimulation(); } return true; - } else if (!_compoundShapeURL.isEmpty()) { - _compoundShapeResource = DependencyManager::get()->getGeometryResource(_compoundShapeURL); + } else if (!getCompoundShapeURL().isEmpty()) { + _compoundShapeResource = DependencyManager::get()->getGeometryResource(getCompoundShapeURL()); } } @@ -775,7 +776,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { pointCollection[i][j] = scaleToFit * (pointCollection[i][j] + _model->getOffset()) - registrationOffset; } } - shapeInfo.setParams(type, dimensions, _compoundShapeURL); + shapeInfo.setParams(type, dimensions, getCompoundShapeURL()); } else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) { // should never fall in here when model not fully loaded assert(_model && _model->isLoaded()); @@ -1001,7 +1002,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { } } - shapeInfo.setParams(type, 0.5f * dimensions, _modelURL); + shapeInfo.setParams(type, 0.5f * dimensions, getModelURL()); } else { ModelEntityItem::computeShapeInfo(shapeInfo); shapeInfo.setParams(type, 0.5f * dimensions); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 9c98e699f1..a58ed8bbff 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -77,14 +77,16 @@ void RenderableTextEntityItem::render(RenderArgs* args) { geometryCache->bindSimpleProgram(batch, false, transparent, false, false, true); geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID); - float scale = _lineHeight / _textRenderer->getFontSize(); + float lineheight = getLineHeight(); + float scale = lineheight / _textRenderer->getFontSize(); transformToTopLeft.setScale(scale); // Scale to have the correct line height batch.setModelTransform(transformToTopLeft); - float leftMargin = 0.1f * _lineHeight, topMargin = 0.1f * _lineHeight; + float leftMargin = 0.1f * lineheight, topMargin = 0.1f * lineheight; glm::vec2 bounds = glm::vec2(dimensions.x - 2.0f * leftMargin, dimensions.y - 2.0f * topMargin); - _textRenderer->draw(batch, leftMargin / scale, -topMargin / scale, _text, textColor, bounds / scale); + auto text = getText(); + _textRenderer->draw(batch, leftMargin / scale, -topMargin / scale, text, textColor, bounds / scale); } From fe84232ab459765041b141b7f458862b0bfd9dac Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 3 Apr 2017 14:22:37 -0700 Subject: [PATCH 061/128] More work on thread safety --- libraries/entities/src/EntityItem.h | 2 +- libraries/entities/src/LightEntityItem.h | 37 ++++++++---------------- libraries/entities/src/LineEntityItem.h | 3 +- libraries/entities/src/ModelEntityItem.h | 2 +- 4 files changed, 16 insertions(+), 28 deletions(-) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index e705fcbe2a..a751fd88b2 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -510,7 +510,7 @@ protected: // NOTE: _volumeMultiplier is used to allow some mass properties code exist in the EntityItem base class // rather than in all of the derived classes. If we ever collapse these classes to one we could do it a // different way. - const float _volumeMultiplier { 1.0f }; + float _volumeMultiplier { 1.0f }; glm::vec3 _gravity; glm::vec3 _acceleration; float _damping; diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index f0ed58f47a..b3cadcf0c7 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -57,41 +57,27 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - const rgbColor& getColor() const { return _color; } - xColor getXColor() const { - xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; - } + const rgbColor& getColor() const; + xColor getXColor() const; - void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); } - void setColor(const xColor& value) { - _color[RED_INDEX] = value.red; - _color[GREEN_INDEX] = value.green; - _color[BLUE_INDEX] = value.blue; - _lightPropertiesChanged = true; - } + void setColor(const rgbColor& value); + void setColor(const xColor& value); - bool getIsSpotlight() const { return _isSpotlight; } + bool getIsSpotlight() const; void setIsSpotlight(bool value); void setIgnoredColor(const rgbColor& value) { } void setIgnoredAttenuation(float value) { } - float getIntensity() const { return _intensity; } - void setIntensity(float value) { - _intensity = value; - _lightPropertiesChanged = true; - } - - float getFalloffRadius() const { return _falloffRadius; } + float getIntensity() const; + void setIntensity(float value); + float getFalloffRadius() const; void setFalloffRadius(float value); - float getExponent() const { return _exponent; } - void setExponent(float value) { - _exponent = value; - _lightPropertiesChanged = true; - } + float getExponent() const; + void setExponent(float value); - float getCutoff() const { return _cutoff; } + float getCutoff() const; void setCutoff(float value); static bool getLightsArePickable() { return _lightsArePickable; } @@ -108,6 +94,7 @@ private: float _exponent { DEFAULT_EXPONENT }; float _cutoff { DEFAULT_CUTOFF }; +protected: // Dirty flag turn true when either light properties is changing values. // This gets back to false in the somethingChangedNotification() call // Which is called after a setProperties() or a readEntitySubClassFromBUfferCall on the entity. diff --git a/libraries/entities/src/LineEntityItem.h b/libraries/entities/src/LineEntityItem.h index 7a882f6b9d..bb8ae8a21a 100644 --- a/libraries/entities/src/LineEntityItem.h +++ b/libraries/entities/src/LineEntityItem.h @@ -73,8 +73,9 @@ class LineEntityItem : public EntityItem { private: rgbColor _color; float _lineWidth; - bool _pointsChanged; QVector _points; +protected: + bool _pointsChanged; }; #endif // hifi_LineEntityItem_h diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 972bf1e18d..e1cb5cd92c 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -130,7 +130,7 @@ private: void setAnimationSettings(const QString& value); // only called for old bitstream format ShapeType computeTrueShapeType() const; -private: +protected: // these are used: // - to bounce joint data from an animation into the model/rig. // - to relay changes from scripts to model/rig. From c58fdb590a170008847fe7ccef0ee436e97edeea Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 4 Apr 2017 11:00:34 -0700 Subject: [PATCH 062/128] Fix for sliding feet when leaning in HMD mode. --- libraries/animation/src/Rig.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 020ea1d657..fb0867e2de 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1204,7 +1204,7 @@ void Rig::updateFromHandAndFeetParameters(const HandAndFeetParameters& params, f } else { _animVars.unset("leftFootPosition"); _animVars.unset("leftFootRotation"); - _animVars.set("leftFootType", (int)IKTarget::Type::HipsRelativeRotationAndPosition); + _animVars.set("leftFootType", (int)IKTarget::Type::RotationAndPosition); } if (params.isRightFootEnabled) { @@ -1214,7 +1214,7 @@ void Rig::updateFromHandAndFeetParameters(const HandAndFeetParameters& params, f } else { _animVars.unset("rightFootPosition"); _animVars.unset("rightFootRotation"); - _animVars.set("rightFootType", (int)IKTarget::Type::HipsRelativeRotationAndPosition); + _animVars.set("rightFootType", (int)IKTarget::Type::RotationAndPosition); } } From b9783d768eecb64011385bf9aa74fd014c19eabd Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Apr 2017 11:08:30 -0700 Subject: [PATCH 063/128] remove fileOnUrl since it is no longer used --- libraries/fbx/src/FBXReader.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 7bab0415f8..0245851256 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -443,20 +443,6 @@ FBXLight extractLight(const FBXNode& object) { return light; } -QByteArray fileOnUrl(const QByteArray& filepath, const QString& url) { - QString path = QFileInfo(url).path(); - QByteArray filename = filepath; - QFileInfo checkFile(path + "/" + filepath); - - // check if the file exists at the RelativeFilename - if (!(checkFile.exists() && checkFile.isFile())) { - // if not, assume it is in the fbx directory - filename = filename.mid(filename.lastIndexOf('/') + 1); - } - - return filename; -} - FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QString& url) { const FBXNode& node = _fbxNode; QMap meshes; From b18d82bd1918d33a0cc1efe3842bf47706974cb0 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 4 Apr 2017 11:50:38 -0700 Subject: [PATCH 064/128] adding different shaders for transparent for simpel --- .../render-utils/src/RenderPipelines.cpp | 8 +++-- .../render-utils/src/simple_textured.slf | 6 ++-- .../src/simple_textured_unlit.slf | 20 ++++------- .../src/simple_transparent_textured.slf | 9 +++-- .../src/simple_transparent_textured_unlit.slf | 33 +++++++++++++++++++ 5 files changed, 56 insertions(+), 20 deletions(-) create mode 100644 libraries/render-utils/src/simple_transparent_textured_unlit.slf diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index efbe09863b..c6a05e0d65 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -31,6 +31,8 @@ #include "simple_vert.h" #include "simple_textured_frag.h" #include "simple_textured_unlit_frag.h" +#include "simple_transparent_textured_frag.h" +#include "simple_transparent_textured_unlit_frag.h" #include "model_frag.h" #include "model_unlit_frag.h" @@ -152,6 +154,8 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { // Pixel shaders auto simplePixel = gpu::Shader::createPixel(std::string(simple_textured_frag)); auto simpleUnlitPixel = gpu::Shader::createPixel(std::string(simple_textured_unlit_frag)); + auto simpleTranslucentPixel = gpu::Shader::createPixel(std::string(simple_transparent_textured_frag)); + auto simpleTranslucentUnlitPixel = gpu::Shader::createPixel(std::string(simple_transparent_textured_unlit_frag)); auto modelPixel = gpu::Shader::createPixel(std::string(model_frag)); auto modelUnlitPixel = gpu::Shader::createPixel(std::string(model_unlit_frag)); auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag)); @@ -196,13 +200,13 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { modelVertex, modelTranslucentPixel); addPipeline( Key::Builder().withTranslucent(), - simpleVertex, simplePixel); + simpleVertex, simpleTranslucentPixel); addPipeline( Key::Builder().withMaterial().withTranslucent().withUnlit(), modelVertex, modelTranslucentUnlitPixel); addPipeline( Key::Builder().withTranslucent().withUnlit(), - simpleVertex, simpleUnlitPixel); + simpleVertex, simpleTranslucentUnlitPixel); addPipeline( Key::Builder().withMaterial().withTranslucent().withTangents(), modelNormalMapVertex, modelTranslucentPixel); diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf index 6067c81a1b..550f6546fd 100644 --- a/libraries/render-utils/src/simple_textured.slf +++ b/libraries/render-utils/src/simple_textured.slf @@ -26,15 +26,17 @@ in vec2 _texCoord0; void main(void) { vec4 texel = texture(originalTexture, _texCoord0); + float colorAlpha = _color.a; if (_color.a <= 0.0) { texel = colorToLinearRGBA(texel); + colorAlpha = -_color.a; } const float ALPHA_THRESHOLD = 0.999; - if (_color.a * texel.a < ALPHA_THRESHOLD) { + if (colorAlpha * texel.a < ALPHA_THRESHOLD) { packDeferredFragmentTranslucent( normalize(_normal), - _color.a * texel.a, + colorAlpha * texel.a, _color.rgb * texel.rgb, DEFAULT_FRESNEL, DEFAULT_ROUGHNESS); diff --git a/libraries/render-utils/src/simple_textured_unlit.slf b/libraries/render-utils/src/simple_textured_unlit.slf index 1ee2011972..d261fb343a 100644 --- a/libraries/render-utils/src/simple_textured_unlit.slf +++ b/libraries/render-utils/src/simple_textured_unlit.slf @@ -25,28 +25,20 @@ in vec2 _texCoord0; void main(void) { vec4 texel = texture(originalTexture, _texCoord0.st); + float colorAlpha = _color.a; if (_color.a <= 0.0) { texel = colorToLinearRGBA(texel); + colorAlpha = -_color.a; } const float ALPHA_THRESHOLD = 0.999; - if (_color.a * texel.a < ALPHA_THRESHOLD) { - - _fragColor0 = vec4(_color.rgb * texel.rgb, _color.a * texel.a); - - if (_color.a * texel.a <= 0.0) { - _fragColor0 = vec4(_color.rgb * texel.rgb, _color.a * texel.a); - //discard; - } else { - _fragColor0 = vec4(_color.rgb * texel.rgb, _color.a * texel.a); - } - // _fragColor0 = vec4(albedo.rgb, alpha); - /* packDeferredFragmentTranslucent( + if (colorAlpha * texel.a < ALPHA_THRESHOLD) { + packDeferredFragmentTranslucent( normalize(_normal), - _color.a * texel.a, + colorAlpha * texel.a, _color.rgb * texel.rgb, DEFAULT_FRESNEL, - DEFAULT_ROUGHNESS);*/ + DEFAULT_ROUGHNESS); } else { packDeferredFragmentUnlit( normalize(_normal), diff --git a/libraries/render-utils/src/simple_transparent_textured.slf b/libraries/render-utils/src/simple_transparent_textured.slf index 0fda804129..f61a2c3608 100644 --- a/libraries/render-utils/src/simple_transparent_textured.slf +++ b/libraries/render-utils/src/simple_transparent_textured.slf @@ -26,10 +26,15 @@ in vec2 _texCoord0; void main(void) { vec4 texel = texture(originalTexture, _texCoord0.st); - texel = colorToLinearRGBA(texel); + float colorAlpha = _color.a; + if (_color.a <= 0.0) { + texel = colorToLinearRGBA(texel); + colorAlpha = -_color.a; + } + packDeferredFragmentTranslucent( normalize(_normal), - _color.a, + colorAlpha, _color.rgb * texel.rgb, DEFAULT_FRESNEL, DEFAULT_ROUGHNESS); diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit.slf b/libraries/render-utils/src/simple_transparent_textured_unlit.slf new file mode 100644 index 0000000000..9ef3e6b82a --- /dev/null +++ b/libraries/render-utils/src/simple_transparent_textured_unlit.slf @@ -0,0 +1,33 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple_transparent_textured_unlit.slf +// fragment shader +// +// Created by Sam Gateau on 4/3/17. +// 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 +// + +<@include gpu/Color.slh@> + +// the albedo texture +uniform sampler2D originalTexture; + +// the interpolated normal +in vec3 _normal; +in vec4 _color; +in vec2 _texCoord0; + +void main(void) { + vec4 texel = texture(originalTexture, _texCoord0.st); + float colorAlpha = _color.a; + if (_color.a <= 0.0) { + texel = colorToLinearRGBA(texel); + colorAlpha = -_color.a; + } + _fragColor0 = vec4(_color.rgb * texel.rgb, colorAlpha * texel.a); +} \ No newline at end of file From a0f0879087a8799cb619b36c2dd9032d991016e6 Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Fri, 10 Mar 2017 18:16:38 -0800 Subject: [PATCH 065/128] added file type filter and interceptor --- interface/resources/qml/controls/WebView.qml | 4 +- interface/resources/qml/hifi/Desktop.qml | 4 +- interface/src/Application.cpp | 2 + interface/src/networking/FileTypeProfile.cpp | 26 +++++++++ interface/src/networking/FileTypeProfile.h | 25 ++++++++ .../networking/FileTypeRequestInterceptor.cpp | 22 +++++++ .../networking/FileTypeRequestInterceptor.h | 26 +++++++++ .../HFWebEngineRequestInterceptor.cpp | 27 +-------- interface/src/networking/RequestFilters.cpp | 58 +++++++++++++++++++ interface/src/networking/RequestFilters.h | 28 +++++++++ 10 files changed, 194 insertions(+), 28 deletions(-) create mode 100644 interface/src/networking/FileTypeProfile.cpp create mode 100644 interface/src/networking/FileTypeProfile.h create mode 100644 interface/src/networking/FileTypeRequestInterceptor.cpp create mode 100644 interface/src/networking/FileTypeRequestInterceptor.h create mode 100644 interface/src/networking/RequestFilters.cpp create mode 100644 interface/src/networking/RequestFilters.h diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index a3badd7e1f..d3e1d97d1a 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -2,7 +2,7 @@ import QtQuick 2.5 import QtWebEngine 1.1 import QtWebChannel 1.0 import "../controls-uit" as HiFiControls -import HFWebEngineProfile 1.0 +import FileTypeProfile 1.0 Item { property alias url: root.url @@ -36,7 +36,7 @@ Item { width: parent.width height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height - profile: HFWebEngineProfile { + profile: FileTypeProfile { id: webviewProfile storageName: "qmlWebEngine" } diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index 7857eda3c2..cd66b014a4 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -2,7 +2,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import QtWebEngine 1.1; import Qt.labs.settings 1.0 -import HFWebEngineProfile 1.0 +import FileTypeProfile 1.0 import "../desktop" as OriginalDesktop import ".." @@ -27,7 +27,7 @@ OriginalDesktop.Desktop { property alias toolWindow: toolWindow ToolWindow { id: toolWindow } - property var browserProfile: HFWebEngineProfile { + property var browserProfile: FileTypeProfile { id: webviewProfile storageName: "qmlWebEngine" } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e19eea0a2e..aa33b66962 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -142,6 +142,7 @@ #include "ModelPackager.h" #include "networking/HFWebEngineProfile.h" #include "networking/HFTabletWebEngineProfile.h" +#include "networking/FileTypeProfile.h" #include "scripting/TestScriptingInterface.h" #include "scripting/AccountScriptingInterface.h" #include "scripting/AssetMappingsScriptingInterface.h" @@ -1934,6 +1935,7 @@ void Application::initializeUi() { qmlRegisterType("HFWebEngineProfile", 1, 0, "HFWebEngineProfile"); qmlRegisterType("HFTabletWebEngineProfile", 1, 0, "HFTabletWebEngineProfile"); + qmlRegisterType("FileTypeProfile", 1, 0, "FileTypeProfile"); auto offscreenUi = DependencyManager::get(); offscreenUi->create(_glWidget->qglContext()); diff --git a/interface/src/networking/FileTypeProfile.cpp b/interface/src/networking/FileTypeProfile.cpp new file mode 100644 index 0000000000..2048751e5d --- /dev/null +++ b/interface/src/networking/FileTypeProfile.cpp @@ -0,0 +1,26 @@ +// +// FileTypeProfile.cpp +// interface/src/networking +// +// Created by Kunal Gosar on 2017-03-10. +// 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 +// + +#include "FileTypeProfile.h" + +#include "FileTypeRequestInterceptor.h" + +static const QString QML_WEB_ENGINE_STORAGE_NAME = "qmlWebEngine"; + +FileTypeProfile::FileTypeProfile(QObject* parent) : + QQuickWebEngineProfile(parent) +{ + static const QString WEB_ENGINE_USER_AGENT = "Chrome/48.0 (HighFidelityInterface)"; + setHttpUserAgent(WEB_ENGINE_USER_AGENT); + + auto requestInterceptor = new FileTypeRequestInterceptor(this); + setRequestInterceptor(requestInterceptor); +} \ No newline at end of file diff --git a/interface/src/networking/FileTypeProfile.h b/interface/src/networking/FileTypeProfile.h new file mode 100644 index 0000000000..99ed5d4b79 --- /dev/null +++ b/interface/src/networking/FileTypeProfile.h @@ -0,0 +1,25 @@ +// +// FileTypeProfile.h +// interface/src/networking +// +// Created by Kunal Gosar on 2017-03-10. +// 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 +// + +#pragma once + +#ifndef hifi_FileTypeProfile_h +#define hifi_FileTypeProfile_h + +#include + +class FileTypeProfile : public QQuickWebEngineProfile { +public: + FileTypeProfile(QObject* parent = Q_NULLPTR); +}; + + +#endif // hifi_FileTypeProfile_h \ No newline at end of file diff --git a/interface/src/networking/FileTypeRequestInterceptor.cpp b/interface/src/networking/FileTypeRequestInterceptor.cpp new file mode 100644 index 0000000000..2dac5db194 --- /dev/null +++ b/interface/src/networking/FileTypeRequestInterceptor.cpp @@ -0,0 +1,22 @@ +// +// FileTypeRequestInterceptor.cpp +// interface/src/networking +// +// Created by Kunal Gosar on 2017-03-10. +// 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 +// + +#include "FileTypeRequestInterceptor.h" + +#include + +#include "RequestFilters.h" + +void FileTypeRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { + RequestFilters* filter = new RequestFilters; + filter->interceptHFWebEngineRequest(info); + filter->interceptFileType(info); +} diff --git a/interface/src/networking/FileTypeRequestInterceptor.h b/interface/src/networking/FileTypeRequestInterceptor.h new file mode 100644 index 0000000000..c39c860b7c --- /dev/null +++ b/interface/src/networking/FileTypeRequestInterceptor.h @@ -0,0 +1,26 @@ +// +// FileTypeRequestInterceptor.h +// interface/src/networking +// +// Created by Kunal Gosar on 2017-03-10. +// 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 +// + +#pragma once + +#ifndef hifi_FileTypeRequestInterceptor_h +#define hifi_FileTypeRequestInterceptor_h + +#include + +class FileTypeRequestInterceptor : public QWebEngineUrlRequestInterceptor { +public: + FileTypeRequestInterceptor(QObject* parent) : QWebEngineUrlRequestInterceptor(parent) {}; + + virtual void interceptRequest(QWebEngineUrlRequestInfo& info) override; +}; + +#endif // hifi_FileTypeRequestInterceptor_h \ No newline at end of file diff --git a/interface/src/networking/HFWebEngineRequestInterceptor.cpp b/interface/src/networking/HFWebEngineRequestInterceptor.cpp index f6b0914f08..400d547d92 100644 --- a/interface/src/networking/HFWebEngineRequestInterceptor.cpp +++ b/interface/src/networking/HFWebEngineRequestInterceptor.cpp @@ -15,30 +15,9 @@ #include #include - -bool isAuthableHighFidelityURL(const QUrl& url) { - static const QStringList HF_HOSTS = { - "highfidelity.com", "highfidelity.io", - "metaverse.highfidelity.com", "metaverse.highfidelity.io" - }; - const auto& scheme = url.scheme(); - const auto& host = url.host(); - - return (scheme == "https" && HF_HOSTS.contains(host)) || - ((scheme == NetworkingConstants::METAVERSE_SERVER_URL.scheme()) && (host == NetworkingConstants::METAVERSE_SERVER_URL.host())); -} +#include "RequestFilters.h" void HFWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { - // check if this is a request to a highfidelity URL - if (isAuthableHighFidelityURL(info.requestUrl())) { - // if we have an access token, add it to the right HTTP header for authorization - auto accountManager = DependencyManager::get(); - - if (accountManager->hasValidAccessToken()) { - static const QString OAUTH_AUTHORIZATION_HEADER = "Authorization"; - - QString bearerTokenString = "Bearer " + accountManager->getAccountInfo().getAccessToken().token; - info.setHttpHeader(OAUTH_AUTHORIZATION_HEADER.toLocal8Bit(), bearerTokenString.toLocal8Bit()); - } - } + RequestFilters* filter = new RequestFilters; + filter->interceptHFWebEngineRequest(info); } diff --git a/interface/src/networking/RequestFilters.cpp b/interface/src/networking/RequestFilters.cpp new file mode 100644 index 0000000000..65845504c0 --- /dev/null +++ b/interface/src/networking/RequestFilters.cpp @@ -0,0 +1,58 @@ +// +// RequestFilters.cpp +// interface/src/networking +// +// Created by Kunal Gosar on 2017-03-10. +// 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 +// + +#include "RequestFilters.h" + +#include + +#include + +bool isAuthableHighFidelityURL(const QUrl& url) { + static const QStringList HF_HOSTS = { + "highfidelity.com", "highfidelity.io", + "metaverse.highfidelity.com", "metaverse.highfidelity.io" + }; + + return url.scheme() == "https" && HF_HOSTS.contains(url.host()); +} + +bool isJavaScriptFile(const QString filename) { + return filename.contains(".js", Qt::CaseInsensitive); +} + +bool isEntityFile(const QString filename) { + return filename.contains(".svo.json", Qt::CaseInsensitive); +} + +void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info) { + // check if this is a request to a highfidelity URL + if (isAuthableHighFidelityURL(info.requestUrl())) { + // if we have an access token, add it to the right HTTP header for authorization + auto accountManager = DependencyManager::get(); + + if (accountManager->hasValidAccessToken()) { + static const QString OAUTH_AUTHORIZATION_HEADER = "Authorization"; + + QString bearerTokenString = "Bearer " + accountManager->getAccountInfo().getAccessToken().token; + info.setHttpHeader(OAUTH_AUTHORIZATION_HEADER.toLocal8Bit(), bearerTokenString.toLocal8Bit()); + } + } +} + +void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info) { + QString filename = info.requestUrl().fileName(); + + if (isJavaScriptFile(filename) || isEntityFile(filename)) { + static const QString CONTENT_HEADER = "Content-Type"; + static const QString HEADER_VALUE = "text/plain"; + info.setHttpHeader(CONTENT_HEADER.toLocal8Bit(), HEADER_VALUE.toLocal8Bit()); + } +} \ No newline at end of file diff --git a/interface/src/networking/RequestFilters.h b/interface/src/networking/RequestFilters.h new file mode 100644 index 0000000000..ab20a267e0 --- /dev/null +++ b/interface/src/networking/RequestFilters.h @@ -0,0 +1,28 @@ +// +// RequestFilters.h +// interface/src/networking +// +// Created by Kunal Gosar on 2017-03-10. +// 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 +// + +#pragma once + +#ifndef hifi_RequestFilters_h +#define hifi_RequestFilters_h + +#include +#include + +class RequestFilters : public QObject { + Q_OBJECT + +public: + void interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info); + void interceptFileType(QWebEngineUrlRequestInfo& info); +}; + +#endif // hifi_RequestFilters_h \ No newline at end of file From 9b758dbdba32d31e1ecda5f08b202c37b2463d84 Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Fri, 10 Mar 2017 18:45:25 -0800 Subject: [PATCH 066/128] updated headers --- interface/src/networking/RequestFilters.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/interface/src/networking/RequestFilters.cpp b/interface/src/networking/RequestFilters.cpp index 65845504c0..5a29b58da9 100644 --- a/interface/src/networking/RequestFilters.cpp +++ b/interface/src/networking/RequestFilters.cpp @@ -51,8 +51,11 @@ void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info) { QString filename = info.requestUrl().fileName(); if (isJavaScriptFile(filename) || isEntityFile(filename)) { - static const QString CONTENT_HEADER = "Content-Type"; - static const QString HEADER_VALUE = "text/plain"; - info.setHttpHeader(CONTENT_HEADER.toLocal8Bit(), HEADER_VALUE.toLocal8Bit()); + static const QString CONTENT_HEADER = "Accept"; + static const QString TYPE_VALUE = "text/html"; + info.setHttpHeader(CONTENT_HEADER.toLocal8Bit(), TYPE_VALUE.toLocal8Bit()); + static const QString CONTENT_DISPOSITION = "Content-Disposition"; + static const QString DISPOSITION_VALUE = "inline"; + info.setHttpHeader(CONTENT_DISPOSITION.toLocal8Bit(), DISPOSITION_VALUE.toLocal8Bit()); } } \ No newline at end of file From 19ab7526d35f9863e84d8602d9141779986c8030 Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Thu, 16 Mar 2017 17:54:42 -0700 Subject: [PATCH 067/128] apply profile to relevant entities --- interface/resources/qml/Browser.qml | 6 ++++++ .../resources/qml/controls/WebEntityView.qml | 20 +++++++++++++++++++ interface/resources/qml/controls/WebView.qml | 6 ++++-- interface/resources/qml/hifi/Desktop.qml | 4 ++-- interface/src/networking/FileTypeProfile.cpp | 2 +- interface/src/networking/FileTypeProfile.h | 2 +- .../networking/FileTypeRequestInterceptor.h | 2 +- interface/src/networking/RequestFilters.cpp | 8 ++------ interface/src/networking/RequestFilters.h | 2 +- .../src/RenderableWebEntityItem.cpp | 2 +- 10 files changed, 39 insertions(+), 15 deletions(-) create mode 100644 interface/resources/qml/controls/WebEntityView.qml diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index c4e0c85642..47fb610469 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -2,6 +2,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.2 import QtWebChannel 1.0 import QtWebEngine 1.2 +import FileTypeProfile 1.0 import "controls-uit" import "styles" as HifiStyles @@ -216,6 +217,11 @@ ScrollingWindow { WebChannel.id: "eventBridgeWrapper" property var eventBridge; } + + profile: FileTypeProfile { + id: webviewProfile + storageName: "qmlWebEngine" + } webChannel.registeredObjects: [eventBridgeWrapper] diff --git a/interface/resources/qml/controls/WebEntityView.qml b/interface/resources/qml/controls/WebEntityView.qml new file mode 100644 index 0000000000..961ebffb38 --- /dev/null +++ b/interface/resources/qml/controls/WebEntityView.qml @@ -0,0 +1,20 @@ +// +// 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 "." +import FileTypeProfile 1.0 + +WebView { + viewProfile: FileTypeProfile { + id: webviewProfile + storageName: "qmlWebEngine" + } +} diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index d3e1d97d1a..8c73eddcc2 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -2,7 +2,7 @@ import QtQuick 2.5 import QtWebEngine 1.1 import QtWebChannel 1.0 import "../controls-uit" as HiFiControls -import FileTypeProfile 1.0 +import HFWebEngineProfile 1.0 Item { property alias url: root.url @@ -27,6 +27,8 @@ Item { WebChannel.id: "eventBridgeWrapper" property var eventBridge; } + + property alias viewProfile: root.profile WebEngineView { id: root @@ -36,7 +38,7 @@ Item { width: parent.width height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height - profile: FileTypeProfile { + profile: HFWebEngineProfile { id: webviewProfile storageName: "qmlWebEngine" } diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index cd66b014a4..7857eda3c2 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -2,7 +2,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import QtWebEngine 1.1; import Qt.labs.settings 1.0 -import FileTypeProfile 1.0 +import HFWebEngineProfile 1.0 import "../desktop" as OriginalDesktop import ".." @@ -27,7 +27,7 @@ OriginalDesktop.Desktop { property alias toolWindow: toolWindow ToolWindow { id: toolWindow } - property var browserProfile: FileTypeProfile { + property var browserProfile: HFWebEngineProfile { id: webviewProfile storageName: "qmlWebEngine" } diff --git a/interface/src/networking/FileTypeProfile.cpp b/interface/src/networking/FileTypeProfile.cpp index 2048751e5d..6fcd8df669 100644 --- a/interface/src/networking/FileTypeProfile.cpp +++ b/interface/src/networking/FileTypeProfile.cpp @@ -23,4 +23,4 @@ FileTypeProfile::FileTypeProfile(QObject* parent) : auto requestInterceptor = new FileTypeRequestInterceptor(this); setRequestInterceptor(requestInterceptor); -} \ No newline at end of file +} diff --git a/interface/src/networking/FileTypeProfile.h b/interface/src/networking/FileTypeProfile.h index 99ed5d4b79..f922fd66de 100644 --- a/interface/src/networking/FileTypeProfile.h +++ b/interface/src/networking/FileTypeProfile.h @@ -22,4 +22,4 @@ public: }; -#endif // hifi_FileTypeProfile_h \ No newline at end of file +#endif // hifi_FileTypeProfile_h diff --git a/interface/src/networking/FileTypeRequestInterceptor.h b/interface/src/networking/FileTypeRequestInterceptor.h index c39c860b7c..be971daf7a 100644 --- a/interface/src/networking/FileTypeRequestInterceptor.h +++ b/interface/src/networking/FileTypeRequestInterceptor.h @@ -23,4 +23,4 @@ public: virtual void interceptRequest(QWebEngineUrlRequestInfo& info) override; }; -#endif // hifi_FileTypeRequestInterceptor_h \ No newline at end of file +#endif // hifi_FileTypeRequestInterceptor_h diff --git a/interface/src/networking/RequestFilters.cpp b/interface/src/networking/RequestFilters.cpp index 5a29b58da9..0f59258b66 100644 --- a/interface/src/networking/RequestFilters.cpp +++ b/interface/src/networking/RequestFilters.cpp @@ -49,13 +49,9 @@ void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info) void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info) { QString filename = info.requestUrl().fileName(); - if (isJavaScriptFile(filename) || isEntityFile(filename)) { static const QString CONTENT_HEADER = "Accept"; - static const QString TYPE_VALUE = "text/html"; + static const QString TYPE_VALUE = "text/plain"; info.setHttpHeader(CONTENT_HEADER.toLocal8Bit(), TYPE_VALUE.toLocal8Bit()); - static const QString CONTENT_DISPOSITION = "Content-Disposition"; - static const QString DISPOSITION_VALUE = "inline"; - info.setHttpHeader(CONTENT_DISPOSITION.toLocal8Bit(), DISPOSITION_VALUE.toLocal8Bit()); } -} \ No newline at end of file +} diff --git a/interface/src/networking/RequestFilters.h b/interface/src/networking/RequestFilters.h index ab20a267e0..d61208a22d 100644 --- a/interface/src/networking/RequestFilters.h +++ b/interface/src/networking/RequestFilters.h @@ -25,4 +25,4 @@ public: void interceptFileType(QWebEngineUrlRequestInfo& info); }; -#endif // hifi_RequestFilters_h \ No newline at end of file +#endif // hifi_RequestFilters_h diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index c4ae0db1aa..109c4cbfe9 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -266,7 +266,7 @@ void RenderableWebEntityItem::loadSourceURL() { _webSurface->setMaxFps(DEFAULT_MAX_FPS); } - _webSurface->load("WebView.qml", [&](QQmlContext* context, QObject* obj) { + _webSurface->load("WebEntityView.qml", [&](QQmlContext* context, QObject* obj) { context->setContextProperty("eventBridgeJavaScriptToInject", QVariant(_javaScriptToInject)); }); From 9d0667cb3150a99e636cc5706f9dc9cca434c8a4 Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Fri, 17 Mar 2017 15:22:36 -0700 Subject: [PATCH 068/128] add url tag to web entities --- interface/resources/qml/controls/WebEntityView.qml | 2 ++ interface/resources/qml/controls/WebView.qml | 5 ++++- interface/src/Application.cpp | 5 ++++- interface/src/networking/FileTypeRequestInterceptor.cpp | 5 ++--- interface/src/networking/HFWebEngineRequestInterceptor.cpp | 3 +-- interface/src/networking/RequestFilters.cpp | 6 +++--- interface/src/networking/RequestFilters.h | 4 ++-- 7 files changed, 18 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/controls/WebEntityView.qml b/interface/resources/qml/controls/WebEntityView.qml index 961ebffb38..821954bf7b 100644 --- a/interface/resources/qml/controls/WebEntityView.qml +++ b/interface/resources/qml/controls/WebEntityView.qml @@ -17,4 +17,6 @@ WebView { id: webviewProfile storageName: "qmlWebEngine" } + + urlTag: "?noDowload=true"; } diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index 8c73eddcc2..dc62721ace 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -10,6 +10,7 @@ Item { property alias eventBridge: eventBridgeWrapper.eventBridge property alias canGoBack: root.canGoBack; property var goBack: root.goBack; + property alias urlTag: root.urlTag property bool keyboardEnabled: true // FIXME - Keyboard HMD only: Default to false property bool keyboardRaised: false property bool punctuationMode: false @@ -68,6 +69,8 @@ Item { injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished. worldId: WebEngineScript.MainWorld } + + property string urlTag: "?noDowload=false"; userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] @@ -95,7 +98,7 @@ Item { // Required to support clicking on "hifi://" links if (WebEngineView.LoadStartedStatus == loadRequest.status) { - var url = loadRequest.url.toString(); + var url = loadRequest.url.toString() + urlTag; if (urlHandler.canHandleUrl(url)) { if (urlHandler.handleUrl(url)) { root.stop(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index aa33b66962..eee9253c76 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -219,6 +219,7 @@ static const QString FST_EXTENSION = ".fst"; static const QString FBX_EXTENSION = ".fbx"; static const QString OBJ_EXTENSION = ".obj"; static const QString AVA_JSON_EXTENSION = ".ava.json"; +static const QString WEB_VIEW_TAG = "?noDowload=true"; static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f; @@ -2607,7 +2608,7 @@ bool Application::event(QEvent* event) { QFileOpenEvent* fileEvent = static_cast(event); QUrl url = fileEvent->url(); - + if (!url.isEmpty()) { QString urlString = url.toString(); @@ -5549,6 +5550,8 @@ bool Application::canAcceptURL(const QString& urlString) const { QUrl url(urlString); if (urlString.startsWith(HIFI_URL_SCHEME)) { return true; + } else if (urlString.endsWith(WEB_VIEW_TAG)) { + return false; } QHashIterator i(_acceptedExtensions); QString lowerPath = url.path().toLower(); diff --git a/interface/src/networking/FileTypeRequestInterceptor.cpp b/interface/src/networking/FileTypeRequestInterceptor.cpp index 2dac5db194..91bacd46a6 100644 --- a/interface/src/networking/FileTypeRequestInterceptor.cpp +++ b/interface/src/networking/FileTypeRequestInterceptor.cpp @@ -16,7 +16,6 @@ #include "RequestFilters.h" void FileTypeRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { - RequestFilters* filter = new RequestFilters; - filter->interceptHFWebEngineRequest(info); - filter->interceptFileType(info); + RequestFilters::interceptHFWebEngineRequest(info); + RequestFilters::interceptFileType(info); } diff --git a/interface/src/networking/HFWebEngineRequestInterceptor.cpp b/interface/src/networking/HFWebEngineRequestInterceptor.cpp index 400d547d92..546edcf95c 100644 --- a/interface/src/networking/HFWebEngineRequestInterceptor.cpp +++ b/interface/src/networking/HFWebEngineRequestInterceptor.cpp @@ -18,6 +18,5 @@ #include "RequestFilters.h" void HFWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { - RequestFilters* filter = new RequestFilters; - filter->interceptHFWebEngineRequest(info); + RequestFilters::interceptHFWebEngineRequest(info); } diff --git a/interface/src/networking/RequestFilters.cpp b/interface/src/networking/RequestFilters.cpp index 0f59258b66..39ed5117ac 100644 --- a/interface/src/networking/RequestFilters.cpp +++ b/interface/src/networking/RequestFilters.cpp @@ -15,7 +15,7 @@ #include -bool isAuthableHighFidelityURL(const QUrl& url) { +bool static isAuthableHighFidelityURL(const QUrl& url) { static const QStringList HF_HOSTS = { "highfidelity.com", "highfidelity.io", "metaverse.highfidelity.com", "metaverse.highfidelity.io" @@ -24,11 +24,11 @@ bool isAuthableHighFidelityURL(const QUrl& url) { return url.scheme() == "https" && HF_HOSTS.contains(url.host()); } -bool isJavaScriptFile(const QString filename) { +bool static isJavaScriptFile(const QString filename) { return filename.contains(".js", Qt::CaseInsensitive); } -bool isEntityFile(const QString filename) { +bool static isEntityFile(const QString filename) { return filename.contains(".svo.json", Qt::CaseInsensitive); } diff --git a/interface/src/networking/RequestFilters.h b/interface/src/networking/RequestFilters.h index d61208a22d..0d7d66e155 100644 --- a/interface/src/networking/RequestFilters.h +++ b/interface/src/networking/RequestFilters.h @@ -21,8 +21,8 @@ class RequestFilters : public QObject { Q_OBJECT public: - void interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info); - void interceptFileType(QWebEngineUrlRequestInfo& info); + static void interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info); + static void interceptFileType(QWebEngineUrlRequestInfo& info); }; #endif // hifi_RequestFilters_h From 3b88553699e62d33ed4eb3a5a4dd97b4ab623dc1 Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Fri, 17 Mar 2017 15:33:42 -0700 Subject: [PATCH 069/128] check scripts --- interface/src/networking/RequestFilters.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/interface/src/networking/RequestFilters.cpp b/interface/src/networking/RequestFilters.cpp index 39ed5117ac..894ed9fdd2 100644 --- a/interface/src/networking/RequestFilters.cpp +++ b/interface/src/networking/RequestFilters.cpp @@ -24,14 +24,10 @@ bool static isAuthableHighFidelityURL(const QUrl& url) { return url.scheme() == "https" && HF_HOSTS.contains(url.host()); } -bool static isJavaScriptFile(const QString filename) { +bool static isScript(const QString filename) { return filename.contains(".js", Qt::CaseInsensitive); } -bool static isEntityFile(const QString filename) { - return filename.contains(".svo.json", Qt::CaseInsensitive); -} - void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info) { // check if this is a request to a highfidelity URL if (isAuthableHighFidelityURL(info.requestUrl())) { @@ -49,9 +45,9 @@ void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info) void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info) { QString filename = info.requestUrl().fileName(); - if (isJavaScriptFile(filename) || isEntityFile(filename)) { + if (isScript(filename)) { static const QString CONTENT_HEADER = "Accept"; - static const QString TYPE_VALUE = "text/plain"; + static const QString TYPE_VALUE = "text/plain,text/html"; info.setHttpHeader(CONTENT_HEADER.toLocal8Bit(), TYPE_VALUE.toLocal8Bit()); } } From 8e4229b2119dc789c1c90f91fe9e4ac56512634a Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Fri, 17 Mar 2017 15:44:46 -0700 Subject: [PATCH 070/128] dont redirect people from webentity --- interface/src/Application.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eee9253c76..2901de23b3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5548,10 +5548,10 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri bool Application::canAcceptURL(const QString& urlString) const { QUrl url(urlString); - if (urlString.startsWith(HIFI_URL_SCHEME)) { - return true; - } else if (urlString.endsWith(WEB_VIEW_TAG)) { + if (urlString.endsWith(WEB_VIEW_TAG)) { return false; + } else if (urlString.startsWith(HIFI_URL_SCHEME)) { + return true; } QHashIterator i(_acceptedExtensions); QString lowerPath = url.path().toLower(); From e5c075f107b95000b1cca4a5e0d7163b7e5e6271 Mon Sep 17 00:00:00 2001 From: Kunal Gosar Date: Fri, 24 Mar 2017 00:10:53 -0700 Subject: [PATCH 071/128] fix typo and namespace --- .../resources/qml/controls/WebEntityView.qml | 2 +- interface/resources/qml/controls/WebView.qml | 2 +- interface/src/Application.cpp | 2 +- interface/src/networking/RequestFilters.cpp | 22 +++++++++++-------- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/controls/WebEntityView.qml b/interface/resources/qml/controls/WebEntityView.qml index 821954bf7b..4b4c8fe46f 100644 --- a/interface/resources/qml/controls/WebEntityView.qml +++ b/interface/resources/qml/controls/WebEntityView.qml @@ -18,5 +18,5 @@ WebView { storageName: "qmlWebEngine" } - urlTag: "?noDowload=true"; + urlTag: "?noDownload=true"; } diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index dc62721ace..b904dd5d55 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -70,7 +70,7 @@ Item { worldId: WebEngineScript.MainWorld } - property string urlTag: "?noDowload=false"; + property string urlTag: "?noDownload=false"; userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2901de23b3..f0897176af 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -219,7 +219,7 @@ static const QString FST_EXTENSION = ".fst"; static const QString FBX_EXTENSION = ".fbx"; static const QString OBJ_EXTENSION = ".obj"; static const QString AVA_JSON_EXTENSION = ".ava.json"; -static const QString WEB_VIEW_TAG = "?noDowload=true"; +static const QString WEB_VIEW_TAG = "?noDownload=true"; static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f; diff --git a/interface/src/networking/RequestFilters.cpp b/interface/src/networking/RequestFilters.cpp index 894ed9fdd2..abf9575bdc 100644 --- a/interface/src/networking/RequestFilters.cpp +++ b/interface/src/networking/RequestFilters.cpp @@ -15,17 +15,21 @@ #include -bool static isAuthableHighFidelityURL(const QUrl& url) { - static const QStringList HF_HOSTS = { - "highfidelity.com", "highfidelity.io", - "metaverse.highfidelity.com", "metaverse.highfidelity.io" - }; +namespace { - return url.scheme() == "https" && HF_HOSTS.contains(url.host()); -} + bool isAuthableHighFidelityURL(const QUrl& url) { + static const QStringList HF_HOSTS = { + "highfidelity.com", "highfidelity.io", + "metaverse.highfidelity.com", "metaverse.highfidelity.io" + }; + + return url.scheme() == "https" && HF_HOSTS.contains(url.host()); + } + + bool isScript(const QString filename) { + return filename.contains(".js", Qt::CaseInsensitive); + } -bool static isScript(const QString filename) { - return filename.contains(".js", Qt::CaseInsensitive); } void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info) { From cc81bcab663dcc3698da8a0cd036afb98047b756 Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Tue, 4 Apr 2017 11:58:38 -0700 Subject: [PATCH 072/128] updating url check from hifi master --- .../HFWebEngineRequestInterceptor.cpp | 1 - interface/src/networking/RequestFilters.cpp | 18 +++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/interface/src/networking/HFWebEngineRequestInterceptor.cpp b/interface/src/networking/HFWebEngineRequestInterceptor.cpp index 546edcf95c..59897d427f 100644 --- a/interface/src/networking/HFWebEngineRequestInterceptor.cpp +++ b/interface/src/networking/HFWebEngineRequestInterceptor.cpp @@ -10,7 +10,6 @@ // #include "HFWebEngineRequestInterceptor.h" -#include "NetworkingConstants.h" #include diff --git a/interface/src/networking/RequestFilters.cpp b/interface/src/networking/RequestFilters.cpp index abf9575bdc..4e08080df0 100644 --- a/interface/src/networking/RequestFilters.cpp +++ b/interface/src/networking/RequestFilters.cpp @@ -10,6 +10,7 @@ // #include "RequestFilters.h" +#include "NetworkingConstants.h" #include @@ -17,14 +18,17 @@ namespace { - bool isAuthableHighFidelityURL(const QUrl& url) { - static const QStringList HF_HOSTS = { - "highfidelity.com", "highfidelity.io", - "metaverse.highfidelity.com", "metaverse.highfidelity.io" - }; + bool isAuthableHighFidelityURL(const QUrl& url) { + static const QStringList HF_HOSTS = { + "highfidelity.com", "highfidelity.io", + "metaverse.highfidelity.com", "metaverse.highfidelity.io" + }; + const auto& scheme = url.scheme(); + const auto& host = url.host(); - return url.scheme() == "https" && HF_HOSTS.contains(url.host()); - } + return (scheme == "https" && HF_HOSTS.contains(host)) || + ((scheme == NetworkingConstants::METAVERSE_SERVER_URL.scheme()) && (host == NetworkingConstants::METAVERSE_SERVER_URL.host())); + } bool isScript(const QString filename) { return filename.contains(".js", Qt::CaseInsensitive); From 6f79b2eaeb9c559abefe7b33560a36a0e6cf4bbd Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 4 Apr 2017 12:05:43 -0700 Subject: [PATCH 073/128] send initial path in location update (e.g., on login) --- interface/src/DiscoverabilityManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index f042330a46..98bfa9c0c7 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -54,7 +54,7 @@ void DiscoverabilityManager::updateLocation() { const QString CONNECTED_KEY_IN_LOCATION = "connected"; locationObject.insert(CONNECTED_KEY_IN_LOCATION, discoverable && domainHandler.isConnected()); - if (discoverable) { // Don't consider changes to these as update-worthy if we're not discoverable. + if (discoverable || _lastLocationObject.isEmpty()) { // Don't consider changes to these as update-worthy if we're not discoverable. const QString PATH_KEY_IN_LOCATION = "path"; locationObject.insert(PATH_KEY_IN_LOCATION, pathString); From 6385a702cdefe23dfd9523636c12065fabe3fdec Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 4 Apr 2017 12:56:43 -0700 Subject: [PATCH 074/128] FIxing the bug for image3D overlay drawn in scene --- .../render-utils/src/RenderPipelines.cpp | 4 +- .../src/simple_transparent_textured.slf | 37 +++++++++++++++---- .../src/simple_transparent_textured_unlit.slf | 3 ++ 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index c6a05e0d65..da264cbf7d 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -178,13 +178,13 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { modelVertex, modelPixel); addPipeline( Key::Builder(), - modelVertex, simplePixel); + simpleVertex, simplePixel); addPipeline( Key::Builder().withMaterial().withUnlit(), modelVertex, modelUnlitPixel); addPipeline( Key::Builder().withUnlit(), - modelVertex, simpleUnlitPixel); + simpleVertex, simpleUnlitPixel); addPipeline( Key::Builder().withMaterial().withTangents(), modelNormalMapVertex, modelNormalMapPixel); diff --git a/libraries/render-utils/src/simple_transparent_textured.slf b/libraries/render-utils/src/simple_transparent_textured.slf index f61a2c3608..b9eb921e9d 100644 --- a/libraries/render-utils/src/simple_transparent_textured.slf +++ b/libraries/render-utils/src/simple_transparent_textured.slf @@ -13,29 +13,50 @@ // <@include gpu/Color.slh@> + <@include DeferredBufferWrite.slh@> -<@include model/Material.slh@> +<@include DeferredGlobalLight.slh@> +<$declareEvalGlobalLightingAlphaBlended()$> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> // the albedo texture uniform sampler2D originalTexture; // the interpolated normal +in vec4 _position; in vec3 _normal; in vec4 _color; in vec2 _texCoord0; void main(void) { vec4 texel = texture(originalTexture, _texCoord0.st); - float colorAlpha = _color.a; + float opacity = _color.a; if (_color.a <= 0.0) { texel = colorToLinearRGBA(texel); - colorAlpha = -_color.a; + opacity = -_color.a; } + opacity *= texel.a; + vec3 albedo = _color.rgb * texel.rgb; - packDeferredFragmentTranslucent( - normalize(_normal), - colorAlpha, - _color.rgb * texel.rgb, + vec3 fragPosition = _position.xyz; + vec3 fragNormal = normalize(_normal); + + TransformCamera cam = getTransformCamera(); + + _fragColor0 = vec4(evalGlobalLightingAlphaBlended( + cam._viewInverse, + 1.0, + 1.0, + fragPosition, + fragNormal, + albedo, DEFAULT_FRESNEL, - DEFAULT_ROUGHNESS); + 0.0, + vec3(0.0f), + DEFAULT_ROUGHNESS, + opacity), + opacity); + } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit.slf b/libraries/render-utils/src/simple_transparent_textured_unlit.slf index 9ef3e6b82a..693d7be2db 100644 --- a/libraries/render-utils/src/simple_transparent_textured_unlit.slf +++ b/libraries/render-utils/src/simple_transparent_textured_unlit.slf @@ -22,6 +22,9 @@ in vec3 _normal; in vec4 _color; in vec2 _texCoord0; + +layout(location = 0) out vec4 _fragColor0; + void main(void) { vec4 texel = texture(originalTexture, _texCoord0.st); float colorAlpha = _color.a; From 8749428ede5203c5f7e383a2d339b646a061dbf3 Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Tue, 4 Apr 2017 13:51:34 -0700 Subject: [PATCH 075/128] dont assume no query tags --- interface/resources/qml/controls/WebEntityView.qml | 2 +- interface/resources/qml/controls/WebView.qml | 5 +++-- interface/src/Application.cpp | 10 ++++++---- interface/src/networking/RequestFilters.cpp | 8 ++++++-- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/interface/resources/qml/controls/WebEntityView.qml b/interface/resources/qml/controls/WebEntityView.qml index 4b4c8fe46f..a3d5fe903b 100644 --- a/interface/resources/qml/controls/WebEntityView.qml +++ b/interface/resources/qml/controls/WebEntityView.qml @@ -18,5 +18,5 @@ WebView { storageName: "qmlWebEngine" } - urlTag: "?noDownload=true"; + urlTag: "noDownload=true"; } diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index b904dd5d55..52f277520f 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -70,7 +70,7 @@ Item { worldId: WebEngineScript.MainWorld } - property string urlTag: "?noDownload=false"; + property string urlTag: "noDownload=false"; userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] @@ -98,7 +98,8 @@ Item { // Required to support clicking on "hifi://" links if (WebEngineView.LoadStartedStatus == loadRequest.status) { - var url = loadRequest.url.toString() + urlTag; + var url = loadRequest.url.toString(); + url = (url.indexOf("?") >= 0) ? url + urlTag : url + "?" + urlTag; if (urlHandler.canHandleUrl(url)) { if (urlHandler.handleUrl(url)) { root.stop(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f0897176af..dec6850497 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -219,7 +219,7 @@ static const QString FST_EXTENSION = ".fst"; static const QString FBX_EXTENSION = ".fbx"; static const QString OBJ_EXTENSION = ".obj"; static const QString AVA_JSON_EXTENSION = ".ava.json"; -static const QString WEB_VIEW_TAG = "?noDownload=true"; +static const QString WEB_VIEW_TAG = "noDownload=true"; static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f; @@ -2608,7 +2608,7 @@ bool Application::event(QEvent* event) { QFileOpenEvent* fileEvent = static_cast(event); QUrl url = fileEvent->url(); - + if (!url.isEmpty()) { QString urlString = url.toString(); @@ -5548,7 +5548,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri bool Application::canAcceptURL(const QString& urlString) const { QUrl url(urlString); - if (urlString.endsWith(WEB_VIEW_TAG)) { + if (url.query().contains(WEB_VIEW_TAG)) { return false; } else if (urlString.startsWith(HIFI_URL_SCHEME)) { return true; @@ -5658,7 +5658,9 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) { QUrl scriptURL { scriptFilenameOrURL }; if (scriptURL.host().endsWith(MARKETPLACE_CDN_HOSTNAME)) { - shortName = shortName.mid(shortName.lastIndexOf('/') + 1); + int startIndex = shortName.lastIndexOf('/') + 1; + int endIndex = shortName.lastIndexOf('?'); + shortName = shortName.mid(startIndex, endIndex - startIndex); } QString message = "Would you like to run this script:\n" + shortName; diff --git a/interface/src/networking/RequestFilters.cpp b/interface/src/networking/RequestFilters.cpp index 4e08080df0..fedde94f15 100644 --- a/interface/src/networking/RequestFilters.cpp +++ b/interface/src/networking/RequestFilters.cpp @@ -31,7 +31,11 @@ namespace { } bool isScript(const QString filename) { - return filename.contains(".js", Qt::CaseInsensitive); + return filename.endsWith(".js", Qt::CaseInsensitive); + } + + bool isJSON(const QString filename) { + return filename.endsWith(".json", Qt::CaseInsensitive); } } @@ -53,7 +57,7 @@ void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info) void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info) { QString filename = info.requestUrl().fileName(); - if (isScript(filename)) { + if (isScript(filename) || isJSON(filename)) { static const QString CONTENT_HEADER = "Accept"; static const QString TYPE_VALUE = "text/plain,text/html"; info.setHttpHeader(CONTENT_HEADER.toLocal8Bit(), TYPE_VALUE.toLocal8Bit()); From 54200c03a73fee13bbbe07e48ce80170c8aafc26 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 4 Apr 2017 13:53:49 -0700 Subject: [PATCH 076/128] Fixing deadlock --- libraries/entities/src/EntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 891196862a..3f732e26cb 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2133,7 +2133,7 @@ void EntityItem::deserializeActionsInternal() { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex(".*action creation failed for.*"); qCDebug(entities) << "EntityItem::deserializeActionsInternal -- action creation failed for" - << getID() << getName(); + << getID() << _name; // getName(); removeActionInternal(actionID, nullptr); } } From 4e07a6a865b36f583b551b581bfc2a02163ba5dd Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Apr 2017 14:02:00 -0700 Subject: [PATCH 077/128] add new logic for absolute texture paths in FBX --- libraries/fbx/src/FBXReader.cpp | 40 +++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 0245851256..33b0f40f40 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -443,6 +443,43 @@ FBXLight extractLight(const FBXNode& object) { return light; } +QByteArray fixedTextureFilepath(QByteArray fbxRelativeFilepath, const QString& urlString) { + // first setup a QFileInfo for the passed relative filepath + auto fileInfo = QFileInfo { fbxRelativeFilepath }; + + if (fileInfo.isRelative()) { + // the RelativeFilename pulled from the FBX is already correctly relative + // so simply return this as the filepath to use + return fbxRelativeFilepath; + } else { + // the RelativeFilename pulled from the FBX is an absolute path + + // use the URL to figure out where the FBX is being loaded from + auto url = QUrl { urlString }; + auto filename = fileInfo.fileName(); + + if (url.scheme() == "file") { + // the FBX is being loaded from the local filesystem + + // in order to match the behaviour with a local FBX, first check if a file with this filename + // is right beside the FBX + QFileInfo fileBesideFBX { QFileInfo(urlString).path() + "/" + filename }; + + if (fileBesideFBX.exists() && fileBesideFBX.isFile()) { + // we found a file that matches right beside the FBX, return just the filename as the relative path + return filename.toUtf8(); + } else { + // did not find a matching file beside the FBX, return the absolute path found in the FBX + return fbxRelativeFilepath; + } + } else { + // this is a remote file, meaning we can't really do anything with the absolute path to the texture + // so assume it will be right beside the fbx + return filename.toUtf8(); + } + } +} + FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QString& url) { const FBXNode& node = _fbxNode; QMap meshes; @@ -819,8 +856,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS const int MODEL_UV_SCALING_MIN_SIZE = 2; const int CROPPING_MIN_SIZE = 4; if (subobject.name == "RelativeFilename" && subobject.properties.length() >= RELATIVE_FILENAME_MIN_SIZE) { - QByteArray filepath = subobject.properties.at(0).toByteArray(); - filepath = filepath.replace('\\', '/'); + auto filepath = fixedTextureFilepath(subobject.properties.at(0).toByteArray(), url); _textureFilepaths.insert(getID(object.properties), filepath); } else if (subobject.name == "TextureName" && subobject.properties.length() >= TEXTURE_NAME_MIN_SIZE) { From cd7c1643a3492c8ed4c2824d98ed2cee8d67207e Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 4 Apr 2017 14:03:30 -0700 Subject: [PATCH 078/128] More thread safety --- libraries/entities/src/LineEntityItem.cpp | 4 +- .../entities/src/ParticleEffectEntityItem.cpp | 17 +++ .../entities/src/ParticleEffectEntityItem.h | 9 +- libraries/entities/src/PolyLineEntityItem.cpp | 110 +++++++++++++----- libraries/entities/src/PolyLineEntityItem.h | 15 +-- 5 files changed, 106 insertions(+), 49 deletions(-) diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index fe2c803f43..58cdb1cd7b 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -34,8 +34,8 @@ EntityItemPointer LineEntityItem::factory(const EntityItemID& entityID, const En LineEntityItem::LineEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID), _lineWidth(DEFAULT_LINE_WIDTH), - _pointsChanged(true), - _points(QVector(0)) + _points(QVector(0)), + _pointsChanged(true) { _type = EntityTypes::Line; } diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 140522b00e..80f7f3b6b8 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -733,3 +733,20 @@ void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) { _timeUntilNextEmit = 0.0f; } } + +QString ParticleEffectEntityItem::getTextures() const { + QString result; + withReadLock([&] { + result = _textures; + }); + return result; +} + +void ParticleEffectEntityItem::setTextures(const QString& textures) { + withWriteLock([&] { + if (_textures != textures) { + _textures = textures; + _texturesChangedFlag = true; + } + }); +} diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 6c6596e7a2..4d053e5a45 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -205,13 +205,8 @@ public: void computeAndUpdateDimensions(); static const QString DEFAULT_TEXTURES; - const QString& getTextures() const { return _textures; } - void setTextures(const QString& textures) { - if (_textures != textures) { - _textures = textures; - _texturesChangedFlag = true; - } - } + QString getTextures() const; + void setTextures(const QString& textures); static const bool DEFAULT_EMITTER_SHOULD_TRAIL; bool getEmitterShouldTrail() const { return _emitterShouldTrail; } diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp index 7abafad627..9fe8ac0c8f 100644 --- a/libraries/entities/src/PolyLineEntityItem.cpp +++ b/libraries/entities/src/PolyLineEntityItem.cpp @@ -104,14 +104,18 @@ bool PolyLineEntityItem::appendPoint(const glm::vec3& point) { bool PolyLineEntityItem::setStrokeWidths(const QVector& strokeWidths) { - _strokeWidths = strokeWidths; - _strokeWidthsChanged = true; + withWriteLock([&] { + _strokeWidths = strokeWidths; + _strokeWidthsChanged = true; + }); return true; } bool PolyLineEntityItem::setNormals(const QVector& normals) { - _normals = normals; - _normalsChanged = true; + withWriteLock([&] { + _normals = normals; + _normalsChanged = true; + }); return true; } @@ -119,35 +123,39 @@ bool PolyLineEntityItem::setLinePoints(const QVector& points) { if (points.size() > MAX_POINTS_PER_LINE) { return false; } - if (points.size() != _points.size()) { - _pointsChanged = true; - } - //Check to see if points actually changed. If they haven't, return before doing anything else - else if (points.size() == _points.size()) { - //same number of points, so now compare every point - for (int i = 0; i < points.size(); i++) { - if (points.at(i) != _points.at(i)){ - _pointsChanged = true; - break; + bool result = false; + withWriteLock([&] { + //Check to see if points actually changed. If they haven't, return before doing anything else + if (points.size() != _points.size()) { + _pointsChanged = true; + } else if (points.size() == _points.size()) { + //same number of points, so now compare every point + for (int i = 0; i < points.size(); i++) { + if (points.at(i) != _points.at(i)) { + _pointsChanged = true; + break; + } } } - } - if (!_pointsChanged) { - return false; - } - - for (int i = 0; i < points.size(); i++) { - glm::vec3 point = points.at(i); - glm::vec3 halfBox = getDimensions() * 0.5f; - if ((point.x < -halfBox.x || point.x > halfBox.x) || - (point.y < -halfBox.y || point.y > halfBox.y) || - (point.z < -halfBox.z || point.z > halfBox.z)) { - qCDebug(entities) << "Point is outside entity's bounding box"; - return false; + if (!_pointsChanged) { + return; } - } - _points = points; - return true; + + for (int i = 0; i < points.size(); i++) { + glm::vec3 point = points.at(i); + glm::vec3 halfBox = getDimensions() * 0.5f; + if ((point.x < -halfBox.x || point.x > halfBox.x) || + (point.y < -halfBox.y || point.y > halfBox.y) || + (point.z < -halfBox.z || point.z > halfBox.z)) { + qCDebug(entities) << "Point is outside entity's bounding box"; + return; + } + } + _points = points; + result = true; + }); + + return result; } int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, @@ -210,3 +218,45 @@ void PolyLineEntityItem::debugDump() const { qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); } + + +QVector PolyLineEntityItem::getLinePoints() const { + QVector result; + withReadLock([&] { + result = _points; + }); + return result; +} + +QVector PolyLineEntityItem::getNormals() const { + QVector result; + withReadLock([&] { + result = _normals; + }); + return result; +} + +QVector PolyLineEntityItem::getStrokeWidths() const { + QVector result; + withReadLock([&] { + result = _strokeWidths; + }); + return result; +} + +QString PolyLineEntityItem::getTextures() const { + QString result; + withReadLock([&] { + result = _textures; + }); + return result; +} + +void PolyLineEntityItem::setTextures(const QString& textures) { + withWriteLock([&] { + if (_textures != textures) { + _textures = textures; + _texturesChangedFlag = true; + } + }); +} diff --git a/libraries/entities/src/PolyLineEntityItem.h b/libraries/entities/src/PolyLineEntityItem.h index 5f9f9124cf..0ee9a638de 100644 --- a/libraries/entities/src/PolyLineEntityItem.h +++ b/libraries/entities/src/PolyLineEntityItem.h @@ -59,21 +59,16 @@ class PolyLineEntityItem : public EntityItem { bool setLinePoints(const QVector& points); bool appendPoint(const glm::vec3& point); - const QVector& getLinePoints() const{ return _points; } + QVector getLinePoints() const; bool setNormals(const QVector& normals); - const QVector& getNormals() const{ return _normals; } + QVector getNormals() const; bool setStrokeWidths(const QVector& strokeWidths); - const QVector& getStrokeWidths() const{ return _strokeWidths; } + QVector getStrokeWidths() const; - const QString& getTextures() const { return _textures; } - void setTextures(const QString& textures) { - if (_textures != textures) { - _textures = textures; - _texturesChangedFlag = true; - } - } + QString getTextures() const; + void setTextures(const QString& textures); virtual bool needsToCallUpdate() const override { return true; } From a31812821ad0baeba2e32855293a3e6b99839753 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 4 Apr 2017 22:10:47 +0100 Subject: [PATCH 079/128] oculus lost tracking, delay hand to side --- .../oculus/src/OculusControllerManager.cpp | 38 ++++++++++++++++--- plugins/oculus/src/OculusControllerManager.h | 5 +++ plugins/oculus/src/OculusHelpers.cpp | 34 +++++++++++++++++ plugins/oculus/src/OculusHelpers.h | 3 ++ 4 files changed, 75 insertions(+), 5 deletions(-) diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 87c52de3e7..6445c3c891 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -33,6 +33,8 @@ static const char* MENU_PATH = "Avatar" ">" "Oculus Touch Controllers"; const char* OculusControllerManager::NAME = "Oculus"; +const quint64 LOST_TRACKING_DELAY = 3000000; + bool OculusControllerManager::isSupported() const { return oculusAvailable(); } @@ -207,9 +209,7 @@ void OculusControllerManager::RemoteDevice::focusOutEvent() { } void OculusControllerManager::TouchDevice::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { - _poseStateMap.clear(); _buttonPressedMap.clear(); - ovrSessionStatus status; if (!OVR_SUCCESS(ovr_GetSessionStatus(_parent._session, &status)) || (ovrFalse == status.HmdMounted)) { // if the HMD isn't on someone's head, don't take input from the controllers @@ -217,15 +217,33 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, const control } int numTrackedControllers = 0; + quint64 currentTime = usecTimestampNow(); static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked | ovrStatus_PositionTracked; auto tracking = ovr_GetTrackingState(_parent._session, 0, false); ovr_for_each_hand([&](ovrHandType hand) { ++numTrackedControllers; + int controller = (hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND); if (REQUIRED_HAND_STATUS == (tracking.HandStatusFlags[hand] & REQUIRED_HAND_STATUS)) { + _poseStateMap.erase(controller); handlePose(deltaTime, inputCalibrationData, hand, tracking.HandPoses[hand]); - } else { - _poseStateMap[hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND].valid = false; + _lostTracking[controller] = false; + _lastControllerPose[controller] = tracking.HandPoses[hand]; + return; } + + if (_lostTracking[controller]) { + if (currentTime > _regainTrackingDeadline[controller]) { + _poseStateMap.erase(controller); + _poseStateMap[controller].valid = false; + return; + } + + } else { + quint64 deadlineToRegainTracking = currentTime + LOST_TRACKING_DELAY; + _regainTrackingDeadline[controller] = deadlineToRegainTracking; + _lostTracking[controller] = true; + } + handleRotationForUntrackedHand(inputCalibrationData, hand, tracking.HandPoses[hand]); }); using namespace controller; // Axes @@ -251,7 +269,7 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, const control if (inputState.Touches & pair.first) { _buttonPressedMap.insert(pair.second); } - } + } // Haptics { @@ -286,6 +304,16 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime, } +void OculusControllerManager::TouchDevice::handleRotationForUntrackedHand(const controller::InputCalibrationData& inputCalibrationData, + ovrHandType hand, const ovrPoseStatef& handPose) { + auto poseId = (hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND); + auto& pose = _poseStateMap[poseId]; + auto lastHandPose = _lastControllerPose[poseId]; + pose = ovrControllerRotationToHandRotation(hand, handPose, lastHandPose); + glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; + pose = pose.transform(controllerToAvatar); +} + bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) { Locker locker(_lock); bool toReturn = true; diff --git a/plugins/oculus/src/OculusControllerManager.h b/plugins/oculus/src/OculusControllerManager.h index 23ef52ab64..11d699ca8e 100644 --- a/plugins/oculus/src/OculusControllerManager.h +++ b/plugins/oculus/src/OculusControllerManager.h @@ -11,6 +11,7 @@ #include #include +#include #include @@ -75,6 +76,7 @@ private: private: void stopHapticPulse(bool leftHand); void handlePose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand, const ovrPoseStatef& handPose); + void handleRotationForUntrackedHand(const controller::InputCalibrationData& inputCalibrationData, ovrHandType hand, const ovrPoseStatef& handPose); int _trackedControllers { 0 }; // perform an action when the TouchDevice mutex is acquired. @@ -87,6 +89,9 @@ private: float _rightHapticDuration { 0.0f }; float _rightHapticStrength { 0.0f }; mutable std::recursive_mutex _lock; + std::map _lostTracking; + std::map _regainTrackingDeadline; + std::map _lastControllerPose; friend class OculusControllerManager; }; diff --git a/plugins/oculus/src/OculusHelpers.cpp b/plugins/oculus/src/OculusHelpers.cpp index 767d191c03..18844a1995 100644 --- a/plugins/oculus/src/OculusHelpers.cpp +++ b/plugins/oculus/src/OculusHelpers.cpp @@ -267,3 +267,37 @@ controller::Pose ovrControllerPoseToHandPose( pose.valid = true; return pose; } + +controller::Pose ovrControllerRotationToHandRotation(ovrHandType hand, const ovrPoseStatef& handPose, + const ovrPoseStatef& lastHandPose) { + static const glm::quat yFlip = glm::angleAxis(PI, Vectors::UNIT_Y); + static const glm::quat quarterX = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_X); + static const glm::quat touchToHand = yFlip * quarterX; + + static const glm::quat leftQuarterZ = glm::angleAxis(-PI_OVER_TWO, Vectors::UNIT_Z); + static const glm::quat rightQuarterZ = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_Z); + + static const glm::quat leftRotationOffset = glm::inverse(leftQuarterZ) * touchToHand; + static const glm::quat rightRotationOffset = glm::inverse(rightQuarterZ) * touchToHand; + + static const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches + static const glm::vec3 CONTROLLER_OFFSET = glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f, + -CONTROLLER_LENGTH_OFFSET / 2.0f, + CONTROLLER_LENGTH_OFFSET * 1.5f); + static const glm::vec3 leftTranslationOffset = glm::vec3(-1.0f, 1.0f, 1.0f) * CONTROLLER_OFFSET; + static const glm::vec3 rightTranslationOffset = CONTROLLER_OFFSET; + + auto translationOffset = (hand == ovrHand_Left ? leftTranslationOffset : rightTranslationOffset); + auto rotationOffset = (hand == ovrHand_Left ? leftRotationOffset : rightRotationOffset); + + glm::quat rotation = toGlm(handPose.ThePose.Orientation); + + controller::Pose pose; + pose.translation = toGlm(lastHandPose.ThePose.Position); + pose.translation += rotation * translationOffset; + pose.rotation = rotation * rotationOffset; + pose.angularVelocity = toGlm(lastHandPose.AngularVelocity); + pose.velocity = toGlm(lastHandPose.LinearVelocity); + pose.valid = true; + return pose; +} diff --git a/plugins/oculus/src/OculusHelpers.h b/plugins/oculus/src/OculusHelpers.h index 50ba355b0c..5743f8576b 100644 --- a/plugins/oculus/src/OculusHelpers.h +++ b/plugins/oculus/src/OculusHelpers.h @@ -118,3 +118,6 @@ inline ovrPosef ovrPoseFromGlm(const glm::mat4 & m) { controller::Pose ovrControllerPoseToHandPose( ovrHandType hand, const ovrPoseStatef& handPose); + +controller::Pose ovrControllerRotationToHandRotation(ovrHandType hand, + const ovrPoseStatef& handPose, const ovrPoseStatef& lastHandPose); From 0a7100e2d855eb10c5bfb2ec9114ff0678b804ed Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Apr 2017 14:32:30 -0700 Subject: [PATCH 080/128] pass URLs to readFBX, not just URL path --- libraries/fbx/src/FBXReader.cpp | 13 ++++++------- libraries/fbx/src/FBXReader.h | 10 +++++----- libraries/fbx/src/FBXReader_Mesh.cpp | 2 +- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 33b0f40f40..8696e26fde 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -443,7 +443,7 @@ FBXLight extractLight(const FBXNode& object) { return light; } -QByteArray fixedTextureFilepath(QByteArray fbxRelativeFilepath, const QString& urlString) { +QByteArray fixedTextureFilepath(QByteArray fbxRelativeFilepath, QUrl url) { // first setup a QFileInfo for the passed relative filepath auto fileInfo = QFileInfo { fbxRelativeFilepath }; @@ -455,15 +455,14 @@ QByteArray fixedTextureFilepath(QByteArray fbxRelativeFilepath, const QString& u // the RelativeFilename pulled from the FBX is an absolute path // use the URL to figure out where the FBX is being loaded from - auto url = QUrl { urlString }; auto filename = fileInfo.fileName(); - if (url.scheme() == "file") { + if (url.isLocalFile()) { // the FBX is being loaded from the local filesystem // in order to match the behaviour with a local FBX, first check if a file with this filename // is right beside the FBX - QFileInfo fileBesideFBX { QFileInfo(urlString).path() + "/" + filename }; + QFileInfo fileBesideFBX { QFileInfo(url.toLocalFile()).path() + "/" + filename }; if (fileBesideFBX.exists() && fileBesideFBX.isFile()) { // we found a file that matches right beside the FBX, return just the filename as the relative path @@ -480,7 +479,7 @@ QByteArray fixedTextureFilepath(QByteArray fbxRelativeFilepath, const QString& u } } -FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QString& url) { +FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QUrl& url) { const FBXNode& node = _fbxNode; QMap meshes; QHash modelIDsToNames; @@ -1839,13 +1838,13 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS return geometryPtr; } -FBXGeometry* readFBX(const QByteArray& model, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) { +FBXGeometry* readFBX(const QByteArray& model, const QVariantHash& mapping, const QUrl& url, bool loadLightmaps, float lightmapLevel) { QBuffer buffer(const_cast(&model)); buffer.open(QIODevice::ReadOnly); return readFBX(&buffer, mapping, url, loadLightmaps, lightmapLevel); } -FBXGeometry* readFBX(QIODevice* device, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) { +FBXGeometry* readFBX(QIODevice* device, const QVariantHash& mapping, const QUrl& url, bool loadLightmaps, float lightmapLevel) { FBXReader reader; reader._fbxNode = FBXReader::parseFBX(device); reader._loadLightmaps = loadLightmaps; diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 79133c4c4a..dd746322e9 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -268,7 +268,7 @@ class FBXGeometry { public: using Pointer = std::shared_ptr; - QString originalURL; + QUrl originalURL; QString author; QString applicationName; ///< the name of the application that generated the model @@ -330,11 +330,11 @@ Q_DECLARE_METATYPE(FBXGeometry::Pointer) /// Reads FBX geometry from the supplied model and mapping data. /// \exception QString if an error occurs in parsing -FBXGeometry* readFBX(const QByteArray& model, const QVariantHash& mapping, const QString& url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f); +FBXGeometry* readFBX(const QByteArray& model, const QVariantHash& mapping, const QUrl& url = QUrl(), bool loadLightmaps = true, float lightmapLevel = 1.0f); /// Reads FBX geometry from the supplied model and mapping data. /// \exception QString if an error occurs in parsing -FBXGeometry* readFBX(QIODevice* device, const QVariantHash& mapping, const QString& url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f); +FBXGeometry* readFBX(QIODevice* device, const QVariantHash& mapping, const QUrl& url = QUrl(), bool loadLightmaps = true, float lightmapLevel = 1.0f); class TextureParam { public: @@ -402,11 +402,11 @@ public: FBXNode _fbxNode; static FBXNode parseFBX(QIODevice* device); - FBXGeometry* extractFBXGeometry(const QVariantHash& mapping, const QString& url); + FBXGeometry* extractFBXGeometry(const QVariantHash& mapping, const QUrl& url); ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex); QHash meshes; - static void buildModelMesh(FBXMesh& extractedMesh, const QString& url); + static void buildModelMesh(FBXMesh& extractedMesh, const QUrl& url); FBXTexture getTexture(const QString& textureID); diff --git a/libraries/fbx/src/FBXReader_Mesh.cpp b/libraries/fbx/src/FBXReader_Mesh.cpp index 4e153dfe3a..a6d70408ae 100644 --- a/libraries/fbx/src/FBXReader_Mesh.cpp +++ b/libraries/fbx/src/FBXReader_Mesh.cpp @@ -388,7 +388,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn return data.extracted; } -void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) { +void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QUrl& url) { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("buildModelMesh failed -- .*"); unsigned int totalSourceIndices = 0; From 137e73cf210e6e74f5ef9c349fb75d526b18439d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Apr 2017 14:42:03 -0700 Subject: [PATCH 081/128] check absolute path before relative path --- libraries/fbx/src/FBXReader.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 8696e26fde..e731261804 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -460,16 +460,13 @@ QByteArray fixedTextureFilepath(QByteArray fbxRelativeFilepath, QUrl url) { if (url.isLocalFile()) { // the FBX is being loaded from the local filesystem - // in order to match the behaviour with a local FBX, first check if a file with this filename - // is right beside the FBX - QFileInfo fileBesideFBX { QFileInfo(url.toLocalFile()).path() + "/" + filename }; - - if (fileBesideFBX.exists() && fileBesideFBX.isFile()) { - // we found a file that matches right beside the FBX, return just the filename as the relative path - return filename.toUtf8(); - } else { - // did not find a matching file beside the FBX, return the absolute path found in the FBX + if (fileInfo.exists() && fileInfo.isFile()) { + // found a file at the absolute path in the FBX, return that path return fbxRelativeFilepath; + } else { + // didn't find a file at the absolute path, assume it is right beside the FBX + // return just the filename as the relative path + return filename.toUtf8(); } } else { // this is a remote file, meaning we can't really do anything with the absolute path to the texture From 0b57b9897021e4dbe272d6f4a9941f9d383b0d81 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Apr 2017 14:53:14 -0700 Subject: [PATCH 082/128] change readFBX calls to use QUrl where possible --- libraries/animation/src/AnimationCache.cpp | 2 +- libraries/model-networking/src/model-networking/ModelCache.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/animation/src/AnimationCache.cpp b/libraries/animation/src/AnimationCache.cpp index 6594482085..23c9d1d0b5 100644 --- a/libraries/animation/src/AnimationCache.cpp +++ b/libraries/animation/src/AnimationCache.cpp @@ -74,7 +74,7 @@ void AnimationReader::run() { // Parse the FBX directly from the QNetworkReply FBXGeometry::Pointer fbxgeo; if (_url.path().toLower().endsWith(".fbx")) { - fbxgeo.reset(readFBX(_data, QVariantHash(), _url.path())); + fbxgeo.reset(readFBX(_data, QVariantHash(), _url)); } else { QString errorStr("usupported format"); emit onError(299, errorStr); diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index dd3193073d..142ea74af4 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -173,7 +173,7 @@ void GeometryReader::run() { FBXGeometry::Pointer fbxGeometry; if (_url.path().toLower().endsWith(".fbx")) { - fbxGeometry.reset(readFBX(_data, _mapping, _url.path())); + fbxGeometry.reset(readFBX(_data, _mapping, _url)); if (fbxGeometry->meshes.size() == 0 && fbxGeometry->joints.size() == 0) { throw QString("empty geometry, possibly due to an unsupported FBX version"); } From 70eada0f76a8ff829b64f952a6d1af1f0a628435 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 4 Apr 2017 15:01:18 -0700 Subject: [PATCH 083/128] replace backslashes in parsed fbx relative filepaths --- libraries/fbx/src/FBXReader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index e731261804..8288403337 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -444,8 +444,8 @@ FBXLight extractLight(const FBXNode& object) { } QByteArray fixedTextureFilepath(QByteArray fbxRelativeFilepath, QUrl url) { - // first setup a QFileInfo for the passed relative filepath - auto fileInfo = QFileInfo { fbxRelativeFilepath }; + // first setup a QFileInfo for the passed relative filepath, with backslashes replaced by forward slashes + auto fileInfo = QFileInfo { fbxRelativeFilepath.replace("\\", "/") }; if (fileInfo.isRelative()) { // the RelativeFilename pulled from the FBX is already correctly relative From 15f7e895aafb0243cdb903eaa637e146985d704e Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 4 Apr 2017 15:09:21 -0700 Subject: [PATCH 084/128] More thread safety --- .../src/RenderablePolyVoxEntityItem.cpp | 12 +- .../src/RenderablePolyVoxEntityItem.h | 6 +- libraries/entities/src/PolyVoxEntityItem.cpp | 126 ++++++++++++++++++ libraries/entities/src/PolyVoxEntityItem.h | 48 +++---- libraries/entities/src/WebEntityItem.cpp | 24 ++-- libraries/entities/src/WebEntityItem.h | 2 +- libraries/entities/src/ZoneEntityItem.cpp | 33 ++++- libraries/entities/src/ZoneEntityItem.h | 6 +- 8 files changed, 207 insertions(+), 50 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 419f32f897..a8e422be0f 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -660,22 +660,22 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { }); } -void RenderablePolyVoxEntityItem::setXTextureURL(QString xTextureURL) { - if (xTextureURL != _xTextureURL) { +void RenderablePolyVoxEntityItem::setXTextureURL(const QString& xTextureURL) { + if (xTextureURL != getXTextureURL()) { _xTexture.clear(); PolyVoxEntityItem::setXTextureURL(xTextureURL); } } -void RenderablePolyVoxEntityItem::setYTextureURL(QString yTextureURL) { - if (yTextureURL != _yTextureURL) { +void RenderablePolyVoxEntityItem::setYTextureURL(const QString& yTextureURL) { + if (yTextureURL != getYTextureURL()) { _yTexture.clear(); PolyVoxEntityItem::setYTextureURL(yTextureURL); } } -void RenderablePolyVoxEntityItem::setZTextureURL(QString zTextureURL) { - if (zTextureURL != _zTextureURL) { +void RenderablePolyVoxEntityItem::setZTextureURL(const QString& zTextureURL) { + if (zTextureURL != getZTextureURL()) { _zTexture.clear(); PolyVoxEntityItem::setZTextureURL(zTextureURL); } diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index cdfe2e38fe..e416f59858 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -101,9 +101,9 @@ public: virtual bool setAll(uint8_t toValue) override; virtual bool setCuboid(const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int toValue) override; - virtual void setXTextureURL(QString xTextureURL) override; - virtual void setYTextureURL(QString yTextureURL) override; - virtual void setZTextureURL(QString zTextureURL) override; + virtual void setXTextureURL(const QString& xTextureURL) override; + virtual void setYTextureURL(const QString& yTextureURL) override; + virtual void setZTextureURL(const QString& zTextureURL) override; virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index 2a374c1d17..711c3b5625 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -242,3 +242,129 @@ const QByteArray PolyVoxEntityItem::getVoxelData() const { }); return voxelDataCopy; } + + +void PolyVoxEntityItem::setXTextureURL(const QString& xTextureURL) { + withWriteLock([&] { + _xTextureURL = xTextureURL; + }); +} + +QString PolyVoxEntityItem::getXTextureURL() const { + QString result; + withReadLock([&] { + result = _xTextureURL; + }); + return result; +} + +void PolyVoxEntityItem::setYTextureURL(const QString& yTextureURL) { + withWriteLock([&] { + _yTextureURL = yTextureURL; + }); +} + +QString PolyVoxEntityItem::getYTextureURL() const { + QString result; + withReadLock([&] { + result = _yTextureURL; + }); + return result; +} + +void PolyVoxEntityItem::setZTextureURL(const QString& zTextureURL) { + withWriteLock([&] { + _zTextureURL = zTextureURL; + }); +} +QString PolyVoxEntityItem::getZTextureURL() const { + QString result; + withReadLock([&] { + result = _zTextureURL; + }); + return result; +} + +void PolyVoxEntityItem::setXNNeighborID(const EntityItemID& xNNeighborID) { + withWriteLock([&] { + _xNNeighborID = xNNeighborID; + }); +} + +EntityItemID PolyVoxEntityItem::getXNNeighborID() const { + EntityItemID result; + withReadLock([&] { + result = _xNNeighborID; + }); + return result; +} + +void PolyVoxEntityItem::setYNNeighborID(const EntityItemID& yNNeighborID) { + withWriteLock([&] { + _yNNeighborID = yNNeighborID; + }); +} + +EntityItemID PolyVoxEntityItem::getYNNeighborID() const { + EntityItemID result; + withReadLock([&] { + result = _yNNeighborID; + }); + return result; +} + +void PolyVoxEntityItem::setZNNeighborID(const EntityItemID& zNNeighborID) { + withWriteLock([&] { + _zNNeighborID = zNNeighborID; + }); +} + +EntityItemID PolyVoxEntityItem::getZNNeighborID() const { + EntityItemID result; + withReadLock([&] { + result = _zNNeighborID; + }); + return result; +} + +void PolyVoxEntityItem::setXPNeighborID(const EntityItemID& xPNeighborID) { + withWriteLock([&] { + _xPNeighborID = xPNeighborID; + }); +} + +EntityItemID PolyVoxEntityItem::getXPNeighborID() const { + EntityItemID result; + withReadLock([&] { + result = _xPNeighborID; + }); + return result; +} + +void PolyVoxEntityItem::setYPNeighborID(const EntityItemID& yPNeighborID) { + withWriteLock([&] { + _yPNeighborID = yPNeighborID; + }); +} + +EntityItemID PolyVoxEntityItem::getYPNeighborID() const { + EntityItemID result; + withReadLock([&] { + result = _yPNeighborID; + }); + return result; +} + +void PolyVoxEntityItem::setZPNeighborID(const EntityItemID& zPNeighborID) { + withWriteLock([&] { + _zPNeighborID = zPNeighborID; + }); +} + +EntityItemID PolyVoxEntityItem::getZPNeighborID() const { + EntityItemID result; + withReadLock([&] { + result = _zPNeighborID; + }); + return result; +} diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index cf7531fc9e..05b5cb33a6 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -99,36 +99,36 @@ class PolyVoxEntityItem : public EntityItem { static QByteArray makeEmptyVoxelData(quint16 voxelXSize = 16, quint16 voxelYSize = 16, quint16 voxelZSize = 16); static const QString DEFAULT_X_TEXTURE_URL; - virtual void setXTextureURL(QString xTextureURL) { _xTextureURL = xTextureURL; } - virtual const QString& getXTextureURL() const { return _xTextureURL; } + virtual void setXTextureURL(const QString& xTextureURL); + QString getXTextureURL() const; static const QString DEFAULT_Y_TEXTURE_URL; - virtual void setYTextureURL(QString yTextureURL) { _yTextureURL = yTextureURL; } - virtual const QString& getYTextureURL() const { return _yTextureURL; } + virtual void setYTextureURL(const QString& yTextureURL); + QString getYTextureURL() const; static const QString DEFAULT_Z_TEXTURE_URL; - virtual void setZTextureURL(QString zTextureURL) { _zTextureURL = zTextureURL; } - virtual const QString& getZTextureURL() const { return _zTextureURL; } + virtual void setZTextureURL(const QString& zTextureURL); + QString getZTextureURL() const; - virtual void setXNNeighborID(const EntityItemID& xNNeighborID) { _xNNeighborID = xNNeighborID; } - void setXNNeighborID(const QString& xNNeighborID) { setXNNeighborID(QUuid(xNNeighborID)); } - virtual const EntityItemID& getXNNeighborID() const { return _xNNeighborID; } - virtual void setYNNeighborID(const EntityItemID& yNNeighborID) { _yNNeighborID = yNNeighborID; } - void setYNNeighborID(const QString& yNNeighborID) { setYNNeighborID(QUuid(yNNeighborID)); } - virtual const EntityItemID& getYNNeighborID() const { return _yNNeighborID; } - virtual void setZNNeighborID(const EntityItemID& zNNeighborID) { _zNNeighborID = zNNeighborID; } - void setZNNeighborID(const QString& zNNeighborID) { setZNNeighborID(QUuid(zNNeighborID)); } - virtual const EntityItemID& getZNNeighborID() const { return _zNNeighborID; } + virtual void setXNNeighborID(const EntityItemID& xNNeighborID); + void setXNNeighborID(const QString& xNNeighborID); + virtual EntityItemID getXNNeighborID() const; + virtual void setYNNeighborID(const EntityItemID& yNNeighborID); + void setYNNeighborID(const QString& yNNeighborID); + virtual EntityItemID getYNNeighborID() const; + virtual void setZNNeighborID(const EntityItemID& zNNeighborID); + void setZNNeighborID(const QString& zNNeighborID); + virtual EntityItemID getZNNeighborID() const; - virtual void setXPNeighborID(const EntityItemID& xPNeighborID) { _xPNeighborID = xPNeighborID; } - void setXPNeighborID(const QString& xPNeighborID) { setXPNeighborID(QUuid(xPNeighborID)); } - virtual const EntityItemID& getXPNeighborID() const { return _xPNeighborID; } - virtual void setYPNeighborID(const EntityItemID& yPNeighborID) { _yPNeighborID = yPNeighborID; } - void setYPNeighborID(const QString& yPNeighborID) { setYPNeighborID(QUuid(yPNeighborID)); } - virtual const EntityItemID& getYPNeighborID() const { return _yPNeighborID; } - virtual void setZPNeighborID(const EntityItemID& zPNeighborID) { _zPNeighborID = zPNeighborID; } - void setZPNeighborID(const QString& zPNeighborID) { setZPNeighborID(QUuid(zPNeighborID)); } - virtual const EntityItemID& getZPNeighborID() const { return _zPNeighborID; } + virtual void setXPNeighborID(const EntityItemID& xPNeighborID); + void setXPNeighborID(const QString& xPNeighborID); + virtual EntityItemID getXPNeighborID() const; + virtual void setYPNeighborID(const EntityItemID& yPNeighborID); + void setYPNeighborID(const QString& yPNeighborID); + virtual EntityItemID getYPNeighborID() const; + virtual void setZPNeighborID(const EntityItemID& zPNeighborID); + void setZPNeighborID(const QString& zPNeighborID); + virtual EntityItemID getZPNeighborID() const; virtual void rebakeMesh() {}; diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 182d58ba36..5b060cc702 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -124,18 +124,26 @@ bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const g } void WebEntityItem::setSourceUrl(const QString& value) { - if (_sourceUrl != value) { - auto newURL = QUrl::fromUserInput(value); + withWriteLock([&] { + if (_sourceUrl != value) { + auto newURL = QUrl::fromUserInput(value); - if (newURL.isValid()) { - _sourceUrl = newURL.toDisplayString(); - } else { - qCDebug(entities) << "Clearing web entity source URL since" << value << "cannot be parsed to a valid URL."; + if (newURL.isValid()) { + _sourceUrl = newURL.toDisplayString(); + } else { + qCDebug(entities) << "Clearing web entity source URL since" << value << "cannot be parsed to a valid URL."; + } } - } + }); } -const QString& WebEntityItem::getSourceUrl() const { return _sourceUrl; } +QString WebEntityItem::getSourceUrl() const { + QString result; + withReadLock([&] { + result = _sourceUrl; + }); + return result; +} void WebEntityItem::setDPI(uint16_t value) { _dpi = value; diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h index 19a7b577fe..5cd081687f 100644 --- a/libraries/entities/src/WebEntityItem.h +++ b/libraries/entities/src/WebEntityItem.h @@ -52,7 +52,7 @@ public: void** intersectedObject, bool precisionPicking) const override; virtual void setSourceUrl(const QString& value); - const QString& getSourceUrl() const; + QString getSourceUrl() const; virtual bool wantsHandControllerPointerEvents() const override { return true; } diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index 37b3be99a3..26d566a795 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -208,10 +208,12 @@ ShapeType ZoneEntityItem::getShapeType() const { } void ZoneEntityItem::setCompoundShapeURL(const QString& url) { - _compoundShapeURL = url; - if (_compoundShapeURL.isEmpty() && _shapeType == SHAPE_TYPE_COMPOUND) { - _shapeType = DEFAULT_SHAPE_TYPE; - } + withWriteLock([&] { + _compoundShapeURL = url; + if (_compoundShapeURL.isEmpty() && _shapeType == SHAPE_TYPE_COMPOUND) { + _shapeType = DEFAULT_SHAPE_TYPE; + } + }); } bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, @@ -223,7 +225,9 @@ bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const } void ZoneEntityItem::setFilterURL(QString url) { - _filterURL = url; + withWriteLock([&] { + _filterURL = url; + }); if (DependencyManager::isSet()) { auto entityEditFilters = DependencyManager::get(); qCDebug(entities) << "adding filter " << url << "for zone" << getEntityItemID(); @@ -231,3 +235,22 @@ void ZoneEntityItem::setFilterURL(QString url) { } } +QString ZoneEntityItem::getFilterURL() const { + QString result; + withReadLock([&] { + result = _filterURL; + }); + return result; +} + +bool ZoneEntityItem::hasCompoundShapeURL() const { + return !getCompoundShapeURL().isEmpty(); +} + +QString ZoneEntityItem::getCompoundShapeURL() const { + QString result; + withReadLock([&] { + result = _compoundShapeURL; + }); + return result; +} diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index 2bef95e452..dfc18aff80 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -58,8 +58,8 @@ public: void setShapeType(ShapeType type) override { _shapeType = type; } virtual ShapeType getShapeType() const override; - virtual bool hasCompoundShapeURL() const { return !_compoundShapeURL.isEmpty(); } - const QString getCompoundShapeURL() const { return _compoundShapeURL; } + virtual bool hasCompoundShapeURL() const; + QString getCompoundShapeURL() const; virtual void setCompoundShapeURL(const QString& url); const KeyLightPropertyGroup& getKeyLightProperties() const { return _keyLightProperties; } @@ -74,7 +74,7 @@ public: void setFlyingAllowed(bool value) { _flyingAllowed = value; } bool getGhostingAllowed() const { return _ghostingAllowed; } void setGhostingAllowed(bool value) { _ghostingAllowed = value; } - QString getFilterURL() const { return _filterURL; } + QString getFilterURL() const; void setFilterURL(const QString url); virtual bool supportsDetailedRayIntersection() const override { return true; } From c33f10ca1be5f79f1657fa5754379ecb80c3e82b Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 4 Apr 2017 18:05:46 -0700 Subject: [PATCH 085/128] Recenter body on teleport, also it works more consistently. If your avatar happens to be squatting, your body will stand up straight after you teleport. Also, setting MyAvatar.position can sometimes fail due to the multi-threaded nature of scripting. Instead, teleport.js uses goToPosition to move the avatar, as a result teleport feels much more responsive now. --- scripts/system/controllers/teleport.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js index 90f8ccb368..33c0b3116e 100644 --- a/scripts/system/controllers/teleport.js +++ b/scripts/system/controllers/teleport.js @@ -297,8 +297,9 @@ function Teleporter() { } else if (teleportLocationType === TARGET.SURFACE) { var offset = getAvatarFootOffset(); intersection.intersection.y += offset; - MyAvatar.position = intersection.intersection; + MyAvatar.goToLocation(intersection.intersection, false, {x: 0, y: 0, z: 0, w: 1}, false); HMD.centerUI(); + MyAvatar.centerBody(); } } }; From 24b89275f2b3f8406abf2d55aa998d0dafca8992 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 5 Apr 2017 18:00:43 +0100 Subject: [PATCH 086/128] fix new model dialog textInput --- .../qml/hifi/tablet/NewModelDialog.qml | 57 ++++++++++++++++++- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/NewModelDialog.qml b/interface/resources/qml/hifi/tablet/NewModelDialog.qml index 2fa48cac07..e7a07bfb9f 100644 --- a/interface/resources/qml/hifi/tablet/NewModelDialog.qml +++ b/interface/resources/qml/hifi/tablet/NewModelDialog.qml @@ -22,15 +22,21 @@ Rectangle { color: hifi.colors.baseGray; property var eventBridge; signal sendToScript(var message); + property bool keyboardEnabled: false + property bool punctuationMode: false + property bool keyboardRasied: false - Column { + Item { id: column1 anchors.rightMargin: 10 anchors.leftMargin: 10 anchors.bottomMargin: 10 anchors.topMargin: 10 - anchors.fill: parent - spacing: 5 + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: keyboard.top + // spacing: 5 Text { id: text1 @@ -43,17 +49,42 @@ Rectangle { id: modelURL height: 20 text: qsTr("") + color: "white" + anchors.top: text1.bottom + anchors.topMargin: 5 anchors.left: parent.left anchors.leftMargin: 0 anchors.right: parent.right anchors.rightMargin: 0 font.pixelSize: 12 + + onAccepted: { + newModelDialog.keyboardEnabled = false; + } + + MouseArea { + anchors.fill: parent + onClicked: { + newModelDialog.keyboardEnabled = HMD.active + parent.focus = true; + parent.forceActiveFocus() + } + } + } + + Rectangle { + id: textInputBox + color: "white" + anchors.fill: modelURL + opacity: 0.1 } Row { id: row1 height: 400 spacing: 30 + anchors.top: modelURL.top + anchors.topMargin: 25 anchors.left: parent.left anchors.leftMargin: 0 anchors.right: parent.right @@ -154,5 +185,25 @@ Rectangle { } } } + MouseArea { + id: modelMouse + anchors.fill: parent + propagateComposedEvents: true + onClicked: { + newModelDialog.keyboardEnabled = false; + mouse.accepted = false; + } + } + } + + Keyboard { + id: keyboard + raised: parent.keyboardEnabled + numeric: parent.punctuationMode + anchors { + bottom: parent.bottom + left: parent.left + right: parent.right + } } } From de8b7eeb27ae691e3b867334329c7ef1d25a40b5 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 5 Apr 2017 18:02:55 +0100 Subject: [PATCH 087/128] removed commented code --- interface/resources/qml/hifi/tablet/NewModelDialog.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/resources/qml/hifi/tablet/NewModelDialog.qml b/interface/resources/qml/hifi/tablet/NewModelDialog.qml index e7a07bfb9f..efc030cbcb 100644 --- a/interface/resources/qml/hifi/tablet/NewModelDialog.qml +++ b/interface/resources/qml/hifi/tablet/NewModelDialog.qml @@ -36,7 +36,6 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.bottom: keyboard.top - // spacing: 5 Text { id: text1 From 34f3c4abee6bfbf6af3126fb5bdec14ea4af3a1e Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 5 Apr 2017 18:08:03 +0100 Subject: [PATCH 088/128] removed mousearea --- interface/resources/qml/hifi/tablet/NewModelDialog.qml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/NewModelDialog.qml b/interface/resources/qml/hifi/tablet/NewModelDialog.qml index efc030cbcb..5dbb733872 100644 --- a/interface/resources/qml/hifi/tablet/NewModelDialog.qml +++ b/interface/resources/qml/hifi/tablet/NewModelDialog.qml @@ -184,15 +184,6 @@ Rectangle { } } } - MouseArea { - id: modelMouse - anchors.fill: parent - propagateComposedEvents: true - onClicked: { - newModelDialog.keyboardEnabled = false; - mouse.accepted = false; - } - } } Keyboard { From 1b6bf90843efaa7171e1bff64bae5471678d12f4 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Wed, 5 Apr 2017 11:10:06 -0700 Subject: [PATCH 089/128] initial analytics for connections --- .../src/UserActivityLoggerScriptingInterface.cpp | 10 ++++++++++ .../src/UserActivityLoggerScriptingInterface.h | 1 + scripts/system/makeUserConnection.js | 3 +++ 3 files changed, 14 insertions(+) diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp b/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp index c8a7b61aa7..9c29e87f16 100644 --- a/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp +++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp @@ -61,6 +61,16 @@ void UserActivityLoggerScriptingInterface::palOpened(float secondsOpened) { }); } +void UserActivityLoggerScriptingInterface::makeUserConnection(QString otherID, bool success, QString detailsString) { + QJsonObject payload; + payload["otherUser"] = otherID; + payload["success"] = success; + if (detailsString.length() > 0) { + payload["details"] = detailsString; + } + logAction("makeUserConnection", payload); +} + void UserActivityLoggerScriptingInterface::logAction(QString action, QJsonObject details) { QMetaObject::invokeMethod(&UserActivityLogger::getInstance(), "logAction", Q_ARG(QString, action), diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.h b/libraries/networking/src/UserActivityLoggerScriptingInterface.h index cf38450891..b68c7beb95 100644 --- a/libraries/networking/src/UserActivityLoggerScriptingInterface.h +++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.h @@ -29,6 +29,7 @@ public: float tutorialElapsedTime, QString tutorialRunID = "", int tutorialVersion = 0, QString controllerType = ""); Q_INVOKABLE void palAction(QString action, QString target); Q_INVOKABLE void palOpened(float secondsOpen); + Q_INVOKABLE void makeUserConnection(QString otherUser, bool success, QString details=""); private: void logAction(QString action, QJsonObject details = {}); }; diff --git a/scripts/system/makeUserConnection.js b/scripts/system/makeUserConnection.js index e70e0a2ea2..0a781a5bb8 100644 --- a/scripts/system/makeUserConnection.js +++ b/scripts/system/makeUserConnection.js @@ -543,12 +543,14 @@ function connectionRequestCompleted() { // Final result is in. Do effects. // don't change state (so animation continues while gripped) // but do send a notification, by calling the slot that emits the signal for it Window.makeConnection(true, result.connection.new_connection ? "You and " + result.connection.username + " are now connected!" : result.connection.username); + UserActivityLogger.makeUserConnection(connectingId, true, result.connection.new_connection ? "new connection" : "already connected"); return; } // failed endHandshake(); debug("failing with result data", result); // IWBNI we also did some fail sound/visual effect. Window.makeConnection(false, result.connection); + UserActivityLogger.makeUserConnection(connectingId, false, result.connection); } var POLL_INTERVAL_MS = 200, POLL_LIMIT = 5; function handleConnectionResponseAndMaybeRepeat(error, response) { @@ -573,6 +575,7 @@ function handleConnectionResponseAndMaybeRepeat(error, response) { } else if (error || (response.status !== 'success')) { debug('server fail', error, response.status); result = error ? {status: 'error', connection: error} : response; + UserActivityLogger.makeUserConnection(connectingId, false, error || response); connectionRequestCompleted(); } else { debug('server success', result); From 6122155880fd829bae5dad42050c14a4d593f6e8 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 5 Apr 2017 13:10:31 -0700 Subject: [PATCH 090/128] Renaming the PendingCHanges class to Transaction --- interface/src/Application.cpp | 30 +++++--- interface/src/avatar/Avatar.cpp | 40 +++++----- interface/src/avatar/Avatar.h | 6 +- interface/src/avatar/AvatarManager.cpp | 30 ++++---- interface/src/avatar/CauterizedModel.cpp | 6 +- interface/src/ui/overlays/Base3DOverlay.cpp | 12 +-- interface/src/ui/overlays/ModelOverlay.cpp | 20 ++--- interface/src/ui/overlays/ModelOverlay.h | 4 +- interface/src/ui/overlays/Overlay.cpp | 8 +- interface/src/ui/overlays/Overlay.h | 4 +- interface/src/ui/overlays/Overlays.cpp | 14 ++-- .../src/EntityTreeRenderer.cpp | 18 ++--- .../src/RenderableEntityItem.h | 18 ++--- .../src/RenderableLightEntityItem.cpp | 18 ++--- .../src/RenderableLightEntityItem.h | 6 +- .../src/RenderableModelEntityItem.cpp | 32 ++++---- .../src/RenderableModelEntityItem.h | 4 +- .../RenderableParticleEffectEntityItem.cpp | 26 +++---- .../src/RenderableParticleEffectEntityItem.h | 4 +- .../src/RenderablePolyVoxEntityItem.cpp | 14 ++-- .../src/RenderablePolyVoxEntityItem.h | 4 +- .../src/RenderableZoneEntityItem.cpp | 30 ++++---- .../src/RenderableZoneEntityItem.h | 4 +- libraries/entities/src/EntityItem.h | 6 +- .../physics/src/PhysicalEntitySimulation.cpp | 14 ++-- .../physics/src/PhysicalEntitySimulation.h | 2 +- libraries/render-utils/src/AnimDebugDraw.cpp | 18 ++--- libraries/render-utils/src/Model.cpp | 76 +++++++++---------- libraries/render-utils/src/Model.h | 10 +-- libraries/render/src/render/Scene.cpp | 50 ++++++------ libraries/render/src/render/Scene.h | 24 +++--- .../src/SceneScriptingInterface.h | 3 +- libraries/shared/src/SettingManager.cpp | 12 +-- libraries/shared/src/SettingManager.h | 2 +- libraries/shared/src/Trace.cpp | 2 +- plugins/openvr/src/ViveControllerManager.cpp | 6 +- plugins/openvr/src/ViveControllerManager.h | 2 +- tests/render-perf/src/main.cpp | 18 ++--- 38 files changed, 305 insertions(+), 292 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e19eea0a2e..9c41a78805 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5036,7 +5036,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se // TODO fix shadows and make them use the GPU library // The pending changes collecting the changes here - render::PendingChanges pendingChanges; + render::Transaction transaction; // FIXME: Move this out of here!, Background / skybox should be driven by the enityt content just like the other entities // Background rendering decision @@ -5044,7 +5044,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se auto backgroundRenderData = make_shared(); auto backgroundRenderPayload = make_shared(backgroundRenderData); BackgroundRenderData::_item = _main3DScene->allocateID(); - pendingChanges.resetItem(BackgroundRenderData::_item, backgroundRenderPayload); + transaction.resetItem(BackgroundRenderData::_item, backgroundRenderPayload); } // Assuming nothing get's rendered through that @@ -5062,7 +5062,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se static_cast(RenderArgs::RENDER_DEBUG_HULLS)); } renderArgs->_debugFlags = renderDebugFlags; - //ViveControllerManager::getInstance().updateRendering(renderArgs, _main3DScene, pendingChanges); + //ViveControllerManager::getInstance().updateRendering(renderArgs, _main3DScene, transaction); } } @@ -5074,9 +5074,9 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se WorldBoxRenderData::_item = _main3DScene->allocateID(); - pendingChanges.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload); + transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload); } else { - pendingChanges.updateItem(WorldBoxRenderData::_item, + transaction.updateItem(WorldBoxRenderData::_item, [](WorldBoxRenderData& payload) { payload._val++; }); @@ -5089,10 +5089,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se } { - PerformanceTimer perfTimer("SceneProcessPendingChanges"); - _main3DScene->enqueuePendingChanges(pendingChanges); + PerformanceTimer perfTimer("SceneProcessTransaction"); + _main3DScene->enqueueTransaction(transaction); - _main3DScene->processPendingChangesQueue(); + _main3DScene->processTransactionQueue(); } // For now every frame pass the renderContext @@ -5786,10 +5786,22 @@ void Application::toggleRunningScriptsWidget() const { } void Application::showScriptLogs() { + auto tabletScriptingInterface = DependencyManager::get(); + auto tablet = dynamic_cast(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system")); auto scriptEngines = DependencyManager::get(); QUrl defaultScriptsLoc = defaultScriptsLocation(); defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/debugging/debugWindow.js"); - scriptEngines->loadScript(defaultScriptsLoc.toString()); + + if (tablet->getToolbarMode()) { + scriptEngines->loadScript(defaultScriptsLoc.toString()); + } else { + QQuickItem* tabletRoot = tablet->getTabletRoot(); + if (!tabletRoot && !isHMDMode()) { + scriptEngines->loadScript(defaultScriptsLoc.toString()); + } else { + tablet->pushOntoStack("../../hifi/dialogs/TabletDebugWindow.qml"); + } + } } void Application::showAssetServerWidget(QString filePath) { diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ade98c63d8..b6ec45b308 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -476,34 +476,34 @@ static TextRenderer3D* textRenderer(TextRendererType type) { return displayNameRenderer; } -bool Avatar::addToScene(AvatarSharedPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { +bool Avatar::addToScene(AvatarSharedPointer self, std::shared_ptr scene, render::Transaction& transaction) { auto avatarPayload = new render::Payload(self); auto avatarPayloadPointer = Avatar::PayloadPointer(avatarPayload); _renderItemID = scene->allocateID(); - pendingChanges.resetItem(_renderItemID, avatarPayloadPointer); - _skeletonModel->addToScene(scene, pendingChanges); + transaction.resetItem(_renderItemID, avatarPayloadPointer); + _skeletonModel->addToScene(scene, transaction); for (auto& attachmentModel : _attachmentModels) { - attachmentModel->addToScene(scene, pendingChanges); + attachmentModel->addToScene(scene, transaction); } _inScene = true; return true; } -void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { - pendingChanges.removeItem(_renderItemID); +void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr scene, render::Transaction& transaction) { + transaction.removeItem(_renderItemID); render::Item::clearID(_renderItemID); - _skeletonModel->removeFromScene(scene, pendingChanges); + _skeletonModel->removeFromScene(scene, transaction); for (auto& attachmentModel : _attachmentModels) { - attachmentModel->removeFromScene(scene, pendingChanges); + attachmentModel->removeFromScene(scene, transaction); } _inScene = false; } -void Avatar::updateRenderItem(render::PendingChanges& pendingChanges) { +void Avatar::updateRenderItem(render::Transaction& transaction) { if (render::Item::isValidID(_renderItemID)) { - pendingChanges.updateItem>(_renderItemID, [](render::Payload& p) {}); + transaction.updateItem>(_renderItemID, [](render::Payload& p) {}); } } @@ -680,24 +680,24 @@ void Avatar::fixupModelsInScene() { // check to see if when we added our models to the scene they were ready, if they were not ready, then // fix them up in the scene render::ScenePointer scene = qApp->getMain3DScene(); - render::PendingChanges pendingChanges; + render::Transaction transaction; if (_skeletonModel->isRenderable() && _skeletonModel->needsFixupInScene()) { - _skeletonModel->removeFromScene(scene, pendingChanges); - _skeletonModel->addToScene(scene, pendingChanges); + _skeletonModel->removeFromScene(scene, transaction); + _skeletonModel->addToScene(scene, transaction); } for (auto attachmentModel : _attachmentModels) { if (attachmentModel->isRenderable() && attachmentModel->needsFixupInScene()) { - attachmentModel->removeFromScene(scene, pendingChanges); - attachmentModel->addToScene(scene, pendingChanges); + attachmentModel->removeFromScene(scene, transaction); + attachmentModel->addToScene(scene, transaction); } } for (auto attachmentModelToRemove : _attachmentsToRemove) { - attachmentModelToRemove->removeFromScene(scene, pendingChanges); + attachmentModelToRemove->removeFromScene(scene, transaction); } _attachmentsToDelete.insert(_attachmentsToDelete.end(), _attachmentsToRemove.begin(), _attachmentsToRemove.end()); _attachmentsToRemove.clear(); - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); } bool Avatar::shouldRenderHead(const RenderArgs* renderArgs) const { @@ -1422,14 +1422,14 @@ QList Avatar::getSkeleton() { void Avatar::addToScene(AvatarSharedPointer myHandle) { render::ScenePointer scene = qApp->getMain3DScene(); if (scene) { - render::PendingChanges pendingChanges; + render::Transaction transaction; auto nodelist = DependencyManager::get(); if (DependencyManager::get()->shouldRenderAvatars() && !nodelist->isIgnoringNode(getSessionUUID()) && !nodelist->isRadiusIgnoringNode(getSessionUUID())) { - addToScene(myHandle, scene, pendingChanges); + addToScene(myHandle, scene, transaction); } - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); } else { qCWarning(interfaceapp) << "AvatarManager::addAvatar() : Unexpected null scene, possibly during application shutdown"; } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index ba7e1c617e..7fadf96e11 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -82,12 +82,12 @@ public: virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition); bool addToScene(AvatarSharedPointer self, std::shared_ptr scene, - render::PendingChanges& pendingChanges); + render::Transaction& transaction); void removeFromScene(AvatarSharedPointer self, std::shared_ptr scene, - render::PendingChanges& pendingChanges); + render::Transaction& transaction); - void updateRenderItem(render::PendingChanges& pendingChanges); + void updateRenderItem(render::Transaction& transaction); virtual void postUpdate(float deltaTime); diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 6152148887..48914908c6 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -104,11 +104,11 @@ void AvatarManager::init() { this, &AvatarManager::updateAvatarRenderStatus, Qt::QueuedConnection); render::ScenePointer scene = qApp->getMain3DScene(); - render::PendingChanges pendingChanges; + render::Transaction transaction; if (DependencyManager::get()->shouldRenderAvatars()) { - _myAvatar->addToScene(_myAvatar, scene, pendingChanges); + _myAvatar->addToScene(_myAvatar, scene, transaction); } - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); } void AvatarManager::updateMyAvatar(float deltaTime) { @@ -192,7 +192,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { return false; }); - render::PendingChanges pendingChanges; + render::Transaction transaction; uint64_t startTime = usecTimestampNow(); const uint64_t UPDATE_BUDGET = 2000; // usec uint64_t updateExpiry = startTime + UPDATE_BUDGET; @@ -228,7 +228,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { numAvatarsUpdated++; } avatar->simulate(deltaTime, inView); - avatar->updateRenderItem(pendingChanges); + avatar->updateRenderItem(transaction); avatar->setLastRenderUpdateTime(startTime); } else { // we've spent our full time budget --> bail on the rest of the avatar updates @@ -262,7 +262,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { _avatarSimulationTime = (float)(usecTimestampNow() - startTime) / (float)USECS_PER_MSEC; _numAvatarsUpdated = numAvatarsUpdated; _numAvatarsNotUpdated = numAVatarsNotUpdated; - qApp->getMain3DScene()->enqueuePendingChanges(pendingChanges); + qApp->getMain3DScene()->enqueueTransaction(transaction); simulateAvatarFades(deltaTime); } @@ -283,13 +283,13 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { const float MIN_FADE_SCALE = MIN_AVATAR_SCALE; render::ScenePointer scene = qApp->getMain3DScene(); - render::PendingChanges pendingChanges; + render::Transaction transaction; while (fadingIterator != _avatarFades.end()) { auto avatar = std::static_pointer_cast(*fadingIterator); avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE); avatar->animateScaleChanges(deltaTime); if (avatar->getTargetScale() <= MIN_FADE_SCALE) { - avatar->removeFromScene(*fadingIterator, scene, pendingChanges); + avatar->removeFromScene(*fadingIterator, scene, transaction); // only remove from _avatarFades if we're sure its motionState has been removed from PhysicsEngine if (_motionStatesToRemoveFromPhysics.empty()) { fadingIterator = _avatarFades.erase(fadingIterator); @@ -302,7 +302,7 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { ++fadingIterator; } } - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); } AvatarSharedPointer AvatarManager::newSharedAvatar() { @@ -479,17 +479,17 @@ void AvatarManager::updateAvatarRenderStatus(bool shouldRenderAvatars) { for (auto avatarData : _avatarHash) { auto avatar = std::static_pointer_cast(avatarData); render::ScenePointer scene = qApp->getMain3DScene(); - render::PendingChanges pendingChanges; - avatar->addToScene(avatar, scene, pendingChanges); - scene->enqueuePendingChanges(pendingChanges); + render::Transaction transaction; + avatar->addToScene(avatar, scene, transaction); + scene->enqueueTransaction(transaction); } } else { for (auto avatarData : _avatarHash) { auto avatar = std::static_pointer_cast(avatarData); render::ScenePointer scene = qApp->getMain3DScene(); - render::PendingChanges pendingChanges; - avatar->removeFromScene(avatar, scene, pendingChanges); - scene->enqueuePendingChanges(pendingChanges); + render::Transaction transaction; + avatar->removeFromScene(avatar, scene, transaction); + scene->enqueueTransaction(transaction); } } } diff --git a/interface/src/avatar/CauterizedModel.cpp b/interface/src/avatar/CauterizedModel.cpp index f479ed9a35..c7d25d3151 100644 --- a/interface/src/avatar/CauterizedModel.cpp +++ b/interface/src/avatar/CauterizedModel.cpp @@ -205,10 +205,10 @@ void CauterizedModel::updateRenderItems() { uint32_t deleteGeometryCounter = self->getGeometryCounter(); - render::PendingChanges pendingChanges; + render::Transaction transaction; QList keys = self->getRenderItems().keys(); foreach (auto itemID, keys) { - pendingChanges.updateItem(itemID, [modelTransform, deleteGeometryCounter](CauterizedMeshPartPayload& data) { + transaction.updateItem(itemID, [modelTransform, deleteGeometryCounter](CauterizedMeshPartPayload& data) { if (data._model && data._model->isLoaded()) { // Ensure the model geometry was not reset between frames if (deleteGeometryCounter == data._model->getGeometryCounter()) { @@ -233,7 +233,7 @@ void CauterizedModel::updateRenderItems() { }); } - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); }); } else { Model::updateRenderItems(); diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 70b1fa4b71..d7057c6faa 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -199,9 +199,9 @@ void Base3DOverlay::setProperties(const QVariantMap& originalProperties) { auto itemID = getRenderItemID(); if (render::Item::isValidID(itemID)) { render::ScenePointer scene = qApp->getMain3DScene(); - render::PendingChanges pendingChanges; - pendingChanges.updateItem(itemID); - scene->enqueuePendingChanges(pendingChanges); + render::Transaction transaction; + transaction.updateItem(itemID); + scene->enqueueTransaction(transaction); } } } @@ -264,9 +264,9 @@ void Base3DOverlay::locationChanged(bool tellPhysics) { auto itemID = getRenderItemID(); if (render::Item::isValidID(itemID)) { render::ScenePointer scene = qApp->getMain3DScene(); - render::PendingChanges pendingChanges; - pendingChanges.updateItem(itemID); - scene->enqueuePendingChanges(pendingChanges); + render::Transaction transaction; + transaction.updateItem(itemID); + scene->enqueueTransaction(transaction); } } diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index a0f7c4e824..98ca7110ae 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -58,15 +58,15 @@ void ModelOverlay::update(float deltatime) { _isLoaded = _model->isActive(); } -bool ModelOverlay::addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges) { - Volume3DOverlay::addToScene(overlay, scene, pendingChanges); - _model->addToScene(scene, pendingChanges); +bool ModelOverlay::addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::Transaction& transaction) { + Volume3DOverlay::addToScene(overlay, scene, transaction); + _model->addToScene(scene, transaction); return true; } -void ModelOverlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges) { - Volume3DOverlay::removeFromScene(overlay, scene, pendingChanges); - _model->removeFromScene(scene, pendingChanges); +void ModelOverlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr scene, render::Transaction& transaction) { + Volume3DOverlay::removeFromScene(overlay, scene, transaction); + _model->removeFromScene(scene, transaction); } void ModelOverlay::render(RenderArgs* args) { @@ -74,16 +74,16 @@ void ModelOverlay::render(RenderArgs* args) { // check to see if when we added our model to the scene they were ready, if they were not ready, then // fix them up in the scene render::ScenePointer scene = qApp->getMain3DScene(); - render::PendingChanges pendingChanges; + render::Transaction transaction; if (_model->needsFixupInScene()) { - _model->removeFromScene(scene, pendingChanges); - _model->addToScene(scene, pendingChanges); + _model->removeFromScene(scene, transaction); + _model->addToScene(scene, transaction); } _model->setVisibleInScene(_visible, scene); _model->setLayeredInFront(getDrawInFront(), scene); - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); } void ModelOverlay::setProperties(const QVariantMap& properties) { diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index d5f709c2db..245688156f 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -36,8 +36,8 @@ public: virtual ModelOverlay* createClone() const override; - virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges) override; - virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges) override; + virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::Transaction& transaction) override; + virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr scene, render::Transaction& transaction) override; void locationChanged(bool tellPhysics) override; diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index 764422019e..e3004bd9c6 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -196,14 +196,14 @@ float Overlay::updatePulse() { return _pulse; } -bool Overlay::addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges) { +bool Overlay::addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::Transaction& transaction) { _renderItemID = scene->allocateID(); - pendingChanges.resetItem(_renderItemID, std::make_shared(overlay)); + transaction.resetItem(_renderItemID, std::make_shared(overlay)); return true; } -void Overlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges) { - pendingChanges.removeItem(_renderItemID); +void Overlay::removeFromScene(Overlay::Pointer overlay, std::shared_ptr scene, render::Transaction& transaction) { + transaction.removeItem(_renderItemID); render::Item::clearID(_renderItemID); } diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 9ad4f0ba70..9849c71a1f 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -48,8 +48,8 @@ public: virtual AABox getBounds() const = 0; virtual bool supportsGetProperty() const { return true; } - virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges); - virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges); + virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::Transaction& transaction); + virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr scene, render::Transaction& transaction); virtual const render::ShapeKey getShapeKey() { return render::ShapeKey::Builder::ownPipeline(); } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 712342087d..61a283b88c 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -78,7 +78,7 @@ void Overlays::update(float deltatime) { void Overlays::cleanupOverlaysToDelete() { if (!_overlaysToDelete.isEmpty()) { render::ScenePointer scene = qApp->getMain3DScene(); - render::PendingChanges pendingChanges; + render::Transaction transaction; { QWriteLocker lock(&_deleteLock); @@ -88,13 +88,13 @@ void Overlays::cleanupOverlaysToDelete() { auto itemID = overlay->getRenderItemID(); if (render::Item::isValidID(itemID)) { - overlay->removeFromScene(overlay, scene, pendingChanges); + overlay->removeFromScene(overlay, scene, transaction); } } while (!_overlaysToDelete.isEmpty()); } - if (pendingChanges._removedItems.size() > 0) { - scene->enqueuePendingChanges(pendingChanges); + if (transaction._removedItems.size() > 0) { + scene->enqueueTransaction(transaction); } } } @@ -197,9 +197,9 @@ OverlayID Overlays::addOverlay(Overlay::Pointer overlay) { _overlaysWorld[thisID] = overlay; render::ScenePointer scene = qApp->getMain3DScene(); - render::PendingChanges pendingChanges; - overlay->addToScene(overlay, scene, pendingChanges); - scene->enqueuePendingChanges(pendingChanges); + render::Transaction transaction; + overlay->addToScene(overlay, scene, transaction); + scene->enqueueTransaction(transaction); } else { _overlaysHUD[thisID] = overlay; } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 4843afd5b1..fd5e07918e 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -127,11 +127,11 @@ void EntityTreeRenderer::clear() { // remove all entities from the scene auto scene = _viewState->getMain3DScene(); if (scene) { - render::PendingChanges pendingChanges; + render::Transaction transaction; foreach(auto entity, _entitiesInScene) { - entity->removeFromScene(entity, scene, pendingChanges); + entity->removeFromScene(entity, scene, transaction); } - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); } else { qCWarning(entitiesrenderer) << "EntitityTreeRenderer::clear(), Unexpected null scene, possibly during application shutdown"; } @@ -951,11 +951,11 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { // here's where we remove the entity payload from the scene if (_entitiesInScene.contains(entityID)) { auto entity = _entitiesInScene.take(entityID); - render::PendingChanges pendingChanges; + render::Transaction transaction; auto scene = _viewState->getMain3DScene(); if (scene) { - entity->removeFromScene(entity, scene, pendingChanges); - scene->enqueuePendingChanges(pendingChanges); + entity->removeFromScene(entity, scene, transaction); + scene->enqueueTransaction(transaction); } else { qCWarning(entitiesrenderer) << "EntityTreeRenderer::deletingEntity(), Unexpected null scene, possibly during application shutdown"; } @@ -973,13 +973,13 @@ void EntityTreeRenderer::addingEntity(const EntityItemID& entityID) { void EntityTreeRenderer::addEntityToScene(EntityItemPointer entity) { // here's where we add the entity payload to the scene - render::PendingChanges pendingChanges; + render::Transaction transaction; auto scene = _viewState->getMain3DScene(); if (scene) { - if (entity->addToScene(entity, scene, pendingChanges)) { + if (entity->addToScene(entity, scene, transaction)) { _entitiesInScene.insert(entity->getEntityItemID(), entity); } - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); } else { qCWarning(entitiesrenderer) << "EntityTreeRenderer::addEntityToScene(), Unexpected null scene, possibly during application shutdown"; } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 98271ddbbb..2f053924ab 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -54,7 +54,7 @@ namespace render { // Mixin class for implementing basic single item rendering class SimpleRenderableEntityItem { public: - bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { + bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::Transaction& transaction) { _myItem = scene->allocateID(); auto renderData = std::make_shared(self, _myItem); @@ -64,13 +64,13 @@ public: makeEntityItemStatusGetters(self, statusGetters); renderPayload->addStatusGetters(statusGetters); - pendingChanges.resetItem(_myItem, renderPayload); + transaction.resetItem(_myItem, renderPayload); return true; } - void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { - pendingChanges.removeItem(_myItem); + void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::Transaction& transaction) { + transaction.removeItem(_myItem); render::Item::clearID(_myItem); } @@ -79,14 +79,14 @@ public: return; } - render::PendingChanges pendingChanges; + render::Transaction transaction; render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); if (scene) { - pendingChanges.updateItem(_myItem, [](RenderableEntityItemProxy& data) { + transaction.updateItem(_myItem, [](RenderableEntityItemProxy& data) { }); - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); } else { qCWarning(entitiesrenderer) << "SimpleRenderableEntityItem::notifyChanged(), Unexpected null scene, possibly during application shutdown"; } @@ -99,8 +99,8 @@ private: #define SIMPLE_RENDERABLE() \ public: \ - virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override { return _renderHelper.addToScene(self, scene, pendingChanges); } \ - virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override { _renderHelper.removeFromScene(self, scene, pendingChanges); } \ + virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::Transaction& transaction) override { return _renderHelper.addToScene(self, scene, transaction); } \ + virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::Transaction& transaction) override { _renderHelper.removeFromScene(self, scene, transaction); } \ virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); _renderHelper.notifyChanged(); } \ virtual void dimensionsChanged() override { EntityItem::dimensionsChanged(); _renderHelper.notifyChanged(); } \ void checkFading() { \ diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index a7fcbf53ae..0b8592e678 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -27,7 +27,7 @@ RenderableLightEntityItem::RenderableLightEntityItem(const EntityItemID& entityI { } -bool RenderableLightEntityItem::addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { +bool RenderableLightEntityItem::addToScene(EntityItemPointer self, std::shared_ptr scene, render::Transaction& transaction) { _myItem = scene->allocateID(); auto renderItem = std::make_shared(); @@ -39,7 +39,7 @@ bool RenderableLightEntityItem::addToScene(EntityItemPointer self, std::shared_p makeEntityItemStatusGetters(self, statusGetters); renderPayload->addStatusGetters(statusGetters); - pendingChanges.resetItem(_myItem, renderPayload); + transaction.resetItem(_myItem, renderPayload); return true; } @@ -51,8 +51,8 @@ void RenderableLightEntityItem::somethingChangedNotification() { LightEntityItem::somethingChangedNotification(); } -void RenderableLightEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { - pendingChanges.removeItem(_myItem); +void RenderableLightEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::Transaction& transaction) { + transaction.removeItem(_myItem); render::Item::clearID(_myItem); } @@ -81,12 +81,12 @@ void RenderableLightEntityItem::notifyChanged() { return; } - render::PendingChanges pendingChanges; + render::Transaction transaction; render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); - updateLightFromEntity(pendingChanges); + updateLightFromEntity(transaction); - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); } bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, @@ -103,13 +103,13 @@ bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& ori } -void RenderableLightEntityItem::updateLightFromEntity(render::PendingChanges& pendingChanges) { +void RenderableLightEntityItem::updateLightFromEntity(render::Transaction& transaction) { if (!render::Item::isValidID(_myItem)) { return; } - pendingChanges.updateItem(_myItem, [&](LightPayload& data) { + transaction.updateItem(_myItem, [&](LightPayload& data) { updateRenderItemFromEntity(data); }); } diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.h b/libraries/entities-renderer/src/RenderableLightEntityItem.h index 36ba0d6311..42a5dbc91a 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.h +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.h @@ -28,12 +28,12 @@ public: BoxFace& face, glm::vec3& surfaceNormal, void** intersectedObject, bool precisionPicking) const override; - void updateLightFromEntity(render::PendingChanges& pendingChanges); + void updateLightFromEntity(render::Transaction& transaction); - virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override; + virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::Transaction& transaction) override; virtual void somethingChangedNotification() override; - virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override; + virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::Transaction& transaction) override; virtual void locationChanged(bool tellPhysics = true) override; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 487a3e1e56..0cd5b718af 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -228,20 +228,20 @@ namespace render { } bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_ptr scene, - render::PendingChanges& pendingChanges) { + render::Transaction& transaction) { _myMetaItem = scene->allocateID(); auto renderData = std::make_shared(self); auto renderPayload = std::make_shared(renderData); - pendingChanges.resetItem(_myMetaItem, renderPayload); + transaction.resetItem(_myMetaItem, renderPayload); if (_model) { render::Item::Status::Getters statusGetters; makeEntityItemStatusGetters(getThisPointer(), statusGetters); // note: we don't mind if the model fails to add, we'll retry (in render()) until it succeeds - _model->addToScene(scene, pendingChanges, statusGetters); + _model->addToScene(scene, transaction, statusGetters); } // we've successfully added _myMetaItem so we always return true @@ -249,11 +249,11 @@ bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_p } void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr scene, - render::PendingChanges& pendingChanges) { - pendingChanges.removeItem(_myMetaItem); + render::Transaction& transaction) { + transaction.removeItem(_myMetaItem); render::Item::clearID(_myMetaItem); if (_model) { - _model->removeFromScene(scene, pendingChanges); + _model->removeFromScene(scene, transaction); } } @@ -467,15 +467,15 @@ void RenderableModelEntityItem::render(RenderArgs* args) { } if (_model->needsFixupInScene()) { - render::PendingChanges pendingChanges; + render::Transaction transaction; - _model->removeFromScene(scene, pendingChanges); + _model->removeFromScene(scene, transaction); render::Item::Status::Getters statusGetters; makeEntityItemStatusGetters(getThisPointer(), statusGetters); - _model->addToScene(scene, pendingChanges, statusGetters); + _model->addToScene(scene, transaction, statusGetters); - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); } auto& currentURL = getParsedModelURL(); @@ -525,9 +525,9 @@ ModelPointer RenderableModelEntityItem::getModel(QSharedPointergetMain3DScene(); - render::PendingChanges pendingChanges; - _model->removeFromScene(scene, pendingChanges); - scene->enqueuePendingChanges(pendingChanges); + render::Transaction transaction; + _model->removeFromScene(scene, transaction); + scene->enqueueTransaction(transaction); // release interest _myRenderer->releaseModel(_model); @@ -1226,10 +1226,10 @@ void RenderableModelEntityItem::locationChanged(bool tellPhysics) { } render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); - render::PendingChanges pendingChanges; + render::Transaction transaction; - pendingChanges.updateItem(myMetaItem); - scene->enqueuePendingChanges(pendingChanges); + transaction.updateItem(myMetaItem); + scene->enqueueTransaction(transaction); }); } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 057ca36e13..c770e85089 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -40,8 +40,8 @@ public: void doInitialModelSimulation(); - virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override; - virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override; + virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::Transaction& transaction) override; + virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::Transaction& transaction) override; void updateModelBounds(); diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 86c3f5ff35..fdf9ba888f 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -162,7 +162,7 @@ RenderableParticleEffectEntityItem::RenderableParticleEffectEntityItem(const Ent bool RenderableParticleEffectEntityItem::addToScene(EntityItemPointer self, render::ScenePointer scene, - render::PendingChanges& pendingChanges) { + render::Transaction& transaction) { _scene = scene; _renderItemId = _scene->allocateID(); auto particlePayloadData = std::make_shared(); @@ -171,14 +171,14 @@ bool RenderableParticleEffectEntityItem::addToScene(EntityItemPointer self, render::Item::Status::Getters statusGetters; makeEntityItemStatusGetters(getThisPointer(), statusGetters); renderPayload->addStatusGetters(statusGetters); - pendingChanges.resetItem(_renderItemId, renderPayload); + transaction.resetItem(_renderItemId, renderPayload); return true; } void RenderableParticleEffectEntityItem::removeFromScene(EntityItemPointer self, render::ScenePointer scene, - render::PendingChanges& pendingChanges) { - pendingChanges.removeItem(_renderItemId); + render::Transaction& transaction) { + transaction.removeItem(_renderItemId); _scene = nullptr; render::Item::clearID(_renderItemId); }; @@ -206,12 +206,12 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { return; } if (!getVisible()) { - render::PendingChanges pendingChanges; - pendingChanges.updateItem(_renderItemId, [](ParticlePayloadData& payload) { + render::Transaction transaction; + transaction.updateItem(_renderItemId, [](ParticlePayloadData& payload) { payload.setVisibleFlag(false); }); - _scene->enqueuePendingChanges(pendingChanges); + _scene->enqueueTransaction(transaction); return; } @@ -253,8 +253,8 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { } - render::PendingChanges pendingChanges; - pendingChanges.updateItem(_renderItemId, [=](ParticlePayloadData& payload) { + render::Transaction transaction; + transaction.updateItem(_renderItemId, [=](ParticlePayloadData& payload) { payload.setVisibleFlag(true); // Update particle uniforms @@ -282,7 +282,7 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { } }); - _scene->enqueuePendingChanges(pendingChanges); + _scene->enqueueTransaction(transaction); } void RenderableParticleEffectEntityItem::createPipelines() { @@ -318,9 +318,9 @@ void RenderableParticleEffectEntityItem::notifyBoundChanged() { if (!render::Item::isValidID(_renderItemId)) { return; } - render::PendingChanges pendingChanges; - pendingChanges.updateItem(_renderItemId, [](ParticlePayloadData& payload) { + render::Transaction transaction; + transaction.updateItem(_renderItemId, [](ParticlePayloadData& payload) { }); - _scene->enqueuePendingChanges(pendingChanges); + _scene->enqueueTransaction(transaction); } \ No newline at end of file diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index a36c3640d6..9b31c92b07 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -25,8 +25,8 @@ public: void updateRenderItem(); - virtual bool addToScene(EntityItemPointer self, render::ScenePointer scene, render::PendingChanges& pendingChanges) override; - virtual void removeFromScene(EntityItemPointer self, render::ScenePointer scene, render::PendingChanges& pendingChanges) override; + virtual bool addToScene(EntityItemPointer self, render::ScenePointer scene, render::Transaction& transaction) override; + virtual void removeFromScene(EntityItemPointer self, render::ScenePointer scene, render::Transaction& transaction) override; protected: virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); notifyBoundChanged(); } diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 419f32f897..b8093d85d0 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -817,7 +817,7 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { bool RenderablePolyVoxEntityItem::addToScene(EntityItemPointer self, std::shared_ptr scene, - render::PendingChanges& pendingChanges) { + render::Transaction& transaction) { _myItem = scene->allocateID(); auto renderItem = std::make_shared(getThisPointer()); @@ -828,15 +828,15 @@ bool RenderablePolyVoxEntityItem::addToScene(EntityItemPointer self, makeEntityItemStatusGetters(getThisPointer(), statusGetters); renderPayload->addStatusGetters(statusGetters); - pendingChanges.resetItem(_myItem, renderPayload); + transaction.resetItem(_myItem, renderPayload); return true; } void RenderablePolyVoxEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr scene, - render::PendingChanges& pendingChanges) { - pendingChanges.removeItem(_myItem); + render::Transaction& transaction) { + transaction.removeItem(_myItem); render::Item::clearID(_myItem); } @@ -1615,10 +1615,10 @@ void RenderablePolyVoxEntityItem::locationChanged(bool tellPhysics) { return; } render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); - render::PendingChanges pendingChanges; - pendingChanges.updateItem(_myItem, [](PolyVoxPayload& payload) {}); + render::Transaction transaction; + transaction.updateItem(_myItem, [](PolyVoxPayload& payload) {}); - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); } bool RenderablePolyVoxEntityItem::getMeshes(MeshProxyList& result) { diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index cdfe2e38fe..ecb1817e94 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -107,10 +107,10 @@ public: virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, - render::PendingChanges& pendingChanges) override; + render::Transaction& transaction) override; virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, - render::PendingChanges& pendingChanges) override; + render::Transaction& transaction) override; virtual void setXNNeighborID(const EntityItemID& xNNeighborID) override; virtual void setYNNeighborID(const EntityItemID& yNNeighborID) override; diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 0215ce4d07..c9a45465c2 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -118,13 +118,13 @@ void RenderableZoneEntityItem::render(RenderArgs* args) { // check to see if when we added our models to the scene they were ready, if they were not ready, then // fix them up in the scene render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); - render::PendingChanges pendingChanges; - _model->removeFromScene(scene, pendingChanges); + render::Transaction transaction; + _model->removeFromScene(scene, transaction); render::Item::Status::Getters statusGetters; makeEntityItemStatusGetters(getThisPointer(), statusGetters); - _model->addToScene(scene, pendingChanges); + _model->addToScene(scene, transaction); - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); _model->setVisibleInScene(getVisible(), scene); } @@ -164,9 +164,9 @@ void RenderableZoneEntityItem::render(RenderArgs* args) { _model && !_model->needsFixupInScene()) { // If the model is in the scene but doesn't need to be, remove it. render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); - render::PendingChanges pendingChanges; - _model->removeFromScene(scene, pendingChanges); - scene->enqueuePendingChanges(pendingChanges); + render::Transaction transaction; + _model->removeFromScene(scene, transaction); + scene->enqueueTransaction(transaction); } } @@ -218,7 +218,7 @@ namespace render { } bool RenderableZoneEntityItem::addToScene(EntityItemPointer self, std::shared_ptr scene, - render::PendingChanges& pendingChanges) { + render::Transaction& transaction) { _myMetaItem = scene->allocateID(); auto renderData = std::make_shared(self); @@ -228,16 +228,16 @@ bool RenderableZoneEntityItem::addToScene(EntityItemPointer self, std::shared_pt makeEntityItemStatusGetters(getThisPointer(), statusGetters); renderPayload->addStatusGetters(statusGetters); - pendingChanges.resetItem(_myMetaItem, renderPayload); + transaction.resetItem(_myMetaItem, renderPayload); return true; } void RenderableZoneEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr scene, - render::PendingChanges& pendingChanges) { - pendingChanges.removeItem(_myMetaItem); + render::Transaction& transaction) { + transaction.removeItem(_myMetaItem); render::Item::clearID(_myMetaItem); if (_model) { - _model->removeFromScene(scene, pendingChanges); + _model->removeFromScene(scene, transaction); } } @@ -246,13 +246,13 @@ void RenderableZoneEntityItem::notifyBoundChanged() { if (!render::Item::isValidID(_myMetaItem)) { return; } - render::PendingChanges pendingChanges; + render::Transaction transaction; render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); if (scene) { - pendingChanges.updateItem(_myMetaItem, [](RenderableZoneEntityItemMeta& data) { + transaction.updateItem(_myMetaItem, [](RenderableZoneEntityItemMeta& data) { }); - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); } else { qCWarning(entitiesrenderer) << "RenderableZoneEntityItem::notifyBoundChanged(), Unexpected null scene, possibly during application shutdown"; } diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.h b/libraries/entities-renderer/src/RenderableZoneEntityItem.h index 58aa951e64..bbb7ed0c01 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.h +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.h @@ -38,8 +38,8 @@ public: virtual void render(RenderArgs* args) override; virtual bool contains(const glm::vec3& point) const override; - virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override; - virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override; + virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::Transaction& transaction) override; + virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::Transaction& transaction) override; private: virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); notifyBoundChanged(); } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index b973d916e6..74d2daccbf 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -53,7 +53,7 @@ using EntityTreeElementExtraEncodeDataPointer = std::shared_ptr scene, - render::PendingChanges& pendingChanges) { return false; } // by default entity items don't add to scene + render::Transaction& transaction) { return false; } // by default entity items don't add to scene virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, - render::PendingChanges& pendingChanges) { } // by default entity items don't add to scene + render::Transaction& transaction) { } // by default entity items don't add to scene virtual void render(RenderArgs* args) { } // by default entity items don't know how to render static int expectedBytes(); diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index 6f5b474810..72b0ef5623 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -96,7 +96,7 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { if (motionState) { if (!entity->shouldBePhysical()) { // the entity should be removed from the physical simulation - _pendingChanges.remove(motionState); + _transaction.remove(motionState); _physicalObjects.remove(motionState); _outgoingChanges.remove(motionState); _entitiesToRemoveFromPhysics.insert(entity); @@ -104,7 +104,7 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { _simpleKinematicEntities.insert(entity); } } else { - _pendingChanges.insert(motionState); + _transaction.insert(motionState); } } else if (entity->shouldBePhysical()) { // The intent is for this object to be in the PhysicsEngine, but it has no MotionState yet. @@ -148,7 +148,7 @@ void PhysicalEntitySimulation::clearEntitiesInternal() { _entitiesToRemoveFromPhysics.clear(); _entitiesToRelease.clear(); _entitiesToAddToPhysics.clear(); - _pendingChanges.clear(); + _transaction.clear(); _outgoingChanges.clear(); } @@ -170,7 +170,7 @@ void PhysicalEntitySimulation::getObjectsToRemoveFromPhysics(VectorOfMotionState EntityMotionState* motionState = static_cast(entity->getPhysicsInfo()); if (motionState) { - _pendingChanges.remove(motionState); + _transaction.remove(motionState); _outgoingChanges.remove(motionState); _physicalObjects.remove(motionState); result.push_back(motionState); @@ -246,18 +246,18 @@ void PhysicalEntitySimulation::getObjectsToAddToPhysics(VectorOfMotionStates& re void PhysicalEntitySimulation::setObjectsToChange(const VectorOfMotionStates& objectsToChange) { QMutexLocker lock(&_mutex); for (auto object : objectsToChange) { - _pendingChanges.insert(static_cast(object)); + _transaction.insert(static_cast(object)); } } void PhysicalEntitySimulation::getObjectsToChange(VectorOfMotionStates& result) { result.clear(); QMutexLocker lock(&_mutex); - for (auto stateItr : _pendingChanges) { + for (auto stateItr : _transaction) { EntityMotionState* motionState = &(*stateItr); result.push_back(motionState); } - _pendingChanges.clear(); + _transaction.clear(); } void PhysicalEntitySimulation::handleDeactivatedMotionStates(const VectorOfMotionStates& motionStates) { diff --git a/libraries/physics/src/PhysicalEntitySimulation.h b/libraries/physics/src/PhysicalEntitySimulation.h index 5f6185add3..c12f9316fc 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.h +++ b/libraries/physics/src/PhysicalEntitySimulation.h @@ -67,7 +67,7 @@ private: SetOfEntities _entitiesToRelease; SetOfEntities _entitiesToAddToPhysics; - SetOfEntityMotionStates _pendingChanges; // EntityMotionStates already in PhysicsEngine that need their physics changed + SetOfEntityMotionStates _transaction; // EntityMotionStates already in PhysicsEngine that need their physics changed SetOfEntityMotionStates _outgoingChanges; // EntityMotionStates for which we may need to send updates to entity-server SetOfMotionStates _physicalObjects; // MotionStates of entities in PhysicsEngine diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index 6066385847..162745e76f 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -114,9 +114,9 @@ AnimDebugDraw::AnimDebugDraw() : render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); if (scene) { _itemID = scene->allocateID(); - render::PendingChanges pendingChanges; - pendingChanges.resetItem(_itemID, _animDebugDrawPayload); - scene->enqueuePendingChanges(pendingChanges); + render::Transaction transaction; + transaction.resetItem(_itemID, _animDebugDrawPayload); + scene->enqueueTransaction(transaction); } // HACK: add red, green and blue axis at (1,1,1) @@ -142,9 +142,9 @@ void AnimDebugDraw::shutdown() { // remove renderItem from main 3d scene. render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); if (scene && _itemID) { - render::PendingChanges pendingChanges; - pendingChanges.removeItem(_itemID); - scene->enqueuePendingChanges(pendingChanges); + render::Transaction transaction; + transaction.removeItem(_itemID); + scene->enqueueTransaction(transaction); } } @@ -317,8 +317,8 @@ void AnimDebugDraw::update() { return; } - render::PendingChanges pendingChanges; - pendingChanges.updateItem(_itemID, [&](AnimDebugDrawData& data) { + render::Transaction transaction; + transaction.updateItem(_itemID, [&](AnimDebugDrawData& data) { const size_t VERTICES_PER_BONE = (6 + (NUM_CIRCLE_SLICES * 2) * 3); const size_t VERTICES_PER_LINK = 8 * 2; @@ -422,5 +422,5 @@ void AnimDebugDraw::update() { data._indexBuffer->setSubData(i, (uint16_t)i);; } }); - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 3448c9e8da..c274d69af6 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -235,9 +235,9 @@ void Model::updateRenderItems() { uint32_t deleteGeometryCounter = self->_deleteGeometryCounter; - render::PendingChanges pendingChanges; + render::Transaction transaction; foreach (auto itemID, self->_modelMeshRenderItemsMap.keys()) { - pendingChanges.updateItem(itemID, [deleteGeometryCounter](ModelMeshPartPayload& data) { + transaction.updateItem(itemID, [deleteGeometryCounter](ModelMeshPartPayload& data) { if (data._model && data._model->isLoaded()) { // Ensure the model geometry was not reset between frames if (deleteGeometryCounter == data._model->_deleteGeometryCounter) { @@ -259,14 +259,14 @@ void Model::updateRenderItems() { Transform collisionMeshOffset; collisionMeshOffset.setIdentity(); Transform modelTransform = self->getTransform(); - foreach(auto itemID, self->_collisionRenderItemsMap.keys()) { - pendingChanges.updateItem(itemID, [modelTransform, collisionMeshOffset](MeshPartPayload& data) { + foreach(auto itemID, self->_collisionRenderItemsMap.keys()) { + transaction.updateItem(itemID, [modelTransform, collisionMeshOffset](MeshPartPayload& data) { // update the model transform for this render item. data.updateTransform(modelTransform, collisionMeshOffset); }); } - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); }); } @@ -538,14 +538,14 @@ void Model::setVisibleInScene(bool newValue, std::shared_ptr scen if (_isVisible != newValue) { _isVisible = newValue; - render::PendingChanges pendingChanges; + render::Transaction transaction; foreach (auto item, _modelMeshRenderItemsMap.keys()) { - pendingChanges.resetItem(item, _modelMeshRenderItemsMap[item]); + transaction.resetItem(item, _modelMeshRenderItemsMap[item]); } - foreach(auto item, _collisionRenderItemsMap.keys()) { - pendingChanges.resetItem(item, _collisionRenderItemsMap[item]); + foreach(auto item, _collisionRenderItemsMap.keys()) { + transaction.resetItem(item, _collisionRenderItemsMap[item]); } - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); } } @@ -554,19 +554,19 @@ void Model::setLayeredInFront(bool layered, std::shared_ptr scene if (_isLayeredInFront != layered) { _isLayeredInFront = layered; - render::PendingChanges pendingChanges; + render::Transaction transaction; foreach(auto item, _modelMeshRenderItemsMap.keys()) { - pendingChanges.resetItem(item, _modelMeshRenderItemsMap[item]); + transaction.resetItem(item, _modelMeshRenderItemsMap[item]); } - foreach(auto item, _collisionRenderItemsMap.keys()) { - pendingChanges.resetItem(item, _collisionRenderItemsMap[item]); + foreach(auto item, _collisionRenderItemsMap.keys()) { + transaction.resetItem(item, _collisionRenderItemsMap[item]); } - scene->enqueuePendingChanges(pendingChanges); + scene->enqueueTransaction(transaction); } } bool Model::addToScene(std::shared_ptr scene, - render::PendingChanges& pendingChanges, + render::Transaction& transaction, render::Item::Status::Getters& statusGetters) { bool readyToRender = _collisionGeometry || isLoaded(); if (!_addedToScene && readyToRender) { @@ -579,11 +579,11 @@ bool Model::addToScene(std::shared_ptr scene, foreach (auto renderItem, _collisionRenderItems) { auto item = scene->allocateID(); auto renderPayload = std::make_shared(renderItem); - if (_collisionRenderItems.empty() && statusGetters.size()) { + if (_collisionRenderItems.empty() && statusGetters.size()) { renderPayload->addStatusGetters(statusGetters); } - pendingChanges.resetItem(item, renderPayload); - _collisionRenderItemsMap.insert(item, renderPayload); + transaction.resetItem(item, renderPayload); + _collisionRenderItemsMap.insert(item, renderPayload); } somethingAdded = !_collisionRenderItems.empty(); } @@ -595,10 +595,10 @@ bool Model::addToScene(std::shared_ptr scene, foreach(auto renderItem, _modelMeshRenderItems) { auto item = scene->allocateID(); auto renderPayload = std::make_shared(renderItem); - if (_modelMeshRenderItemsMap.empty() && statusGetters.size()) { + if (_modelMeshRenderItemsMap.empty() && statusGetters.size()) { renderPayload->addStatusGetters(statusGetters); } - pendingChanges.resetItem(item, renderPayload); + transaction.resetItem(item, renderPayload); hasTransparent = hasTransparent || renderItem.get()->getShapeKey().isTranslucent(); verticesCount += renderItem.get()->getVerticesCount(); @@ -622,16 +622,16 @@ bool Model::addToScene(std::shared_ptr scene, return somethingAdded; } -void Model::removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges) { +void Model::removeFromScene(std::shared_ptr scene, render::Transaction& transaction) { foreach (auto item, _modelMeshRenderItemsMap.keys()) { - pendingChanges.removeItem(item); + transaction.removeItem(item); } _modelMeshRenderItemIDs.clear(); _modelMeshRenderItemsMap.clear(); _modelMeshRenderItems.clear(); - foreach(auto item, _collisionRenderItemsMap.keys()) { - pendingChanges.removeItem(item); + foreach(auto item, _collisionRenderItemsMap.keys()) { + transaction.removeItem(item); } _collisionRenderItems.clear(); _collisionRenderItems.clear(); @@ -794,11 +794,11 @@ void Model::setURL(const QUrl& url) { _url = url; { - render::PendingChanges pendingChanges; + render::Transaction transaction; render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); if (scene) { - removeFromScene(scene, pendingChanges); - scene->enqueuePendingChanges(pendingChanges); + removeFromScene(scene, transaction); + scene->enqueueTransaction(transaction); } else { qCWarning(renderutils) << "Model::setURL(), Unexpected null scene, possibly during application shutdown"; } @@ -1279,17 +1279,17 @@ bool Model::initWhenReady(render::ScenePointer scene) { createRenderItemSet(); - render::PendingChanges pendingChanges; + render::Transaction transaction; - bool addedPendingChanges = false; + bool addedTransaction = false; if (_collisionGeometry) { foreach (auto renderItem, _collisionRenderItems) { auto item = scene->allocateID(); auto renderPayload = std::make_shared(renderItem); _collisionRenderItemsMap.insert(item, renderPayload); - pendingChanges.resetItem(item, renderPayload); + transaction.resetItem(item, renderPayload); } - addedPendingChanges = !_collisionRenderItems.empty(); + addedTransaction = !_collisionRenderItems.empty(); } else { bool hasTransparent = false; size_t verticesCount = 0; @@ -1300,17 +1300,17 @@ bool Model::initWhenReady(render::ScenePointer scene) { hasTransparent = hasTransparent || renderItem.get()->getShapeKey().isTranslucent(); verticesCount += renderItem.get()->getVerticesCount(); _modelMeshRenderItemsMap.insert(item, renderPayload); - pendingChanges.resetItem(item, renderPayload); + transaction.resetItem(item, renderPayload); } - addedPendingChanges = !_modelMeshRenderItemsMap.empty(); + addedTransaction = !_modelMeshRenderItemsMap.empty(); _renderInfoVertexCount = verticesCount; _renderInfoDrawCalls = _modelMeshRenderItemsMap.count(); _renderInfoHasTransparent = hasTransparent; } - _addedToScene = addedPendingChanges; - if (addedPendingChanges) { - scene->enqueuePendingChanges(pendingChanges); - // NOTE: updateRender items enqueues identical pendingChanges (using a lambda) + _addedToScene = addedTransaction; + if (addedTransaction) { + scene->enqueueTransaction(transaction); + // NOTE: updateRender items enqueues identical transaction (using a lambda) // so it looks like we're doing double work here, but I don't want to remove the call // for fear there is some side effect we'll miss. -- Andrew 2016.07.21 // TODO: figure out if we really need this call to updateRenderItems() or not. diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index bb283cce1f..e852358bc4 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -42,7 +42,7 @@ class ViewFrustum; namespace render { class Scene; - class PendingChanges; + class Transaction; typedef unsigned int ItemID; } class MeshPartPayload; @@ -88,14 +88,14 @@ public: bool needsReload() const { return _needsReload; } bool initWhenReady(render::ScenePointer scene); bool addToScene(std::shared_ptr scene, - render::PendingChanges& pendingChanges) { + render::Transaction& transaction) { auto getters = render::Item::Status::Getters(0); - return addToScene(scene, pendingChanges, getters); + return addToScene(scene, transaction, getters); } bool addToScene(std::shared_ptr scene, - render::PendingChanges& pendingChanges, + render::Transaction& transaction, render::Item::Status::Getters& statusGetters); - void removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); + void removeFromScene(std::shared_ptr scene, render::Transaction& transaction); bool isRenderable() const; bool isVisible() const { return _isVisible; } diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 076879ae25..45685a9407 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -16,31 +16,31 @@ using namespace render; -void PendingChanges::resetItem(ItemID id, const PayloadPointer& payload) { +void Transaction::resetItem(ItemID id, const PayloadPointer& payload) { if (payload) { _resetItems.push_back(id); _resetPayloads.push_back(payload); } else { - qCDebug(renderlogging) << "WARNING: PendingChanges::resetItem with a null payload!"; + qCDebug(renderlogging) << "WARNING: Transaction::resetItem with a null payload!"; removeItem(id); } } -void PendingChanges::removeItem(ItemID id) { +void Transaction::removeItem(ItemID id) { _removedItems.push_back(id); } -void PendingChanges::updateItem(ItemID id, const UpdateFunctorPointer& functor) { +void Transaction::updateItem(ItemID id, const UpdateFunctorPointer& functor) { _updatedItems.push_back(id); _updateFunctors.push_back(functor); } -void PendingChanges::merge(const PendingChanges& changes) { - _resetItems.insert(_resetItems.end(), changes._resetItems.begin(), changes._resetItems.end()); - _resetPayloads.insert(_resetPayloads.end(), changes._resetPayloads.begin(), changes._resetPayloads.end()); - _removedItems.insert(_removedItems.end(), changes._removedItems.begin(), changes._removedItems.end()); - _updatedItems.insert(_updatedItems.end(), changes._updatedItems.begin(), changes._updatedItems.end()); - _updateFunctors.insert(_updateFunctors.end(), changes._updateFunctors.begin(), changes._updateFunctors.end()); +void Transaction::merge(const Transaction& change) { + _resetItems.insert(_resetItems.end(), change._resetItems.begin(), change._resetItems.end()); + _resetPayloads.insert(_resetPayloads.end(), change._resetPayloads.begin(), change._resetPayloads.end()); + _removedItems.insert(_removedItems.end(), change._removedItems.begin(), change._removedItems.end()); + _updatedItems.insert(_updatedItems.end(), change._updatedItems.begin(), change._updatedItems.end()); + _updateFunctors.insert(_updateFunctors.end(), change._updateFunctors.begin(), change._updateFunctors.end()); } Scene::Scene(glm::vec3 origin, float size) : @@ -63,27 +63,27 @@ bool Scene::isAllocatedID(const ItemID& id) const { } /// Enqueue change batch to the scene -void Scene::enqueuePendingChanges(const PendingChanges& pendingChanges) { - _changeQueueMutex.lock(); - _changeQueue.push(pendingChanges); - _changeQueueMutex.unlock(); +void Scene::enqueueTransaction(const Transaction& transaction) { + _transactionQueueMutex.lock(); + _transactionQueue.push(transaction); + _transactionQueueMutex.unlock(); } -void consolidateChangeQueue(PendingChangesQueue& queue, PendingChanges& singleBatch) { +void consolidateTransaction(TransactionQueue& queue, Transaction& singleBatch) { while (!queue.empty()) { - const auto& pendingChanges = queue.front(); - singleBatch.merge(pendingChanges); + const auto& transaction = queue.front(); + singleBatch.merge(transaction); queue.pop(); }; } -void Scene::processPendingChangesQueue() { +void Scene::processTransactionQueue() { PROFILE_RANGE(render, __FUNCTION__); - PendingChanges consolidatedPendingChanges; + Transaction consolidatedTransaction; { - std::unique_lock lock(_changeQueueMutex); - consolidateChangeQueue(_changeQueue, consolidatedPendingChanges); + std::unique_lock lock(_transactionQueueMutex); + consolidateTransaction(_transactionQueue, consolidatedTransaction); } { @@ -95,19 +95,19 @@ void Scene::processPendingChangesQueue() { _items.resize(maxID + 100); // allocate the maxId and more } // Now we know for sure that we have enough items in the array to - // capture anything coming from the pendingChanges + // capture anything coming from the transaction // resets and potential NEW items - resetItems(consolidatedPendingChanges._resetItems, consolidatedPendingChanges._resetPayloads); + resetItems(consolidatedTransaction._resetItems, consolidatedTransaction._resetPayloads); // Update the numItemsAtomic counter AFTER the reset changes went through _numAllocatedItems.exchange(maxID); // updates - updateItems(consolidatedPendingChanges._updatedItems, consolidatedPendingChanges._updateFunctors); + updateItems(consolidatedTransaction._updatedItems, consolidatedTransaction._updateFunctors); // removes - removeItems(consolidatedPendingChanges._removedItems); + removeItems(consolidatedTransaction._removedItems); // Update the numItemsAtomic counter AFTER the pending changes went through _numAllocatedItems.exchange(maxID); diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index f2f8403dc9..d277f50650 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -19,10 +19,10 @@ namespace render { class Engine; -class PendingChanges { +class Transaction { public: - PendingChanges() {} - ~PendingChanges() {} + Transaction() {} + ~Transaction() {} void resetItem(ItemID id, const PayloadPointer& payload); void removeItem(ItemID id); @@ -34,7 +34,7 @@ public: void updateItem(ItemID id, const UpdateFunctorPointer& functor); void updateItem(ItemID id) { updateItem(id, nullptr); } - void merge(const PendingChanges& changes); + void merge(const Transaction& change); ItemIDs _resetItems; Payloads _resetPayloads; @@ -44,12 +44,12 @@ public: protected: }; -typedef std::queue PendingChangesQueue; +typedef std::queue TransactionQueue; // Scene is a container for Items -// Items are introduced, modified or erased in the scene through PendingChanges -// Once per Frame, the PendingChanges are all flushed +// Items are introduced, modified or erased in the scene through Transaction +// Once per Frame, the Transaction are all flushed // During the flush the standard buckets are updated // Items are notified accordingly on any update message happening class Scene { @@ -67,10 +67,10 @@ public: size_t getNumItems() const { return _numAllocatedItems.load(); } // Enqueue change batch to the scene - void enqueuePendingChanges(const PendingChanges& pendingChanges); + void enqueueTransaction(const Transaction& transaction); - // Process the penging changes equeued - void processPendingChangesQueue(); + // Process the pending transactions equeued + void processTransactionQueue(); // This next call are NOT threadsafe, you have to call them from the correct thread to avoid any potential issues @@ -91,8 +91,8 @@ protected: // Thread safe elements that can be accessed from anywhere std::atomic _IDAllocator{ 1 }; // first valid itemID will be One std::atomic _numAllocatedItems{ 1 }; // num of allocated items, matching the _items.size() - std::mutex _changeQueueMutex; - PendingChangesQueue _changeQueue; + std::mutex _transactionQueueMutex; + TransactionQueue _transactionQueue; // The actual database // database of items is protected for editing by a mutex diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index e8ea2e0217..7bc22eb3e6 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -133,7 +133,8 @@ namespace SceneScripting { class SceneScriptingInterface : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY - + + public: Q_PROPERTY(bool shouldRenderAvatars READ shouldRenderAvatars WRITE setShouldRenderAvatars) Q_PROPERTY(bool shouldRenderEntities READ shouldRenderEntities WRITE setShouldRenderEntities) diff --git a/libraries/shared/src/SettingManager.cpp b/libraries/shared/src/SettingManager.cpp index 6c246d4cea..6acd758ad7 100644 --- a/libraries/shared/src/SettingManager.cpp +++ b/libraries/shared/src/SettingManager.cpp @@ -53,8 +53,8 @@ namespace Setting { const auto& key = handle->getKey(); withWriteLock([&] { QVariant loadedValue; - if (_pendingChanges.contains(key) && _pendingChanges[key] != UNSET_VALUE) { - loadedValue = _pendingChanges[key]; + if (_transaction.contains(key) && _transaction[key] != UNSET_VALUE) { + loadedValue = _transaction[key]; } else { loadedValue = value(key); } @@ -73,7 +73,7 @@ namespace Setting { } withWriteLock([&] { - _pendingChanges[key] = handleValue; + _transaction[key] = handleValue; }); } @@ -98,8 +98,8 @@ namespace Setting { void Manager::saveAll() { bool forceSync = false; withWriteLock([&] { - for (auto key : _pendingChanges.keys()) { - auto newValue = _pendingChanges[key]; + for (auto key : _transaction.keys()) { + auto newValue = _transaction[key]; auto savedValue = value(key, UNSET_VALUE); if (newValue == savedValue) { continue; @@ -112,7 +112,7 @@ namespace Setting { setValue(key, newValue); } } - _pendingChanges.clear(); + _transaction.clear(); }); if (forceSync) { diff --git a/libraries/shared/src/SettingManager.h b/libraries/shared/src/SettingManager.h index ffdd4ba42a..507e11edaa 100644 --- a/libraries/shared/src/SettingManager.h +++ b/libraries/shared/src/SettingManager.h @@ -47,7 +47,7 @@ namespace Setting { QHash _handles; QPointer _saveTimer = nullptr; const QVariant UNSET_VALUE { QUuid::createUuid() }; - QHash _pendingChanges; + QHash _transaction; friend class Interface; friend void cleanupPrivateInstance(); diff --git a/libraries/shared/src/Trace.cpp b/libraries/shared/src/Trace.cpp index 1e3d490a9c..d7feb65ff3 100644 --- a/libraries/shared/src/Trace.cpp +++ b/libraries/shared/src/Trace.cpp @@ -179,7 +179,7 @@ void Tracer::serialize(const QString& originalPath) { { // "traceEvents":[ - // {"args":{"nv_payload":0},"cat":"hifi.render","name":"render::Scene::processPendingChangesQueue","ph":"B","pid":14796,"tid":21636,"ts":68795933487} + // {"args":{"nv_payload":0},"cat":"hifi.render","name":"render::Scene::processTransactionQueue","ph":"B","pid":14796,"tid":21636,"ts":68795933487} QJsonArray traceEvents; diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 2e930c0fdc..d6e816346a 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -145,7 +145,7 @@ void ViveControllerManager::deactivate() { _registeredWithInputMapper = false; } -void ViveControllerManager::updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges) { +void ViveControllerManager::updateRendering(RenderArgs* args, render::ScenePointer scene, render::Transaction transaction) { PerformanceTimer perfTimer("ViveControllerManager::updateRendering"); /* @@ -154,9 +154,9 @@ void ViveControllerManager::updateRendering(RenderArgs* args, render::ScenePoint //auto controllerPayloadPointer = ViveControllerManager::PayloadPointer(controllerPayload); //if (_leftHandRenderID == 0) { // _leftHandRenderID = scene->allocateID(); - // pendingChanges.resetItem(_leftHandRenderID, controllerPayloadPointer); + // transaction.resetItem(_leftHandRenderID, controllerPayloadPointer); //} - //pendingChanges.updateItem(_leftHandRenderID, ); + //transaction.updateItem(_leftHandRenderID, ); controller::Pose leftHand = _inputDevice->_poseStateMap[controller::StandardPoseChannel::LEFT_HAND]; diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 3fb166c842..9b34f987ab 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -43,7 +43,7 @@ public: void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); } void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; - void updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges); + void updateRendering(RenderArgs* args, render::ScenePointer scene, render::Transaction transaction); void setRenderControllers(bool renderControllers) { _renderControllers = renderControllers; } diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index 522fe79b10..b76776b1ab 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -880,7 +880,7 @@ private: getEntities()->update(); // The pending changes collecting the changes here - render::PendingChanges pendingChanges; + render::Transaction transaction; // FIXME: Move this out of here!, Background / skybox should be driven by the enityt content just like the other entities // Background rendering decision @@ -888,7 +888,7 @@ private: auto backgroundRenderData = std::make_shared(); auto backgroundRenderPayload = std::make_shared(backgroundRenderData); BackgroundRenderData::_item = _main3DScene->allocateID(); - pendingChanges.resetItem(BackgroundRenderData::_item, backgroundRenderPayload); + transaction.resetItem(BackgroundRenderData::_item, backgroundRenderPayload); } // Setup the current Zone Entity lighting { @@ -897,10 +897,10 @@ private: } { - PerformanceTimer perfTimer("SceneProcessPendingChanges"); - _main3DScene->enqueuePendingChanges(pendingChanges); + PerformanceTimer perfTimer("SceneProcessTransaction"); + _main3DScene->enqueueTransaction(transaction); - _main3DScene->processPendingChangesQueue(); + _main3DScene->processTransactionQueue(); } } @@ -914,13 +914,13 @@ private: PROFILE_RANGE(render, __FUNCTION__); PerformanceTimer perfTimer("draw"); // The pending changes collecting the changes here - render::PendingChanges pendingChanges; + render::Transaction transaction; // Setup the current Zone Entity lighting DependencyManager::get()->setGlobalLight(_sunSkyStage.getSunLight()); { - PerformanceTimer perfTimer("SceneProcessPendingChanges"); - _main3DScene->enqueuePendingChanges(pendingChanges); - _main3DScene->processPendingChangesQueue(); + PerformanceTimer perfTimer("SceneProcessTransaction"); + _main3DScene->enqueueTransaction(transaction); + _main3DScene->processTransactionQueue(); } // For now every frame pass the renderContext From 5629cf425ec5bb0b464ad8b3fed9908a1aecdad8 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 5 Apr 2017 13:49:07 -0700 Subject: [PATCH 091/128] Cleaning up the files updated --- libraries/physics/src/PhysicalEntitySimulation.cpp | 14 +++++++------- libraries/physics/src/PhysicalEntitySimulation.h | 2 +- libraries/render/src/render/Scene.cpp | 12 ++++++------ libraries/render/src/render/Scene.h | 2 +- libraries/shared/src/SettingManager.cpp | 12 ++++++------ libraries/shared/src/SettingManager.h | 2 +- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index 72b0ef5623..6f5b474810 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -96,7 +96,7 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { if (motionState) { if (!entity->shouldBePhysical()) { // the entity should be removed from the physical simulation - _transaction.remove(motionState); + _pendingChanges.remove(motionState); _physicalObjects.remove(motionState); _outgoingChanges.remove(motionState); _entitiesToRemoveFromPhysics.insert(entity); @@ -104,7 +104,7 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { _simpleKinematicEntities.insert(entity); } } else { - _transaction.insert(motionState); + _pendingChanges.insert(motionState); } } else if (entity->shouldBePhysical()) { // The intent is for this object to be in the PhysicsEngine, but it has no MotionState yet. @@ -148,7 +148,7 @@ void PhysicalEntitySimulation::clearEntitiesInternal() { _entitiesToRemoveFromPhysics.clear(); _entitiesToRelease.clear(); _entitiesToAddToPhysics.clear(); - _transaction.clear(); + _pendingChanges.clear(); _outgoingChanges.clear(); } @@ -170,7 +170,7 @@ void PhysicalEntitySimulation::getObjectsToRemoveFromPhysics(VectorOfMotionState EntityMotionState* motionState = static_cast(entity->getPhysicsInfo()); if (motionState) { - _transaction.remove(motionState); + _pendingChanges.remove(motionState); _outgoingChanges.remove(motionState); _physicalObjects.remove(motionState); result.push_back(motionState); @@ -246,18 +246,18 @@ void PhysicalEntitySimulation::getObjectsToAddToPhysics(VectorOfMotionStates& re void PhysicalEntitySimulation::setObjectsToChange(const VectorOfMotionStates& objectsToChange) { QMutexLocker lock(&_mutex); for (auto object : objectsToChange) { - _transaction.insert(static_cast(object)); + _pendingChanges.insert(static_cast(object)); } } void PhysicalEntitySimulation::getObjectsToChange(VectorOfMotionStates& result) { result.clear(); QMutexLocker lock(&_mutex); - for (auto stateItr : _transaction) { + for (auto stateItr : _pendingChanges) { EntityMotionState* motionState = &(*stateItr); result.push_back(motionState); } - _transaction.clear(); + _pendingChanges.clear(); } void PhysicalEntitySimulation::handleDeactivatedMotionStates(const VectorOfMotionStates& motionStates) { diff --git a/libraries/physics/src/PhysicalEntitySimulation.h b/libraries/physics/src/PhysicalEntitySimulation.h index c12f9316fc..5f6185add3 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.h +++ b/libraries/physics/src/PhysicalEntitySimulation.h @@ -67,7 +67,7 @@ private: SetOfEntities _entitiesToRelease; SetOfEntities _entitiesToAddToPhysics; - SetOfEntityMotionStates _transaction; // EntityMotionStates already in PhysicsEngine that need their physics changed + SetOfEntityMotionStates _pendingChanges; // EntityMotionStates already in PhysicsEngine that need their physics changed SetOfEntityMotionStates _outgoingChanges; // EntityMotionStates for which we may need to send updates to entity-server SetOfMotionStates _physicalObjects; // MotionStates of entities in PhysicsEngine diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 45685a9407..537d8c1337 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -35,12 +35,12 @@ void Transaction::updateItem(ItemID id, const UpdateFunctorPointer& functor) { _updateFunctors.push_back(functor); } -void Transaction::merge(const Transaction& change) { - _resetItems.insert(_resetItems.end(), change._resetItems.begin(), change._resetItems.end()); - _resetPayloads.insert(_resetPayloads.end(), change._resetPayloads.begin(), change._resetPayloads.end()); - _removedItems.insert(_removedItems.end(), change._removedItems.begin(), change._removedItems.end()); - _updatedItems.insert(_updatedItems.end(), change._updatedItems.begin(), change._updatedItems.end()); - _updateFunctors.insert(_updateFunctors.end(), change._updateFunctors.begin(), change._updateFunctors.end()); +void Transaction::merge(const Transaction& transaction) { + _resetItems.insert(_resetItems.end(), transaction._resetItems.begin(), transaction._resetItems.end()); + _resetPayloads.insert(_resetPayloads.end(), transaction._resetPayloads.begin(), transaction._resetPayloads.end()); + _removedItems.insert(_removedItems.end(), transaction._removedItems.begin(), transaction._removedItems.end()); + _updatedItems.insert(_updatedItems.end(), transaction._updatedItems.begin(), transaction._updatedItems.end()); + _updateFunctors.insert(_updateFunctors.end(), transaction._updateFunctors.begin(), transaction._updateFunctors.end()); } Scene::Scene(glm::vec3 origin, float size) : diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index d277f50650..dcbd87b74a 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -34,7 +34,7 @@ public: void updateItem(ItemID id, const UpdateFunctorPointer& functor); void updateItem(ItemID id) { updateItem(id, nullptr); } - void merge(const Transaction& change); + void merge(const Transaction& transaction); ItemIDs _resetItems; Payloads _resetPayloads; diff --git a/libraries/shared/src/SettingManager.cpp b/libraries/shared/src/SettingManager.cpp index 6acd758ad7..6c246d4cea 100644 --- a/libraries/shared/src/SettingManager.cpp +++ b/libraries/shared/src/SettingManager.cpp @@ -53,8 +53,8 @@ namespace Setting { const auto& key = handle->getKey(); withWriteLock([&] { QVariant loadedValue; - if (_transaction.contains(key) && _transaction[key] != UNSET_VALUE) { - loadedValue = _transaction[key]; + if (_pendingChanges.contains(key) && _pendingChanges[key] != UNSET_VALUE) { + loadedValue = _pendingChanges[key]; } else { loadedValue = value(key); } @@ -73,7 +73,7 @@ namespace Setting { } withWriteLock([&] { - _transaction[key] = handleValue; + _pendingChanges[key] = handleValue; }); } @@ -98,8 +98,8 @@ namespace Setting { void Manager::saveAll() { bool forceSync = false; withWriteLock([&] { - for (auto key : _transaction.keys()) { - auto newValue = _transaction[key]; + for (auto key : _pendingChanges.keys()) { + auto newValue = _pendingChanges[key]; auto savedValue = value(key, UNSET_VALUE); if (newValue == savedValue) { continue; @@ -112,7 +112,7 @@ namespace Setting { setValue(key, newValue); } } - _transaction.clear(); + _pendingChanges.clear(); }); if (forceSync) { diff --git a/libraries/shared/src/SettingManager.h b/libraries/shared/src/SettingManager.h index 507e11edaa..ffdd4ba42a 100644 --- a/libraries/shared/src/SettingManager.h +++ b/libraries/shared/src/SettingManager.h @@ -47,7 +47,7 @@ namespace Setting { QHash _handles; QPointer _saveTimer = nullptr; const QVariant UNSET_VALUE { QUuid::createUuid() }; - QHash _transaction; + QHash _pendingChanges; friend class Interface; friend void cleanupPrivateInstance(); From 1a9005ed8bc439fa93f037896175d1e345dcc6d7 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 5 Apr 2017 13:57:40 -0700 Subject: [PATCH 092/128] Avoid unexpected changes --- interface/src/Application.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9c41a78805..342d325f58 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5786,22 +5786,10 @@ void Application::toggleRunningScriptsWidget() const { } void Application::showScriptLogs() { - auto tabletScriptingInterface = DependencyManager::get(); - auto tablet = dynamic_cast(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system")); auto scriptEngines = DependencyManager::get(); QUrl defaultScriptsLoc = defaultScriptsLocation(); defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/debugging/debugWindow.js"); - - if (tablet->getToolbarMode()) { - scriptEngines->loadScript(defaultScriptsLoc.toString()); - } else { - QQuickItem* tabletRoot = tablet->getTabletRoot(); - if (!tabletRoot && !isHMDMode()) { - scriptEngines->loadScript(defaultScriptsLoc.toString()); - } else { - tablet->pushOntoStack("../../hifi/dialogs/TabletDebugWindow.qml"); - } - } + scriptEngines->loadScript(defaultScriptsLoc.toString()); } void Application::showAssetServerWidget(QString filePath) { From 026e7bc249d04fe12c5918f5ab5ec398564fb3f7 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 5 Apr 2017 14:17:26 -0700 Subject: [PATCH 093/128] Add a description of the Transaction class --- libraries/render/src/render/Scene.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index dcbd87b74a..cca72bb3c6 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -19,6 +19,15 @@ namespace render { class Engine; +// Transaction is the mechanism to make any change to the scene. +// Whenever a new item need to be reset, +// or when an item changes its position or its size +// or when an item's payload has to be be updated with new states (coming from outside the scene knowledge) +// or when an item is destroyed +// These changes must be expressed through the corresponding command from the Transaction +// THe Transaction is then queued on the Scene so all the pending transactions can be consolidated and processed at the time +// of updating the scene before it s rendered. +// class Transaction { public: Transaction() {} From 8267db6ce5220422cc7d2e47568593eeb6c8005a Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 5 Apr 2017 14:19:00 -0700 Subject: [PATCH 094/128] Add a description of the Transaction class --- libraries/render/src/render/Scene.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index cca72bb3c6..09a725205d 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -75,10 +75,10 @@ public: // THis is the total number of allocated items, this a threadsafe call size_t getNumItems() const { return _numAllocatedItems.load(); } - // Enqueue change batch to the scene + // Enqueue transaction to the scene void enqueueTransaction(const Transaction& transaction); - // Process the pending transactions equeued + // Process the pending transactions queued void processTransactionQueue(); // This next call are NOT threadsafe, you have to call them from the correct thread to avoid any potential issues From e9934ac696b7d70466ca962d97b18a2272592719 Mon Sep 17 00:00:00 2001 From: Faye Li Date: Wed, 5 Apr 2017 14:59:19 -0700 Subject: [PATCH 095/128] selfie stick script --- script-archive/selfieStick.js | 104 ++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 script-archive/selfieStick.js diff --git a/script-archive/selfieStick.js b/script-archive/selfieStick.js new file mode 100644 index 0000000000..767cf55144 --- /dev/null +++ b/script-archive/selfieStick.js @@ -0,0 +1,104 @@ +// selfieStick.js +// +// Created by Faye Li on March 23, 2016 +// +// Usage instruction: Spacebar toggles camera control - WASD first person free movement or no movement but allowing others to grab the selfie stick +// and control your camera. +// For best result, turn off avatar collisions(Developer > Avatar > Uncheck Enable Avatar Collisions) +// + +(function() { // BEGIN LOCAL_SCOPE + var MODEL_URL = "https://hifi-content.s3.amazonaws.com/faye/twitch-stream/selfie_stick.json"; + var AVATAR_URL = "https://hifi-content.s3.amazonaws.com/jimi/avatar/camera/fst/camera.fst"; + var originalAvatar = null; + var importedEntityIDs = []; + var selfieStickEntityID = null; + var lensEntityID = null; + var freeMovementMode = true; + + changeAvatar(); + importModel(); + processImportedEntities(); + parentEntityToAvatar(); + setupSpaceBarControl(); + + function changeAvatar() { + originalAvatar = MyAvatar.skeletonModelURL; + MyAvatar.skeletonModelURL = AVATAR_URL; + } + + function importModel() { + var success = Clipboard.importEntities(MODEL_URL); + var spawnLocation = MyAvatar.position; + if (success) { + importedEntityIDs = Clipboard.pasteEntities(spawnLocation); + } + } + + function processImportedEntities() { + importedEntityIDs.forEach(function(id){ + var props = Entities.getEntityProperties(id); + if (props.name === "Selfie Stick") { + selfieStickEntityID = id; + } else if (props.name === "Lens") { + lensEntityID = id; + } + }); + } + + function parentEntityToAvatar() { + var props = { + "parentID" : MyAvatar.sessionUUID + }; + Entities.editEntity(selfieStickEntityID, props); + } + + function unparentEntityFromAvatar() { + var props = { + "parentID" : 0 + }; + Entities.editEntity(selfieStickEntityID, props); + } + + function parentAvatarToEntity() { + MyAvatar.setParentID(selfieStickEntityID); + } + + function unparentAvatarFromEntity() { + MyAvatar.setParentID(0); + } + + function setupSpaceBarControl() { + var mappingName = "Handheld-Cam-Space-Bar"; + var myMapping = Controller.newMapping(mappingName); + myMapping.from(Controller.Hardware.Keyboard.Space).to(function(value){ + if ( value === 0 ) { + return; + } + if (freeMovementMode) { + freeMovementMode = false; + // Camera.mode = "entity"; + // Camera.cameraEntity = lensEntityID; + unparentEntityFromAvatar(); + parentAvatarToEntity(); + } else { + freeMovementMode = true; + // Camera.mode = "first person"; + unparentAvatarFromEntity(); + parentEntityToAvatar(); + } + }); + Controller.enableMapping(mappingName); + } + + // Removes all entities we imported and reset settings we've changed + function cleanup() { + importedEntityIDs.forEach(function(id) { + Entities.deleteEntity(id); + }); + Camera.mode = "first person"; + Controller.disableMapping("Handheld-Cam-Space-Bar"); + MyAvatar.skeletonModelURL = originalAvatar; + } + Script.scriptEnding.connect(cleanup); +}()); // END LOCAL_SCOPE \ No newline at end of file From 97d75e654e22cf732d104334e66357bb99b43054 Mon Sep 17 00:00:00 2001 From: Faye Li Date: Wed, 5 Apr 2017 15:04:21 -0700 Subject: [PATCH 096/128] mannually bind avatar and entity --- script-archive/selfieStick.js | 68 +++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/script-archive/selfieStick.js b/script-archive/selfieStick.js index 767cf55144..c6fb9c5349 100644 --- a/script-archive/selfieStick.js +++ b/script-archive/selfieStick.js @@ -7,6 +7,15 @@ // For best result, turn off avatar collisions(Developer > Avatar > Uncheck Enable Avatar Collisions) // +// selfieStick.js +// +// Created by Faye Li on March 23, 2016 +// +// Usage instruction: Spacebar toggles camera control - WASD first person free movement or no movement but allowing others to grab the selfie stick +// and control your camera. +// For best result, turn off avatar collisions(Developer > Avatar > Uncheck Enable Avatar Collisions) +// + (function() { // BEGIN LOCAL_SCOPE var MODEL_URL = "https://hifi-content.s3.amazonaws.com/faye/twitch-stream/selfie_stick.json"; var AVATAR_URL = "https://hifi-content.s3.amazonaws.com/jimi/avatar/camera/fst/camera.fst"; @@ -19,8 +28,8 @@ changeAvatar(); importModel(); processImportedEntities(); - parentEntityToAvatar(); setupSpaceBarControl(); + Script.update.connect(update); function changeAvatar() { originalAvatar = MyAvatar.skeletonModelURL; @@ -46,28 +55,6 @@ }); } - function parentEntityToAvatar() { - var props = { - "parentID" : MyAvatar.sessionUUID - }; - Entities.editEntity(selfieStickEntityID, props); - } - - function unparentEntityFromAvatar() { - var props = { - "parentID" : 0 - }; - Entities.editEntity(selfieStickEntityID, props); - } - - function parentAvatarToEntity() { - MyAvatar.setParentID(selfieStickEntityID); - } - - function unparentAvatarFromEntity() { - MyAvatar.setParentID(0); - } - function setupSpaceBarControl() { var mappingName = "Handheld-Cam-Space-Bar"; var myMapping = Controller.newMapping(mappingName); @@ -77,20 +64,41 @@ } if (freeMovementMode) { freeMovementMode = false; - // Camera.mode = "entity"; - // Camera.cameraEntity = lensEntityID; - unparentEntityFromAvatar(); - parentAvatarToEntity(); + Camera.mode = "entity"; + Camera.cameraEntity = lensEntityID; } else { freeMovementMode = true; - // Camera.mode = "first person"; - unparentAvatarFromEntity(); - parentEntityToAvatar(); + Camera.mode = "first person"; } }); Controller.enableMapping(mappingName); } + function update(deltaTime) { + if (freeMovementMode) { + var upFactor = 0.1; + var upUnitVec = Vec3.normalize(Quat.getUp(MyAvatar.orientation)); + var upOffset = Vec3.multiply(upUnitVec, upFactor); + var forwardFactor = -0.1; + var forwardUnitVec = Vec3.normalize(Quat.getFront(MyAvatar.orientation)); + var forwardOffset = Vec3.multiply(forwardUnitVec, forwardFactor); + var newPos = Vec3.sum(Vec3.sum(MyAvatar.position, upOffset), forwardOffset); + var newRot = MyAvatar.orientation; + Entities.editEntity(selfieStickEntityID, {position: newPos, rotation: newRot}); + } else { + var props = Entities.getEntityProperties(selfieStickEntityID); + var upFactor = 0.1; + var upUnitVec = Vec3.normalize(Quat.getUp(props.rotation)); + var upOffset = Vec3.multiply(upUnitVec, -upFactor); + var forwardFactor = -0.1; + var forwardUnitVec = Vec3.normalize(Quat.getFront(props.rotation)); + var forwardOffset = Vec3.multiply(forwardUnitVec, -forwardFactor); + var newPos = Vec3.sum(Vec3.sum(props.position, upOffset), forwardOffset); + MyAvatar.position = newPos; + MyAvatar.orientation = props.rotation; + } + } + // Removes all entities we imported and reset settings we've changed function cleanup() { importedEntityIDs.forEach(function(id) { From 90f5d02c990db8f79b25002da949d4947423fbc6 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 6 Apr 2017 00:13:53 +0100 Subject: [PATCH 097/128] goto toggle option --- interface/src/ui/DialogsManager.cpp | 43 +++++++++++++++++-- interface/src/ui/DialogsManager.h | 1 + .../src/TabletScriptingInterface.cpp | 8 ++++ .../src/TabletScriptingInterface.h | 3 ++ 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 402e27e256..a95ac8d91f 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -31,6 +31,7 @@ #include "TabletScriptingInterface.h" #include "scripting/HMDScriptingInterface.h" +static const QVariant TABLET_ADDRESS_DIALOG = "TabletAddressDialog.qml"; template void DialogsManager::maybeCreateDialog(QPointer& member) { if (!member) { @@ -46,12 +47,48 @@ void DialogsManager::maybeCreateDialog(QPointer& member) { } void DialogsManager::toggleAddressBar() { - AddressBarDialog::toggle(); - emit addressBarToggled(); + auto hmd = DependencyManager::get(); + auto tabletScriptingInterface = DependencyManager::get(); + auto tablet = dynamic_cast(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system")); + if (tablet->getToolbarMode()) { + if (tablet->isPathLoaded(TABLET_ADDRESS_DIALOG)) { + tablet->gotoHomeScreen(); + emit addressBarToggled(); + } else { + tablet->loadQMLSource(TABLET_ADDRESS_DIALOG); + emit addressBarToggled(); + } + } else { + if (hmd->getShouldShowTablet()) { + if (tablet->isPathLoaded(TABLET_ADDRESS_DIALOG) && _closeAddressBar) { + tablet->gotoHomeScreen(); + hmd->closeTablet(); + _closeAddressBar = false; + emit addressBarToggled(); + } else { + tablet->loadQMLSource(TABLET_ADDRESS_DIALOG); + _closeAddressBar = true; + emit addressBarToggled(); + } + } else { + tablet->loadQMLSource(TABLET_ADDRESS_DIALOG); + hmd->openTablet(); + _closeAddressBar = true; + emit addressBarToggled(); + } + + } } void DialogsManager::showAddressBar() { - AddressBarDialog::show(); + auto hmd = DependencyManager::get(); + auto tabletScriptingInterface = DependencyManager::get(); + auto tablet = dynamic_cast(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system")); + tablet->loadQMLSource(TABLET_ADDRESS_DIALOG); + + if (!hmd->getShouldShowTablet()) { + hmd->openTablet(); + } } void DialogsManager::showFeed() { diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index 608195aca7..24b9078baf 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -79,6 +79,7 @@ private: QPointer _octreeStatsDialog; QPointer _testingDialog; QPointer _domainConnectionDialog; + bool _closeAddressBar { false }; }; #endif // hifi_DialogsManager_h diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp index b4d8977b6d..7747e1b6dc 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.cpp +++ b/libraries/script-engine/src/TabletScriptingInterface.cpp @@ -275,6 +275,9 @@ void TabletProxy::emitWebEvent(QVariant msg) { emit webEventReceived(msg); } +bool TabletProxy::isPathLoaded(QVariant path) { + return path.toString() == _currentPathLoaded.toString(); +} void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface) { std::lock_guard guard(_mutex); _qmlOffscreenSurface = qmlOffscreenSurface; @@ -322,6 +325,7 @@ void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscr removeButtonsFromHomeScreen(); _state = State::Uninitialized; emit screenChanged(QVariant("Closed"), QVariant("")); + _currentPathLoaded = ""; } } @@ -345,6 +349,7 @@ void TabletProxy::gotoMenuScreen(const QString& submenu) { QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, QVariant(VRMENU_SOURCE_URL))); _state = State::Menu; emit screenChanged(QVariant("Menu"), QVariant(VRMENU_SOURCE_URL)); + _currentPathLoaded = VRMENU_SOURCE_URL; QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); } } @@ -364,6 +369,7 @@ void TabletProxy::loadQMLSource(const QVariant& path) { QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, path)); _state = State::QML; emit screenChanged(QVariant("QML"), path); + _currentPathLoaded = path; QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); } } else { @@ -426,6 +432,7 @@ void TabletProxy::loadHomeScreen(bool forceOntoHomeScreen) { } _state = State::Home; emit screenChanged(QVariant("Home"), QVariant(TABLET_SOURCE_URL)); + _currentPathLoaded = TABLET_SOURCE_URL; } } @@ -450,6 +457,7 @@ void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaS } _state = State::Web; emit screenChanged(QVariant("Web"), QVariant(url)); + _currentPathLoaded = QVariant(url); } QObject* TabletProxy::addButton(const QVariant& properties) { diff --git a/libraries/script-engine/src/TabletScriptingInterface.h b/libraries/script-engine/src/TabletScriptingInterface.h index e9ae60fee1..195db02789 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.h +++ b/libraries/script-engine/src/TabletScriptingInterface.h @@ -183,6 +183,8 @@ public: Q_INVOKABLE void setLandscape(bool landscape) { _landscape = landscape; } Q_INVOKABLE bool getLandscape() { return _landscape; } + Q_INVOKABLE bool isPathLoaded(QVariant path); + QQuickItem* getTabletRoot() const { return _qmlTabletRoot; } QObject* getTabletSurface(); @@ -235,6 +237,7 @@ protected: bool _initialScreen { false }; QVariant _initialPath { "" }; + QVariant _currentPathLoaded { "" }; QString _name; std::mutex _mutex; std::vector> _tabletButtonProxies; From e4021c168e7ef32b27d6cf2c17f2ef22bcf7cd99 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 5 Apr 2017 16:52:22 -0700 Subject: [PATCH 098/128] add special handling for abs drive letter paths from windows --- libraries/fbx/src/FBXReader.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 8288403337..bcd2be3384 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -447,7 +447,15 @@ QByteArray fixedTextureFilepath(QByteArray fbxRelativeFilepath, QUrl url) { // first setup a QFileInfo for the passed relative filepath, with backslashes replaced by forward slashes auto fileInfo = QFileInfo { fbxRelativeFilepath.replace("\\", "/") }; - if (fileInfo.isRelative()) { +#ifndef Q_OS_WIN + // it turns out that absolute windows paths starting with drive letters look like relative paths to QFileInfo on UNIX + // so we add a check for that here to work around it + bool isRelative = fbxRelativeFilepath[1] != ':' && fileInfo.isRelative(); +#else + bool isRelative = fileInfo.isRelative(); +#endif + + if (isRelative) { // the RelativeFilename pulled from the FBX is already correctly relative // so simply return this as the filepath to use return fbxRelativeFilepath; From 61ece265f4b43c4d2cd994acc124e17db878c23c Mon Sep 17 00:00:00 2001 From: David Kelly Date: Wed, 5 Apr 2017 18:16:16 -0700 Subject: [PATCH 099/128] now you can forget connections --- interface/resources/qml/hifi/NameCard.qml | 96 ++++++++++++++++++++++- interface/resources/qml/hifi/Pal.qml | 7 +- scripts/system/pal.js | 15 ++++ 3 files changed, 112 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 86cc0218a4..a298540d39 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -14,6 +14,7 @@ import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import QtGraphicalEffects 1.0 import "../styles-uit" +import "../controls-uit" as HifiControls import "toolbars" // references Users, UserActivityLogger, MyAvatar, Vec3, Quat, AddressManager from root context @@ -42,6 +43,7 @@ Item { property bool selected: false property bool isAdmin: false property bool isPresent: true + property string placeName: "" property string profilePicBorderColor: (connectionStatus == "connection" ? hifi.colors.indigoAccent : (connectionStatus == "friend" ? hifi.colors.greenHighlight : "transparent")) Item { @@ -316,9 +318,10 @@ Item { visible: thisNameCard.userName !== ""; // Size width: parent.width - height: pal.activeTab == "nearbyTab" || isMyCard ? usernameTextPixelSize + 4 : parent.height; + height: usernameTextPixelSize + 4 // Anchors - anchors.top: isMyCard ? myDisplayName.bottom : (pal.activeTab == "nearbyTab" ? displayNameContainer.bottom : parent.top); + anchors.top: isMyCard ? myDisplayName.bottom : pal.activeTab == "nearbyTab" ? displayNameContainer.bottom : undefined //(parent.height - displayNameTextPixelSize/2)); + anchors.verticalCenter: pal.activeTab == "connectionsTab" ? avatarImage.verticalCenter : undefined anchors.left: avatarImage.right; anchors.leftMargin: avatarImage.visible ? 5 : 0; anchors.rightMargin: 5; @@ -346,6 +349,93 @@ Item { } } } + StateImage { + id: nameCardConnectionInfoImage + visible: selected && !isMyCard && pal.activeTab == "connectionsTab" + imageURL: "../../images/info-icon-2-state.svg" // PLACEHOLDER!!! + size: 32; + buttonState: 0; + anchors.left: avatarImage.right + anchors.bottom: parent.bottom + } + MouseArea { + anchors.fill:nameCardConnectionInfoImage + enabled: selected + hoverEnabled: true + onClicked: { + userInfoViewer.url = defaultBaseUrl + "/users/" + userName; + userInfoViewer.visible = true; + } + onEntered: { + nameCardConnectionInfoImage.buttonState = 1; + } + onExited: { + nameCardConnectionInfoImage.buttonState = 0; + } + } + FiraSansRegular { + id: nameCardConnectionInfoText + visible: selected && !isMyCard && pal.activeTab == "connectionsTab" && !isMyCard + width: parent.width + height: displayNameTextPixelSize + size: displayNameTextPixelSize - 4 + anchors.left: nameCardConnectionInfoImage.right + anchors.verticalCenter: nameCardConnectionInfoImage.verticalCenter + anchors.leftMargin: 5 + verticalAlignment: Text.AlignVCenter + text: "Info" + color: hifi.colors.baseGray + } + StateImage { + id: nameCardRemoveConnectionImage + visible: selected && !isMyCard && pal.activeTab == "connectionsTab" + imageURL: "../../images/info-icon-2-state.svg" // PLACEHOLDER!!! + size: 32; + buttonState: 0; + x: 120 + anchors.bottom: parent.bottom + } + MouseArea { + anchors.fill:nameCardRemoveConnectionImage + enabled: selected + hoverEnabled: true + onClicked: { + // send message to pal.js to forgetConnection + pal.sendToScript({method: 'removeConnection', params: thisNameCard.userName}); + } + onEntered: { + nameCardRemoveConnectionImage.buttonState = 1; + } + onExited: { + nameCardRemoveConnectionImage.buttonState = 0; + } + } + FiraSansRegular { + id: nameCardRemoveConnectionText + visible: selected && !isMyCard && pal.activeTab == "connectionsTab" && !isMyCard + width: parent.width + height: displayNameTextPixelSize + size: displayNameTextPixelSize - 4 + anchors.left: nameCardRemoveConnectionImage.right + anchors.verticalCenter: nameCardRemoveConnectionImage.verticalCenter + anchors.leftMargin: 5 + verticalAlignment: Text.AlignVCenter + text: "Forget" + color: hifi.colors.baseGray + } + HifiControls.Button { + id: visitConnectionButton + visible: selected && !isMyCard && pal.activeTab == "connectionsTab" && !isMyCard + text: "Visit" + enabled: thisNameCard.placeName !== "" + anchors.verticalCenter: nameCardRemoveConnectionImage.verticalCenter + x: 240 + onClicked: { + AddressManager.goToUser(thisNameCard.userName); + UserActivityLogger.palAction("go_to_user", thisNameCard.userName); + } + } + // VU Meter Rectangle { id: nameCardVUMeter @@ -484,7 +574,7 @@ Item { } } } - + function updateGainFromQML(avatarUuid, sliderValue, isReleased) { Users.setAvatarGain(avatarUuid, sliderValue); if (isReleased) { diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 66803621ec..b7e11e97e6 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -763,7 +763,7 @@ Rectangle { // This Rectangle refers to each Row in the connectionsTable. rowDelegate: Rectangle { // Size - height: rowHeight; + height: rowHeight + (styleData.selected ? 15 : 0); color: rowColor(styleData.selected, styleData.alternate); } @@ -779,6 +779,7 @@ Rectangle { profileUrl: (model && model.profileUrl) || ""; displayName: ""; userName: model ? model.userName : ""; + placeName: model ? model.placeName : "" connectionStatus : model ? model.connection : ""; selected: styleData.selected; // Size @@ -792,7 +793,7 @@ Rectangle { FiraSansRegular { id: connectionsLocationData // Properties - visible: styleData.role === "placeName"; + visible: !connectionsNameCard.selected && styleData.role === "placeName"; text: (model && model.placeName) || ""; elide: Text.ElideRight; // Size @@ -822,7 +823,7 @@ Rectangle { // "Friends" checkbox HifiControlsUit.CheckBox { id: friendsCheckBox; - visible: styleData.role === "friends" && model.userName !== myData.userName; + visible: styleData.role === "friends" && model && model.userName !== myData.userName; anchors.centerIn: parent; checked: model ? (model["connection"] === "friend" ? true : false) : false; boxSize: 24; diff --git a/scripts/system/pal.js b/scripts/system/pal.js index b39c993894..263ee444cc 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -269,6 +269,21 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See getConnectionData(); UserActivityLogger.palAction("refresh_connections", ""); break; + case 'removeConnection': + connectionUserName = message.params; + request({ + uri: METAVERSE_BASE + '/api/v1/user/connections/' + connectionUserName, + method: 'DELETE' + }, function (error, response) { + print(JSON.stringify(response)); + if (error || (response.status !== 'success')) { + print("Error: unable to remove connection", connectionUserName, error || response.status); + return; + } + getConnectionData(); + }); + break + case 'removeFriend': friendUserName = message.params; request({ From 06bd9c97bf160e45d29414b54016e47f6f172414 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Wed, 5 Apr 2017 18:21:54 -0700 Subject: [PATCH 100/128] remove info button from avatar image --- interface/resources/qml/hifi/NameCard.qml | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index a298540d39..679920dc1c 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -81,25 +81,6 @@ Item { anchors.fill: parent; visible: userImage.status != Image.Ready; } - StateImage { - id: infoHoverImage; - visible: false; - imageURL: "../../images/info-icon-2-state.svg"; - size: 32; - buttonState: 1; - anchors.centerIn: parent; - } - MouseArea { - anchors.fill: parent - enabled: selected || isMyCard; - hoverEnabled: enabled - onClicked: { - userInfoViewer.url = defaultBaseUrl + "/users/" + userName; - userInfoViewer.visible = true; - } - onEntered: infoHoverImage.visible = true; - onExited: infoHoverImage.visible = false; - } } // Colored border around avatarImage From 42262aac78843dc9a8f7e58445f42471fd055b2a Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 5 Apr 2017 18:41:43 -0700 Subject: [PATCH 101/128] OpenVR: upgrade to version 1.0.6, for better generic tracker support --- cmake/externals/openvr/CMakeLists.txt | 4 ++-- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 8 ++++---- plugins/openvr/src/OpenVrHelpers.cpp | 2 +- plugins/openvr/src/ViveControllerManager.cpp | 12 +++++++++--- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/cmake/externals/openvr/CMakeLists.txt b/cmake/externals/openvr/CMakeLists.txt index 19a9dd1f15..cb4aafcf8b 100644 --- a/cmake/externals/openvr/CMakeLists.txt +++ b/cmake/externals/openvr/CMakeLists.txt @@ -7,8 +7,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) ExternalProject_Add( ${EXTERNAL_NAME} - URL https://github.com/ValveSoftware/openvr/archive/v1.0.3.zip - URL_MD5 b484b12901917cc739e40389583c8b0d + URL https://github.com/ValveSoftware/openvr/archive/v1.0.6.zip + URL_MD5 f6892cd3a3078f505d03b4297f5a1951 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 9f95e64361..1adfa8d333 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -277,8 +277,8 @@ public: glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); static const vr::VRTextureBounds_t leftBounds{ 0, 0, 0.5f, 1 }; static const vr::VRTextureBounds_t rightBounds{ 0.5f, 0, 1, 1 }; - - vr::Texture_t texture{ (void*)_colors[currentColorBuffer], vr::API_OpenGL, vr::ColorSpace_Auto }; + + vr::Texture_t texture{ (void*)_colors[currentColorBuffer], vr::TextureType_OpenGL, vr::ColorSpace_Auto }; vr::VRCompositor()->Submit(vr::Eye_Left, &texture, &leftBounds); vr::VRCompositor()->Submit(vr::Eye_Right, &texture, &rightBounds); _plugin._presentRate.increment(); @@ -422,7 +422,7 @@ bool OpenVrDisplayPlugin::internalActivate() { withNonPresentThreadLock([&] { openvr_for_each_eye([&](vr::Hmd_Eye eye) { _eyeOffsets[eye] = toGlm(_system->GetEyeToHeadTransform(eye)); - _eyeProjections[eye] = toGlm(_system->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL)); + _eyeProjections[eye] = toGlm(_system->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); }); // FIXME Calculate the proper combined projection by using GetProjectionRaw values from both eyes _cullingProjection = _eyeProjections[0]; @@ -639,7 +639,7 @@ void OpenVrDisplayPlugin::hmdPresent() { _submitThread->waitForPresent(); } else { GLuint glTexId = getGLBackend()->getTextureID(_compositeFramebuffer->getRenderBuffer(0)); - vr::Texture_t vrTexture { (void*)glTexId, vr::API_OpenGL, vr::ColorSpace_Auto }; + vr::Texture_t vrTexture { (void*)glTexId, vr::TextureType_OpenGL, vr::ColorSpace_Auto }; vr::VRCompositor()->Submit(vr::Eye_Left, &vrTexture, &OPENVR_TEXTURE_BOUNDS_LEFT); vr::VRCompositor()->Submit(vr::Eye_Right, &vrTexture, &OPENVR_TEXTURE_BOUNDS_RIGHT); vr::VRCompositor()->PostPresentHandoff(); diff --git a/plugins/openvr/src/OpenVrHelpers.cpp b/plugins/openvr/src/OpenVrHelpers.cpp index 29ef640bf3..d9db757b2f 100644 --- a/plugins/openvr/src/OpenVrHelpers.cpp +++ b/plugins/openvr/src/OpenVrHelpers.cpp @@ -114,7 +114,7 @@ void releaseOpenVrSystem() { // HACK: workaround openvr crash, call submit with an invalid texture, right before VR_Shutdown. const GLuint INVALID_GL_TEXTURE_HANDLE = -1; - vr::Texture_t vrTexture{ (void*)INVALID_GL_TEXTURE_HANDLE, vr::API_OpenGL, vr::ColorSpace_Auto }; + vr::Texture_t vrTexture{ (void*)INVALID_GL_TEXTURE_HANDLE, vr::TextureType_OpenGL, vr::ColorSpace_Auto }; static vr::VRTextureBounds_t OPENVR_TEXTURE_BOUNDS_LEFT{ 0, 0, 0.5f, 1 }; static vr::VRTextureBounds_t OPENVR_TEXTURE_BOUNDS_RIGHT{ 0.5f, 0, 1, 1 }; diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 8cedee2d8f..6fe640b618 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -140,9 +140,15 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle handleHandController(deltaTime, leftHandDeviceIndex, inputCalibrationData, true); handleHandController(deltaTime, rightHandDeviceIndex, inputCalibrationData, false); - // collect raw poses + // collect poses for all generic trackers for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) { - handleTrackedObject(i, inputCalibrationData); + if (_system->GetTrackedDeviceClass(i) == vr::TrackedDeviceClass_GenericTracker) { + handleTrackedObject(i, inputCalibrationData); + } else { + uint32_t poseIndex = controller::TRACKED_OBJECT_00 + i; + controller::Pose invalidPose; + _poseStateMap[poseIndex] = invalidPose; + } } // handle haptics @@ -203,7 +209,7 @@ void ViveControllerManager::InputDevice::handleHandController(float deltaTime, u handlePoseEvent(deltaTime, inputCalibrationData, mat, linearVelocity, angularVelocity, isLeftHand); vr::VRControllerState_t controllerState = vr::VRControllerState_t(); - if (_system->GetControllerState(deviceIndex, &controllerState)) { + if (_system->GetControllerState(deviceIndex, &controllerState, sizeof(vr::VRControllerState_t))) { // process each button for (uint32_t i = 0; i < vr::k_EButton_Max; ++i) { auto mask = vr::ButtonMaskFromId((vr::EVRButtonId)i); From a92162dea9f8ba90af6ad755840f8be699ca95ff Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 6 Apr 2017 08:50:22 -0700 Subject: [PATCH 102/128] no mo useless debug statements --- scripts/system/pal.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 263ee444cc..5fbea90025 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -275,7 +275,6 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See uri: METAVERSE_BASE + '/api/v1/user/connections/' + connectionUserName, method: 'DELETE' }, function (error, response) { - print(JSON.stringify(response)); if (error || (response.status !== 'success')) { print("Error: unable to remove connection", connectionUserName, error || response.status); return; @@ -290,7 +289,6 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See uri: METAVERSE_BASE + '/api/v1/user/friends/' + friendUserName, method: 'DELETE' }, function (error, response) { - print(JSON.stringify(response)); if (error || (response.status !== 'success')) { print("Error: unable to unfriend", friendUserName, error || response.status); return; From 16fa7988f6d7adcccaceef913419edf1031780b7 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Thu, 6 Apr 2017 17:53:46 +0200 Subject: [PATCH 103/128] TabletWebView redesigned to single WebView instance --- interface/resources/qml/TabletBrowser.qml | 193 ++++++--------- .../resources/qml/controls/TabletWebView.qml | 226 ++++++------------ 2 files changed, 154 insertions(+), 265 deletions(-) diff --git a/interface/resources/qml/TabletBrowser.qml b/interface/resources/qml/TabletBrowser.qml index 85fff59207..2650102b27 100644 --- a/interface/resources/qml/TabletBrowser.qml +++ b/interface/resources/qml/TabletBrowser.qml @@ -1,5 +1,5 @@ import QtQuick 2.5 -import QtQuick.Controls 1.2 +import QtQuick.Controls 1.4 import QtWebChannel 1.0 import QtWebEngine 1.2 @@ -7,7 +7,7 @@ import "controls" import "styles" as HifiStyles import "styles-uit" import "windows" -import HFWebEngineProfile 1.0 +import HFTabletWebEngineProfile 1.0 Item { id: root @@ -27,138 +27,103 @@ Item { x: 0 y: 0 - - function goBack() { - webview.goBack(); - } - - function goForward() { - webview.goForward(); - } - - function gotoPage(url) { - webview.url = url; - } function setProfile(profile) { webview.profile = profile; } - function reloadPage() { - webview.reloadAndBypassCache(); - webview.setActiveFocusOnPress(true); - webview.setEnabled(true); + QtObject { + id: eventBridgeWrapper + WebChannel.id: "eventBridgeWrapper" + property var eventBridge; } - Item { - id:item + WebEngineView { + id: webview + objectName: "webEngineView" + x: 0 + y: 0 width: parent.width - implicitHeight: parent.height + height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height - - QtObject { - id: eventBridgeWrapper - WebChannel.id: "eventBridgeWrapper" - property var eventBridge; + profile: HFTabletWebEngineProfile { + id: webviewTabletProfile + storageName: "qmlTabletWebEngine" } - WebEngineView { - id: webview - objectName: "webEngineView" - x: 0 - y: 0 - width: parent.width - height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height - - profile: HFWebEngineProfile { - id: webviewProfile - storageName: "qmlWebEngine" - } + property string userScriptUrl: "" - property string userScriptUrl: "" - - // creates a global EventBridge object. - WebEngineScript { - id: createGlobalEventBridge - sourceCode: eventBridgeJavaScriptToInject - injectionPoint: WebEngineScript.DocumentCreation - worldId: WebEngineScript.MainWorld - } - - // detects when to raise and lower virtual keyboard - WebEngineScript { - id: raiseAndLowerKeyboard - injectionPoint: WebEngineScript.Deferred - sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js" - worldId: WebEngineScript.MainWorld - } - - // User script. - WebEngineScript { - id: userScript - sourceUrl: webview.userScriptUrl - injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished. - worldId: WebEngineScript.MainWorld - } + // creates a global EventBridge object. + WebEngineScript { + id: createGlobalEventBridge + sourceCode: eventBridgeJavaScriptToInject + injectionPoint: WebEngineScript.DocumentCreation + worldId: WebEngineScript.MainWorld + } - userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] - - property string newUrl: "" - - webChannel.registeredObjects: [eventBridgeWrapper] + // detects when to raise and lower virtual keyboard + WebEngineScript { + id: raiseAndLowerKeyboard + injectionPoint: WebEngineScript.Deferred + sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js" + worldId: WebEngineScript.MainWorld + } - Component.onCompleted: { - // Ensure the JS from the web-engine makes it to our logging - webview.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) { - console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message); - }); - - webview.profile.httpUserAgent = "Mozilla/5.0 Chrome (HighFidelityInterface"; - web.address = url; - } - - onFeaturePermissionRequested: { - grantFeaturePermission(securityOrigin, feature, true); - } + // User script. + WebEngineScript { + id: userScript + sourceUrl: webview.userScriptUrl + injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished. + worldId: WebEngineScript.MainWorld + } - onLoadingChanged: { - keyboardRaised = false; - punctuationMode = false; - keyboard.resetShiftMode(false); - - // Required to support clicking on "hifi://" links - if (WebEngineView.LoadStartedStatus == loadRequest.status) { - var url = loadRequest.url.toString(); - if (urlHandler.canHandleUrl(url)) { - if (urlHandler.handleUrl(url)) { - root.stop(); - } + userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] + + property string newUrl: "" + + webChannel.registeredObjects: [eventBridgeWrapper] + + Component.onCompleted: { + // Ensure the JS from the web-engine makes it to our logging + webview.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) { + console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message); + }); + + webview.profile.httpUserAgent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36"; + web.address = url; + } + + onFeaturePermissionRequested: { + grantFeaturePermission(securityOrigin, feature, true); + } + + onLoadingChanged: { + keyboardRaised = false; + punctuationMode = false; + keyboard.resetShiftMode(false); + + // Required to support clicking on "hifi://" links + if (WebEngineView.LoadStartedStatus == loadRequest.status) { + var url = loadRequest.url.toString(); + if (urlHandler.canHandleUrl(url)) { + if (urlHandler.handleUrl(url)) { + root.stop(); } } } + } - onNewViewRequested: { - var component = Qt.createComponent("./TabletBrowser.qml"); - - if (component.status != Component.Ready) { - if (component.status == Component.Error) { - console.log("Error: " + component.errorString()); - } - return; - } - var newWindow = component.createObject(); - newWindow.setProfile(webview.profile); - request.openIn(newWindow.webView); - newWindow.eventBridge = web.eventBridge; - stackRoot.push(newWindow); - newWindow.webView.forceActiveFocus(); - + onNavigationRequested: { + if (request.navigationType == WebEngineNavigationRequest.LinkClickedNavigation) { + pagesModel.append({webUrl: request.url.toString()}) } } - - } // item - - + + onNewViewRequested: { + request.openIn(webView); + } + } + Keys.onPressed: { switch(event.key) { case Qt.Key_L: @@ -171,4 +136,4 @@ Item { } } - } // dialog +} diff --git a/interface/resources/qml/controls/TabletWebView.qml b/interface/resources/qml/controls/TabletWebView.qml index 742ab2d333..50d6e1c504 100644 --- a/interface/resources/qml/controls/TabletWebView.qml +++ b/interface/resources/qml/controls/TabletWebView.qml @@ -1,6 +1,6 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 -import QtWebEngine 1.1 +import QtWebEngine 1.2 import QtWebChannel 1.0 import "../controls-uit" as HiFiControls import "../styles" as HifiStyles @@ -14,17 +14,20 @@ Item { height: parent.height property var parentStackItem: null property int headerHeight: 38 - property alias url: root.url - property string address: url - property alias scriptURL: root.userScriptUrl + property string url + property string address: url //for compatibility + property string scriptURL property alias eventBridge: eventBridgeWrapper.eventBridge property bool keyboardEnabled: HMD.active property bool keyboardRaised: false property bool punctuationMode: false property bool isDesktop: false - property WebEngineView view: root + property WebEngineView view: loader.currentView + property int currentPage: -1 // used as a model for repeater + property alias pagesModel: pagesModel + Row { id: buttons HifiConstants { id: hifi } @@ -37,29 +40,29 @@ Item { anchors.leftMargin: 8 HiFiGlyphs { id: back; - enabled: true; + enabled: currentPage > 0 text: hifi.glyphs.backward color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText size: 48 - MouseArea { anchors.fill: parent; onClicked: stackRoot.goBack() } + MouseArea { anchors.fill: parent; onClicked: goBack() } } HiFiGlyphs { id: forward; - enabled: stackRoot.currentItem.canGoForward; + enabled: currentPage < pagesModel.count - 1 text: hifi.glyphs.forward color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText size: 48 - MouseArea { anchors.fill: parent; onClicked: stackRoot.currentItem.goForward() } + MouseArea { anchors.fill: parent; onClicked: goForward() } } HiFiGlyphs { id: reload; - enabled: true; - text: webview.loading ? hifi.glyphs.close : hifi.glyphs.reload + enabled: view != null; + text: (view !== null && view.loading) ? hifi.glyphs.close : hifi.glyphs.reload color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText size: 48 - MouseArea { anchors.fill: parent; onClicked: stackRoot.currentItem.reloadPage(); } + MouseArea { anchors.fill: parent; onClicked: reloadPage(); } } } @@ -86,7 +89,7 @@ Item { } //root.hidePermissionsBar(); web.keyboardRaised = false; - stackRoot.currentItem.gotoPage(text); + gotoPage(text); break; @@ -94,157 +97,78 @@ Item { } } + ListModel { + id: pagesModel + onCountChanged: { + currentPage = count - 1 + } + } + function goBack() { + if (currentPage > 0) { + currentPage--; + } + } + + function goForward() { + if (currentPage < pagesModel.count - 1) { + currentPage++; + } + } + + function gotoPage(url) { + pagesModel.append({webUrl: url}) + } + + function reloadPage() { + view.reloadAndBypassCache() + view.setActiveFocusOnPress(true); + view.setEnabled(true); + } + + onCurrentPageChanged: { + if (currentPage >= 0 && currentPage < pagesModel.count && loader.item !== null) { + loader.item.url = pagesModel.get(currentPage).webUrl + } + } + + onUrlChanged: { + gotoPage(url) + } + + QtObject { + id: eventBridgeWrapper + WebChannel.id: "eventBridgeWrapper" + property var eventBridge; + } + + Loader { + id: loader + + property WebEngineView currentView: null - StackView { - id: stackRoot width: parent.width height: parent.height - web.headerHeight + asynchronous: true anchors.top: buttons.bottom - //property var goBack: currentItem.goBack(); - property WebEngineView view: root - - initialItem: root; - - function goBack() { - if (depth > 1 ) { - if (currentItem.canGoBack) { - currentItem.goBack(); - } else { - stackRoot.pop(); - currentItem.webView.focus = true; - currentItem.webView.forceActiveFocus(); - web.address = currentItem.webView.url; - } - } else { - if (currentItem.canGoBack) { - currentItem.goBack(); - } else if (parentStackItem) { - web.parentStackItem.pop(); + active: false + source: "../TabletBrowser.qml" + onStatusChanged: { + if (loader.status === Loader.Ready) { + currentView = item.webView + item.webView.userScriptUrl = web.scriptURL + if (currentPage >= 0) { + //we got something to load already + item.url = pagesModel.get(currentPage).webUrl } } } - - QtObject { - id: eventBridgeWrapper - WebChannel.id: "eventBridgeWrapper" - property var eventBridge; - } - - WebEngineView { - id: root - objectName: "webEngineView" - x: 0 - y: 0 - width: parent.width - height: keyboardEnabled && keyboardRaised ? (parent.height - keyboard.height) : parent.height - profile: HFTabletWebEngineProfile { - id: webviewTabletProfile - storageName: "qmlTabletWebEngine" - } - - property WebEngineView webView: root - function reloadPage() { - root.reload(); - } - - function gotoPage(url) { - root.url = url; - } - - property string userScriptUrl: "" - - // creates a global EventBridge object. - WebEngineScript { - id: createGlobalEventBridge - sourceCode: eventBridgeJavaScriptToInject - injectionPoint: WebEngineScript.DocumentCreation - worldId: WebEngineScript.MainWorld - } - - // detects when to raise and lower virtual keyboard - WebEngineScript { - id: raiseAndLowerKeyboard - injectionPoint: WebEngineScript.Deferred - sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js" - worldId: WebEngineScript.MainWorld - } - - // User script. - WebEngineScript { - id: userScript - sourceUrl: root.userScriptUrl - injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished. - worldId: WebEngineScript.MainWorld - } - - userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] - - property string newUrl: "" - - webChannel.registeredObjects: [eventBridgeWrapper] - - Component.onCompleted: { - // Ensure the JS from the web-engine makes it to our logging - root.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) { - console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message); - }); - - root.profile.httpUserAgent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36" - - } - - onFeaturePermissionRequested: { - grantFeaturePermission(securityOrigin, feature, true); - } - - onLoadingChanged: { - keyboardRaised = false; - punctuationMode = false; - keyboard.resetShiftMode(false); - // Required to support clicking on "hifi://" links - if (WebEngineView.LoadStartedStatus == loadRequest.status) { - var url = loadRequest.url.toString(); - if (urlHandler.canHandleUrl(url)) { - if (urlHandler.handleUrl(url)) { - root.stop(); - } - } - } - } - - onNewViewRequested:{ - var component = Qt.createComponent("../TabletBrowser.qml"); - if (component.status != Component.Ready) { - if (component.status == Component.Error) { - console.log("Error: " + component.errorString()); - } - return; - } - var newWindow = component.createObject(); - newWindow.setProfile(root.profile); - request.openIn(newWindow.webView); - newWindow.eventBridge = web.eventBridge; - stackRoot.push(newWindow); - } - } - - HiFiControls.Keyboard { - id: keyboard - raised: web.keyboardEnabled && web.keyboardRaised - numeric: web.punctuationMode - anchors { - left: parent.left - right: parent.right - bottom: parent.bottom - } - } - } Component.onCompleted: { web.isDesktop = (typeof desktop !== "undefined"); address = url; + loader.active = true } Keys.onPressed: { From 057a9feaf133a181a6a1a91843eb21e0beedb41f Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 6 Apr 2017 09:39:38 -0700 Subject: [PATCH 104/128] Don't crash if KTX file is invalid --- libraries/gpu/src/gpu/Texture_ktx.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index 8befdf3e16..28de0c70eb 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -72,6 +72,15 @@ Size KtxStorage::getMipFaceSize(uint16 level, uint8 face) const { } void Texture::setKtxBacking(const std::string& filename) { + // Check the KTX file for validity before using it as backing storage + { + ktx::StoragePointer storage { new storage::FileStorage(filename.c_str()) }; + auto ktxPointer = ktx::KTX::create(storage); + if (!ktxPointer) { + return; + } + } + auto newBacking = std::unique_ptr(new KtxStorage(filename)); setStorage(newBacking); } @@ -185,7 +194,12 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) { } Texture* Texture::unserialize(const std::string& ktxfile, TextureUsageType usageType, Usage usage, const Sampler::Desc& sampler) { - ktx::KTXDescriptor descriptor { ktx::KTX::create(ktx::StoragePointer { new storage::FileStorage(ktxfile.c_str()) })->toDescriptor() }; + std::unique_ptr ktxPointer = ktx::KTX::create(ktx::StoragePointer { new storage::FileStorage(ktxfile.c_str()) }); + if (!ktxPointer) { + return nullptr; + } + + ktx::KTXDescriptor descriptor { ktxPointer->toDescriptor() }; const auto& header = descriptor.header; Format mipFormat = Format::COLOR_BGRA_32; From 85c78da83959fb3381776158f3b0ac8502f036a7 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 6 Apr 2017 11:16:51 -0700 Subject: [PATCH 105/128] updated, plus fixed some annoying errors in logs from Pal.qml --- interface/resources/qml/hifi/NameCard.qml | 15 +++++++-------- interface/resources/qml/hifi/Pal.qml | 19 +++++++++++++------ 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 679920dc1c..3343cec26f 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -45,7 +45,7 @@ Item { property bool isPresent: true property string placeName: "" property string profilePicBorderColor: (connectionStatus == "connection" ? hifi.colors.indigoAccent : (connectionStatus == "friend" ? hifi.colors.greenHighlight : "transparent")) - + property alias avImage: avatarImage Item { id: avatarImage visible: profileUrl !== "" && userName !== ""; @@ -367,14 +367,13 @@ Item { text: "Info" color: hifi.colors.baseGray } - StateImage { + HiFiGlyphs { id: nameCardRemoveConnectionImage visible: selected && !isMyCard && pal.activeTab == "connectionsTab" - imageURL: "../../images/info-icon-2-state.svg" // PLACEHOLDER!!! - size: 32; - buttonState: 0; + text: hifi.glyphs.close + size: 28; x: 120 - anchors.bottom: parent.bottom + anchors.verticalCenter: nameCardConnectionInfoImage.verticalCenter } MouseArea { anchors.fill:nameCardRemoveConnectionImage @@ -385,10 +384,10 @@ Item { pal.sendToScript({method: 'removeConnection', params: thisNameCard.userName}); } onEntered: { - nameCardRemoveConnectionImage.buttonState = 1; + nameCardRemoveConnectionImage.text = hifi.glyphs.closeInverted; } onExited: { - nameCardRemoveConnectionImage.buttonState = 0; + nameCardRemoveConnectionImage.text = hifi.glyphs.close; } } FiraSansRegular { diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index b7e11e97e6..a3d555f817 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -793,17 +793,21 @@ Rectangle { FiraSansRegular { id: connectionsLocationData // Properties - visible: !connectionsNameCard.selected && styleData.role === "placeName"; + visible: styleData.role === "placeName"; text: (model && model.placeName) || ""; elide: Text.ElideRight; // Size width: parent.width; - // Anchors - anchors.fill: parent; + // you would think that this would work: + // anchors.verticalCenter: connectionsNameCard.avImage.verticalCenter + // but no! you cannot anchor to a non-sibling or parent. So I will + // align with the friends checkbox, where I did the manual alignment + anchors.verticalCenter: friendsCheckBox.verticalCenter // Text Size size: 16; // Text Positioning verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter // Style color: hifi.colors.blueAccent; font.underline: true; @@ -824,7 +828,11 @@ Rectangle { HifiControlsUit.CheckBox { id: friendsCheckBox; visible: styleData.role === "friends" && model && model.userName !== myData.userName; - anchors.centerIn: parent; + // you would think that this would work: + // anchors.verticalCenter: connectionsNameCard.avImage.verticalCenter + // but no! you cannot anchor to a non-sibling or parent. So: + x: parent.width/2 - boxSize/2 + y: connectionsNameCard.avImage.y + connectionsNameCard.avImage.height/2 - boxSize/2 checked: model ? (model["connection"] === "friend" ? true : false) : false; boxSize: 24; onClicked: { @@ -902,7 +910,7 @@ Rectangle { wrapMode: Text.WordWrap textFormat: Text.StyledText; // Text - text: HMD.active ? + text: HMD.isMounted ? "When you meet someone you want to remember later, you can connect with a handshake:

" + "1. Put your hand out onto their hand and squeeze your controller's grip button on its side.
" + "2. Once the other person puts their hand onto yours, you'll see your connection form.
" + @@ -961,7 +969,6 @@ Rectangle { // Text size size: hifi.fontSizes.tabularData; // Anchors - anchors.top: myCard.top; anchors.left: parent.left; // Style color: hifi.colors.baseGrayHighlight; From 1d60a55d5f0b7d8262db0316333f18bf27b99b98 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 6 Apr 2017 11:20:08 -0700 Subject: [PATCH 106/128] notice login/logout change in pal --- interface/resources/qml/hifi/Pal.qml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 66803621ec..50fba660d8 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -52,6 +52,13 @@ Rectangle { id: letterboxMessage; z: 999; // Force the popup on top of everything else } + Connections { + target: GlobalServices + onMyUsernameChanged: { + myData.userName = Account.username; + myDataChanged(); // Setting a property within an object isn't enough to update dependencies. This will do it. + } + } // The ComboDialog used for setting availability ComboDialog { id: comboDialog; From e0a14223457d9dedee7ff1b0020e3eeaff5f58d4 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 6 Apr 2017 12:07:51 -0700 Subject: [PATCH 107/128] pal selection changes --- interface/resources/qml/hifi/Pal.qml | 11 ++++++++--- interface/resources/qml/styles-uit/HifiConstants.qml | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 66803621ec..2f10f0fdf5 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -436,7 +436,7 @@ Rectangle { rowDelegate: Rectangle { // The only way I know to specify a row height. // Size height: rowHeight + (styleData.selected ? 15 : 0); - color: rowColor(styleData.selected, styleData.alternate); + color: nearbyRowColor(styleData.selected, styleData.alternate); } // This Item refers to the contents of each Cell @@ -764,7 +764,7 @@ Rectangle { rowDelegate: Rectangle { // Size height: rowHeight; - color: rowColor(styleData.selected, styleData.alternate); + color: connectionsRowColor(styleData.selected, styleData.alternate); } // This Item refers to the contents of each Cell @@ -1184,9 +1184,12 @@ Rectangle { } } - function rowColor(selected, alternate) { + function nearbyRowColor(selected, alternate) { return selected ? hifi.colors.orangeHighlight : alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd; } + function connectionsRowColor(selected, alternate) { + return selected ? hifi.colors.lightBlueHighlight : alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd; + } function findNearbySessionIndex(sessionId, optionalData) { // no findIndex in .qml var data = optionalData || nearbyUserModelData, length = data.length; for (var i = 0; i < length; i++) { @@ -1257,6 +1260,8 @@ Rectangle { selectionTimer.userIndex = userIndex; selectionTimer.start(); } + // in any case make sure we are in the nearby tab + activeTab="nearbyTab"; break; // Received an "updateUsername()" request from the JS case 'updateUsername': diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index 386af206e1..7b6efbd573 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -72,6 +72,7 @@ Item { readonly property color magentaAccent: "#A2277C" readonly property color checkboxCheckedRed: "#FF0000" readonly property color checkboxCheckedBorderRed: "#D00000" + readonly property color lightBlueHighlight: "#d6f6ff" // Semitransparent readonly property color darkGray30: "#4d121212" From d163b343681f35e90136e7505c073e3021fb475e Mon Sep 17 00:00:00 2001 From: Trent Polack Date: Thu, 6 Apr 2017 15:57:32 -0400 Subject: [PATCH 108/128] Link to coding standards. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 00e7cbc45b..6294981e9a 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ Documentation ========= Documentation is available at [docs.highfidelity.com](https://docs.highfidelity.com), if something is missing, please suggest it via a new job on Worklist (add to the hifi-docs project). +There is also detailed [documentation on our coding standards](https://wiki.highfidelity.com/wiki/Coding_Standards). + Build Instructions ========= All information required to build is found in the [build guide](BUILD.md). From 4e49774d0efff81324ee6d13171a379089aaafeb Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 6 Apr 2017 13:20:00 -0700 Subject: [PATCH 109/128] Moved device class check into handleTrackedObject --- plugins/openvr/src/ViveControllerManager.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 6fe640b618..86b37135d2 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -142,13 +142,7 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle // collect poses for all generic trackers for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) { - if (_system->GetTrackedDeviceClass(i) == vr::TrackedDeviceClass_GenericTracker) { - handleTrackedObject(i, inputCalibrationData); - } else { - uint32_t poseIndex = controller::TRACKED_OBJECT_00 + i; - controller::Pose invalidPose; - _poseStateMap[poseIndex] = invalidPose; - } + handleTrackedObject(i, inputCalibrationData); } // handle haptics @@ -177,6 +171,7 @@ void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceInde uint32_t poseIndex = controller::TRACKED_OBJECT_00 + deviceIndex; if (_system->IsTrackedDeviceConnected(deviceIndex) && + _system->GetTrackedDeviceClass(deviceIndex) == vr::TrackedDeviceClass_GenericTracker && _nextSimPoseData.vrPoses[deviceIndex].bPoseIsValid && poseIndex <= controller::TRACKED_OBJECT_15) { From 726395ac3eaef6983e2e76aea8ae3d5b5a388fe8 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 6 Apr 2017 14:07:07 -0700 Subject: [PATCH 110/128] friends checkbox speedup --- interface/resources/qml/hifi/Pal.qml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 50fba660d8..5c8c5cd2b4 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -840,11 +840,7 @@ Rectangle { pal.sendToScript({method: newValue ? 'addFriend' : 'removeFriend', params: model.userName}); UserActivityLogger["palAction"](newValue ? styleData.role : "un-" + styleData.role, model.sessionId); - - // http://doc.qt.io/qt-5/qtqml-syntax-propertybinding.html#creating-property-bindings-from-javascript - // I'm using an explicit binding here because clicking a checkbox breaks the implicit binding as set by - // "checked:" statement above. - checked = Qt.binding(function() { return (model["connection"] === "friend" ? true : false)}); + checked = newValue; } } } From 52fd446d4d5bc965acd6d60b11a2d05236206df3 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 6 Apr 2017 22:27:37 +0100 Subject: [PATCH 111/128] toggle goto in tablet --- interface/resources/qml/hifi/Card.qml | 7 +----- .../qml/hifi/tablet/TabletAddressDialog.qml | 25 ++++++++++++++----- interface/src/Application.cpp | 1 + .../src/TabletScriptingInterface.cpp | 2 +- scripts/system/tablet-goto.js | 13 +++++++--- 5 files changed, 31 insertions(+), 17 deletions(-) diff --git a/interface/resources/qml/hifi/Card.qml b/interface/resources/qml/hifi/Card.qml index 217cfec707..b72901fbdf 100644 --- a/interface/resources/qml/hifi/Card.qml +++ b/interface/resources/qml/hifi/Card.qml @@ -243,12 +243,7 @@ Rectangle { } } } - DropShadow { - anchors.fill: actionIcon - radius: 8.0 - color: "#80000000" - source: actionIcon - } + MouseArea { id: messageArea; width: rectIcon.width; diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index b0b8c68789..fbb78d2694 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -25,22 +25,31 @@ StackView { HifiConstants { id: hifi } HifiStyles.HifiConstants { id: hifiStyleConstants } initialItem: addressBarDialog - width: parent.width - height: parent.height property var eventBridge; property var allStories: []; property int cardWidth: 460; property int cardHeight: 320; property string metaverseBase: addressBarDialog.metaverseServerUrl + "/api/v1/"; + property var tablet: null; + property bool isDesktop: false; + Component { id: tabletStoryCard; TabletStoryCard {} } Component.onCompleted: { root.currentItem.focus = true; root.currentItem.forceActiveFocus(); + addressLine.focus = true; + addressLine.forceActiveFocus(); fillDestinations(); updateLocationText(false); root.parentChanged.connect(center); center(); + isDesktop = (typeof desktop !== "undefined"); + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + + if (desktop) { + root.title = "GOTO"; + } } Component.onDestruction: { root.parentChanged.disconnect(center); @@ -107,7 +116,6 @@ StackView { imageURL: "../../../images/home.svg" onClicked: { addressBarDialog.loadHome(); - root.shown = false; } anchors { left: parent.left @@ -291,9 +299,8 @@ StackView { left: parent.left right: parent.right leftMargin: 10 - verticalCenter: parent.verticalCenter; - horizontalCenter: parent.horizontalCenter; } + model: suggestions orientation: ListView.Vertical @@ -547,7 +554,13 @@ StackView { if (addressLine.text !== "") { addressBarDialog.loadAddress(addressLine.text, fromSuggestions) } - root.shown = false; + + if (root.desktop) { + tablet.gotoHomeScreen(); + } else { + HMD.closeTablet(); + } + } Keys.onPressed: { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e19eea0a2e..feba5a74a7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2010,6 +2010,7 @@ void Application::initializeUi() { rootContext->setContextProperty("SoundCache", DependencyManager::get().data()); rootContext->setContextProperty("Account", AccountScriptingInterface::getInstance()); + rootContext->setContextProperty("Tablet", DependencyManager::get().data()); rootContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface); rootContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance()); rootContext->setContextProperty("FaceTracker", DependencyManager::get().data()); diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp index 7747e1b6dc..3aa0cc99e7 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.cpp +++ b/libraries/script-engine/src/TabletScriptingInterface.cpp @@ -83,7 +83,7 @@ QQuickWindow* TabletScriptingInterface::getTabletWindow() { QObject* qmlSurface = tablet->getTabletSurface(); OffscreenQmlSurface* surface = dynamic_cast(qmlSurface); - if (!surface) { + if (!surface) { return nullptr; } QQuickWindow* window = surface->getWindow(); diff --git a/scripts/system/tablet-goto.js b/scripts/system/tablet-goto.js index eb95d9d8a3..84f7357b1a 100644 --- a/scripts/system/tablet-goto.js +++ b/scripts/system/tablet-goto.js @@ -29,10 +29,15 @@ } function onScreenChanged(type, url) { - // for toolbar mode: change button to active when window is first openend, false otherwise. - button.editProperties({isActive: shouldActivateButton}); - shouldActivateButton = false; - onGotoScreen = false; + if (url === gotoQmlSource) { + onGotoScreen = true; + shouldActivateButton = true; + button.editProperties({isActive: shouldActivateButton}); + } else { + shouldActivateButton = false; + onGotoScreen = false; + button.editProperties({isActive: shouldActivateButton}); + } } var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); From 9577102c229f503846d731315d789672ed541f3a Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 6 Apr 2017 14:45:08 -0700 Subject: [PATCH 112/128] fix sorting by pal connections-tab friends column --- interface/resources/qml/hifi/Pal.qml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index d627fb54f9..9e93ddc8d7 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -756,7 +756,7 @@ Rectangle { resizable: false; } TableViewColumn { - role: "friends"; + role: "connection"; title: "FRIEND"; width: actionButtonWidth; movable: false; @@ -834,16 +834,16 @@ Rectangle { // "Friends" checkbox HifiControlsUit.CheckBox { id: friendsCheckBox; - visible: styleData.role === "friends" && model && model.userName !== myData.userName; + visible: styleData.role === "connection" && model && model.userName !== myData.userName; // you would think that this would work: // anchors.verticalCenter: connectionsNameCard.avImage.verticalCenter // but no! you cannot anchor to a non-sibling or parent. So: - x: parent.width/2 - boxSize/2 - y: connectionsNameCard.avImage.y + connectionsNameCard.avImage.height/2 - boxSize/2 - checked: model ? (model["connection"] === "friend" ? true : false) : false; + x: parent.width/2 - boxSize/2; + y: connectionsNameCard.avImage.y + connectionsNameCard.avImage.height/2 - boxSize/2; + checked: model && (model.connection === "friend"); boxSize: 24; onClicked: { - var newValue = !(model["connection"] === "friend"); + var newValue = model.connection !== "friend"; connectionsUserModel.setProperty(model.userIndex, styleData.role, newValue); connectionsUserModelData[model.userIndex][styleData.role] = newValue; // Defensive programming pal.sendToScript({method: newValue ? 'addFriend' : 'removeFriend', params: model.userName}); From 22521526ece9f2b4af843169906c87500911323c Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 6 Apr 2017 23:41:30 +0100 Subject: [PATCH 113/128] removed stray space --- libraries/script-engine/src/TabletScriptingInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp index 3aa0cc99e7..7747e1b6dc 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.cpp +++ b/libraries/script-engine/src/TabletScriptingInterface.cpp @@ -83,7 +83,7 @@ QQuickWindow* TabletScriptingInterface::getTabletWindow() { QObject* qmlSurface = tablet->getTabletSurface(); OffscreenQmlSurface* surface = dynamic_cast(qmlSurface); - if (!surface) { + if (!surface) { return nullptr; } QQuickWindow* window = surface->getWindow(); From d64a803451ceb11db8106ae9f7874450aad12138 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 6 Apr 2017 16:08:48 -0700 Subject: [PATCH 114/128] no need to set checked --- interface/resources/qml/hifi/Pal.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 5c8c5cd2b4..94b6b00fbe 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -840,7 +840,6 @@ Rectangle { pal.sendToScript({method: newValue ? 'addFriend' : 'removeFriend', params: model.userName}); UserActivityLogger["palAction"](newValue ? styleData.role : "un-" + styleData.role, model.sessionId); - checked = newValue; } } } From b089fd03b8ba9d3c0dba1cd13daf5cae2ffa61fc Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Thu, 6 Apr 2017 16:48:11 -0700 Subject: [PATCH 115/128] make connection messaging when not logged in --- scripts/system/makeUserConnection.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/scripts/system/makeUserConnection.js b/scripts/system/makeUserConnection.js index 0a781a5bb8..674da2d677 100644 --- a/scripts/system/makeUserConnection.js +++ b/scripts/system/makeUserConnection.js @@ -131,7 +131,6 @@ function request(options, callback) { // cb(error, responseOfCorrectContentType) var error = (httpRequest.status !== HTTP_OK) && httpRequest.status.toString() + ':' + httpRequest.statusText, response = !error && httpRequest.responseText, contentType = !error && httpRequest.getResponseHeader('content-type'); - debug('FIXME REMOVE: server response', options, error, response, contentType); if (!error && contentType.indexOf('application/json') === 0) { // ignoring charset, etc. try { response = JSON.parse(response); @@ -139,6 +138,9 @@ function request(options, callback) { // cb(error, responseOfCorrectContentType) error = e; } } + if (error) { + response = {statusCode: httpRequest.status}; + } callback(error, response); } }; @@ -164,7 +166,6 @@ function request(options, callback) { // cb(error, responseOfCorrectContentType) options.headers["Content-type"] = "application/json"; options.body = JSON.stringify(options.body); } - debug("FIXME REMOVE: final options to send", options); for (key in options.headers || {}) { httpRequest.setRequestHeader(key, options.headers[key]); } @@ -574,6 +575,9 @@ function handleConnectionResponseAndMaybeRepeat(error, response) { } } else if (error || (response.status !== 'success')) { debug('server fail', error, response.status); + if (response && (response.statusCode === 401)) { + error = "All participants must be logged in to connect."; + } result = error ? {status: 'error', connection: error} : response; UserActivityLogger.makeUserConnection(connectingId, false, error || response); connectionRequestCompleted(); @@ -603,6 +607,15 @@ function makeConnection(id) { // probably, in which we do this. Controller.triggerHapticPulse(HAPTIC_DATA.background.strength, MAKING_CONNECTION_TIMEOUT, handToHaptic(currentHand)); requestBody = {node_id: cleanId(MyAvatar.sessionUUID), proposed_node_id: cleanId(id)}; // for use when repeating + + // It would be "simpler" to skip this and just look at the response, but: + // 1. We don't want to bother the metaverse with request that we know will fail. + // 2. We don't want our code here to be dependent on precisely how the metaverse responds (400, 401, etc.) + if (!Account.isLoggedIn()) { + handleConnectionResponseAndMaybeRepeat("401:Unauthorized", {statusCode: 401}); + return; + } + // This will immediately set response if successfull (e.g., the other guy got his request in first), or immediate failure, // and will otherwise poll (using the requestBody we just set). request({ // From aae7349c40df89931373b7e0de1cd939cd4254b5 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 6 Apr 2017 18:31:03 -0700 Subject: [PATCH 116/128] trying to understand the bug with nvidia new driver --- libraries/gl/src/gl/Config.h | 2 +- libraries/render-utils/src/DeferredBufferRead.slh | 6 ++++-- libraries/render-utils/src/DeferredFramebuffer.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/gl/src/gl/Config.h b/libraries/gl/src/gl/Config.h index 9efae96f2a..07cf65c03a 100644 --- a/libraries/gl/src/gl/Config.h +++ b/libraries/gl/src/gl/Config.h @@ -29,7 +29,7 @@ #include // Uncomment this define and recompile to be able to avoid code path preventing to be able to run nsight graphics debug -//#define HIFI_ENABLE_NSIGHT_DEBUG 1 +#define HIFI_ENABLE_NSIGHT_DEBUG 1 #endif diff --git a/libraries/render-utils/src/DeferredBufferRead.slh b/libraries/render-utils/src/DeferredBufferRead.slh index 7c81b2c142..fff7973871 100644 --- a/libraries/render-utils/src/DeferredBufferRead.slh +++ b/libraries/render-utils/src/DeferredBufferRead.slh @@ -67,8 +67,10 @@ DeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) { frag.scattering = 0.0; unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic); - //frag.emissive = specularVal.xyz; - frag.obscurance = min(specularVal.w, frag.obscurance); + + // frag.obscurance = min(specularVal.w, frag.obscurance); + + frag.obscurance = specularVal.w; if (frag.mode == FRAG_MODE_SCATTERING) { diff --git a/libraries/render-utils/src/DeferredFramebuffer.cpp b/libraries/render-utils/src/DeferredFramebuffer.cpp index 52329931d0..5d345f0851 100644 --- a/libraries/render-utils/src/DeferredFramebuffer.cpp +++ b/libraries/render-utils/src/DeferredFramebuffer.cpp @@ -55,7 +55,7 @@ void DeferredFramebuffer::allocate() { _deferredColorTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(colorFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); _deferredNormalTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(linearFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); - _deferredSpecularTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(colorFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); + _deferredSpecularTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(linearFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); _deferredFramebuffer->setRenderBuffer(0, _deferredColorTexture); _deferredFramebuffer->setRenderBuffer(1, _deferredNormalTexture); From da1355dc3247da05dc8436fdbaa358160c1638ec Mon Sep 17 00:00:00 2001 From: Sam Cake Date: Fri, 7 Apr 2017 01:03:07 -0700 Subject: [PATCH 117/128] Introducing a fix to the graphics bug --- libraries/gl/src/gl/Config.h | 2 +- .../render-utils/src/DebugDeferredBuffer.cpp | 23 ++++++++++++++++--- libraries/render-utils/src/LightAmbient.slh | 13 +++++------ .../src/debug_deferred_buffer.slf | 9 ++++++-- .../utilities/render/deferredLighting.qml | 3 ++- 5 files changed, 36 insertions(+), 14 deletions(-) diff --git a/libraries/gl/src/gl/Config.h b/libraries/gl/src/gl/Config.h index 07cf65c03a..9efae96f2a 100644 --- a/libraries/gl/src/gl/Config.h +++ b/libraries/gl/src/gl/Config.h @@ -29,7 +29,7 @@ #include // Uncomment this define and recompile to be able to avoid code path preventing to be able to run nsight graphics debug -#define HIFI_ENABLE_NSIGHT_DEBUG 1 +//#define HIFI_ENABLE_NSIGHT_DEBUG 1 #endif diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 9ffd94af38..8b505bbe97 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -85,13 +85,30 @@ static const std::string DEFAULT_NORMAL_SHADER { " return vec4(vec3(0.5) + (frag.normal * 0.5), 1.0);" " }" }; - +/* static const std::string DEFAULT_OCCLUSION_SHADER{ "vec4 getFragmentColor() {" - " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" - " return vec4(vec3(pow(frag.obscurance, 1.0 / 2.2)), 1.0);" + // " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" + // " return vec4(vec3(pow(frag.obscurance, 1.0 / 2.2)), 1.0);" + // " return vec4(vec3(pow(texture(specularMap, uv).a, 1.0 / 2.2)), 1.0);" + " return vec4(vec3(texture(specularMap, uv).w), 1.0);" " }" }; +*/ +static const std::string DEFAULT_OCCLUSION_SHADER{ + "vec4 getFragmentColor() {" + // " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" + // " return vec4(vec3(pow(frag.obscurance, 1.0 / 2.2)), 1.0);" + " vec4 midNormalCurvature;" + " vec4 lowNormalCurvature;" + " unpackMidLowNormalCurvature(uv, midNormalCurvature, lowNormalCurvature);" + " float ambientOcclusion = curvatureAO(lowNormalCurvature.a * 20.0f) * 0.5f;" + " float ambientOcclusionHF = curvatureAO(midNormalCurvature.a * 8.0f) * 0.5f;" + " ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);" + " return vec4(vec3(ambientOcclusion), 1.0);" + " }" +}; + static const std::string DEFAULT_EMISSIVE_SHADER{ "vec4 getFragmentColor() {" diff --git a/libraries/render-utils/src/LightAmbient.slh b/libraries/render-utils/src/LightAmbient.slh index b919108115..5f74b46d3e 100644 --- a/libraries/render-utils/src/LightAmbient.slh +++ b/libraries/render-utils/src/LightAmbient.slh @@ -62,7 +62,7 @@ vec3 evalAmbientSpecularIrradiance(LightAmbient ambient, vec3 fragEyeDir, vec3 f <@if supportScattering@> float curvatureAO(in float k) { - return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369; + return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f; } <@endif@> @@ -83,13 +83,12 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambie specular = evalAmbientSpecularIrradiance(ambient, eyeDir, normal, roughness) * ambientFresnel; <@if supportScattering@> - float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f; - float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f; - ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF); - - obscurance = min(obscurance, ambientOcclusion); - if (scattering * isScatteringEnabled() > 0.0) { + float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f; + float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f; + ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF); + + obscurance = min(obscurance, ambientOcclusion); // Diffuse from ambient diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lowNormalCurvature.xyz).xyz; diff --git a/libraries/render-utils/src/debug_deferred_buffer.slf b/libraries/render-utils/src/debug_deferred_buffer.slf index c018e5e526..e9750f0054 100644 --- a/libraries/render-utils/src/debug_deferred_buffer.slf +++ b/libraries/render-utils/src/debug_deferred_buffer.slf @@ -16,15 +16,20 @@ <@include gpu/Color.slh@> <$declareColorWheel()$> + uniform sampler2D linearDepthMap; uniform sampler2D halfLinearDepthMap; uniform sampler2D halfNormalMap; uniform sampler2D occlusionMap; uniform sampler2D occlusionBlurredMap; -uniform sampler2D curvatureMap; -uniform sampler2D diffusedCurvatureMap; uniform sampler2D scatteringMap; +<$declareDeferredCurvature()$> + +float curvatureAO(float k) { + return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f; +} + in vec2 uv; out vec4 outFragColor; diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index c7ec8e1153..a444338c0f 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -63,7 +63,8 @@ Column { "Directional:LightingModel:enableDirectionalLight", "Point:LightingModel:enablePointLight", "Spot:LightingModel:enableSpotLight", - "Light Contour:LightingModel:showLightContour" + "Light Contour:LightingModel:showLightContour", + "Shadow:RenderShadowTask:enabled" ] CheckBox { text: modelData.split(":")[0] From b1a4bc329be3ad754e4e079620e4f6d30ef0419e Mon Sep 17 00:00:00 2001 From: Sam Cake Date: Fri, 7 Apr 2017 01:10:18 -0700 Subject: [PATCH 118/128] Introducing a fix to the graphics bug --- .../render-utils/src/DebugDeferredBuffer.cpp | 46 +++++++++---------- .../render-utils/src/DebugDeferredBuffer.h | 1 + .../render-utils/src/DeferredBufferRead.slh | 6 +-- .../utilities/render/deferredLighting.qml | 1 + 4 files changed, 25 insertions(+), 29 deletions(-) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 8b505bbe97..e534628c83 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -85,30 +85,14 @@ static const std::string DEFAULT_NORMAL_SHADER { " return vec4(vec3(0.5) + (frag.normal * 0.5), 1.0);" " }" }; -/* -static const std::string DEFAULT_OCCLUSION_SHADER{ - "vec4 getFragmentColor() {" - // " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" - // " return vec4(vec3(pow(frag.obscurance, 1.0 / 2.2)), 1.0);" - // " return vec4(vec3(pow(texture(specularMap, uv).a, 1.0 / 2.2)), 1.0);" - " return vec4(vec3(texture(specularMap, uv).w), 1.0);" - " }" -}; -*/ -static const std::string DEFAULT_OCCLUSION_SHADER{ - "vec4 getFragmentColor() {" - // " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" - // " return vec4(vec3(pow(frag.obscurance, 1.0 / 2.2)), 1.0);" - " vec4 midNormalCurvature;" - " vec4 lowNormalCurvature;" - " unpackMidLowNormalCurvature(uv, midNormalCurvature, lowNormalCurvature);" - " float ambientOcclusion = curvatureAO(lowNormalCurvature.a * 20.0f) * 0.5f;" - " float ambientOcclusionHF = curvatureAO(midNormalCurvature.a * 8.0f) * 0.5f;" - " ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);" - " return vec4(vec3(ambientOcclusion), 1.0);" - " }" -}; +static const std::string DEFAULT_OCCLUSION_SHADER{ + "vec4 getFragmentColor() {" + // " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" + // " return vec4(vec3(pow(frag.obscurance, 1.0 / 2.2)), 1.0);" + " return vec4(vec3(pow(texture(specularMap, uv).a, 1.0 / 2.2)), 1.0);" + " }" +}; static const std::string DEFAULT_EMISSIVE_SHADER{ "vec4 getFragmentColor() {" @@ -211,6 +195,18 @@ static const std::string DEFAULT_DIFFUSED_NORMAL_CURVATURE_SHADER{ " }" }; +static const std::string DEFAULT_CURVATURE_OCCLUSION_SHADER{ + "vec4 getFragmentColor() {" + " vec4 midNormalCurvature;" + " vec4 lowNormalCurvature;" + " unpackMidLowNormalCurvature(uv, midNormalCurvature, lowNormalCurvature);" + " float ambientOcclusion = curvatureAO(lowNormalCurvature.a * 20.0f) * 0.5f;" + " float ambientOcclusionHF = curvatureAO(midNormalCurvature.a * 8.0f) * 0.5f;" + " ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);" + " return vec4(vec3(ambientOcclusion), 1.0);" + " }" +}; + static const std::string DEFAULT_DEBUG_SCATTERING_SHADER{ "vec4 getFragmentColor() {" " return vec4(pow(vec3(texture(scatteringMap, uv).xyz), vec3(1.0 / 2.2)), 1.0);" @@ -220,7 +216,7 @@ static const std::string DEFAULT_DEBUG_SCATTERING_SHADER{ static const std::string DEFAULT_AMBIENT_OCCLUSION_SHADER{ "vec4 getFragmentColor() {" - " return vec4(vec3(texture(obscuranceMap, uv).xyz), 1.0);" + " return vec4(vec3(texture(obscuranceMap, uv).x), 1.0);" // When drawing color " return vec4(vec3(texture(occlusionMap, uv).xyz), 1.0);" // when drawing normal" return vec4(normalize(texture(occlusionMap, uv).xyz * 2.0 - vec3(1.0)), 1.0);" " }" @@ -305,6 +301,8 @@ std::string DebugDeferredBuffer::getShaderSourceCode(Mode mode, std::string cust return DEFAULT_DIFFUSED_CURVATURE_SHADER; case DiffusedNormalCurvatureMode: return DEFAULT_DIFFUSED_NORMAL_CURVATURE_SHADER; + case CurvatureOcclusionMode: + return DEFAULT_CURVATURE_OCCLUSION_SHADER; case ScatteringDebugMode: return DEFAULT_DEBUG_SCATTERING_SHADER; case AmbientOcclusionMode: diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index eb1a541d2e..be775e052f 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -72,6 +72,7 @@ protected: NormalCurvatureMode, DiffusedCurvatureMode, DiffusedNormalCurvatureMode, + CurvatureOcclusionMode, ScatteringDebugMode, AmbientOcclusionMode, AmbientOcclusionBlurredMode, diff --git a/libraries/render-utils/src/DeferredBufferRead.slh b/libraries/render-utils/src/DeferredBufferRead.slh index fff7973871..315de30fea 100644 --- a/libraries/render-utils/src/DeferredBufferRead.slh +++ b/libraries/render-utils/src/DeferredBufferRead.slh @@ -67,11 +67,7 @@ DeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) { frag.scattering = 0.0; unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic); - - // frag.obscurance = min(specularVal.w, frag.obscurance); - - frag.obscurance = specularVal.w; - + frag.obscurance = min(specularVal.w, frag.obscurance); if (frag.mode == FRAG_MODE_SCATTERING) { frag.scattering = specularVal.x; diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index a444338c0f..778e0e1905 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -151,6 +151,7 @@ Column { ListElement { text: "Mid Normal"; color: "White" } ListElement { text: "Low Curvature"; color: "White" } ListElement { text: "Low Normal"; color: "White" } + ListElement { text: "Curvature Occlusion"; color: "White" } ListElement { text: "Debug Scattering"; color: "White" } ListElement { text: "Ambient Occlusion"; color: "White" } ListElement { text: "Ambient Occlusion Blurred"; color: "White" } From ab3d39951edc406d7d4bb22c5d3d801703a6950c Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 7 Apr 2017 02:03:31 -0700 Subject: [PATCH 119/128] Revert "Fixing the rendering bug triggered with Nvidia driver 381.65" --- .../render-utils/src/DebugDeferredBuffer.cpp | 21 +++---------------- .../render-utils/src/DebugDeferredBuffer.h | 1 - .../render-utils/src/DeferredBufferRead.slh | 2 ++ .../render-utils/src/DeferredFramebuffer.cpp | 2 +- libraries/render-utils/src/LightAmbient.slh | 13 ++++++------ .../src/debug_deferred_buffer.slf | 9 ++------ .../utilities/render/deferredLighting.qml | 4 +--- 7 files changed, 16 insertions(+), 36 deletions(-) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index e534628c83..9ffd94af38 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -88,9 +88,8 @@ static const std::string DEFAULT_NORMAL_SHADER { static const std::string DEFAULT_OCCLUSION_SHADER{ "vec4 getFragmentColor() {" - // " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" - // " return vec4(vec3(pow(frag.obscurance, 1.0 / 2.2)), 1.0);" - " return vec4(vec3(pow(texture(specularMap, uv).a, 1.0 / 2.2)), 1.0);" + " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" + " return vec4(vec3(pow(frag.obscurance, 1.0 / 2.2)), 1.0);" " }" }; @@ -195,18 +194,6 @@ static const std::string DEFAULT_DIFFUSED_NORMAL_CURVATURE_SHADER{ " }" }; -static const std::string DEFAULT_CURVATURE_OCCLUSION_SHADER{ - "vec4 getFragmentColor() {" - " vec4 midNormalCurvature;" - " vec4 lowNormalCurvature;" - " unpackMidLowNormalCurvature(uv, midNormalCurvature, lowNormalCurvature);" - " float ambientOcclusion = curvatureAO(lowNormalCurvature.a * 20.0f) * 0.5f;" - " float ambientOcclusionHF = curvatureAO(midNormalCurvature.a * 8.0f) * 0.5f;" - " ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);" - " return vec4(vec3(ambientOcclusion), 1.0);" - " }" -}; - static const std::string DEFAULT_DEBUG_SCATTERING_SHADER{ "vec4 getFragmentColor() {" " return vec4(pow(vec3(texture(scatteringMap, uv).xyz), vec3(1.0 / 2.2)), 1.0);" @@ -216,7 +203,7 @@ static const std::string DEFAULT_DEBUG_SCATTERING_SHADER{ static const std::string DEFAULT_AMBIENT_OCCLUSION_SHADER{ "vec4 getFragmentColor() {" - " return vec4(vec3(texture(obscuranceMap, uv).x), 1.0);" + " return vec4(vec3(texture(obscuranceMap, uv).xyz), 1.0);" // When drawing color " return vec4(vec3(texture(occlusionMap, uv).xyz), 1.0);" // when drawing normal" return vec4(normalize(texture(occlusionMap, uv).xyz * 2.0 - vec3(1.0)), 1.0);" " }" @@ -301,8 +288,6 @@ std::string DebugDeferredBuffer::getShaderSourceCode(Mode mode, std::string cust return DEFAULT_DIFFUSED_CURVATURE_SHADER; case DiffusedNormalCurvatureMode: return DEFAULT_DIFFUSED_NORMAL_CURVATURE_SHADER; - case CurvatureOcclusionMode: - return DEFAULT_CURVATURE_OCCLUSION_SHADER; case ScatteringDebugMode: return DEFAULT_DEBUG_SCATTERING_SHADER; case AmbientOcclusionMode: diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index be775e052f..eb1a541d2e 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -72,7 +72,6 @@ protected: NormalCurvatureMode, DiffusedCurvatureMode, DiffusedNormalCurvatureMode, - CurvatureOcclusionMode, ScatteringDebugMode, AmbientOcclusionMode, AmbientOcclusionBlurredMode, diff --git a/libraries/render-utils/src/DeferredBufferRead.slh b/libraries/render-utils/src/DeferredBufferRead.slh index 315de30fea..7c81b2c142 100644 --- a/libraries/render-utils/src/DeferredBufferRead.slh +++ b/libraries/render-utils/src/DeferredBufferRead.slh @@ -67,8 +67,10 @@ DeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) { frag.scattering = 0.0; unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic); + //frag.emissive = specularVal.xyz; frag.obscurance = min(specularVal.w, frag.obscurance); + if (frag.mode == FRAG_MODE_SCATTERING) { frag.scattering = specularVal.x; } diff --git a/libraries/render-utils/src/DeferredFramebuffer.cpp b/libraries/render-utils/src/DeferredFramebuffer.cpp index 5d345f0851..52329931d0 100644 --- a/libraries/render-utils/src/DeferredFramebuffer.cpp +++ b/libraries/render-utils/src/DeferredFramebuffer.cpp @@ -55,7 +55,7 @@ void DeferredFramebuffer::allocate() { _deferredColorTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(colorFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); _deferredNormalTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(linearFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); - _deferredSpecularTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(linearFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); + _deferredSpecularTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(colorFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); _deferredFramebuffer->setRenderBuffer(0, _deferredColorTexture); _deferredFramebuffer->setRenderBuffer(1, _deferredNormalTexture); diff --git a/libraries/render-utils/src/LightAmbient.slh b/libraries/render-utils/src/LightAmbient.slh index 5f74b46d3e..b919108115 100644 --- a/libraries/render-utils/src/LightAmbient.slh +++ b/libraries/render-utils/src/LightAmbient.slh @@ -62,7 +62,7 @@ vec3 evalAmbientSpecularIrradiance(LightAmbient ambient, vec3 fragEyeDir, vec3 f <@if supportScattering@> float curvatureAO(in float k) { - return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f; + return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369; } <@endif@> @@ -83,12 +83,13 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambie specular = evalAmbientSpecularIrradiance(ambient, eyeDir, normal, roughness) * ambientFresnel; <@if supportScattering@> - if (scattering * isScatteringEnabled() > 0.0) { - float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f; - float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f; - ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF); + float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f; + float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f; + ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF); - obscurance = min(obscurance, ambientOcclusion); + obscurance = min(obscurance, ambientOcclusion); + + if (scattering * isScatteringEnabled() > 0.0) { // Diffuse from ambient diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lowNormalCurvature.xyz).xyz; diff --git a/libraries/render-utils/src/debug_deferred_buffer.slf b/libraries/render-utils/src/debug_deferred_buffer.slf index e9750f0054..c018e5e526 100644 --- a/libraries/render-utils/src/debug_deferred_buffer.slf +++ b/libraries/render-utils/src/debug_deferred_buffer.slf @@ -16,20 +16,15 @@ <@include gpu/Color.slh@> <$declareColorWheel()$> - uniform sampler2D linearDepthMap; uniform sampler2D halfLinearDepthMap; uniform sampler2D halfNormalMap; uniform sampler2D occlusionMap; uniform sampler2D occlusionBlurredMap; +uniform sampler2D curvatureMap; +uniform sampler2D diffusedCurvatureMap; uniform sampler2D scatteringMap; -<$declareDeferredCurvature()$> - -float curvatureAO(float k) { - return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f; -} - in vec2 uv; out vec4 outFragColor; diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index 778e0e1905..c7ec8e1153 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -63,8 +63,7 @@ Column { "Directional:LightingModel:enableDirectionalLight", "Point:LightingModel:enablePointLight", "Spot:LightingModel:enableSpotLight", - "Light Contour:LightingModel:showLightContour", - "Shadow:RenderShadowTask:enabled" + "Light Contour:LightingModel:showLightContour" ] CheckBox { text: modelData.split(":")[0] @@ -151,7 +150,6 @@ Column { ListElement { text: "Mid Normal"; color: "White" } ListElement { text: "Low Curvature"; color: "White" } ListElement { text: "Low Normal"; color: "White" } - ListElement { text: "Curvature Occlusion"; color: "White" } ListElement { text: "Debug Scattering"; color: "White" } ListElement { text: "Ambient Occlusion"; color: "White" } ListElement { text: "Ambient Occlusion Blurred"; color: "White" } From f82310545cdafb14aba5519ff272c88b7d3f1138 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 7 Apr 2017 02:03:58 -0700 Subject: [PATCH 120/128] Revert "Revert "Fixing the rendering bug triggered with Nvidia driver 381.65"" --- .../render-utils/src/DebugDeferredBuffer.cpp | 21 ++++++++++++++++--- .../render-utils/src/DebugDeferredBuffer.h | 1 + .../render-utils/src/DeferredBufferRead.slh | 2 -- .../render-utils/src/DeferredFramebuffer.cpp | 2 +- libraries/render-utils/src/LightAmbient.slh | 13 ++++++------ .../src/debug_deferred_buffer.slf | 9 ++++++-- .../utilities/render/deferredLighting.qml | 4 +++- 7 files changed, 36 insertions(+), 16 deletions(-) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 9ffd94af38..e534628c83 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -88,8 +88,9 @@ static const std::string DEFAULT_NORMAL_SHADER { static const std::string DEFAULT_OCCLUSION_SHADER{ "vec4 getFragmentColor() {" - " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" - " return vec4(vec3(pow(frag.obscurance, 1.0 / 2.2)), 1.0);" + // " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" + // " return vec4(vec3(pow(frag.obscurance, 1.0 / 2.2)), 1.0);" + " return vec4(vec3(pow(texture(specularMap, uv).a, 1.0 / 2.2)), 1.0);" " }" }; @@ -194,6 +195,18 @@ static const std::string DEFAULT_DIFFUSED_NORMAL_CURVATURE_SHADER{ " }" }; +static const std::string DEFAULT_CURVATURE_OCCLUSION_SHADER{ + "vec4 getFragmentColor() {" + " vec4 midNormalCurvature;" + " vec4 lowNormalCurvature;" + " unpackMidLowNormalCurvature(uv, midNormalCurvature, lowNormalCurvature);" + " float ambientOcclusion = curvatureAO(lowNormalCurvature.a * 20.0f) * 0.5f;" + " float ambientOcclusionHF = curvatureAO(midNormalCurvature.a * 8.0f) * 0.5f;" + " ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF);" + " return vec4(vec3(ambientOcclusion), 1.0);" + " }" +}; + static const std::string DEFAULT_DEBUG_SCATTERING_SHADER{ "vec4 getFragmentColor() {" " return vec4(pow(vec3(texture(scatteringMap, uv).xyz), vec3(1.0 / 2.2)), 1.0);" @@ -203,7 +216,7 @@ static const std::string DEFAULT_DEBUG_SCATTERING_SHADER{ static const std::string DEFAULT_AMBIENT_OCCLUSION_SHADER{ "vec4 getFragmentColor() {" - " return vec4(vec3(texture(obscuranceMap, uv).xyz), 1.0);" + " return vec4(vec3(texture(obscuranceMap, uv).x), 1.0);" // When drawing color " return vec4(vec3(texture(occlusionMap, uv).xyz), 1.0);" // when drawing normal" return vec4(normalize(texture(occlusionMap, uv).xyz * 2.0 - vec3(1.0)), 1.0);" " }" @@ -288,6 +301,8 @@ std::string DebugDeferredBuffer::getShaderSourceCode(Mode mode, std::string cust return DEFAULT_DIFFUSED_CURVATURE_SHADER; case DiffusedNormalCurvatureMode: return DEFAULT_DIFFUSED_NORMAL_CURVATURE_SHADER; + case CurvatureOcclusionMode: + return DEFAULT_CURVATURE_OCCLUSION_SHADER; case ScatteringDebugMode: return DEFAULT_DEBUG_SCATTERING_SHADER; case AmbientOcclusionMode: diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index eb1a541d2e..be775e052f 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -72,6 +72,7 @@ protected: NormalCurvatureMode, DiffusedCurvatureMode, DiffusedNormalCurvatureMode, + CurvatureOcclusionMode, ScatteringDebugMode, AmbientOcclusionMode, AmbientOcclusionBlurredMode, diff --git a/libraries/render-utils/src/DeferredBufferRead.slh b/libraries/render-utils/src/DeferredBufferRead.slh index 7c81b2c142..315de30fea 100644 --- a/libraries/render-utils/src/DeferredBufferRead.slh +++ b/libraries/render-utils/src/DeferredBufferRead.slh @@ -67,10 +67,8 @@ DeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) { frag.scattering = 0.0; unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic); - //frag.emissive = specularVal.xyz; frag.obscurance = min(specularVal.w, frag.obscurance); - if (frag.mode == FRAG_MODE_SCATTERING) { frag.scattering = specularVal.x; } diff --git a/libraries/render-utils/src/DeferredFramebuffer.cpp b/libraries/render-utils/src/DeferredFramebuffer.cpp index 52329931d0..5d345f0851 100644 --- a/libraries/render-utils/src/DeferredFramebuffer.cpp +++ b/libraries/render-utils/src/DeferredFramebuffer.cpp @@ -55,7 +55,7 @@ void DeferredFramebuffer::allocate() { _deferredColorTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(colorFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); _deferredNormalTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(linearFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); - _deferredSpecularTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(colorFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); + _deferredSpecularTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(linearFormat, width, height, gpu::Texture::SINGLE_MIP, defaultSampler)); _deferredFramebuffer->setRenderBuffer(0, _deferredColorTexture); _deferredFramebuffer->setRenderBuffer(1, _deferredNormalTexture); diff --git a/libraries/render-utils/src/LightAmbient.slh b/libraries/render-utils/src/LightAmbient.slh index b919108115..5f74b46d3e 100644 --- a/libraries/render-utils/src/LightAmbient.slh +++ b/libraries/render-utils/src/LightAmbient.slh @@ -62,7 +62,7 @@ vec3 evalAmbientSpecularIrradiance(LightAmbient ambient, vec3 fragEyeDir, vec3 f <@if supportScattering@> float curvatureAO(in float k) { - return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369; + return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f; } <@endif@> @@ -83,13 +83,12 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambie specular = evalAmbientSpecularIrradiance(ambient, eyeDir, normal, roughness) * ambientFresnel; <@if supportScattering@> - float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f; - float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f; - ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF); - - obscurance = min(obscurance, ambientOcclusion); - if (scattering * isScatteringEnabled() > 0.0) { + float ambientOcclusion = curvatureAO(lowNormalCurvature.w * 20.0f) * 0.5f; + float ambientOcclusionHF = curvatureAO(midNormalCurvature.w * 8.0f) * 0.5f; + ambientOcclusion = min(ambientOcclusion, ambientOcclusionHF); + + obscurance = min(obscurance, ambientOcclusion); // Diffuse from ambient diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lowNormalCurvature.xyz).xyz; diff --git a/libraries/render-utils/src/debug_deferred_buffer.slf b/libraries/render-utils/src/debug_deferred_buffer.slf index c018e5e526..e9750f0054 100644 --- a/libraries/render-utils/src/debug_deferred_buffer.slf +++ b/libraries/render-utils/src/debug_deferred_buffer.slf @@ -16,15 +16,20 @@ <@include gpu/Color.slh@> <$declareColorWheel()$> + uniform sampler2D linearDepthMap; uniform sampler2D halfLinearDepthMap; uniform sampler2D halfNormalMap; uniform sampler2D occlusionMap; uniform sampler2D occlusionBlurredMap; -uniform sampler2D curvatureMap; -uniform sampler2D diffusedCurvatureMap; uniform sampler2D scatteringMap; +<$declareDeferredCurvature()$> + +float curvatureAO(float k) { + return 1.0f - (0.0022f * k * k) + (0.0776f * k) + 0.7369f; +} + in vec2 uv; out vec4 outFragColor; diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index c7ec8e1153..778e0e1905 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -63,7 +63,8 @@ Column { "Directional:LightingModel:enableDirectionalLight", "Point:LightingModel:enablePointLight", "Spot:LightingModel:enableSpotLight", - "Light Contour:LightingModel:showLightContour" + "Light Contour:LightingModel:showLightContour", + "Shadow:RenderShadowTask:enabled" ] CheckBox { text: modelData.split(":")[0] @@ -150,6 +151,7 @@ Column { ListElement { text: "Mid Normal"; color: "White" } ListElement { text: "Low Curvature"; color: "White" } ListElement { text: "Low Normal"; color: "White" } + ListElement { text: "Curvature Occlusion"; color: "White" } ListElement { text: "Debug Scattering"; color: "White" } ListElement { text: "Ambient Occlusion"; color: "White" } ListElement { text: "Ambient Occlusion Blurred"; color: "White" } From 5d341778c5d558949a5c88905645dca2a9526483 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 7 Apr 2017 07:08:19 -0700 Subject: [PATCH 121/128] fix notification word wrapping --- scripts/system/notifications.js | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/scripts/system/notifications.js b/scripts/system/notifications.js index 3989e8e372..25a5edf3a3 100644 --- a/scripts/system/notifications.js +++ b/scripts/system/notifications.js @@ -427,21 +427,24 @@ function deleteNotification(index) { arrays.splice(index, 1); } -// wraps whole word to newline -function stringDivider(str, slotWidth, spaceReplacer) { - var left, right; - if (str.length > slotWidth && slotWidth > 0) { - left = str.substring(0, slotWidth); - right = str.substring(slotWidth); - return left + spaceReplacer + stringDivider(right, slotWidth, spaceReplacer); +// Trims extra whitespace and breaks into lines of length no more than MAX_LENGTH, breaking at spaces. Trims extra whitespace. +var MAX_LENGTH = 42; +function wordWrap(string) { + var finishedLines = [], currentLine = ''; + string.split(/\s/).forEach(function (word) { + var tail = currentLine ? ' ' + word : word; + if ((currentLine.length + tail.length) <= MAX_LENGTH) { + currentLine += tail; + } else { + finishedLines.push(currentLine); + currentLine = word; + } + }); + if (currentLine) { + finishedLines.push(currentLine); } - return str; -} - -// formats string to add newline every 43 chars -function wordWrap(str) { - return stringDivider(str, 43.0, "\n"); + return finishedLines.join('\n'); } function update() { From 03013ecb3aa32080028b3bca42afd0de05750b22 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 7 Apr 2017 07:30:36 -0700 Subject: [PATCH 122/128] fix pal connections-tab help trigger --- interface/resources/qml/hifi/Pal.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 809ff24b62..d8c8149946 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -308,7 +308,6 @@ Rectangle { MouseArea { anchors.fill: parent; hoverEnabled: true; - enabled: activeTab === "connectionsTab"; onClicked: letterbox(hifi.glyphs.question, "Connections and Friends", "Purple borders around profile pictures are Connections.
" + From 3caea886413f63e6835ece7c3f3858d4f05c3f0e Mon Sep 17 00:00:00 2001 From: Faye Li Date: Fri, 7 Apr 2017 10:02:30 -0700 Subject: [PATCH 123/128] use JS method to enable/disable avatar collisions --- script-archive/selfieStick.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/script-archive/selfieStick.js b/script-archive/selfieStick.js index c6fb9c5349..fd3bb82145 100644 --- a/script-archive/selfieStick.js +++ b/script-archive/selfieStick.js @@ -13,7 +13,6 @@ // // Usage instruction: Spacebar toggles camera control - WASD first person free movement or no movement but allowing others to grab the selfie stick // and control your camera. -// For best result, turn off avatar collisions(Developer > Avatar > Uncheck Enable Avatar Collisions) // (function() { // BEGIN LOCAL_SCOPE @@ -25,12 +24,21 @@ var lensEntityID = null; var freeMovementMode = true; + turnOffAvatarCollisions(); changeAvatar(); importModel(); processImportedEntities(); setupSpaceBarControl(); Script.update.connect(update); + function turnOffAvatarCollisions() { + Menu.setIsOptionChecked("Enable avatar collisions", 0); + } + + function turnOnAvatarCollisions() { + Menu.setIsOptionChecked("Enable avatar collisions", 1); + } + function changeAvatar() { originalAvatar = MyAvatar.skeletonModelURL; MyAvatar.skeletonModelURL = AVATAR_URL; @@ -107,6 +115,7 @@ Camera.mode = "first person"; Controller.disableMapping("Handheld-Cam-Space-Bar"); MyAvatar.skeletonModelURL = originalAvatar; + turnOnAvatarCollisions(); } Script.scriptEnding.connect(cleanup); }()); // END LOCAL_SCOPE \ No newline at end of file From 9a563ba02fc76e06ce100c278c444190ebd95aad Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Fri, 7 Apr 2017 19:17:09 +0200 Subject: [PATCH 124/128] Check if offset outside image, set to last image --- interface/resources/qml/hifi/toolbars/StateImage.qml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/toolbars/StateImage.qml b/interface/resources/qml/hifi/toolbars/StateImage.qml index e0389c5e02..ebf1544f2b 100644 --- a/interface/resources/qml/hifi/toolbars/StateImage.qml +++ b/interface/resources/qml/hifi/toolbars/StateImage.qml @@ -12,7 +12,10 @@ Item { property bool pinned: false clip: true - function updateYOffset() { yOffset = size * buttonState; } + function updateYOffset() { + //make sure offset not set outside image + yOffset = (size * buttonState >= image.height) ? image.height - size : size * buttonState + } onButtonStateChanged: updateYOffset(); Component.onCompleted: { From ee9bc0bfa4e6a4a97c05826403e81e2f936375d6 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Fri, 7 Apr 2017 10:25:37 -0700 Subject: [PATCH 125/128] updated availability combo dialog --- interface/resources/qml/hifi/ComboDialog.qml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/ComboDialog.qml b/interface/resources/qml/hifi/ComboDialog.qml index 8905ed9c17..e9d32aa7f8 100644 --- a/interface/resources/qml/hifi/ComboDialog.qml +++ b/interface/resources/qml/hifi/ComboDialog.qml @@ -92,8 +92,7 @@ Item { color: selectedOptionIndex === index ? '#cee6ff' : 'white'; Rectangle { id: comboOptionSelected; - visible: selectedOptionIndex === index ? true : false; - color: hifi.colors.blueAccent; + color: selectedOptionIndex == index ? hifi.colors.blueAccent : 'white'; anchors.left: parent.left; anchors.leftMargin: 20; anchors.top: parent.top; @@ -102,7 +101,7 @@ Item { height: width; radius: width; border.width: 3; - border.color: hifi.colors.blueHighlight; + border.color: selectedOptionIndex === index ? hifi.colors.blueHighlight: hifi.colors.lightGrayText; } From 870e00331178e253b1863a824473b529764c4090 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Fri, 7 Apr 2017 11:12:54 -0700 Subject: [PATCH 126/128] Scattered X glyphs around the letterbox and combo dialogs --- interface/resources/qml/hifi/ComboDialog.qml | 24 +++++++++++++++++++ .../resources/qml/hifi/LetterboxMessage.qml | 22 +++++++++++++++++ interface/resources/qml/hifi/Pal.qml | 4 ++-- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/ComboDialog.qml b/interface/resources/qml/hifi/ComboDialog.qml index e9d32aa7f8..e328805d74 100644 --- a/interface/resources/qml/hifi/ComboDialog.qml +++ b/interface/resources/qml/hifi/ComboDialog.qml @@ -12,6 +12,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import "../styles-uit" +import "../controls-uit" Item { property var dialogTitleText : ""; @@ -67,6 +68,29 @@ Item { verticalAlignment: Text.AlignTop; } + HiFiGlyphs { + id: closeGlyphButton; + text: hifi.glyphs.close; + size: 32; + anchors.verticalCenter: dialogTitle.verticalCenter; + anchors.right: parent.right; + anchors.rightMargin: 20; + MouseArea { + anchors.fill: closeGlyphButton; + hoverEnabled: true; + onEntered: { + parent.text = hifi.glyphs.closeInverted; + } + onExited: { + parent.text = hifi.glyphs.close; + } + onClicked: { + combo.visible = false; + } + } + } + + ListModel { id: comboListViewModel; } diff --git a/interface/resources/qml/hifi/LetterboxMessage.qml b/interface/resources/qml/hifi/LetterboxMessage.qml index e50d1de547..754876b2c1 100644 --- a/interface/resources/qml/hifi/LetterboxMessage.qml +++ b/interface/resources/qml/hifi/LetterboxMessage.qml @@ -85,6 +85,28 @@ Item { wrapMode: Text.WordWrap textFormat: Text.StyledText } + HiFiGlyphs { + id: closeGlyphButton + text: hifi.glyphs.close + size: headerTextPixelSize + anchors.top: parent.top + anchors.topMargin: -20 + anchors.right: parent.right + anchors.rightMargin: -25 + MouseArea { + anchors.fill: closeGlyphButton + hoverEnabled: true + onEntered: { + parent.text = hifi.glyphs.closeInverted; + } + onExited: { + parent.text = hifi.glyphs.close; + } + onClicked: { + letterbox.visible = false; + } + } + } } // Popup Text Text { diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 809ff24b62..f97d034db9 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -311,9 +311,9 @@ Rectangle { enabled: activeTab === "connectionsTab"; onClicked: letterbox(hifi.glyphs.question, "Connections and Friends", - "Purple borders around profile pictures are Connections.
" + + "Purple borders around profile pictures represent Connections.
" + "When your availability is set to Everyone, Connections can see your username and location.

" + - "Green borders around profile pictures are Friends.
" + + "Green borders around profile pictures represent Friends.
" + "When your availability is set to Friends, only Friends can see your username and location."); onEntered: connectionsHelpText.color = hifi.colors.blueHighlight; onExited: connectionsHelpText.color = hifi.colors.blueAccent; From 909fda98a48ec9bd6ab57b5fa77f5870e74c66e6 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 7 Apr 2017 21:01:53 +0100 Subject: [PATCH 127/128] git goto button toggle hightlight --- interface/resources/qml/hifi/tablet/TabletAddressDialog.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index 396f03a1c9..e4f6aa3407 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -560,7 +560,7 @@ StackView { addressBarDialog.loadAddress(addressLine.text, fromSuggestions) } - if (root.desktop) { + if (isDesktop) { tablet.gotoHomeScreen(); } else { HMD.closeTablet(); From cde9310f3e1c56ae6afb8b74012acd3f5ba2b7ba Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 7 Apr 2017 21:35:28 +0100 Subject: [PATCH 128/128] goto home button fix --- interface/resources/qml/hifi/tablet/TabletAddressDialog.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index e4f6aa3407..39892f27a4 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -119,6 +119,8 @@ StackView { onClicked: { addressBarDialog.loadHome(); tabletRoot.shown = false; + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet.gotoHomeScreen(); } anchors { left: parent.left