From d93828f2f084d7eed463123d92235ac47a66204c Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 21 Dec 2017 11:50:02 -0700 Subject: [PATCH 01/10] Fix an improve currentAPI.js --- interface/resources/qml/CurrentAPI.qml | 617 ++++++++++++++++++ libraries/script-engine/src/ScriptEngines.h | 5 + .../developer/utilities/tools/currentAPI.js | 201 ++++-- 3 files changed, 785 insertions(+), 38 deletions(-) create mode 100644 interface/resources/qml/CurrentAPI.qml diff --git a/interface/resources/qml/CurrentAPI.qml b/interface/resources/qml/CurrentAPI.qml new file mode 100644 index 0000000000..98eb639e50 --- /dev/null +++ b/interface/resources/qml/CurrentAPI.qml @@ -0,0 +1,617 @@ +// +// ScriptAPI.qml +// +// Created by Luis Cuenca on 12/18/2017 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import "styles-uit" +import "controls-uit" as HifiControls + +Item { + id: root + width: parent.width + height: parent.height + + + property bool keyboardEnabled: false + property bool keyboardRaised: false + property bool punctuationMode: false + + property var maxUpdateValues: 20 + property var maxReloadValues: 200 + property var apiMembers: [] + property var membersWithValues: [] + property var isReloading: false + property var evaluatingIdx: -1 + property Component scrollSlider + property Component keyboard + + Rectangle { + color: "white" + width: parent.width + height: parent.height + } + + FontLoader { id: ralewayRegular; source: pathToFonts + "fonts/Raleway-Regular.ttf"; } + + Timer { + id: updateList + interval: 200 + repeat: false + running: false + onTriggered: { + scrollSlider.y = 0; + list.contentY = 0; + } + } + + Row { + id: topBar + anchors.left: parent.left + anchors.leftMargin: 8 + width: parent.width + height: 50 + HifiControls.GlyphButton { + id: search + enabled: true + glyph: hifi.glyphs.search + color: hifi.colors.text + size: 48 + width: 50 + height: 50 + onClicked: { + addListElements(searchBar.text); + focus = true; + } + } + + HifiControls.GlyphButton { + id: back; + enabled: true; + glyph: hifi.glyphs.backward + color: hifi.colors.text + size: 48 + width: 30 + height: 50 + anchors.margins: 2 + onClicked: { + var text = searchBar.text; + var chain = text.split("."); + if (chain.length > 2) { + var result = chain[0]+"."; + for (var i = 1; i < chain.length-2; i++) { + result += chain[i] + "."; + } + result += chain[chain.length-2]; + searchBar.text = result; + } else { + searchBar.text = (chain.length > 1) ? chain[0] : ""; + } + if (chain.length > 1) { + addListElements(searchBar.text); + } else { + addListElements(); + } + focus = true; + } + } + + TextField { + id: searchBar + focus: true + font.pixelSize: 16 + width: 2*(parent.width-back.width-search.width-reload.width-update.width-evaluate.width-addMember.width-16)/3 + height: parent.height + font.family: ralewayRegular.name + placeholderText: "Search" + onAccepted: { + console.log("Enter Pressed"); + search.clicked(); + } + onActiveFocusChanged: { + if (activeFocus && HMD.mounted) { + keyboard.raised = true; + } else { + keyboard.raised = false; + } + } + + } + + HifiControls.Button { + id: addMember; + enabled: true; + fontSize: 30 + text: "+" + width: 50 + height: 50 + anchors.margins: 2 + onClicked: { + addNewMember(); + updateList.start(); + focus = true; + } + } + + HifiControls.Button { + id: evaluate; + enabled: true; + text: "Eval" + width: 50 + height: 50 + anchors.margins: 2 + onClicked: { + evaluateMember(); + focus = true; + } + } + TextField { + id: valueBar + focus: true + font.pixelSize: 16 + width: (parent.width-back.width-search.width-reload.width-update.width-evaluate.width-addMember.width-16)/3 + height: parent.height + font.family: ralewayRegular.name + placeholderText: "Value" + textColor: "#4466DD" + anchors.margins: 2 + } + + HifiControls.GlyphButton { + id: reload; + enabled: false; + glyph: hifi.glyphs.reload + color: hifi.colors.text + size: 48 + width: 50 + height: 50 + anchors.margins: 2 + onClicked: { + reloadListValues(); + focus = true; + } + } + + HifiControls.GlyphButton { + id: update; + enabled: false; + glyph: hifi.glyphs.playback_play + size: 48 + width: 50 + height: 50 + anchors.margins: 2 + onClicked: { + if (isReloading) { + update.glyph = hifi.glyphs.playback_play + isReloading = false; + stopReload(); + } else { + update.glyph = hifi.glyphs.stop_square + isReloading = true; + startReload(); + } + focus = true; + } + } + } + + ListModel { + id: memberModel + } + + Component { + id: memberDelegate + + Row { + id: memberRow + property var isMainKey: apiType === "class"; + spacing: 10 + Rectangle { + width: isMainKey ? 20 : 40; + height: parent.height + } + + RalewayRegular { + text: apiMember + size: !isMainKey ? 16 : 22 + MouseArea { + width: list.width + height: parent.height + onClicked: { + searchBar.text = apiType=="function()" ? apiMember + "()" : apiMember; + valueBar.text = !apiValue ? "" : apiValue; + list.currentIndex = index; + evaluatingIdx = index; + } + onDoubleClicked: { + if (apiType === "class") { + addListElements(apiMember+"."); + } else { + isolateElement(evaluatingIdx); + } + + } + } + } + + + RalewayRegular { + text: apiType + size: 14 + color: hifi.colors.baseGrayHighlight + } + + RalewayRegular { + text: !apiValue ? "" : apiValue; + size: 16 + color: "#4466DD" + } + } + } + + + Rectangle { + id: membersBackground + anchors { + left: parent.left; right: parent.right; top: topBar.bottom; bottom: parent.bottom; + margins: hifi.dimensions.contentMargin.x + bottomMargin: hifi.dimensions.contentSpacing.y + 40 + } + color: "white" + radius: 4 + + ListView { + id: list + anchors { + top: parent.top + left: parent.left + right: scrollBar.left + bottom: parent.bottom + margins: 4 + } + clip: true + cacheBuffer: 4000 + model: memberModel + delegate: memberDelegate + highlightMoveDuration: 0 + + highlight: Rectangle { + anchors { + left: parent ? parent.left : undefined + right: parent ? parent.right : undefined + leftMargin: hifi.dimensions.borderWidth + rightMargin: hifi.dimensions.borderWidth + } + color: "#BBDDFF" + } + onMovementStarted: { + scrollSlider.manual = true; + } + onMovementEnded: { + if (list.contentHeight > list.height) { + var range = list.contentY/(list.contentHeight-list.height); + range = range > 1 ? 1 : range; + var idx = Math.round((list.count-1)*range); + scrollSlider.positionSlider(idx); + } + scrollSlider.manual = false; + returnToBounds() + } + } + + Rectangle { + id: scrollBar + + property bool scrolling: list.contentHeight > list.height + + anchors { + top: parent.top + right: parent.right + bottom: parent.bottom + topMargin: 4 + bottomMargin: 4 + } + width: scrolling ? 18 : 0 + radius: 4 + color: hifi.colors.baseGrayShadow + + MouseArea { + anchors.fill: parent + + onClicked: { + var index = scrollSlider.y * (list.count - 1) / (scrollBar.height - scrollSlider.height); + index = Math.round(index); + var scrollAmount = Math.round(list.count/10); + index = index + (mouse.y <= scrollSlider.y ? -scrollAmount : scrollAmount); + if (index < 0) { + index = 0; + } + if (index > list.count - 1) { + index = list.count - 1; + } + scrollSlider.positionSlider(index); + } + } + + Rectangle { + id: scrollSlider + + property var manual: false + + function positionSlider(index){ + y = index*(scrollBar.height - scrollSlider.height)/(list.count - 1); + } + + anchors { + right: parent.right + rightMargin: 3 + } + width: 12 + height: (list.height / list.contentHeight) * list.height + radius: width / 4 + color: "white" + + visible: scrollBar.scrolling; + + onYChanged: { + var index = y * (list.count - 1) / (scrollBar.height - scrollSlider.height); + index = Math.round(index); + if (!manual) { + list.positionViewAtIndex(index, ListView.Visible); + } + } + + MouseArea { + anchors.fill: parent + drag.target: scrollSlider + drag.axis: Drag.YAxis + drag.minimumY: 0 + drag.maximumY: scrollBar.height - scrollSlider.height + } + } + } + + + + } + + HifiControls.GlyphButton { + id: clipboard; + enabled: true; + glyph: hifi.glyphs.scriptNew + size: 38 + width: 50 + height: 50 + anchors.left: parent.left + anchors.bottom: parent.bottom + anchors.margins: 2 + anchors.leftMargin: 8 + onClicked: { + var buffer = ""; + for (var i = 0; i < memberModel.count; i++) { + var datarow = memberModel.get(i); + buffer += "\n" + datarow.apiMember + " " + datarow.apiType + " " + datarow.apiValue; + } + Window.copyToClipboard(buffer); + focus = true; + } + } + + HifiControls.Button { + id: debug; + enabled: true; + text: "Debug Script" + width: 120 + height: 50 + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.margins: 2 + anchors.rightMargin: 8 + onClicked: { + sendToScript({type: "selectScript"}); + } + } + + HifiControls.Keyboard { + id: keyboard; + raised: false; + anchors { + bottom: parent.bottom; + left: parent.left; + right: parent.right; + } + // "\ue02b" + Keys.onPressed: { + console.log(event.nativeScanCode); + if (event.key == Qt.Key_Left) { + keyboard.raised = false; + } + } + } + + + + function addNewMember() { + apiMembers.push({member: searchBar.text, type: "user", value: valueBar.text, hasValue: true}); + var data = {'memberIndex': apiMembers.length-1, 'apiMember': searchBar.text, 'apiType':"user", 'apiValue': valueBar.text}; + memberModel.insert(0, data); + computeMembersWithValues(); + } + + function evaluateMember() { + sendToScript({type: "evaluateMember", data:{member: searchBar.text, index: evaluatingIdx}}); + } + + function getValuesToRefresh() { + var valuesToRefresh = []; + for (var i = 0; i < membersWithValues.length; i++) { + var index = membersWithValues[i]; + var row = memberModel.get(index); + valuesToRefresh.push({index: index, member: (row.apiType == "function()") ? row.apiMember+"()" : row.apiMember, value: row.apiValue}); + } + return valuesToRefresh; + } + + + function reloadListValues(){ + var valuesToRefresh = getValuesToRefresh(); + sendToScript({type: "refreshValues", data:valuesToRefresh}); + } + + function startReload(){ + var valuesToRefresh = getValuesToRefresh(); + sendToScript({type: "startRefreshValues", data:valuesToRefresh}); + } + + function stopReload(){ + sendToScript({type: "stopRefreshValues"}); + } + + function refreshValues(data) { + var buffer = ""; + for (var i = 0; i < data.length; i++) { + var row = memberModel.get(data[i].index); + row.apiValue = data[i].value; + apiMembers[row.memberIndex].value = data[i].value; + memberModel.set(data[i].index, row); + buffer += "\n" + apiMembers[row.memberIndex].member + " : " + data[i].value; + } + print(buffer); + } + + + function fromScript(message) { + if (message.type === "methods") { + apiMembers = message.data; + if (ScriptDiscoveryService.debugScriptUrl != "") { + addListElements("GlobalDebugger"); + if (memberModel.count == 0) { + addListElements(); + } + } else { + addListElements(); + } + + } else if (message.type === "debugMethods") { + addListElements("GlobalDebugger"); + } else if (message.type === "refreshValues") { + refreshValues(message.data); + } else if (message.type === "evaluateMember") { + valueBar.text = message.data.value; + var selrow = memberModel.get(message.data.index); + if (selrow.apiMember === searchBar.text || selrow.apiMember === searchBar.text + "()") { + selrow.apiValue = message.data.value; + apiMembers[selrow.memberIndex].value = message.data.value; + apiMembers[selrow.memberIndex].hasValue = true; + memberModel.set(message.data.index, selrow); + } + } else if (message.type === "selectScript") { + if (message.data.length > 0) { + ScriptDiscoveryService.debugScriptUrl = message.data; + } + } + } + + + function getFilterPairs(filter){ + var filteredArray = []; + var filterChain; + filterChain = filter.split(" "); + for (var i = 0; i < filterChain.length; i++) { + filterChain[i] = filterChain[i].toUpperCase(); + } + var matchPairs = []; + + for (var i = 0; i < apiMembers.length; i++) { + if (filterChain != undefined) { + var found = 0; + var memberComp = apiMembers[i].member.toUpperCase(); + for (var j = 0; j < filterChain.length; j++) { + found += memberComp.indexOf(filterChain[j]) >= 0 ? 1 : 0; + } + if (found === 0) { + continue; + } + matchPairs.push({index: i, found: found, member: apiMembers[i].member}); + } + } + + matchPairs.sort(function(a, b){ + if(a.found > b.found) return -1; + if(a.found < b.found) return 1; + if(a.member > b.member) return 1; + if(a.member < b.member) return -1; + return 0; + }); + + return matchPairs; + } + + function isolateElement(index) { + var oldElement = memberModel.get(index); + var newElement = {memberIndex: oldElement.memberIndex, apiMember: oldElement.apiMember, apiType: oldElement.apiType, apiValue: oldElement.apiValue}; + membersWithValues = apiMembers[oldElement.memberIndex].hasValue ? [0] : []; + memberModel.remove(0, memberModel.count); + memberModel.append(newElement); + } + + function computeMembersWithValues() { + membersWithValues = []; + for (var i = 0; i < memberModel.count; i++) { + var idx = memberModel.get(i).memberIndex; + if (apiMembers[idx].hasValue) { + membersWithValues.push(i); + } + } + update.enabled = membersWithValues.length <= maxUpdateValues; + reload.enabled = membersWithValues.length <= maxReloadValues; + } + + function addListElements(filter) { + valueBar.text = ""; + memberModel.remove(0, memberModel.count); + + var filteredArray = (filter != undefined) ? [] : apiMembers; + var matchPairs; + if (filter != undefined) { + matchPairs = getFilterPairs(filter); + for (var i = 0; i < matchPairs.length; i++) { + if (matchPairs[i].found < matchPairs[0].found) { + break; + } + var idx = matchPairs[i].index; + filteredArray.push(apiMembers[idx]); + } + } + + for (var i = 0; i < filteredArray.length; i++) { + var data = {'memberIndex': matchPairs ? matchPairs[i].index : i, + 'apiMember': filteredArray[i].member, + 'apiType': filteredArray[i].type, + 'apiValue': filteredArray[i].value}; + + memberModel.append(data); + } + + computeMembersWithValues(); + + if (isReloading) { + update.glyph = hifi.glyphs.playback_play + isReloading = false; + stopReload(); + } + + if (memberModel.count > 0) { + scrollSlider.y = 0; + list.contentY = 0; + } + } + + signal sendToScript(var message); +} \ No newline at end of file diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index f2b0105be1..0f807b08cf 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -31,6 +31,7 @@ class ScriptEngines : public QObject, public Dependency { Q_PROPERTY(ScriptsModel* scriptsModel READ scriptsModel CONSTANT) Q_PROPERTY(ScriptsModelFilter* scriptsModelFilter READ scriptsModelFilter CONSTANT) + Q_PROPERTY(QString debugScriptUrl READ getDebugScriptUrl WRITE setDebugScriptUrl) public: using ScriptInitializer = std::function; @@ -41,6 +42,9 @@ public: void loadScripts(); void saveScripts(); + QString getDebugScriptUrl() { return _debugScriptUrl; }; + void setDebugScriptUrl(const QString& url) { _debugScriptUrl = url; }; + QString getScriptsLocation() const; void loadDefaultScripts(); void setScriptsLocation(const QString& scriptsLocation); @@ -117,6 +121,7 @@ protected: std::atomic _isStopped { false }; std::atomic _isReloading { false }; bool _defaultScriptsLocationOverridden { false }; + QString _debugScriptUrl; }; QUrl normalizeScriptURL(const QUrl& rawScriptURL); diff --git a/scripts/developer/utilities/tools/currentAPI.js b/scripts/developer/utilities/tools/currentAPI.js index cb9f152794..f282c2dba9 100644 --- a/scripts/developer/utilities/tools/currentAPI.js +++ b/scripts/developer/utilities/tools/currentAPI.js @@ -1,42 +1,167 @@ -// -// currentAPI.js -// examples -// -// Created by Clément Brisset on 5/30/14. -// Copyright 2014 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 -// +(function(){ + var array = []; + var mainKeys = Object.keys(this); + var qml = Script.resourcesPath() + '/qml/CurrentAPI.qml'; + var needsUpdate = false; + var updateTime = 20; + var updateData = []; + var deltaTime = 0; + var maxUpdatingMethods = 20; + var scriptPath = ""; + + if (ScriptDiscoveryService.debugScriptUrl != "") { + Script.include(ScriptDiscoveryService.debugScriptUrl); + } + + var window = new OverlayWindow({ + title: 'API methods', + source: qml, + width: 1200, + height: 500 + }); -var array = []; -function listKeys(string, object) { - if (string === "listKeys" || string === "array" || string === "buffer" || string === "i") { - return; - } - - if (typeof(object) !== "object" || object === null) { - array.push(string + " " + typeof(object)); - return; - } - - var keys = Object.keys(object); - for (var i = 0; i < keys.length; ++i) { - if (string === "") { - listKeys(keys[i], object[keys[i]]); - } else if (keys[i] !== "parent") { - listKeys(string + "." + keys[i], object[keys[i]]); - } - } -} + window.closed.connect(function () { + Script.stop(); + }); -listKeys("", this); -array.sort(); + function addMainKeys(){ + var keys = Object.keys(this); + for (var i = 0; i < keys.length; i++) { + array.push({member:keys[i] , type: "class"}); + } + } -var buffer = "\n======= JS API list ======="; -for (var i = 0; i < array.length; ++i) { - buffer += "\n" + array[i]; -} -buffer += "\n========= API END =========\n"; + function memberHasValue(member, type) { + if (type === "function()") { + if (member.indexOf(".has") < 0 && member.indexOf(".is") < 0) { + return false; + } + if (member.indexOf("indow") < 0) { + return true; + } + } else if (type === "boolean" || type === "string" || type === "number" || type === "user") { + return true; + } + return false; + } + + function listKeys(string, object) { + if (string === "listKeys" || string === "array" || string === "buffer" || string === "i") { + return; + } + + if (typeof(object) !== "object" || object === null) { + var type = typeof(object); + if (type === "function") { + chain = string.split("("); + if (chain.length > 1) { + string = chain[0]; + type = "function(" + chain[1]; + } + } + var value = ""; + var hasValue = false; + if (memberHasValue(string, type)){ + var evalstring = type === "function()" ? string+"()" : string; + try{ + value = "" + eval(evalstring); + hasValue = true; + } catch(e) { + value = "Error evaluating"; + } + } + array.push({member:string , type: type, value: value, hasValue: hasValue}); + return; + } + + var keys = Object.keys(object); + for (var i = 0; i < keys.length; ++i) { + if (string === "") { + listKeys(keys[i], object[keys[i]]); + } else if (keys[i] !== "parent") { + listKeys(string + "." + keys[i], object[keys[i]]); + } + } + } + + function findMethods(addon, object, addkeys) { + array = []; + var string = addkeys ? "" : addon+"."; + listKeys(string, object); + if (addkeys) { + addMainKeys(); + } + array.sort(function(a, b){ + if(a.member < b.member) return -1; + if(a.member > b.member) return 1; + return 0; + }); + }; + + findMethods("", this, true); + window.sendToQml({type:"methods", data:array}); + + window.fromQml.connect(function(message){ + if (message.type == "refreshValues") { + updateData = message.data; + updateValues(); + } else if (message.type == "startRefreshValues") { + updateData = message.data; + if (updateData.length > maxUpdatingMethods) { + updateData = message.data; + updateValues(); + } else { + needsUpdate = true; + deltaTime = updateTime; + } + } else if (message.type == "stopRefreshValues") { + needsUpdate = false; + deltaTime = 0; + } else if (message.type == "evaluateMember") { + var value = "" + try { + value = "" + eval(message.data.member); + } catch(e) { + value = "Error evaluating" + } + window.sendToQml({type:"evaluateMember", data:{value:value, index:message.data.index}}); + } else if (message.type == "selectScript") { + scriptPath = Window.browse("Select script to debug", "*.js", "JS files(*.js)"); + if (scriptPath) { + ScriptDiscoveryService.stopScript(Paths.defaultScripts + "/developer/utilities/tools/currentAPI.js", true); + } + } + }); + + function updateValues() { + for (var i = 0; i < updateData.length; i++) { + try { + updateData[i].value = "" + eval(updateData[i].member); + } catch(e) { + updateData[i].value = "Error evaluating" + } + } + window.sendToQml({type: "refreshValues", data: updateData}); + } + + Script.update.connect(function(){ + deltaTime++; + if (deltaTime > updateTime) { + deltaTime = 0; + if (needsUpdate) { + updateValues(); + } + } + }); + + Script.scriptEnding.connect(function(){ + if (!scriptPath || scriptPath.length == 0) { + ScriptDiscoveryService.debugScriptUrl = ""; + } else { + ScriptDiscoveryService.debugScriptUrl = scriptPath; + } + console.log("done running"); + window.close(); + }); +}()); -print(buffer); From 54297e00a8038c3f6e9e15d0f53be85918ee9209 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 21 Dec 2017 12:48:21 -0700 Subject: [PATCH 02/10] button size fix --- interface/resources/qml/CurrentAPI.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/resources/qml/CurrentAPI.qml b/interface/resources/qml/CurrentAPI.qml index 98eb639e50..735cbdbab5 100644 --- a/interface/resources/qml/CurrentAPI.qml +++ b/interface/resources/qml/CurrentAPI.qml @@ -127,7 +127,6 @@ Item { HifiControls.Button { id: addMember; enabled: true; - fontSize: 30 text: "+" width: 50 height: 50 From 38bfddf78647d8e0c1ce9af533f5348fe86e4201 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 21 Dec 2017 16:26:06 -0700 Subject: [PATCH 03/10] Added filter for QT autogenerated functions and integrated it to Developers menu --- interface/resources/qml/CurrentAPI.qml | 50 ++- interface/src/Menu.cpp | 8 + .../developer/utilities/tools/currentAPI.js | 324 +++++++++--------- 3 files changed, 215 insertions(+), 167 deletions(-) diff --git a/interface/resources/qml/CurrentAPI.qml b/interface/resources/qml/CurrentAPI.qml index 735cbdbab5..45cf09925a 100644 --- a/interface/resources/qml/CurrentAPI.qml +++ b/interface/resources/qml/CurrentAPI.qml @@ -18,10 +18,7 @@ Item { width: parent.width height: parent.height - - property bool keyboardEnabled: false - property bool keyboardRaised: false - property bool punctuationMode: false + property var hideQtMethods: true property var maxUpdateValues: 20 property var maxReloadValues: 200 @@ -31,7 +28,7 @@ Item { property var evaluatingIdx: -1 property Component scrollSlider property Component keyboard - + Rectangle { color: "white" width: parent.width @@ -375,9 +372,6 @@ Item { } } } - - - } HifiControls.GlyphButton { @@ -417,6 +411,30 @@ Item { } } + HifiControls.CheckBox { + id: hideQt + boxSize: 25 + boxRadius: 3 + checked: true + anchors.left: clipboard.right + anchors.leftMargin: 8 + anchors.verticalCenter: clipboard.verticalCenter + anchors.margins: 2 + onClicked: { + hideQtMethods = checked; + addListElements(); + } + } + + HifiControls.Label { + id: hideLabel + anchors.left: hideQt.right + anchors.verticalCenter: clipboard.verticalCenter + anchors.margins: 2 + font.pixelSize: 15 + text: "Hide Qt Methods" + } + HifiControls.Keyboard { id: keyboard; raised: false; @@ -425,7 +443,7 @@ Item { left: parent.left; right: parent.right; } - // "\ue02b" + Keys.onPressed: { console.log(event.nativeScanCode); if (event.key == Qt.Key_Left) { @@ -433,8 +451,6 @@ Item { } } } - - function addNewMember() { apiMembers.push({member: searchBar.text, type: "user", value: valueBar.text, hasValue: true}); @@ -595,7 +611,17 @@ Item { 'apiType': filteredArray[i].type, 'apiValue': filteredArray[i].value}; - memberModel.append(data); + if (hideQtMethods) { + var chain = data.apiMember.split("."); + var method = chain[chain.length-1]; + if (method != "destroyed" && + method != "objectName" && + method != "objectNameChanged") { + memberModel.append(data); + } + } else { + memberModel.append(data); + } } computeMembersWithValues(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 9bbb72357b..25148f1d23 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -757,6 +757,14 @@ Menu::Menu() { // Developer > Stats addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Stats); + // Developer > API Debugger + action = addActionToQMenuAndActionHash(developerMenu, "API Debugger"); + connect(action, &QAction::triggered, [] { + auto scriptEngines = DependencyManager::get(); + QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation(); + defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/utilities/tools/currentAPI.js"); + scriptEngines->loadScript(defaultScriptsLoc.toString()); + }); #if 0 /// -------------- REMOVED FOR NOW -------------- addDisabledActionAndSeparator(navigateMenu, "History"); diff --git a/scripts/developer/utilities/tools/currentAPI.js b/scripts/developer/utilities/tools/currentAPI.js index f282c2dba9..175b84b8d9 100644 --- a/scripts/developer/utilities/tools/currentAPI.js +++ b/scripts/developer/utilities/tools/currentAPI.js @@ -1,167 +1,181 @@ +// +// currentAPI.js +// examples +// +// Created by Clément Brisset on 5/30/14. +// Copyright 2014 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 +// + + (function(){ - var array = []; - var mainKeys = Object.keys(this); - var qml = Script.resourcesPath() + '/qml/CurrentAPI.qml'; - var needsUpdate = false; - var updateTime = 20; - var updateData = []; - var deltaTime = 0; - var maxUpdatingMethods = 20; - var scriptPath = ""; - - if (ScriptDiscoveryService.debugScriptUrl != "") { - Script.include(ScriptDiscoveryService.debugScriptUrl); - } - - var window = new OverlayWindow({ - title: 'API methods', - source: qml, - width: 1200, - height: 500 - }); + var array = []; + var mainKeys = Object.keys(this); + var qml = Script.resourcesPath() + '/qml/CurrentAPI.qml'; + var needsUpdate = false; + var updateTime = 20; + var updateData = []; + var deltaTime = 0; + var maxUpdatingMethods = 20; + var scriptPath = ""; + + if (ScriptDiscoveryService.debugScriptUrl != "") { + Script.include(ScriptDiscoveryService.debugScriptUrl); + } + + var window = new OverlayWindow({ + title: 'API Debugger', + source: qml, + width: 1200, + height: 500 + }); - window.closed.connect(function () { - Script.stop(); - }); + window.closed.connect(function () { + Script.stop(); + }); - function addMainKeys(){ - var keys = Object.keys(this); - for (var i = 0; i < keys.length; i++) { - array.push({member:keys[i] , type: "class"}); - } - } + function addMainKeys(){ + var keys = Object.keys(this); + for (var i = 0; i < keys.length; i++) { + array.push({member:keys[i] , type: "class"}); + } + } - function memberHasValue(member, type) { - if (type === "function()") { - if (member.indexOf(".has") < 0 && member.indexOf(".is") < 0) { - return false; - } - if (member.indexOf("indow") < 0) { - return true; - } - } else if (type === "boolean" || type === "string" || type === "number" || type === "user") { - return true; - } - return false; - } + function memberHasValue(member, type) { + if (type === "function()") { + if (member.indexOf(".has") < 0 && member.indexOf(".is") < 0 && member.indexOf(".get") < 0) { + return false; + } + if (member.indexOf("indow") < 0) { + return true; + } + } else if (type === "boolean" || type === "string" || type === "number" || type === "user") { + return true; + } + return false; + } - function listKeys(string, object) { - if (string === "listKeys" || string === "array" || string === "buffer" || string === "i") { - return; - } - - if (typeof(object) !== "object" || object === null) { - var type = typeof(object); - if (type === "function") { - chain = string.split("("); - if (chain.length > 1) { - string = chain[0]; - type = "function(" + chain[1]; - } - } - var value = ""; - var hasValue = false; - if (memberHasValue(string, type)){ - var evalstring = type === "function()" ? string+"()" : string; - try{ - value = "" + eval(evalstring); - hasValue = true; - } catch(e) { - value = "Error evaluating"; - } - } - array.push({member:string , type: type, value: value, hasValue: hasValue}); - return; - } - - var keys = Object.keys(object); - for (var i = 0; i < keys.length; ++i) { - if (string === "") { - listKeys(keys[i], object[keys[i]]); - } else if (keys[i] !== "parent") { - listKeys(string + "." + keys[i], object[keys[i]]); - } - } - } + function listKeys(string, object) { + if (string === "listKeys" || string === "array" || string === "buffer" || string === "i") { + return; + } + + if (typeof(object) !== "object" || object === null) { + var type = typeof(object); + if (type === "function") { + chain = string.split("("); + if (chain.length > 1) { + string = chain[0]; + type = "function(" + chain[1]; + } else { + type = "function()"; + } + } + var value = ""; + var hasValue = false; + if (memberHasValue(string, type)){ + var evalstring = type === "function()" ? string+"()" : string; + try{ + value = "" + eval(evalstring); + hasValue = true; + } catch(e) { + value = "Error evaluating"; + } + } + array.push({member:string , type: type, value: value, hasValue: hasValue}); + return; + } + + var keys = Object.keys(object); + for (var i = 0; i < keys.length; ++i) { + if (string === "") { + listKeys(keys[i], object[keys[i]]); + } else if (keys[i] !== "parent") { + listKeys(string + "." + keys[i], object[keys[i]]); + } + } + } - function findMethods(addon, object, addkeys) { - array = []; - var string = addkeys ? "" : addon+"."; - listKeys(string, object); - if (addkeys) { - addMainKeys(); - } - array.sort(function(a, b){ - if(a.member < b.member) return -1; - if(a.member > b.member) return 1; - return 0; - }); - }; + function findMethods(addon, object, addkeys) { + array = []; + var string = addkeys ? "" : addon+"."; + listKeys(string, object); + if (addkeys) { + addMainKeys(); + } + array.sort(function(a, b){ + if(a.member < b.member) return -1; + if(a.member > b.member) return 1; + return 0; + }); + }; - findMethods("", this, true); - window.sendToQml({type:"methods", data:array}); + findMethods("", this, true); + window.sendToQml({type:"methods", data:array}); - window.fromQml.connect(function(message){ - if (message.type == "refreshValues") { - updateData = message.data; - updateValues(); - } else if (message.type == "startRefreshValues") { - updateData = message.data; - if (updateData.length > maxUpdatingMethods) { - updateData = message.data; - updateValues(); - } else { - needsUpdate = true; - deltaTime = updateTime; - } - } else if (message.type == "stopRefreshValues") { - needsUpdate = false; - deltaTime = 0; - } else if (message.type == "evaluateMember") { - var value = "" - try { - value = "" + eval(message.data.member); - } catch(e) { - value = "Error evaluating" - } - window.sendToQml({type:"evaluateMember", data:{value:value, index:message.data.index}}); - } else if (message.type == "selectScript") { - scriptPath = Window.browse("Select script to debug", "*.js", "JS files(*.js)"); - if (scriptPath) { - ScriptDiscoveryService.stopScript(Paths.defaultScripts + "/developer/utilities/tools/currentAPI.js", true); - } - } - }); + window.fromQml.connect(function(message){ + if (message.type == "refreshValues") { + updateData = message.data; + updateValues(); + } else if (message.type == "startRefreshValues") { + updateData = message.data; + if (updateData.length > maxUpdatingMethods) { + updateData = message.data; + updateValues(); + } else { + needsUpdate = true; + deltaTime = updateTime; + } + } else if (message.type == "stopRefreshValues") { + needsUpdate = false; + deltaTime = 0; + } else if (message.type == "evaluateMember") { + var value = "" + try { + value = "" + eval(message.data.member); + } catch(e) { + value = "Error evaluating" + } + window.sendToQml({type:"evaluateMember", data:{value:value, index:message.data.index}}); + } else if (message.type == "selectScript") { + scriptPath = Window.browse("Select script to debug", "*.js", "JS files(*.js)"); + if (scriptPath) { + ScriptDiscoveryService.stopScript(Paths.defaultScripts + "/developer/utilities/tools/currentAPI.js", true); + } + } + }); - function updateValues() { - for (var i = 0; i < updateData.length; i++) { - try { - updateData[i].value = "" + eval(updateData[i].member); - } catch(e) { - updateData[i].value = "Error evaluating" - } - } - window.sendToQml({type: "refreshValues", data: updateData}); - } + function updateValues() { + for (var i = 0; i < updateData.length; i++) { + try { + updateData[i].value = "" + eval(updateData[i].member); + } catch(e) { + updateData[i].value = "Error evaluating" + } + } + window.sendToQml({type: "refreshValues", data: updateData}); + } - Script.update.connect(function(){ - deltaTime++; - if (deltaTime > updateTime) { - deltaTime = 0; - if (needsUpdate) { - updateValues(); - } - } - }); - - Script.scriptEnding.connect(function(){ - if (!scriptPath || scriptPath.length == 0) { - ScriptDiscoveryService.debugScriptUrl = ""; - } else { - ScriptDiscoveryService.debugScriptUrl = scriptPath; - } - console.log("done running"); - window.close(); - }); + Script.update.connect(function(){ + deltaTime++; + if (deltaTime > updateTime) { + deltaTime = 0; + if (needsUpdate) { + updateValues(); + } + } + }); + + Script.scriptEnding.connect(function(){ + if (!scriptPath || scriptPath.length == 0) { + ScriptDiscoveryService.debugScriptUrl = ""; + } else { + ScriptDiscoveryService.debugScriptUrl = scriptPath; + } + console.log("done running"); + window.close(); + }); }()); From 61edd83987dbe2c5629f82b4387439d2f33af42d Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 12 Dec 2017 17:02:07 -0800 Subject: [PATCH 04/10] Improve stability for HMD third person avatars Previously there was a hack where the sensor to world matrix was NOT updated in HMD mode if the camera was third person. The reason the hack existed was to make third person camera less nauseating for users. However this had a major drawbacks. It led to avatar hip spasms when the user turned around in the tracked volume, while in third person camera. To fix this issue properly, the hack which prevented updating the sensor to world matrix was removed, and now the third person camera is now computed in sensor space relative to the hmd. --- interface/src/Application.cpp | 30 ++++++++++++++++++------ interface/src/Application.h | 5 +++- interface/src/avatar/MyAvatar.cpp | 11 +++------ interface/src/avatar/MySkeletonModel.cpp | 1 - 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f3c41565f8..2d5ec4c62c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2441,7 +2441,7 @@ void Application::initializeUi() { offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2); } -void Application::updateCamera(RenderArgs& renderArgs) { +void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) { PROFILE_RANGE(render, __FUNCTION__); PerformanceTimer perfTimer("updateCamera"); @@ -2456,6 +2456,7 @@ void Application::updateCamera(RenderArgs& renderArgs) { // Using the latter will cause the camera to wobble with idle animations, // or with changes from the face tracker if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { + _thirdPersonHMDCameraBoomValid= false; if (isHMDMode()) { mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); _myCamera.setPosition(extractTranslation(camMat)); @@ -2468,12 +2469,25 @@ void Application::updateCamera(RenderArgs& renderArgs) { } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { if (isHMDMode()) { - auto hmdWorldMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); - _myCamera.setOrientation(glm::normalize(glmExtractRotation(hmdWorldMat))); - _myCamera.setPosition(extractTranslation(hmdWorldMat) + - myAvatar->getWorldOrientation() * boomOffset); + + if (!_thirdPersonHMDCameraBoomValid) { + const glm::vec3 CAMERA_OFFSET = glm::vec3(0.0f, 0.0f, 0.7f); + _thirdPersonHMDCameraBoom = cancelOutRollAndPitch(myAvatar->getHMDSensorOrientation()) * CAMERA_OFFSET; + _thirdPersonHMDCameraBoomValid = true; + } + + glm::mat4 thirdPersonCameraSensorToWorldMatrix = myAvatar->getSensorToWorldMatrix(); + + const glm::vec3 cameraPos = myAvatar->getHMDSensorPosition() + _thirdPersonHMDCameraBoom * myAvatar->getBoomLength(); + glm::mat4 sensorCameraMat = createMatFromQuatAndPos(myAvatar->getHMDSensorOrientation(), cameraPos); + glm::mat4 worldCameraMat = thirdPersonCameraSensorToWorldMatrix * sensorCameraMat; + + _myCamera.setOrientation(glm::normalize(glmExtractRotation(worldCameraMat))); + _myCamera.setPosition(extractTranslation(worldCameraMat)); } else { + _thirdPersonHMDCameraBoomValid = false; + _myCamera.setOrientation(myAvatar->getHead()->getOrientation()); if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) { _myCamera.setPosition(myAvatar->getDefaultEyePosition() @@ -2486,6 +2500,7 @@ void Application::updateCamera(RenderArgs& renderArgs) { } } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { + _thirdPersonHMDCameraBoomValid= false; if (isHMDMode()) { auto mirrorBodyOrientation = myAvatar->getWorldOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)); @@ -2520,6 +2535,7 @@ void Application::updateCamera(RenderArgs& renderArgs) { renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; } else if (_myCamera.getMode() == CAMERA_MODE_ENTITY) { + _thirdPersonHMDCameraBoomValid= false; EntityItemPointer cameraEntity = _myCamera.getCameraEntityPointer(); if (cameraEntity != nullptr) { if (isHMDMode()) { @@ -5094,7 +5110,7 @@ void Application::update(float deltaTime) { _postUpdateLambdas.clear(); } - editRenderArgs([this](AppRenderArgs& appRenderArgs) { + editRenderArgs([this, deltaTime](AppRenderArgs& appRenderArgs) { appRenderArgs._headPose= getHMDSensorPose(); auto myAvatar = getMyAvatar(); @@ -5140,7 +5156,7 @@ void Application::update(float deltaTime) { resizeGL(); } - this->updateCamera(appRenderArgs._renderArgs); + this->updateCamera(appRenderArgs._renderArgs, deltaTime); appRenderArgs._eyeToWorld = _myCamera.getTransform(); appRenderArgs._isStereo = false; diff --git a/interface/src/Application.h b/interface/src/Application.h index 479ce919a3..b01e998a21 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -146,7 +146,7 @@ public: void initializeGL(); void initializeUi(); - void updateCamera(RenderArgs& renderArgs); + void updateCamera(RenderArgs& renderArgs, float deltaTime); void paintGL(); void resizeGL(); @@ -695,6 +695,9 @@ private: void startHMDStandBySession(); void endHMDSession(); + glm::vec3 _thirdPersonHMDCameraBoom { 0.0f, 0.0f, -1.0f }; + bool _thirdPersonHMDCameraBoomValid { true }; + QUrl _avatarOverrideUrl; bool _saveAvatarOverrideUrl { false }; QObject* _renderEventHandler{ nullptr }; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 68e417ba1d..e863a58e14 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2799,14 +2799,9 @@ void MyAvatar::FollowHelper::decrementTimeRemaining(float dt) { } bool MyAvatar::FollowHelper::shouldActivateRotation(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const { - auto cameraMode = qApp->getCamera().getMode(); - if (cameraMode == CAMERA_MODE_THIRD_PERSON) { - return false; - } else { - const float FOLLOW_ROTATION_THRESHOLD = cosf(PI / 6.0f); // 30 degrees - glm::vec2 bodyFacing = getFacingDir2D(currentBodyMatrix); - return glm::dot(-myAvatar.getHeadControllerFacingMovingAverage(), bodyFacing) < FOLLOW_ROTATION_THRESHOLD; - } + const float FOLLOW_ROTATION_THRESHOLD = cosf(PI / 6.0f); // 30 degrees + glm::vec2 bodyFacing = getFacingDir2D(currentBodyMatrix); + return glm::dot(-myAvatar.getHeadControllerFacingMovingAverage(), bodyFacing) < FOLLOW_ROTATION_THRESHOLD; } bool MyAvatar::FollowHelper::shouldActivateHorizontal(const MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, const glm::mat4& currentBodyMatrix) const { diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 50e0474831..17bce655fd 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -34,7 +34,6 @@ Rig::CharacterControllerState convertCharacterControllerState(CharacterControlle } static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) { - glm::mat4 worldToSensorMat = glm::inverse(myAvatar->getSensorToWorldMatrix()); // check for pinned hips. From a42b0cf485183186c0c1571e8d26c1e23e583633 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 9 Jan 2018 14:58:23 -0800 Subject: [PATCH 05/10] comment out logging --- interface/resources/qml/hifi/tablet/TabletAddressDialog.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index 217adc5083..f3cda533e9 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -62,7 +62,8 @@ StackView { var callback = rpcCalls[message.id]; if (!callback) { - console.log('No callback for message fromScript', JSON.stringify(message)); + // FIXME: We often recieve very long messages here, the logging of which is drastically slowing down the main thread + //console.log('No callback for message fromScript', JSON.stringify(message)); return; } delete rpcCalls[message.id]; From c46531296f71644fc63b988513c80be1aa677a2b Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 9 Jan 2018 18:28:54 -0800 Subject: [PATCH 06/10] move key logic from onClicked to onReleased --- interface/resources/qml/controls-uit/Key.qml | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/controls-uit/Key.qml b/interface/resources/qml/controls-uit/Key.qml index b2c720368d..dd77fc92dc 100644 --- a/interface/resources/qml/controls-uit/Key.qml +++ b/interface/resources/qml/controls-uit/Key.qml @@ -45,18 +45,6 @@ Item { } } - onClicked: { - mouse.accepted = true; - Tablet.playSound(TabletEnums.ButtonClick); - - webEntity.synthesizeKeyPress(glyph); - webEntity.synthesizeKeyPress(glyph, mirrorText); - - if (toggle) { - toggled = !toggled; - } - } - onDoubleClicked: { mouse.accepted = true; } @@ -94,6 +82,14 @@ Item { onReleased: { if (containsMouse) { + Tablet.playSound(TabletEnums.ButtonClick); + + webEntity.synthesizeKeyPress(glyph); + webEntity.synthesizeKeyPress(glyph, mirrorText); + + if (toggle) { + toggled = !toggled; + } keyItem.state = "mouseOver"; } else { if (toggled) { From df574c6bc94e5438a064c6420e9a108be011a12a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 10 Jan 2018 13:19:53 -0800 Subject: [PATCH 07/10] keep requesting render update until textures load --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 676f3a1ccd..86237e75a4 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1095,7 +1095,7 @@ bool ModelEntityRenderer::needsRenderUpdate() const { return true; } - if (!_texturesLoaded && model->getGeometry() && model->getGeometry()->areTexturesLoaded()) { + if (!_texturesLoaded) { return true; } @@ -1328,6 +1328,8 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce if (!_texturesLoaded && model->getGeometry() && model->getGeometry()->areTexturesLoaded()) { _texturesLoaded = true; model->updateRenderItems(); + } else if (!_texturesLoaded) { + emit requestRenderUpdate(); } // When the individual mesh parts of a model finish fading, they will mark their Model as needing updating From 1deb75daf7fbc7684c3209d2ac6d878a89472ca8 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 10 Jan 2018 16:03:53 -0800 Subject: [PATCH 08/10] Fix for black screen when clicking Settings from Snap app (cherry picked from commit d5e3b97c934bdd1435d60373e0f7aa60659e12c6) --- interface/resources/qml/hifi/tablet/TabletRoot.qml | 2 +- scripts/system/snapshot.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletRoot.qml b/interface/resources/qml/hifi/tablet/TabletRoot.qml index da544c2114..e7614e11b7 100644 --- a/interface/resources/qml/hifi/tablet/TabletRoot.qml +++ b/interface/resources/qml/hifi/tablet/TabletRoot.qml @@ -106,7 +106,7 @@ Item { if (isWebPage) { var webUrl = tabletApps.get(currentApp).appWebUrl; var scriptUrl = tabletApps.get(currentApp).scriptUrl; - loadSource("TabletWebView.qml"); + loadSource("hifi/tablet/TabletWebView.qml"); loadWebUrl(webUrl, scriptUrl); } else { loader.load(tabletApps.get(currentApp).appUrl); diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 9afdb4ec53..dad642075f 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -121,7 +121,7 @@ function onMessage(message) { || (!HMD.active && Settings.getValue("desktopTabletBecomesToolbar", true))) { Desktop.show("hifi/dialogs/GeneralPreferencesDialog.qml", "GeneralPreferencesDialog"); } else { - tablet.loadQMLOnTop("TabletGeneralPreferences.qml"); + tablet.loadQMLOnTop("hifi/tablet/TabletGeneralPreferences.qml"); } break; case 'captureStillAndGif': From e9d751fd23f85b980aa47faf702b89292c01e20d Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 10 Jan 2018 17:01:01 -0800 Subject: [PATCH 09/10] try to avoid reusing uniform buffer locations --- .../src/RenderableParticleEffectEntityItem.cpp | 7 ++++++- .../src/RenderablePolyLineEntityItem.cpp | 5 +++-- libraries/render-utils/src/LightClusters.cpp | 13 ++++++------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index bc96e45881..a3e6cd4341 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -23,6 +23,8 @@ using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER = 0; static gpu::Stream::FormatPointer _vertexFormat; static std::weak_ptr _texturedPipeline; +// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 11 to avoid collisions +static int32_t PARTICLE_UNIFORM_SLOT { 11 }; static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key) { auto texturedPipeline = _texturedPipeline.lock(); @@ -38,6 +40,9 @@ static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, co auto fragShader = gpu::Shader::createPixel(std::string(textured_particle_frag)); auto program = gpu::Shader::createProgram(vertShader, fragShader); + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("particleBuffer"), PARTICLE_UNIFORM_SLOT)); + gpu::Shader::makeProgram(*program, slotBindings); _texturedPipeline = texturedPipeline = gpu::Pipeline::create(program, state); } @@ -320,7 +325,7 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) { transform.setScale(vec3(1)); } batch.setModelTransform(transform); - batch.setUniformBuffer(0, _uniformBuffer); + batch.setUniformBuffer(PARTICLE_UNIFORM_SLOT, _uniformBuffer); batch.setInputFormat(_vertexFormat); batch.setInputBuffer(0, _particleBuffer, 0, sizeof(GpuParticle)); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 21764dff7f..b362721cde 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -33,8 +33,9 @@ using namespace render; using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER { 0 }; -static const int32_t PAINTSTROKE_TEXTURE_SLOT{ 0 }; -static const int32_t PAINTSTROKE_UNIFORM_SLOT{ 0 }; +static const int32_t PAINTSTROKE_TEXTURE_SLOT { 0 }; +// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 11 to avoid collisions +static const int32_t PAINTSTROKE_UNIFORM_SLOT { 11 }; static gpu::Stream::FormatPointer polylineFormat; static gpu::PipelinePointer polylinePipeline; #ifdef POLYLINE_ENTITY_USE_FADE_EFFECT diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index eedb9053c7..d6ac7fd2e2 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -37,14 +37,13 @@ enum LightClusterGridShader_MapSlot { }; enum LightClusterGridShader_BufferSlot { - LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT = 0, - DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT =1, - CAMERA_CORRECTION_BUFFER_SLOT = 2, + DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT = 0, + CAMERA_CORRECTION_BUFFER_SLOT = 1, LIGHT_GPU_SLOT = render::ShapePipeline::Slot::LIGHT, - LIGHT_INDEX_GPU_SLOT = 5, - - LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT = 6, - LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT = 7, + LIGHT_INDEX_GPU_SLOT = 7, + LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT = 8, + LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT = 9, + LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT = 10, }; FrustumGrid::FrustumGrid(const FrustumGrid& source) : From cff80e86b6573a727f8e9417d9c8cf3f8e2a9fe1 Mon Sep 17 00:00:00 2001 From: vladest Date: Thu, 11 Jan 2018 22:18:22 +0100 Subject: [PATCH 10/10] Temporarily disable magnification until further notice --- interface/resources/qml/hifi/tablet/TabletHome.qml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletHome.qml b/interface/resources/qml/hifi/tablet/TabletHome.qml index 21d025fd30..524bbf5f4d 100644 --- a/interface/resources/qml/hifi/tablet/TabletHome.qml +++ b/interface/resources/qml/hifi/tablet/TabletHome.qml @@ -188,8 +188,10 @@ Item { TabletButton { id: tabletButton - scale: wrapper.hovered ? 1.25 : wrapper.containsMouse ? 0.75 : 1.0 - Behavior on scale { NumberAnimation { duration: 200; easing.type: Easing.Linear } } + + // Temporarily disable magnification + // scale: wrapper.hovered ? 1.25 : wrapper.containsMouse ? 0.75 : 1.0 + // Behavior on scale { NumberAnimation { duration: 200; easing.type: Easing.Linear } } anchors.centerIn: parent gridView: wrapper.GridView.view