diff --git a/interface/resources/qml/TabletBrowser.qml b/interface/resources/qml/TabletBrowser.qml
index 85fff59207..2650102b27 100644
--- a/interface/resources/qml/TabletBrowser.qml
+++ b/interface/resources/qml/TabletBrowser.qml
@@ -1,5 +1,5 @@
import QtQuick 2.5
-import QtQuick.Controls 1.2
+import QtQuick.Controls 1.4
import QtWebChannel 1.0
import QtWebEngine 1.2
@@ -7,7 +7,7 @@ import "controls"
import "styles" as HifiStyles
import "styles-uit"
import "windows"
-import HFWebEngineProfile 1.0
+import HFTabletWebEngineProfile 1.0
Item {
id: root
@@ -27,138 +27,103 @@ Item {
x: 0
y: 0
-
- function goBack() {
- webview.goBack();
- }
-
- function goForward() {
- webview.goForward();
- }
-
- function gotoPage(url) {
- webview.url = url;
- }
function setProfile(profile) {
webview.profile = profile;
}
- function reloadPage() {
- webview.reloadAndBypassCache();
- webview.setActiveFocusOnPress(true);
- webview.setEnabled(true);
+ QtObject {
+ id: eventBridgeWrapper
+ WebChannel.id: "eventBridgeWrapper"
+ property var eventBridge;
}
- Item {
- id:item
+ WebEngineView {
+ id: webview
+ objectName: "webEngineView"
+ x: 0
+ y: 0
width: parent.width
- implicitHeight: parent.height
+ height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height
-
- QtObject {
- id: eventBridgeWrapper
- WebChannel.id: "eventBridgeWrapper"
- property var eventBridge;
+ profile: HFTabletWebEngineProfile {
+ id: webviewTabletProfile
+ storageName: "qmlTabletWebEngine"
}
- WebEngineView {
- id: webview
- objectName: "webEngineView"
- x: 0
- y: 0
- width: parent.width
- height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height
-
- profile: HFWebEngineProfile {
- id: webviewProfile
- storageName: "qmlWebEngine"
- }
+ property string userScriptUrl: ""
- property string userScriptUrl: ""
-
- // creates a global EventBridge object.
- WebEngineScript {
- id: createGlobalEventBridge
- sourceCode: eventBridgeJavaScriptToInject
- injectionPoint: WebEngineScript.DocumentCreation
- worldId: WebEngineScript.MainWorld
- }
-
- // detects when to raise and lower virtual keyboard
- WebEngineScript {
- id: raiseAndLowerKeyboard
- injectionPoint: WebEngineScript.Deferred
- sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js"
- worldId: WebEngineScript.MainWorld
- }
-
- // User script.
- WebEngineScript {
- id: userScript
- sourceUrl: webview.userScriptUrl
- injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished.
- worldId: WebEngineScript.MainWorld
- }
+ // creates a global EventBridge object.
+ WebEngineScript {
+ id: createGlobalEventBridge
+ sourceCode: eventBridgeJavaScriptToInject
+ injectionPoint: WebEngineScript.DocumentCreation
+ worldId: WebEngineScript.MainWorld
+ }
- userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
-
- property string newUrl: ""
-
- webChannel.registeredObjects: [eventBridgeWrapper]
+ // detects when to raise and lower virtual keyboard
+ WebEngineScript {
+ id: raiseAndLowerKeyboard
+ injectionPoint: WebEngineScript.Deferred
+ sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js"
+ worldId: WebEngineScript.MainWorld
+ }
- Component.onCompleted: {
- // Ensure the JS from the web-engine makes it to our logging
- webview.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) {
- console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message);
- });
-
- webview.profile.httpUserAgent = "Mozilla/5.0 Chrome (HighFidelityInterface";
- web.address = url;
- }
-
- onFeaturePermissionRequested: {
- grantFeaturePermission(securityOrigin, feature, true);
- }
+ // User script.
+ WebEngineScript {
+ id: userScript
+ sourceUrl: webview.userScriptUrl
+ injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished.
+ worldId: WebEngineScript.MainWorld
+ }
- onLoadingChanged: {
- keyboardRaised = false;
- punctuationMode = false;
- keyboard.resetShiftMode(false);
-
- // Required to support clicking on "hifi://" links
- if (WebEngineView.LoadStartedStatus == loadRequest.status) {
- var url = loadRequest.url.toString();
- if (urlHandler.canHandleUrl(url)) {
- if (urlHandler.handleUrl(url)) {
- root.stop();
- }
+ userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
+
+ property string newUrl: ""
+
+ webChannel.registeredObjects: [eventBridgeWrapper]
+
+ Component.onCompleted: {
+ // Ensure the JS from the web-engine makes it to our logging
+ webview.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) {
+ console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message);
+ });
+
+ webview.profile.httpUserAgent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36";
+ web.address = url;
+ }
+
+ onFeaturePermissionRequested: {
+ grantFeaturePermission(securityOrigin, feature, true);
+ }
+
+ onLoadingChanged: {
+ keyboardRaised = false;
+ punctuationMode = false;
+ keyboard.resetShiftMode(false);
+
+ // Required to support clicking on "hifi://" links
+ if (WebEngineView.LoadStartedStatus == loadRequest.status) {
+ var url = loadRequest.url.toString();
+ if (urlHandler.canHandleUrl(url)) {
+ if (urlHandler.handleUrl(url)) {
+ root.stop();
}
}
}
+ }
- onNewViewRequested: {
- var component = Qt.createComponent("./TabletBrowser.qml");
-
- if (component.status != Component.Ready) {
- if (component.status == Component.Error) {
- console.log("Error: " + component.errorString());
- }
- return;
- }
- var newWindow = component.createObject();
- newWindow.setProfile(webview.profile);
- request.openIn(newWindow.webView);
- newWindow.eventBridge = web.eventBridge;
- stackRoot.push(newWindow);
- newWindow.webView.forceActiveFocus();
-
+ onNavigationRequested: {
+ if (request.navigationType == WebEngineNavigationRequest.LinkClickedNavigation) {
+ pagesModel.append({webUrl: request.url.toString()})
}
}
-
- } // item
-
-
+
+ onNewViewRequested: {
+ request.openIn(webView);
+ }
+ }
+
Keys.onPressed: {
switch(event.key) {
case Qt.Key_L:
@@ -171,4 +136,4 @@ Item {
}
}
- } // dialog
+}
diff --git a/interface/resources/qml/controls/TabletWebView.qml b/interface/resources/qml/controls/TabletWebView.qml
index 742ab2d333..50d6e1c504 100644
--- a/interface/resources/qml/controls/TabletWebView.qml
+++ b/interface/resources/qml/controls/TabletWebView.qml
@@ -1,6 +1,6 @@
import QtQuick 2.5
import QtQuick.Controls 1.4
-import QtWebEngine 1.1
+import QtWebEngine 1.2
import QtWebChannel 1.0
import "../controls-uit" as HiFiControls
import "../styles" as HifiStyles
@@ -14,17 +14,20 @@ Item {
height: parent.height
property var parentStackItem: null
property int headerHeight: 38
- property alias url: root.url
- property string address: url
- property alias scriptURL: root.userScriptUrl
+ property string url
+ property string address: url //for compatibility
+ property string scriptURL
property alias eventBridge: eventBridgeWrapper.eventBridge
property bool keyboardEnabled: HMD.active
property bool keyboardRaised: false
property bool punctuationMode: false
property bool isDesktop: false
- property WebEngineView view: root
+ property WebEngineView view: loader.currentView
+ property int currentPage: -1 // used as a model for repeater
+ property alias pagesModel: pagesModel
+
Row {
id: buttons
HifiConstants { id: hifi }
@@ -37,29 +40,29 @@ Item {
anchors.leftMargin: 8
HiFiGlyphs {
id: back;
- enabled: true;
+ enabled: currentPage > 0
text: hifi.glyphs.backward
color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText
size: 48
- MouseArea { anchors.fill: parent; onClicked: stackRoot.goBack() }
+ MouseArea { anchors.fill: parent; onClicked: goBack() }
}
HiFiGlyphs {
id: forward;
- enabled: stackRoot.currentItem.canGoForward;
+ enabled: currentPage < pagesModel.count - 1
text: hifi.glyphs.forward
color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText
size: 48
- MouseArea { anchors.fill: parent; onClicked: stackRoot.currentItem.goForward() }
+ MouseArea { anchors.fill: parent; onClicked: goForward() }
}
HiFiGlyphs {
id: reload;
- enabled: true;
- text: webview.loading ? hifi.glyphs.close : hifi.glyphs.reload
+ enabled: view != null;
+ text: (view !== null && view.loading) ? hifi.glyphs.close : hifi.glyphs.reload
color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText
size: 48
- MouseArea { anchors.fill: parent; onClicked: stackRoot.currentItem.reloadPage(); }
+ MouseArea { anchors.fill: parent; onClicked: reloadPage(); }
}
}
@@ -86,7 +89,7 @@ Item {
}
//root.hidePermissionsBar();
web.keyboardRaised = false;
- stackRoot.currentItem.gotoPage(text);
+ gotoPage(text);
break;
@@ -94,157 +97,78 @@ Item {
}
}
+ ListModel {
+ id: pagesModel
+ onCountChanged: {
+ currentPage = count - 1
+ }
+ }
+ function goBack() {
+ if (currentPage > 0) {
+ currentPage--;
+ }
+ }
+
+ function goForward() {
+ if (currentPage < pagesModel.count - 1) {
+ currentPage++;
+ }
+ }
+
+ function gotoPage(url) {
+ pagesModel.append({webUrl: url})
+ }
+
+ function reloadPage() {
+ view.reloadAndBypassCache()
+ view.setActiveFocusOnPress(true);
+ view.setEnabled(true);
+ }
+
+ onCurrentPageChanged: {
+ if (currentPage >= 0 && currentPage < pagesModel.count && loader.item !== null) {
+ loader.item.url = pagesModel.get(currentPage).webUrl
+ }
+ }
+
+ onUrlChanged: {
+ gotoPage(url)
+ }
+
+ QtObject {
+ id: eventBridgeWrapper
+ WebChannel.id: "eventBridgeWrapper"
+ property var eventBridge;
+ }
+
+ Loader {
+ id: loader
+
+ property WebEngineView currentView: null
- StackView {
- id: stackRoot
width: parent.width
height: parent.height - web.headerHeight
+ asynchronous: true
anchors.top: buttons.bottom
- //property var goBack: currentItem.goBack();
- property WebEngineView view: root
-
- initialItem: root;
-
- function goBack() {
- if (depth > 1 ) {
- if (currentItem.canGoBack) {
- currentItem.goBack();
- } else {
- stackRoot.pop();
- currentItem.webView.focus = true;
- currentItem.webView.forceActiveFocus();
- web.address = currentItem.webView.url;
- }
- } else {
- if (currentItem.canGoBack) {
- currentItem.goBack();
- } else if (parentStackItem) {
- web.parentStackItem.pop();
+ active: false
+ source: "../TabletBrowser.qml"
+ onStatusChanged: {
+ if (loader.status === Loader.Ready) {
+ currentView = item.webView
+ item.webView.userScriptUrl = web.scriptURL
+ if (currentPage >= 0) {
+ //we got something to load already
+ item.url = pagesModel.get(currentPage).webUrl
}
}
}
-
- QtObject {
- id: eventBridgeWrapper
- WebChannel.id: "eventBridgeWrapper"
- property var eventBridge;
- }
-
- WebEngineView {
- id: root
- objectName: "webEngineView"
- x: 0
- y: 0
- width: parent.width
- height: keyboardEnabled && keyboardRaised ? (parent.height - keyboard.height) : parent.height
- profile: HFTabletWebEngineProfile {
- id: webviewTabletProfile
- storageName: "qmlTabletWebEngine"
- }
-
- property WebEngineView webView: root
- function reloadPage() {
- root.reload();
- }
-
- function gotoPage(url) {
- root.url = url;
- }
-
- property string userScriptUrl: ""
-
- // creates a global EventBridge object.
- WebEngineScript {
- id: createGlobalEventBridge
- sourceCode: eventBridgeJavaScriptToInject
- injectionPoint: WebEngineScript.DocumentCreation
- worldId: WebEngineScript.MainWorld
- }
-
- // detects when to raise and lower virtual keyboard
- WebEngineScript {
- id: raiseAndLowerKeyboard
- injectionPoint: WebEngineScript.Deferred
- sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js"
- worldId: WebEngineScript.MainWorld
- }
-
- // User script.
- WebEngineScript {
- id: userScript
- sourceUrl: root.userScriptUrl
- injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished.
- worldId: WebEngineScript.MainWorld
- }
-
- userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
-
- property string newUrl: ""
-
- webChannel.registeredObjects: [eventBridgeWrapper]
-
- Component.onCompleted: {
- // Ensure the JS from the web-engine makes it to our logging
- root.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) {
- console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message);
- });
-
- root.profile.httpUserAgent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36"
-
- }
-
- onFeaturePermissionRequested: {
- grantFeaturePermission(securityOrigin, feature, true);
- }
-
- onLoadingChanged: {
- keyboardRaised = false;
- punctuationMode = false;
- keyboard.resetShiftMode(false);
- // Required to support clicking on "hifi://" links
- if (WebEngineView.LoadStartedStatus == loadRequest.status) {
- var url = loadRequest.url.toString();
- if (urlHandler.canHandleUrl(url)) {
- if (urlHandler.handleUrl(url)) {
- root.stop();
- }
- }
- }
- }
-
- onNewViewRequested:{
- var component = Qt.createComponent("../TabletBrowser.qml");
- if (component.status != Component.Ready) {
- if (component.status == Component.Error) {
- console.log("Error: " + component.errorString());
- }
- return;
- }
- var newWindow = component.createObject();
- newWindow.setProfile(root.profile);
- request.openIn(newWindow.webView);
- newWindow.eventBridge = web.eventBridge;
- stackRoot.push(newWindow);
- }
- }
-
- HiFiControls.Keyboard {
- id: keyboard
- raised: web.keyboardEnabled && web.keyboardRaised
- numeric: web.punctuationMode
- anchors {
- left: parent.left
- right: parent.right
- bottom: parent.bottom
- }
- }
-
}
Component.onCompleted: {
web.isDesktop = (typeof desktop !== "undefined");
address = url;
+ loader.active = true
}
Keys.onPressed: {
diff --git a/interface/resources/qml/hifi/Audio.qml b/interface/resources/qml/hifi/Audio.qml
index deb44b9bd5..d0c3122100 100644
--- a/interface/resources/qml/hifi/Audio.qml
+++ b/interface/resources/qml/hifi/Audio.qml
@@ -127,7 +127,7 @@ Rectangle {
text: hifi.glyphs.mic
color: hifi.colors.primaryHighlight
anchors.verticalCenter: parent.verticalCenter
- font.pointSize: 27
+ size: 32
}
RalewayRegular {
anchors.verticalCenter: parent.verticalCenter
@@ -182,7 +182,7 @@ Rectangle {
text: hifi.glyphs.unmuted
color: hifi.colors.primaryHighlight
anchors.verticalCenter: parent.verticalCenter
- font.pointSize: 27
+ size: 32
}
RalewayRegular {
anchors.verticalCenter: parent.verticalCenter
diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml
index 86cc0218a4..3343cec26f 100644
--- a/interface/resources/qml/hifi/NameCard.qml
+++ b/interface/resources/qml/hifi/NameCard.qml
@@ -14,6 +14,7 @@ import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtGraphicalEffects 1.0
import "../styles-uit"
+import "../controls-uit" as HifiControls
import "toolbars"
// references Users, UserActivityLogger, MyAvatar, Vec3, Quat, AddressManager from root context
@@ -42,8 +43,9 @@ Item {
property bool selected: false
property bool isAdmin: false
property bool isPresent: true
+ property string placeName: ""
property string profilePicBorderColor: (connectionStatus == "connection" ? hifi.colors.indigoAccent : (connectionStatus == "friend" ? hifi.colors.greenHighlight : "transparent"))
-
+ property alias avImage: avatarImage
Item {
id: avatarImage
visible: profileUrl !== "" && userName !== "";
@@ -79,25 +81,6 @@ Item {
anchors.fill: parent;
visible: userImage.status != Image.Ready;
}
- StateImage {
- id: infoHoverImage;
- visible: false;
- imageURL: "../../images/info-icon-2-state.svg";
- size: 32;
- buttonState: 1;
- anchors.centerIn: parent;
- }
- MouseArea {
- anchors.fill: parent
- enabled: selected || isMyCard;
- hoverEnabled: enabled
- onClicked: {
- userInfoViewer.url = defaultBaseUrl + "/users/" + userName;
- userInfoViewer.visible = true;
- }
- onEntered: infoHoverImage.visible = true;
- onExited: infoHoverImage.visible = false;
- }
}
// Colored border around avatarImage
@@ -316,9 +299,10 @@ Item {
visible: thisNameCard.userName !== "";
// Size
width: parent.width
- height: pal.activeTab == "nearbyTab" || isMyCard ? usernameTextPixelSize + 4 : parent.height;
+ height: usernameTextPixelSize + 4
// Anchors
- anchors.top: isMyCard ? myDisplayName.bottom : (pal.activeTab == "nearbyTab" ? displayNameContainer.bottom : parent.top);
+ anchors.top: isMyCard ? myDisplayName.bottom : pal.activeTab == "nearbyTab" ? displayNameContainer.bottom : undefined //(parent.height - displayNameTextPixelSize/2));
+ anchors.verticalCenter: pal.activeTab == "connectionsTab" ? avatarImage.verticalCenter : undefined
anchors.left: avatarImage.right;
anchors.leftMargin: avatarImage.visible ? 5 : 0;
anchors.rightMargin: 5;
@@ -346,6 +330,92 @@ Item {
}
}
}
+ StateImage {
+ id: nameCardConnectionInfoImage
+ visible: selected && !isMyCard && pal.activeTab == "connectionsTab"
+ imageURL: "../../images/info-icon-2-state.svg" // PLACEHOLDER!!!
+ size: 32;
+ buttonState: 0;
+ anchors.left: avatarImage.right
+ anchors.bottom: parent.bottom
+ }
+ MouseArea {
+ anchors.fill:nameCardConnectionInfoImage
+ enabled: selected
+ hoverEnabled: true
+ onClicked: {
+ userInfoViewer.url = defaultBaseUrl + "/users/" + userName;
+ userInfoViewer.visible = true;
+ }
+ onEntered: {
+ nameCardConnectionInfoImage.buttonState = 1;
+ }
+ onExited: {
+ nameCardConnectionInfoImage.buttonState = 0;
+ }
+ }
+ FiraSansRegular {
+ id: nameCardConnectionInfoText
+ visible: selected && !isMyCard && pal.activeTab == "connectionsTab" && !isMyCard
+ width: parent.width
+ height: displayNameTextPixelSize
+ size: displayNameTextPixelSize - 4
+ anchors.left: nameCardConnectionInfoImage.right
+ anchors.verticalCenter: nameCardConnectionInfoImage.verticalCenter
+ anchors.leftMargin: 5
+ verticalAlignment: Text.AlignVCenter
+ text: "Info"
+ color: hifi.colors.baseGray
+ }
+ HiFiGlyphs {
+ id: nameCardRemoveConnectionImage
+ visible: selected && !isMyCard && pal.activeTab == "connectionsTab"
+ text: hifi.glyphs.close
+ size: 28;
+ x: 120
+ anchors.verticalCenter: nameCardConnectionInfoImage.verticalCenter
+ }
+ MouseArea {
+ anchors.fill:nameCardRemoveConnectionImage
+ enabled: selected
+ hoverEnabled: true
+ onClicked: {
+ // send message to pal.js to forgetConnection
+ pal.sendToScript({method: 'removeConnection', params: thisNameCard.userName});
+ }
+ onEntered: {
+ nameCardRemoveConnectionImage.text = hifi.glyphs.closeInverted;
+ }
+ onExited: {
+ nameCardRemoveConnectionImage.text = hifi.glyphs.close;
+ }
+ }
+ FiraSansRegular {
+ id: nameCardRemoveConnectionText
+ visible: selected && !isMyCard && pal.activeTab == "connectionsTab" && !isMyCard
+ width: parent.width
+ height: displayNameTextPixelSize
+ size: displayNameTextPixelSize - 4
+ anchors.left: nameCardRemoveConnectionImage.right
+ anchors.verticalCenter: nameCardRemoveConnectionImage.verticalCenter
+ anchors.leftMargin: 5
+ verticalAlignment: Text.AlignVCenter
+ text: "Forget"
+ color: hifi.colors.baseGray
+ }
+ HifiControls.Button {
+ id: visitConnectionButton
+ visible: selected && !isMyCard && pal.activeTab == "connectionsTab" && !isMyCard
+ text: "Visit"
+ enabled: thisNameCard.placeName !== ""
+ anchors.verticalCenter: nameCardRemoveConnectionImage.verticalCenter
+ x: 240
+ onClicked: {
+ AddressManager.goToUser(thisNameCard.userName);
+ UserActivityLogger.palAction("go_to_user", thisNameCard.userName);
+ }
+ }
+
// VU Meter
Rectangle {
id: nameCardVUMeter
@@ -484,7 +554,7 @@ Item {
}
}
}
-
+
function updateGainFromQML(avatarUuid, sliderValue, isReleased) {
Users.setAvatarGain(avatarUuid, sliderValue);
if (isReleased) {
diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml
index 66803621ec..d627fb54f9 100644
--- a/interface/resources/qml/hifi/Pal.qml
+++ b/interface/resources/qml/hifi/Pal.qml
@@ -52,6 +52,13 @@ Rectangle {
id: letterboxMessage;
z: 999; // Force the popup on top of everything else
}
+ Connections {
+ target: GlobalServices
+ onMyUsernameChanged: {
+ myData.userName = Account.username;
+ myDataChanged(); // Setting a property within an object isn't enough to update dependencies. This will do it.
+ }
+ }
// The ComboDialog used for setting availability
ComboDialog {
id: comboDialog;
@@ -763,7 +770,7 @@ Rectangle {
// This Rectangle refers to each Row in the connectionsTable.
rowDelegate: Rectangle {
// Size
- height: rowHeight;
+ height: rowHeight + (styleData.selected ? 15 : 0);
color: rowColor(styleData.selected, styleData.alternate);
}
@@ -779,6 +786,7 @@ Rectangle {
profileUrl: (model && model.profileUrl) || "";
displayName: "";
userName: model ? model.userName : "";
+ placeName: model ? model.placeName : ""
connectionStatus : model ? model.connection : "";
selected: styleData.selected;
// Size
@@ -797,12 +805,16 @@ Rectangle {
elide: Text.ElideRight;
// Size
width: parent.width;
- // Anchors
- anchors.fill: parent;
+ // you would think that this would work:
+ // anchors.verticalCenter: connectionsNameCard.avImage.verticalCenter
+ // but no! you cannot anchor to a non-sibling or parent. So I will
+ // align with the friends checkbox, where I did the manual alignment
+ anchors.verticalCenter: friendsCheckBox.verticalCenter
// Text Size
size: 16;
// Text Positioning
verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
// Style
color: hifi.colors.blueAccent;
font.underline: true;
@@ -822,8 +834,12 @@ Rectangle {
// "Friends" checkbox
HifiControlsUit.CheckBox {
id: friendsCheckBox;
- visible: styleData.role === "friends" && model.userName !== myData.userName;
- anchors.centerIn: parent;
+ visible: styleData.role === "friends" && model && model.userName !== myData.userName;
+ // you would think that this would work:
+ // anchors.verticalCenter: connectionsNameCard.avImage.verticalCenter
+ // but no! you cannot anchor to a non-sibling or parent. So:
+ x: parent.width/2 - boxSize/2
+ y: connectionsNameCard.avImage.y + connectionsNameCard.avImage.height/2 - boxSize/2
checked: model ? (model["connection"] === "friend" ? true : false) : false;
boxSize: 24;
onClicked: {
@@ -901,7 +917,7 @@ Rectangle {
wrapMode: Text.WordWrap
textFormat: Text.StyledText;
// Text
- text: HMD.active ?
+ text: HMD.isMounted ?
"When you meet someone you want to remember later, you can connect with a handshake:
" +
"1. Put your hand out onto their hand and squeeze your controller's grip button on its side.
" +
"2. Once the other person puts their hand onto yours, you'll see your connection form.
" +
@@ -960,7 +976,6 @@ Rectangle {
// Text size
size: hifi.fontSizes.tabularData;
// Anchors
- anchors.top: myCard.top;
anchors.left: parent.left;
// Style
color: hifi.colors.baseGrayHighlight;
diff --git a/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml b/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml
index 2460fc39d5..85f8a2f59e 100644
--- a/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml
+++ b/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml
@@ -21,6 +21,9 @@ Rectangle {
id: root
objectName: "AssetServer"
+ property string title: "Asset Browser"
+ property bool keyboardRaised: false
+
property var eventBridge;
signal sendToScript(var message);
property bool isHMD: false
@@ -415,7 +418,6 @@ Rectangle {
Column {
width: parent.width
- y: hifi.dimensions.tabletMenuHeader //-bgNavBar
spacing: 10
HifiControls.TabletContentSection {
diff --git a/interface/resources/qml/hifi/dialogs/TabletRunningScripts.qml b/interface/resources/qml/hifi/dialogs/TabletRunningScripts.qml
index dee0d0e21f..d826b40ad1 100644
--- a/interface/resources/qml/hifi/dialogs/TabletRunningScripts.qml
+++ b/interface/resources/qml/hifi/dialogs/TabletRunningScripts.qml
@@ -20,7 +20,7 @@ import "../../windows"
Rectangle {
id: root
objectName: "RunningScripts"
- property var title: "Running Scripts"
+ property string title: "Running Scripts"
HifiConstants { id: hifi }
signal sendToScript(var message);
property var eventBridge;
@@ -81,9 +81,9 @@ Rectangle {
Flickable {
id: flickable
- width: parent.width
+ width: tabletRoot.width
height: parent.height - (keyboard.raised ? keyboard.raisedHeight : 0)
- contentWidth: parent.width
+ contentWidth: column.width
contentHeight: column.childrenRect.height
clip: true
@@ -121,9 +121,8 @@ Rectangle {
model: runningScriptsModel
id: table
height: 185
+ width: parent.width
colorScheme: hifi.colorSchemes.dark
- anchors.left: parent.left
- anchors.right: parent.right
expandSelectedRow: true
itemDelegate: Item {
diff --git a/interface/resources/qml/hifi/tablet/Tablet.qml b/interface/resources/qml/hifi/tablet/Tablet.qml
index 3fb70f9cca..8ad6339d88 100644
--- a/interface/resources/qml/hifi/tablet/Tablet.qml
+++ b/interface/resources/qml/hifi/tablet/Tablet.qml
@@ -202,7 +202,7 @@ Item {
RalewaySemiBold {
id: usernameText
- text: tablet.parent.parent.username
+ text: tabletRoot.username
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 20
diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml
index fbb78d2694..396f03a1c9 100644
--- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml
+++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml
@@ -25,6 +25,8 @@ StackView {
HifiConstants { id: hifi }
HifiStyles.HifiConstants { id: hifiStyleConstants }
initialItem: addressBarDialog
+ width: parent !== null ? parent.width : undefined
+ height: parent !== null ? parent.height : undefined
property var eventBridge;
property var allStories: [];
property int cardWidth: 460;
@@ -116,6 +118,7 @@ StackView {
imageURL: "../../../images/home.svg"
onClicked: {
addressBarDialog.loadHome();
+ tabletRoot.shown = false;
}
anchors {
left: parent.left
@@ -150,7 +153,9 @@ StackView {
anchors {
top: navBar.bottom
right: parent.right
+ rightMargin: 16
left: parent.left
+ leftMargin: 16
}
property int inputAreaHeight: 70
@@ -554,20 +559,21 @@ StackView {
if (addressLine.text !== "") {
addressBarDialog.loadAddress(addressLine.text, fromSuggestions)
}
-
+
if (root.desktop) {
tablet.gotoHomeScreen();
} else {
HMD.closeTablet();
}
+ tabletRoot.shown = false;
}
Keys.onPressed: {
switch (event.key) {
case Qt.Key_Escape:
case Qt.Key_Back:
- root.shown = false
+ tabletRoot.shown = false
clearAddressLineTimer.start();
event.accepted = true
break
diff --git a/interface/resources/qml/hifi/tablet/TabletRoot.qml b/interface/resources/qml/hifi/tablet/TabletRoot.qml
index 8037c1280e..f5144e698f 100644
--- a/interface/resources/qml/hifi/tablet/TabletRoot.qml
+++ b/interface/resources/qml/hifi/tablet/TabletRoot.qml
@@ -13,6 +13,7 @@ Item {
property var openMessage: null;
property string subMenu: ""
signal showDesktop();
+ property bool shown: true
function setOption(value) {
option = value;
diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp
index 5d197f5ddc..7700874d9a 100644
--- a/interface/src/ui/JSConsole.cpp
+++ b/interface/src/ui/JSConsole.cpp
@@ -76,8 +76,8 @@ void JSConsole::setScriptEngine(ScriptEngine* scriptEngine) {
return;
}
if (_scriptEngine != NULL) {
- disconnect(_scriptEngine, SIGNAL(printedMessage(const QString&)), this, SLOT(handlePrint(const QString&)));
- disconnect(_scriptEngine, SIGNAL(errorMessage(const QString&)), this, SLOT(handleError(const QString&)));
+ disconnect(_scriptEngine, &ScriptEngine::printedMessage, this, &JSConsole::handlePrint);
+ disconnect(_scriptEngine, &ScriptEngine::errorMessage, this, &JSConsole::handleError);
if (_ownScriptEngine) {
_scriptEngine->deleteLater();
}
@@ -87,8 +87,8 @@ void JSConsole::setScriptEngine(ScriptEngine* scriptEngine) {
_ownScriptEngine = scriptEngine == NULL;
_scriptEngine = _ownScriptEngine ? DependencyManager::get()->loadScript(QString(), false) : scriptEngine;
- connect(_scriptEngine, SIGNAL(printedMessage(const QString&)), this, SLOT(handlePrint(const QString&)));
- connect(_scriptEngine, SIGNAL(errorMessage(const QString&)), this, SLOT(handleError(const QString&)));
+ connect(_scriptEngine, &ScriptEngine::printedMessage, this, &JSConsole::handlePrint);
+ connect(_scriptEngine, &ScriptEngine::errorMessage, this, &JSConsole::handleError);
}
void JSConsole::executeCommand(const QString& command) {
@@ -134,11 +134,13 @@ void JSConsole::commandFinished() {
resetCurrentCommandHistory();
}
-void JSConsole::handleError(const QString& message) {
+void JSConsole::handleError(const QString& scriptName, const QString& message) {
+ Q_UNUSED(scriptName);
appendMessage(GUTTER_ERROR, "" + message.toHtmlEscaped() + "");
}
-void JSConsole::handlePrint(const QString& message) {
+void JSConsole::handlePrint(const QString& scriptName, const QString& message) {
+ Q_UNUSED(scriptName);
appendMessage("", message);
}
diff --git a/interface/src/ui/JSConsole.h b/interface/src/ui/JSConsole.h
index 47878fea99..d5f5aff301 100644
--- a/interface/src/ui/JSConsole.h
+++ b/interface/src/ui/JSConsole.h
@@ -47,8 +47,8 @@ protected:
protected slots:
void scrollToBottom();
void resizeTextInput();
- void handlePrint(const QString& message);
- void handleError(const QString& message);
+ void handlePrint(const QString& scriptName, const QString& message);
+ void handleError(const QString& scriptName, const QString& message);
void commandFinished();
private:
diff --git a/libraries/controllers/src/controllers/StandardControls.h b/libraries/controllers/src/controllers/StandardControls.h
index c21d8a2f6e..f521ab81cf 100644
--- a/libraries/controllers/src/controllers/StandardControls.h
+++ b/libraries/controllers/src/controllers/StandardControls.h
@@ -158,6 +158,22 @@ namespace controller {
LEFT_HAND_PINKY2,
LEFT_HAND_PINKY3,
LEFT_HAND_PINKY4,
+ TRACKED_OBJECT_00,
+ TRACKED_OBJECT_01,
+ TRACKED_OBJECT_02,
+ TRACKED_OBJECT_03,
+ TRACKED_OBJECT_04,
+ TRACKED_OBJECT_05,
+ TRACKED_OBJECT_06,
+ TRACKED_OBJECT_07,
+ TRACKED_OBJECT_08,
+ TRACKED_OBJECT_09,
+ TRACKED_OBJECT_10,
+ TRACKED_OBJECT_11,
+ TRACKED_OBJECT_12,
+ TRACKED_OBJECT_13,
+ TRACKED_OBJECT_14,
+ TRACKED_OBJECT_15,
NUM_STANDARD_POSES
};
diff --git a/libraries/gl/src/gl/OffscreenGLCanvas.cpp b/libraries/gl/src/gl/OffscreenGLCanvas.cpp
index e54846196b..e5c630d97e 100644
--- a/libraries/gl/src/gl/OffscreenGLCanvas.cpp
+++ b/libraries/gl/src/gl/OffscreenGLCanvas.cpp
@@ -60,6 +60,7 @@ bool OffscreenGLCanvas::create(QOpenGLContext* sharedContext) {
bool OffscreenGLCanvas::makeCurrent() {
bool result = _context->makeCurrent(_offscreenSurface);
Q_ASSERT(result);
+
std::call_once(_reportOnce, [this]{
qCDebug(glLogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION));
qCDebug(glLogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp
index 9e6c18bb96..16e32ab42e 100644
--- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp
+++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp
@@ -278,11 +278,9 @@ void OffscreenQmlSurface::cleanup() {
}
void OffscreenQmlSurface::render() {
-
#ifdef HIFI_ENABLE_NSIGHT_DEBUG
return;
#endif
-
if (_paused) {
return;
}
@@ -614,7 +612,11 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::functionmetaObject()->indexOfSignal("sendToScript");
+ if (sendToScriptIndex != -1) {
+ connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant)));
+ }
// The root item is ready. Associate it with the window.
_rootItem = newItem;
diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp b/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp
index c8a7b61aa7..9c29e87f16 100644
--- a/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp
+++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp
@@ -61,6 +61,16 @@ void UserActivityLoggerScriptingInterface::palOpened(float secondsOpened) {
});
}
+void UserActivityLoggerScriptingInterface::makeUserConnection(QString otherID, bool success, QString detailsString) {
+ QJsonObject payload;
+ payload["otherUser"] = otherID;
+ payload["success"] = success;
+ if (detailsString.length() > 0) {
+ payload["details"] = detailsString;
+ }
+ logAction("makeUserConnection", payload);
+}
+
void UserActivityLoggerScriptingInterface::logAction(QString action, QJsonObject details) {
QMetaObject::invokeMethod(&UserActivityLogger::getInstance(), "logAction",
Q_ARG(QString, action),
diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.h b/libraries/networking/src/UserActivityLoggerScriptingInterface.h
index cf38450891..b68c7beb95 100644
--- a/libraries/networking/src/UserActivityLoggerScriptingInterface.h
+++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.h
@@ -29,6 +29,7 @@ public:
float tutorialElapsedTime, QString tutorialRunID = "", int tutorialVersion = 0, QString controllerType = "");
Q_INVOKABLE void palAction(QString action, QString target);
Q_INVOKABLE void palOpened(float secondsOpen);
+ Q_INVOKABLE void makeUserConnection(QString otherUser, bool success, QString details="");
private:
void logAction(QString action, QJsonObject details = {});
};
diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp
index 414bcf0d63..da264cbf7d 100644
--- a/libraries/render-utils/src/RenderPipelines.cpp
+++ b/libraries/render-utils/src/RenderPipelines.cpp
@@ -28,6 +28,12 @@
#include "skin_model_shadow_vert.h"
#include "skin_model_normal_map_vert.h"
+#include "simple_vert.h"
+#include "simple_textured_frag.h"
+#include "simple_textured_unlit_frag.h"
+#include "simple_transparent_textured_frag.h"
+#include "simple_transparent_textured_unlit_frag.h"
+
#include "model_frag.h"
#include "model_unlit_frag.h"
#include "model_shadow_frag.h"
@@ -135,6 +141,7 @@ void initOverlay3DPipelines(ShapePlumber& plumber) {
void initDeferredPipelines(render::ShapePlumber& plumber) {
// Vertex shaders
+ auto simpleVertex = gpu::Shader::createVertex(std::string(simple_vert));
auto modelVertex = gpu::Shader::createVertex(std::string(model_vert));
auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert));
auto modelLightmapVertex = gpu::Shader::createVertex(std::string(model_lightmap_vert));
@@ -145,6 +152,10 @@ void initDeferredPipelines(render::ShapePlumber& plumber) {
auto skinModelShadowVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert));
// Pixel shaders
+ auto simplePixel = gpu::Shader::createPixel(std::string(simple_textured_frag));
+ auto simpleUnlitPixel = gpu::Shader::createPixel(std::string(simple_textured_unlit_frag));
+ auto simpleTranslucentPixel = gpu::Shader::createPixel(std::string(simple_transparent_textured_frag));
+ auto simpleTranslucentUnlitPixel = gpu::Shader::createPixel(std::string(simple_transparent_textured_unlit_frag));
auto modelPixel = gpu::Shader::createPixel(std::string(model_frag));
auto modelUnlitPixel = gpu::Shader::createPixel(std::string(model_unlit_frag));
auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag));
@@ -167,13 +178,13 @@ void initDeferredPipelines(render::ShapePlumber& plumber) {
modelVertex, modelPixel);
addPipeline(
Key::Builder(),
- modelVertex, modelPixel);
+ simpleVertex, simplePixel);
addPipeline(
Key::Builder().withMaterial().withUnlit(),
modelVertex, modelUnlitPixel);
addPipeline(
Key::Builder().withUnlit(),
- modelVertex, modelUnlitPixel);
+ simpleVertex, simpleUnlitPixel);
addPipeline(
Key::Builder().withMaterial().withTangents(),
modelNormalMapVertex, modelNormalMapPixel);
@@ -189,13 +200,13 @@ void initDeferredPipelines(render::ShapePlumber& plumber) {
modelVertex, modelTranslucentPixel);
addPipeline(
Key::Builder().withTranslucent(),
- modelVertex, modelTranslucentPixel);
+ simpleVertex, simpleTranslucentPixel);
addPipeline(
Key::Builder().withMaterial().withTranslucent().withUnlit(),
modelVertex, modelTranslucentUnlitPixel);
addPipeline(
Key::Builder().withTranslucent().withUnlit(),
- modelVertex, modelTranslucentUnlitPixel);
+ simpleVertex, simpleTranslucentUnlitPixel);
addPipeline(
Key::Builder().withMaterial().withTranslucent().withTangents(),
modelNormalMapVertex, modelTranslucentPixel);
diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf
index 6067c81a1b..550f6546fd 100644
--- a/libraries/render-utils/src/simple_textured.slf
+++ b/libraries/render-utils/src/simple_textured.slf
@@ -26,15 +26,17 @@ in vec2 _texCoord0;
void main(void) {
vec4 texel = texture(originalTexture, _texCoord0);
+ float colorAlpha = _color.a;
if (_color.a <= 0.0) {
texel = colorToLinearRGBA(texel);
+ colorAlpha = -_color.a;
}
const float ALPHA_THRESHOLD = 0.999;
- if (_color.a * texel.a < ALPHA_THRESHOLD) {
+ if (colorAlpha * texel.a < ALPHA_THRESHOLD) {
packDeferredFragmentTranslucent(
normalize(_normal),
- _color.a * texel.a,
+ colorAlpha * texel.a,
_color.rgb * texel.rgb,
DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS);
diff --git a/libraries/render-utils/src/simple_textured_unlit.slf b/libraries/render-utils/src/simple_textured_unlit.slf
index 4f02140825..d261fb343a 100644
--- a/libraries/render-utils/src/simple_textured_unlit.slf
+++ b/libraries/render-utils/src/simple_textured_unlit.slf
@@ -2,7 +2,7 @@
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
-// simple.frag
+// simple_textured_unlit.frag
// fragment shader
//
// Created by Clément Brisset on 5/29/15.
@@ -25,15 +25,17 @@ in vec2 _texCoord0;
void main(void) {
vec4 texel = texture(originalTexture, _texCoord0.st);
+ float colorAlpha = _color.a;
if (_color.a <= 0.0) {
texel = colorToLinearRGBA(texel);
+ colorAlpha = -_color.a;
}
const float ALPHA_THRESHOLD = 0.999;
- if (_color.a * texel.a < ALPHA_THRESHOLD) {
- packDeferredFragmentTranslucent(
+ if (colorAlpha * texel.a < ALPHA_THRESHOLD) {
+ packDeferredFragmentTranslucent(
normalize(_normal),
- _color.a * texel.a,
+ colorAlpha * texel.a,
_color.rgb * texel.rgb,
DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS);
diff --git a/libraries/render-utils/src/simple_transparent_textured.slf b/libraries/render-utils/src/simple_transparent_textured.slf
new file mode 100644
index 0000000000..b9eb921e9d
--- /dev/null
+++ b/libraries/render-utils/src/simple_transparent_textured.slf
@@ -0,0 +1,62 @@
+<@include gpu/Config.slh@>
+<$VERSION_HEADER$>
+// Generated on <$_SCRIBE_DATE$>
+//
+// simple_transparent_textured.slf
+// fragment shader
+//
+// Created by Sam Gateau on 4/3/17.
+// Copyright 2017 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+<@include gpu/Color.slh@>
+
+<@include DeferredBufferWrite.slh@>
+<@include DeferredGlobalLight.slh@>
+<$declareEvalGlobalLightingAlphaBlended()$>
+
+<@include gpu/Transform.slh@>
+<$declareStandardCameraTransform()$>
+
+// the albedo texture
+uniform sampler2D originalTexture;
+
+// the interpolated normal
+in vec4 _position;
+in vec3 _normal;
+in vec4 _color;
+in vec2 _texCoord0;
+
+void main(void) {
+ vec4 texel = texture(originalTexture, _texCoord0.st);
+ float opacity = _color.a;
+ if (_color.a <= 0.0) {
+ texel = colorToLinearRGBA(texel);
+ opacity = -_color.a;
+ }
+ opacity *= texel.a;
+ vec3 albedo = _color.rgb * texel.rgb;
+
+ vec3 fragPosition = _position.xyz;
+ vec3 fragNormal = normalize(_normal);
+
+ TransformCamera cam = getTransformCamera();
+
+ _fragColor0 = vec4(evalGlobalLightingAlphaBlended(
+ cam._viewInverse,
+ 1.0,
+ 1.0,
+ fragPosition,
+ fragNormal,
+ albedo,
+ DEFAULT_FRESNEL,
+ 0.0,
+ vec3(0.0f),
+ DEFAULT_ROUGHNESS,
+ opacity),
+ opacity);
+
+}
\ No newline at end of file
diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit.slf b/libraries/render-utils/src/simple_transparent_textured_unlit.slf
new file mode 100644
index 0000000000..693d7be2db
--- /dev/null
+++ b/libraries/render-utils/src/simple_transparent_textured_unlit.slf
@@ -0,0 +1,36 @@
+<@include gpu/Config.slh@>
+<$VERSION_HEADER$>
+// Generated on <$_SCRIBE_DATE$>
+//
+// simple_transparent_textured_unlit.slf
+// fragment shader
+//
+// Created by Sam Gateau on 4/3/17.
+// Copyright 2017 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+<@include gpu/Color.slh@>
+
+// the albedo texture
+uniform sampler2D originalTexture;
+
+// the interpolated normal
+in vec3 _normal;
+in vec4 _color;
+in vec2 _texCoord0;
+
+
+layout(location = 0) out vec4 _fragColor0;
+
+void main(void) {
+ vec4 texel = texture(originalTexture, _texCoord0.st);
+ float colorAlpha = _color.a;
+ if (_color.a <= 0.0) {
+ texel = colorToLinearRGBA(texel);
+ colorAlpha = -_color.a;
+ }
+ _fragColor0 = vec4(_color.rgb * texel.rgb, colorAlpha * texel.a);
+}
\ No newline at end of file
diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp
index c60e4fa698..c0e94058ae 100644
--- a/libraries/ui/src/QmlWindowClass.cpp
+++ b/libraries/ui/src/QmlWindowClass.cpp
@@ -122,12 +122,15 @@ void QmlWindowClass::initQml(QVariantMap properties) {
object->setProperty(OFFSCREEN_VISIBILITY_PROPERTY, visible);
object->setProperty(SOURCE_PROPERTY, _source);
+ const QMetaObject *metaObject = _qmlWindow->metaObject();
// Forward messages received from QML on to the script
connect(_qmlWindow, SIGNAL(sendToScript(QVariant)), this, SLOT(qmlToScript(const QVariant&)), Qt::QueuedConnection);
connect(_qmlWindow, SIGNAL(visibleChanged()), this, SIGNAL(visibleChanged()), Qt::QueuedConnection);
- connect(_qmlWindow, SIGNAL(resized(QSizeF)), this, SIGNAL(resized(QSizeF)), Qt::QueuedConnection);
- connect(_qmlWindow, SIGNAL(moved(QVector2D)), this, SLOT(hasMoved(QVector2D)), Qt::QueuedConnection);
+ if (metaObject->indexOfSignal("resized") >= 0)
+ connect(_qmlWindow, SIGNAL(resized(QSizeF)), this, SIGNAL(resized(QSizeF)), Qt::QueuedConnection);
+ if (metaObject->indexOfSignal("moved") >= 0)
+ connect(_qmlWindow, SIGNAL(moved(QVector2D)), this, SLOT(hasMoved(QVector2D)), Qt::QueuedConnection);
connect(_qmlWindow, SIGNAL(windowClosed()), this, SLOT(hasClosed()), Qt::QueuedConnection);
});
}
diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp
index 2e930c0fdc..8cedee2d8f 100644
--- a/plugins/openvr/src/ViveControllerManager.cpp
+++ b/plugins/openvr/src/ViveControllerManager.cpp
@@ -63,59 +63,6 @@ bool ViveControllerManager::activate() {
enableOpenVrKeyboard(_container);
- // OpenVR provides 3d mesh representations of the controllers
- // Disabled controller rendering code
- /*
- auto renderModels = vr::VRRenderModels();
-
- vr::RenderModel_t model;
- if (!_system->LoadRenderModel(CONTROLLER_MODEL_STRING, &model)) {
- qDebug() << QString("Unable to load render model %1\n").arg(CONTROLLER_MODEL_STRING);
- } else {
- model::Mesh* mesh = new model::Mesh();
- model::MeshPointer meshPtr(mesh);
- _modelGeometry.setMesh(meshPtr);
-
- auto indexBuffer = new gpu::Buffer(3 * model.unTriangleCount * sizeof(uint16_t), (gpu::Byte*)model.rIndexData);
- auto indexBufferPtr = gpu::BufferPointer(indexBuffer);
- auto indexBufferView = new gpu::BufferView(indexBufferPtr, gpu::Element(gpu::SCALAR, gpu::UINT16, gpu::RAW));
- mesh->setIndexBuffer(*indexBufferView);
-
- auto vertexBuffer = new gpu::Buffer(model.unVertexCount * sizeof(vr::RenderModel_Vertex_t),
- (gpu::Byte*)model.rVertexData);
- auto vertexBufferPtr = gpu::BufferPointer(vertexBuffer);
- auto vertexBufferView = new gpu::BufferView(vertexBufferPtr,
- 0,
- vertexBufferPtr->getSize() - sizeof(float) * 3,
- sizeof(vr::RenderModel_Vertex_t),
- gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW));
- mesh->setVertexBuffer(*vertexBufferView);
- mesh->addAttribute(gpu::Stream::NORMAL,
- gpu::BufferView(vertexBufferPtr,
- sizeof(float) * 3,
- vertexBufferPtr->getSize() - sizeof(float) * 3,
- sizeof(vr::RenderModel_Vertex_t),
- gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RAW)));
- //mesh->addAttribute(gpu::Stream::TEXCOORD,
- // gpu::BufferView(vertexBufferPtr,
- // 2 * sizeof(float) * 3,
- // vertexBufferPtr->getSize() - sizeof(float) * 2,
- // sizeof(vr::RenderModel_Vertex_t),
- // gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::RAW)));
-
- gpu::Element formatGPU = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA);
- gpu::Element formatMip = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA);
- _texture = gpu::TexturePointer(
- gpu::Texture::create2D(formatGPU, model.diffuseTexture.unWidth, model.diffuseTexture.unHeight,
- gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)));
- _texture->assignStoredMip(0, formatMip, model.diffuseTexture.unWidth * model.diffuseTexture.unHeight * 4 * sizeof(uint8_t), model.diffuseTexture.rubTextureMapData);
- _texture->autoGenerateMips(-1);
-
- _modelLoaded = true;
- _renderControllers = true;
- }
- */
-
// register with UserInputMapper
auto userInputMapper = DependencyManager::get();
userInputMapper->registerDevice(_inputDevice);
@@ -145,70 +92,6 @@ void ViveControllerManager::deactivate() {
_registeredWithInputMapper = false;
}
-void ViveControllerManager::updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges) {
- PerformanceTimer perfTimer("ViveControllerManager::updateRendering");
-
- /*
- if (_modelLoaded) {
- //auto controllerPayload = new render::Payload(this);
- //auto controllerPayloadPointer = ViveControllerManager::PayloadPointer(controllerPayload);
- //if (_leftHandRenderID == 0) {
- // _leftHandRenderID = scene->allocateID();
- // pendingChanges.resetItem(_leftHandRenderID, controllerPayloadPointer);
- //}
- //pendingChanges.updateItem(_leftHandRenderID, );
-
-
- controller::Pose leftHand = _inputDevice->_poseStateMap[controller::StandardPoseChannel::LEFT_HAND];
- controller::Pose rightHand = _inputDevice->_poseStateMap[controller::StandardPoseChannel::RIGHT_HAND];
-
- gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
- auto geometryCache = DependencyManager::get();
- geometryCache->useSimpleDrawPipeline(batch);
- DependencyManager::get()->bindSimpleProgram(batch, true);
-
- auto mesh = _modelGeometry.getMesh();
- batch.setInputFormat(mesh->getVertexFormat());
- //batch._glBindTexture(GL_TEXTURE_2D, _uexture);
-
- if (leftHand.isValid()) {
- renderHand(leftHand, batch, 1);
- }
- if (rightHand.isValid()) {
- renderHand(rightHand, batch, -1);
- }
- });
- }
- */
-}
-
-void ViveControllerManager::renderHand(const controller::Pose& pose, gpu::Batch& batch, int sign) {
- /*
- auto userInputMapper = DependencyManager::get();
- Transform transform(userInputMapper->getSensorToWorldMat());
- transform.postTranslate(pose.getTranslation() + pose.getRotation() * glm::vec3(0, 0, CONTROLLER_LENGTH_OFFSET));
-
- glm::quat rotation = pose.getRotation() * glm::angleAxis(PI, glm::vec3(1.0f, 0.0f, 0.0f)) * glm::angleAxis(sign * PI_OVER_TWO, glm::vec3(0.0f, 0.0f, 1.0f));
- transform.postRotate(rotation);
-
- batch.setModelTransform(transform);
-
- auto mesh = _modelGeometry.getMesh();
- batch.setInputBuffer(gpu::Stream::POSITION, mesh->getVertexBuffer());
- batch.setInputBuffer(gpu::Stream::NORMAL,
- mesh->getVertexBuffer()._buffer,
- sizeof(float) * 3,
- mesh->getVertexBuffer()._stride);
- //batch.setInputBuffer(gpu::Stream::TEXCOORD,
- // mesh->getVertexBuffer()._buffer,
- // 2 * 3 * sizeof(float),
- // mesh->getVertexBuffer()._stride);
- batch.setIndexBuffer(gpu::UINT16, mesh->getIndexBuffer()._buffer, 0);
- batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0);
- */
-}
-
-
void ViveControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
if (!_system) {
@@ -257,6 +140,11 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle
handleHandController(deltaTime, leftHandDeviceIndex, inputCalibrationData, true);
handleHandController(deltaTime, rightHandDeviceIndex, inputCalibrationData, false);
+ // collect raw poses
+ for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
+ handleTrackedObject(i, inputCalibrationData);
+ }
+
// handle haptics
{
Locker locker(_lock);
@@ -278,6 +166,30 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle
_trackedControllers = numTrackedControllers;
}
+void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData) {
+
+ uint32_t poseIndex = controller::TRACKED_OBJECT_00 + deviceIndex;
+
+ if (_system->IsTrackedDeviceConnected(deviceIndex) &&
+ _nextSimPoseData.vrPoses[deviceIndex].bPoseIsValid &&
+ poseIndex <= controller::TRACKED_OBJECT_15) {
+
+ // process pose
+ const mat4& mat = _nextSimPoseData.poses[deviceIndex];
+ const vec3 linearVelocity = _nextSimPoseData.linearVelocities[deviceIndex];
+ const vec3 angularVelocity = _nextSimPoseData.angularVelocities[deviceIndex];
+
+ controller::Pose pose(extractTranslation(mat), glmExtractRotation(mat), linearVelocity, angularVelocity);
+
+ // transform into avatar frame
+ glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
+ _poseStateMap[poseIndex] = pose.transform(controllerToAvatar);
+ } else {
+ controller::Pose invalidPose;
+ _poseStateMap[poseIndex] = invalidPose;
+ }
+}
+
void ViveControllerManager::InputDevice::handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand) {
if (_system->IsTrackedDeviceConnected(deviceIndex) &&
@@ -492,6 +404,24 @@ controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableI
makePair(LEFT_HAND, "LeftHand"),
makePair(RIGHT_HAND, "RightHand"),
+ // 16 tracked poses
+ makePair(TRACKED_OBJECT_00, "TrackedObject00"),
+ makePair(TRACKED_OBJECT_01, "TrackedObject01"),
+ makePair(TRACKED_OBJECT_02, "TrackedObject02"),
+ makePair(TRACKED_OBJECT_03, "TrackedObject03"),
+ makePair(TRACKED_OBJECT_04, "TrackedObject04"),
+ makePair(TRACKED_OBJECT_05, "TrackedObject05"),
+ makePair(TRACKED_OBJECT_06, "TrackedObject06"),
+ makePair(TRACKED_OBJECT_07, "TrackedObject07"),
+ makePair(TRACKED_OBJECT_08, "TrackedObject08"),
+ makePair(TRACKED_OBJECT_09, "TrackedObject09"),
+ makePair(TRACKED_OBJECT_10, "TrackedObject10"),
+ makePair(TRACKED_OBJECT_11, "TrackedObject11"),
+ makePair(TRACKED_OBJECT_12, "TrackedObject12"),
+ makePair(TRACKED_OBJECT_13, "TrackedObject13"),
+ makePair(TRACKED_OBJECT_14, "TrackedObject14"),
+ makePair(TRACKED_OBJECT_15, "TrackedObject15"),
+
// app button above trackpad.
Input::NamedPair(Input(_deviceID, LEFT_APP_MENU, ChannelType::BUTTON), "LeftApplicationMenu"),
Input::NamedPair(Input(_deviceID, RIGHT_APP_MENU, ChannelType::BUTTON), "RightApplicationMenu"),
diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h
index 3fb166c842..dc1883d5e4 100644
--- a/plugins/openvr/src/ViveControllerManager.h
+++ b/plugins/openvr/src/ViveControllerManager.h
@@ -43,8 +43,6 @@ public:
void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); }
void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override;
- void updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges);
-
void setRenderControllers(bool renderControllers) { _renderControllers = renderControllers; }
private:
@@ -62,6 +60,7 @@ private:
void hapticsHelper(float deltaTime, bool leftHand);
void handleHandController(float deltaTime, uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData, bool isLeftHand);
+ void handleTrackedObject(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData);
void handleButtonEvent(float deltaTime, uint32_t button, bool pressed, bool touched, bool isLeftHand);
void handleAxisEvent(float deltaTime, uint32_t axis, float x, float y, bool isLeftHand);
void handlePoseEvent(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, const mat4& mat,
diff --git a/scripts/developer/debugging/debugWindow.qml b/scripts/developer/debugging/debugWindow.qml
index f046a949ef..20fa24358d 100644
--- a/scripts/developer/debugging/debugWindow.qml
+++ b/scripts/developer/debugging/debugWindow.qml
@@ -18,6 +18,9 @@ Rectangle {
width: parent ? parent.width : 100
height: parent ? parent.height : 100
+ signal moved(vector2d position);
+ signal resized(size size);
+
property var channel;
TextArea {
diff --git a/scripts/developer/tests/viveTrackedObjects.js b/scripts/developer/tests/viveTrackedObjects.js
new file mode 100644
index 0000000000..78911538e4
--- /dev/null
+++ b/scripts/developer/tests/viveTrackedObjects.js
@@ -0,0 +1,36 @@
+
+var TRACKED_OBJECT_POSES = [
+ "TrackedObject00", "TrackedObject01", "TrackedObject02", "TrackedObject03",
+ "TrackedObject04", "TrackedObject05", "TrackedObject06", "TrackedObject07",
+ "TrackedObject08", "TrackedObject09", "TrackedObject10", "TrackedObject11",
+ "TrackedObject12", "TrackedObject13", "TrackedObject14", "TrackedObject15"
+];
+
+function init() {
+ Script.update.connect(update);
+}
+
+function shutdown() {
+ Script.update.disconnect(update);
+
+ TRACKED_OBJECT_POSES.forEach(function (key) {
+ DebugDraw.removeMyAvatarMarker(key);
+ });
+}
+
+var WHITE = {x: 1, y: 1, z: 1, w: 1};
+
+function update(dt) {
+ if (Controller.Hardware.Vive) {
+ TRACKED_OBJECT_POSES.forEach(function (key) {
+ var pose = Controller.getPoseValue(Controller.Hardware.Vive[key]);
+ if (pose.valid) {
+ DebugDraw.addMyAvatarMarker(key, pose.rotation, pose.translation, WHITE);
+ } else {
+ DebugDraw.removeMyAvatarMarker(key);
+ }
+ });
+ }
+}
+
+init();
diff --git a/scripts/system/controllers/teleport.js b/scripts/system/controllers/teleport.js
index 90f8ccb368..33c0b3116e 100644
--- a/scripts/system/controllers/teleport.js
+++ b/scripts/system/controllers/teleport.js
@@ -297,8 +297,9 @@ function Teleporter() {
} else if (teleportLocationType === TARGET.SURFACE) {
var offset = getAvatarFootOffset();
intersection.intersection.y += offset;
- MyAvatar.position = intersection.intersection;
+ MyAvatar.goToLocation(intersection.intersection, false, {x: 0, y: 0, z: 0, w: 1}, false);
HMD.centerUI();
+ MyAvatar.centerBody();
}
}
};
diff --git a/scripts/system/makeUserConnection.js b/scripts/system/makeUserConnection.js
index e70e0a2ea2..0a781a5bb8 100644
--- a/scripts/system/makeUserConnection.js
+++ b/scripts/system/makeUserConnection.js
@@ -543,12 +543,14 @@ function connectionRequestCompleted() { // Final result is in. Do effects.
// don't change state (so animation continues while gripped)
// but do send a notification, by calling the slot that emits the signal for it
Window.makeConnection(true, result.connection.new_connection ? "You and " + result.connection.username + " are now connected!" : result.connection.username);
+ UserActivityLogger.makeUserConnection(connectingId, true, result.connection.new_connection ? "new connection" : "already connected");
return;
} // failed
endHandshake();
debug("failing with result data", result);
// IWBNI we also did some fail sound/visual effect.
Window.makeConnection(false, result.connection);
+ UserActivityLogger.makeUserConnection(connectingId, false, result.connection);
}
var POLL_INTERVAL_MS = 200, POLL_LIMIT = 5;
function handleConnectionResponseAndMaybeRepeat(error, response) {
@@ -573,6 +575,7 @@ function handleConnectionResponseAndMaybeRepeat(error, response) {
} else if (error || (response.status !== 'success')) {
debug('server fail', error, response.status);
result = error ? {status: 'error', connection: error} : response;
+ UserActivityLogger.makeUserConnection(connectingId, false, error || response);
connectionRequestCompleted();
} else {
debug('server success', result);
diff --git a/scripts/system/pal.js b/scripts/system/pal.js
index b39c993894..5fbea90025 100644
--- a/scripts/system/pal.js
+++ b/scripts/system/pal.js
@@ -269,13 +269,26 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See
getConnectionData();
UserActivityLogger.palAction("refresh_connections", "");
break;
+ case 'removeConnection':
+ connectionUserName = message.params;
+ request({
+ uri: METAVERSE_BASE + '/api/v1/user/connections/' + connectionUserName,
+ method: 'DELETE'
+ }, function (error, response) {
+ if (error || (response.status !== 'success')) {
+ print("Error: unable to remove connection", connectionUserName, error || response.status);
+ return;
+ }
+ getConnectionData();
+ });
+ break
+
case 'removeFriend':
friendUserName = message.params;
request({
uri: METAVERSE_BASE + '/api/v1/user/friends/' + friendUserName,
method: 'DELETE'
}, function (error, response) {
- print(JSON.stringify(response));
if (error || (response.status !== 'success')) {
print("Error: unable to unfriend", friendUserName, error || response.status);
return;