From 18db5f1724b180d7a518007f6144a7931fbdeab0 Mon Sep 17 00:00:00 2001 From: Faye Li Date: Wed, 15 Feb 2017 14:19:03 -0800 Subject: [PATCH 01/35] 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 02/35] 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 03/35] 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 05/35] 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 06/35] 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 07/35] 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 08/35] 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 09/35] 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 10/35] 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 13/35] 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 14/35] 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 15/35] 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 98221936448cdcf757576acbb257049eca826331 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Wed, 29 Mar 2017 14:41:18 +0200 Subject: [PATCH 16/35] 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 53c439ffba3e4cc105d011b42ed207a4b6fb68c3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 30 Mar 2017 19:11:16 -0700 Subject: [PATCH 17/35] 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 18/35] 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 19/35] 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 20/35] 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 21/35] 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 3090629f77fc43b18e1702356db5a1cdcabbb8c1 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 3 Apr 2017 18:51:39 +0100 Subject: [PATCH 22/35] 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 23/35] 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 24/35] 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 25/35] 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 26/35] 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 27/35] 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 6ed4295b8bb9d102af401ef4c07c0652bad7c9a0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 3 Apr 2017 13:55:11 -0700 Subject: [PATCH 28/35] 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 29/35] 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 55c2d367527ab76bd3cdbefbdbd9a161d9233b87 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 3 Apr 2017 15:30:06 -0700 Subject: [PATCH 30/35] 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 31/35] 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 8ff457a1b62e8a63e651516d5f30cda105cb0087 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 3 Apr 2017 16:03:55 -0700 Subject: [PATCH 32/35] 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 4d6886d1f489772c4640872e5a8115520156d2f8 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Mon, 3 Apr 2017 17:03:14 -0700 Subject: [PATCH 33/35] 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 08ac25473fa27ab4927a16f26c99727213fc75a0 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Tue, 4 Apr 2017 09:53:09 -0700 Subject: [PATCH 34/35] 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 6f79b2eaeb9c559abefe7b33560a36a0e6cf4bbd Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 4 Apr 2017 12:05:43 -0700 Subject: [PATCH 35/35] 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);