diff --git a/BUILD_OSX.md b/BUILD_OSX.md
index 3365627b8c..586f81def3 100644
--- a/BUILD_OSX.md
+++ b/BUILD_OSX.md
@@ -4,7 +4,6 @@ Please read the [general build guide](BUILD.md) for information on dependencies
[Homebrew](https://brew.sh/) is an excellent package manager for OS X. It makes install of some High Fidelity dependencies very simple.
- brew tap homebrew/versions
brew install cmake openssl
### OpenSSL
diff --git a/domain-server/resources/web/assignment/placeholder.js b/domain-server/resources/web/assignment/placeholder.js
index 2c1d8253aa..bf64539bea 100644
--- a/domain-server/resources/web/assignment/placeholder.js
+++ b/domain-server/resources/web/assignment/placeholder.js
@@ -1,3 +1,3 @@
// Here you can put a script that will be run by an assignment-client (AC)
-// For examples, please go to http://public.highfidelity.io/scripts
+// For examples, please go to https://github.com/highfidelity/hifi/tree/master/script-archive/acScripts
// The directory named acScripts contains assignment-client specific scripts you can try.
diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml
index 2e7ff39ed6..e21e8b7354 100644
--- a/interface/resources/qml/LoginDialog.qml
+++ b/interface/resources/qml/LoginDialog.qml
@@ -27,6 +27,8 @@ ModalWindow {
destroyOnHidden: true
visible: true
+ readonly property bool isTablet: false
+
property string iconText: ""
property int iconSize: 50
@@ -35,6 +37,10 @@ ModalWindow {
keyboardOverride: true // Disable ModalWindow's keyboard.
+ function tryDestroy() {
+ root.destroy()
+ }
+
LoginDialog {
id: loginDialog
diff --git a/interface/resources/qml/LoginDialog/CompleteProfileBody.qml b/interface/resources/qml/LoginDialog/CompleteProfileBody.qml
index e06ce239ab..fe4c511f1d 100644
--- a/interface/resources/qml/LoginDialog/CompleteProfileBody.qml
+++ b/interface/resources/qml/LoginDialog/CompleteProfileBody.qml
@@ -29,11 +29,12 @@ Item {
readonly property int maxHeight: 720
function resize() {
- var targetWidth = Math.max(titleWidth, Math.max(additionalTextContainer.contentWidth,
- termsContainer.contentWidth))
+ if (root.isTablet === false) {
+ var targetWidth = Math.max(titleWidth, Math.max(additionalTextContainer.contentWidth,
+ termsContainer.contentWidth))
+ parent.width = root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth))
+ }
var targetHeight = 5 * hifi.dimensions.contentSpacing.y + buttons.height + additionalTextContainer.height + termsContainer.height
-
- parent.width = root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth))
parent.height = root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight))
}
}
@@ -61,11 +62,8 @@ Item {
Button {
anchors.verticalCenter: parent.verticalCenter
-
text: qsTr("Cancel")
-
-
- onClicked: root.destroy()
+ onClicked: root.tryDestroy()
}
}
@@ -96,17 +94,19 @@ Item {
id: termsContainer
anchors {
top: additionalTextContainer.bottom
- left: parent.left
margins: 0
topMargin: 2 * hifi.dimensions.contentSpacing.y
+ horizontalCenter: parent.horizontalCenter
}
+ width: parent.width
text: qsTr("By creating this user profile, you agree to High Fidelity's Terms of Service")
wrapMode: Text.WordWrap
color: hifi.colors.baseGrayHighlight
lineHeight: 1
lineHeightMode: Text.ProportionalHeight
- horizontalAlignment: Text.AlignHCenter
+ fontSizeMode: Text.HorizontalFit
+ horizontalAlignment: Text.AlignVCenter
onLinkActivated: loginDialog.openUrl(link)
}
@@ -128,8 +128,10 @@ Item {
console.log("Create Failed: " + error)
bodyLoader.source = "UsernameCollisionBody.qml"
- bodyLoader.item.width = root.pane.width
- bodyLoader.item.height = root.pane.height
+ if (!root.isTablet) {
+ bodyLoader.item.width = root.pane.width
+ bodyLoader.item.height = root.pane.height
+ }
}
onHandleLoginCompleted: {
console.log("Login Succeeded")
diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml
index e27635dbbd..c73aab08c3 100644
--- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml
+++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml
@@ -9,7 +9,7 @@
//
import Hifi 1.0
-import QtQuick 2.4
+import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4 as OriginalStyles
@@ -45,8 +45,7 @@ Item {
function resize() {
var targetWidth = Math.max(titleWidth, form.contentWidth);
var targetHeight = hifi.dimensions.contentSpacing.y + mainTextContainer.height +
- 4 * hifi.dimensions.contentSpacing.y + form.height +
- hifi.dimensions.contentSpacing.y + buttons.height;
+ 4 * hifi.dimensions.contentSpacing.y + form.height;
if (additionalInformation.visible) {
targetWidth = Math.max(targetWidth, additionalInformation.width);
@@ -66,9 +65,6 @@ Item {
if (loginDialog.isSteamRunning()) {
additionalInformation.visible = !isLoading
}
-
- leftButton.visible = !isLoading
- buttons.visible = !isLoading
}
BusyIndicator {
@@ -108,30 +104,27 @@ Item {
Column {
id: form
+ width: parent.width
+ onHeightChanged: d.resize(); onWidthChanged: d.resize();
+
anchors {
top: mainTextContainer.bottom
- left: parent.left
- margins: 0
topMargin: 2 * hifi.dimensions.contentSpacing.y
}
spacing: 2 * hifi.dimensions.contentSpacing.y
- Row {
- spacing: hifi.dimensions.contentSpacing.x
- TextField {
- id: usernameField
- anchors {
- verticalCenter: parent.verticalCenter
- }
- width: 350
-
- label: "Username or Email"
- }
+ TextField {
+ id: usernameField
+ width: parent.width
+ focus: true
+ label: "Username or Email"
ShortcutText {
anchors {
- verticalCenter: parent.verticalCenter
+ verticalCenter: usernameField.textFieldLabel.verticalCenter
+ left: usernameField.textFieldLabel.right
+ leftMargin: 10
}
text: "Forgot Username?"
@@ -143,23 +136,19 @@ Item {
onLinkActivated: loginDialog.openUrl(link)
}
}
- Row {
- spacing: hifi.dimensions.contentSpacing.x
- TextField {
- id: passwordField
- anchors {
- verticalCenter: parent.verticalCenter
- }
- width: 350
+ TextField {
+ id: passwordField
+ width: parent.width
- label: "Password"
- echoMode: TextInput.Password
- }
+ label: "Password"
+ echoMode: showPassword.checked ? TextInput.Normal : TextInput.Password
ShortcutText {
anchors {
- verticalCenter: parent.verticalCenter
+ verticalCenter: passwordField.textFieldLabel.verticalCenter
+ left: passwordField.textFieldLabel.right
+ leftMargin: 10
}
text: "Forgot Password?"
@@ -172,25 +161,76 @@ Item {
}
}
- }
-
- InfoItem {
- id: additionalInformation
- anchors {
- top: form.bottom
- left: parent.left
- margins: 0
- topMargin: hifi.dimensions.contentSpacing.y
+ CheckBoxQQC2 {
+ id: showPassword
+ text: "Show password"
}
- visible: loginDialog.isSteamRunning()
+ InfoItem {
+ id: additionalInformation
- text: qsTr("Your steam account informations will not be exposed to other users.")
- wrapMode: Text.WordWrap
- color: hifi.colors.baseGrayHighlight
- lineHeight: 1
- lineHeightMode: Text.ProportionalHeight
- horizontalAlignment: Text.AlignHCenter
+ visible: loginDialog.isSteamRunning()
+
+ text: qsTr("Your steam account informations will not be exposed to other users.")
+ wrapMode: Text.WordWrap
+ color: hifi.colors.baseGrayHighlight
+ lineHeight: 1
+ lineHeightMode: Text.ProportionalHeight
+ horizontalAlignment: Text.AlignHCenter
+ }
+
+ Row {
+ id: buttons
+ spacing: hifi.dimensions.contentSpacing.y*2
+ onHeightChanged: d.resize(); onWidthChanged: d.resize();
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ Button {
+ id: linkAccountButton
+ anchors.verticalCenter: parent.verticalCenter
+ width: 200
+
+ text: qsTr(loginDialog.isSteamRunning() ? "Link Account" : "Login")
+ color: hifi.buttons.blue
+
+ onClicked: linkAccountBody.login()
+ }
+
+ Button {
+ anchors.verticalCenter: parent.verticalCenter
+ text: qsTr("Cancel")
+ onClicked: root.tryDestroy()
+ }
+ }
+
+ Row {
+ id: leftButton
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: hifi.dimensions.contentSpacing.y*2
+ onHeightChanged: d.resize(); onWidthChanged: d.resize();
+
+ RalewaySemiBold {
+ size: hifi.fontSizes.inputLabel
+ anchors.verticalCenter: parent.verticalCenter
+ text: qsTr("Don't have an account?")
+ }
+
+ Button {
+ anchors.verticalCenter: parent.verticalCenter
+
+ text: qsTr("Sign Up")
+ visible: !loginDialog.isSteamRunning()
+
+ onClicked: {
+ bodyLoader.setSource("SignUpBody.qml")
+ if (!root.isTablet) {
+ bodyLoader.item.width = root.pane.width
+ bodyLoader.item.height = root.pane.height
+ }
+ }
+ }
+ }
}
// Override ScrollingWindow's keyboard that would be at very bottom of dialog.
@@ -200,70 +240,22 @@ Item {
anchors {
left: parent.left
right: parent.right
- bottom: buttons.top
+ bottom: parent.bottom
bottomMargin: keyboardRaised ? 2 * hifi.dimensions.contentSpacing.y : 0
}
}
- Row {
- id: leftButton
- anchors {
- left: parent.left
- bottom: parent.bottom
- bottomMargin: hifi.dimensions.contentSpacing.y
- }
-
- spacing: hifi.dimensions.contentSpacing.x
- onHeightChanged: d.resize(); onWidthChanged: d.resize();
-
- Button {
- anchors.verticalCenter: parent.verticalCenter
-
- text: qsTr("Sign Up")
- visible: !loginDialog.isSteamRunning()
-
- onClicked: {
- bodyLoader.setSource("SignUpBody.qml")
- bodyLoader.item.width = root.pane.width
- bodyLoader.item.height = root.pane.height
- }
- }
- }
-
- Row {
- id: buttons
- anchors {
- right: parent.right
- bottom: parent.bottom
- bottomMargin: hifi.dimensions.contentSpacing.y
- }
- spacing: hifi.dimensions.contentSpacing.x
- onHeightChanged: d.resize(); onWidthChanged: d.resize();
-
- Button {
- id: linkAccountButton
- anchors.verticalCenter: parent.verticalCenter
- width: 200
-
- text: qsTr(loginDialog.isSteamRunning() ? "Link Account" : "Login")
- color: hifi.buttons.blue
-
- onClicked: linkAccountBody.login()
- }
-
- Button {
- anchors.verticalCenter: parent.verticalCenter
-
- text: qsTr("Cancel")
-
- onClicked: root.destroy()
- }
- }
-
Component.onCompleted: {
root.title = qsTr("Sign Into High Fidelity")
root.iconText = "<"
- keyboardEnabled = HMD.active;
+
+ //dont rise local keyboard
+ keyboardEnabled = !root.isTablet && HMD.active;
+ //but rise Tablet's one instead for Tablet interface
+ if (root.isTablet) {
+ root.keyboardEnabled = HMD.active;
+ root.keyboardRaised = Qt.binding( function() { return keyboardRaised; })
+ }
d.resize();
if (failAfterSignUp) {
@@ -311,11 +303,11 @@ Item {
}
switch (event.key) {
- case Qt.Key_Enter:
- case Qt.Key_Return:
- event.accepted = true
- linkAccountBody.login()
- break
+ case Qt.Key_Enter:
+ case Qt.Key_Return:
+ event.accepted = true
+ linkAccountBody.login()
+ break
}
}
}
diff --git a/interface/resources/qml/LoginDialog/SignInBody.qml b/interface/resources/qml/LoginDialog/SignInBody.qml
index 167ed1640a..c4b6c2aee1 100644
--- a/interface/resources/qml/LoginDialog/SignInBody.qml
+++ b/interface/resources/qml/LoginDialog/SignInBody.qml
@@ -9,7 +9,7 @@
//
import Hifi 1.0
-import QtQuick 2.4
+import QtQuick 2.7
import QtQuick.Controls.Styles 1.4 as OriginalStyles
import "../controls-uit"
@@ -18,8 +18,8 @@ import "../styles-uit"
Item {
id: signInBody
clip: true
- width: root.pane.width
height: root.pane.height
+ width: root.pane.width
property bool required: false
@@ -29,7 +29,7 @@ Item {
}
function cancel() {
- root.destroy()
+ root.tryDestroy()
}
QtObject {
@@ -121,8 +121,10 @@ Item {
console.log("Login Failed")
bodyLoader.source = "CompleteProfileBody.qml"
- bodyLoader.item.width = root.pane.width
- bodyLoader.item.height = root.pane.height
+ if (!root.isTablet) {
+ bodyLoader.item.width = root.pane.width
+ bodyLoader.item.height = root.pane.height
+ }
}
}
}
diff --git a/interface/resources/qml/LoginDialog/SignUpBody.qml b/interface/resources/qml/LoginDialog/SignUpBody.qml
index c0ff2d77cb..f6cf40db8e 100644
--- a/interface/resources/qml/LoginDialog/SignUpBody.qml
+++ b/interface/resources/qml/LoginDialog/SignUpBody.qml
@@ -9,7 +9,7 @@
//
import Hifi 1.0
-import QtQuick 2.4
+import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4 as OriginalStyles
@@ -44,8 +44,7 @@ Item {
function resize() {
var targetWidth = Math.max(titleWidth, form.contentWidth);
var targetHeight = hifi.dimensions.contentSpacing.y + mainTextContainer.height +
- 4 * hifi.dimensions.contentSpacing.y + form.height +
- hifi.dimensions.contentSpacing.y + buttons.height;
+ 4 * hifi.dimensions.contentSpacing.y + form.height;
parent.width = root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth));
parent.height = root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight))
@@ -96,44 +95,31 @@ Item {
Column {
id: form
+ width: parent.width
+ onHeightChanged: d.resize(); onWidthChanged: d.resize();
+
anchors {
top: mainTextContainer.bottom
- left: parent.left
- margins: 0
topMargin: 2 * hifi.dimensions.contentSpacing.y
}
spacing: 2 * hifi.dimensions.contentSpacing.y
- Row {
- spacing: hifi.dimensions.contentSpacing.x
-
- TextField {
- id: emailField
- anchors {
- verticalCenter: parent.verticalCenter
- }
- width: 350
-
- label: "Email"
- }
+ TextField {
+ id: emailField
+ width: parent.width
+ label: "Email"
}
- Row {
- spacing: hifi.dimensions.contentSpacing.x
-
- TextField {
- id: usernameField
- anchors {
- verticalCenter: parent.verticalCenter
- }
- width: 350
-
- label: "Username"
- }
+ TextField {
+ id: usernameField
+ width: parent.width
+ label: "Username"
ShortcutText {
anchors {
- verticalCenter: parent.verticalCenter
+ verticalCenter: parent.textFieldLabel.verticalCenter
+ left: parent.textFieldLabel.right
+ leftMargin: 10
}
text: qsTr("No spaces / special chars.")
@@ -145,23 +131,17 @@ Item {
}
}
- Row {
- spacing: hifi.dimensions.contentSpacing.x
-
- TextField {
- id: passwordField
- anchors {
- verticalCenter: parent.verticalCenter
- }
- width: 350
-
- label: "Password"
- echoMode: TextInput.Password
- }
+ TextField {
+ id: passwordField
+ width: parent.width
+ label: "Password"
+ echoMode: TextInput.Password
ShortcutText {
anchors {
- verticalCenter: parent.verticalCenter
+ verticalCenter: parent.textFieldLabel.verticalCenter
+ left: parent.textFieldLabel.right
+ leftMargin: 10
}
text: qsTr("At least 6 characters")
@@ -173,6 +153,53 @@ Item {
}
}
+ Row {
+ id: leftButton
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ spacing: hifi.dimensions.contentSpacing.x
+ onHeightChanged: d.resize(); onWidthChanged: d.resize();
+
+ Button {
+ anchors.verticalCenter: parent.verticalCenter
+
+ text: qsTr("Existing User")
+
+ onClicked: {
+ bodyLoader.setSource("LinkAccountBody.qml")
+ if (!root.isTablet) {
+ bodyLoader.item.width = root.pane.width
+ bodyLoader.item.height = root.pane.height
+ }
+ }
+ }
+ }
+
+ Row {
+ id: buttons
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: hifi.dimensions.contentSpacing.x
+ onHeightChanged: d.resize(); onWidthChanged: d.resize();
+
+ Button {
+ id: linkAccountButton
+ anchors.verticalCenter: parent.verticalCenter
+ width: 200
+
+ text: qsTr("Sign Up")
+ color: hifi.buttons.blue
+
+ onClicked: signupBody.signup()
+ }
+
+ Button {
+ anchors.verticalCenter: parent.verticalCenter
+
+ text: qsTr("Cancel")
+
+ onClicked: root.tryDestroy()
+ }
+ }
}
// Override ScrollingWindow's keyboard that would be at very bottom of dialog.
@@ -182,69 +209,21 @@ Item {
anchors {
left: parent.left
right: parent.right
- bottom: buttons.top
+ bottom: parent.bottom
bottomMargin: keyboardRaised ? 2 * hifi.dimensions.contentSpacing.y : 0
}
}
- Row {
- id: leftButton
- anchors {
- left: parent.left
- bottom: parent.bottom
- bottomMargin: hifi.dimensions.contentSpacing.y
- }
-
- spacing: hifi.dimensions.contentSpacing.x
- onHeightChanged: d.resize(); onWidthChanged: d.resize();
-
- Button {
- anchors.verticalCenter: parent.verticalCenter
-
- text: qsTr("Existing User")
-
- onClicked: {
- bodyLoader.setSource("LinkAccountBody.qml")
- bodyLoader.item.width = root.pane.width
- bodyLoader.item.height = root.pane.height
- }
- }
- }
-
- Row {
- id: buttons
- anchors {
- right: parent.right
- bottom: parent.bottom
- bottomMargin: hifi.dimensions.contentSpacing.y
- }
- spacing: hifi.dimensions.contentSpacing.x
- onHeightChanged: d.resize(); onWidthChanged: d.resize();
-
- Button {
- id: linkAccountButton
- anchors.verticalCenter: parent.verticalCenter
- width: 200
-
- text: qsTr("Sign Up")
- color: hifi.buttons.blue
-
- onClicked: signupBody.signup()
- }
-
- Button {
- anchors.verticalCenter: parent.verticalCenter
-
- text: qsTr("Cancel")
-
- onClicked: root.destroy()
- }
- }
-
Component.onCompleted: {
root.title = qsTr("Create an Account")
root.iconText = "<"
- keyboardEnabled = HMD.active;
+ //dont rise local keyboard
+ keyboardEnabled = !root.isTablet && HMD.active;
+ //but rise Tablet's one instead for Tablet interface
+ if (root.isTablet) {
+ root.keyboardEnabled = HMD.active;
+ root.keyboardRaised = Qt.binding( function() { return keyboardRaised; })
+ }
d.resize();
emailField.forceActiveFocus();
@@ -275,8 +254,10 @@ Item {
onHandleLoginFailed: {
// we failed to login, show the LoginDialog so the user will try again
bodyLoader.setSource("LinkAccountBody.qml", { "failAfterSignUp": true })
- bodyLoader.item.width = root.pane.width
- bodyLoader.item.height = root.pane.height
+ if (!root.isTablet) {
+ bodyLoader.item.width = root.pane.width
+ bodyLoader.item.height = root.pane.height
+ }
}
}
diff --git a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml
index 18c831b3a9..5c212578b8 100644
--- a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml
+++ b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml
@@ -79,7 +79,7 @@ Item {
margins: 0
topMargin: hifi.dimensions.contentSpacing.y
}
- width: 250
+ width: parent.width
placeholderText: "Choose your own"
}
@@ -102,7 +102,7 @@ Item {
bottom: parent.bottom
right: parent.right
margins: 0
- topMargin: hifi.dimensions.contentSpacing.y
+ bottomMargin: hifi.dimensions.contentSpacing.y
}
spacing: hifi.dimensions.contentSpacing.x
onHeightChanged: d.resize(); onWidthChanged: d.resize();
@@ -122,14 +122,21 @@ Item {
text: qsTr("Cancel")
- onClicked: root.destroy()
+ onClicked: root.tryDestroy()
}
}
Component.onCompleted: {
root.title = qsTr("Complete Your Profile")
root.iconText = "<"
- keyboardEnabled = HMD.active;
+ //dont rise local keyboard
+ keyboardEnabled = !root.isTablet && HMD.active;
+ //but rise Tablet's one instead for Tablet interface
+ if (root.isTablet) {
+ root.keyboardEnabled = HMD.active;
+ root.keyboardRaised = Qt.binding( function() { return keyboardRaised; })
+ }
+
d.resize();
}
diff --git a/interface/resources/qml/LoginDialog/WelcomeBody.qml b/interface/resources/qml/LoginDialog/WelcomeBody.qml
index eb91956532..551ec263b7 100644
--- a/interface/resources/qml/LoginDialog/WelcomeBody.qml
+++ b/interface/resources/qml/LoginDialog/WelcomeBody.qml
@@ -77,7 +77,7 @@ Item {
text: qsTr("Close");
- onClicked: root.destroy()
+ onClicked: root.tryDestroy()
}
}
diff --git a/interface/resources/qml/TabletLoginDialog/CompleteProfileBody.qml b/interface/resources/qml/TabletLoginDialog/CompleteProfileBody.qml
deleted file mode 100644
index 6024563bcf..0000000000
--- a/interface/resources/qml/TabletLoginDialog/CompleteProfileBody.qml
+++ /dev/null
@@ -1,124 +0,0 @@
-//
-// CompleteProfileBody.qml
-//
-// Created by Clement on 7/18/16
-// Copyright 2015 High Fidelity, Inc.
-//
-// Distributed under the Apache License, Version 2.0.
-// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-//
-
-import Hifi 1.0
-import QtQuick 2.4
-import QtQuick.Controls.Styles 1.4 as OriginalStyles
-
-import "../controls-uit"
-import "../styles-uit"
-
-Item {
- id: completeProfileBody
- clip: true
-
- QtObject {
- id: d
- function resize() {}
- }
-
- Row {
- id: buttons
- anchors {
- top: parent.top
- horizontalCenter: parent.horizontalCenter
- margins: 0
- topMargin: 2 * hifi.dimensions.contentSpacing.y
- }
- spacing: hifi.dimensions.contentSpacing.x
- onHeightChanged: d.resize(); onWidthChanged: d.resize();
-
- Button {
- anchors.verticalCenter: parent.verticalCenter
- width: 200
-
- text: qsTr("Create your profile")
- color: hifi.buttons.blue
-
- onClicked: loginDialog.createAccountFromStream()
- }
-
- Button {
- anchors.verticalCenter: parent.verticalCenter
-
- text: qsTr("Cancel")
-
- onClicked: bodyLoader.popup()
- }
- }
-
- ShortcutText {
- id: additionalTextContainer
- anchors {
- top: buttons.bottom
- horizontalCenter: parent.horizontalCenter
- margins: 0
- topMargin: hifi.dimensions.contentSpacing.y
- }
-
- text: "Already have a High Fidelity profile? Link to an existing profile here."
-
- wrapMode: Text.WordWrap
- lineHeight: 2
- lineHeightMode: Text.ProportionalHeight
- horizontalAlignment: Text.AlignHCenter
-
- onLinkActivated: {
- bodyLoader.setSource("LinkAccountBody.qml")
- }
- }
-
- InfoItem {
- id: termsContainer
- anchors {
- top: additionalTextContainer.bottom
- left: parent.left
- margins: 0
- topMargin: 2 * hifi.dimensions.contentSpacing.y
- }
-
- text: qsTr("By creating this user profile, you agree to High Fidelity's Terms of Service")
- wrapMode: Text.WordWrap
- color: hifi.colors.baseGrayHighlight
- lineHeight: 1
- lineHeightMode: Text.ProportionalHeight
- horizontalAlignment: Text.AlignHCenter
-
- onLinkActivated: loginDialog.openUrl(link)
- }
-
- Component.onCompleted: {
- loginDialogRoot.title = qsTr("Complete Your Profile")
- loginDialogRoot.iconText = "<"
- d.resize();
- }
-
- Connections {
- target: loginDialog
- onHandleCreateCompleted: {
- console.log("Create Succeeded")
-
- loginDialog.loginThroughSteam()
- }
- onHandleCreateFailed: {
- console.log("Create Failed: " + error)
-
- bodyLoadersetSource("UsernameCollisionBody.qml")
- }
- onHandleLoginCompleted: {
- console.log("Login Succeeded")
-
- bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : false })
- }
- onHandleLoginFailed: {
- console.log("Login Failed")
- }
- }
-}
diff --git a/interface/resources/qml/TabletLoginDialog/LinkAccountBody.qml b/interface/resources/qml/TabletLoginDialog/LinkAccountBody.qml
deleted file mode 100644
index 8010a34250..0000000000
--- a/interface/resources/qml/TabletLoginDialog/LinkAccountBody.qml
+++ /dev/null
@@ -1,296 +0,0 @@
-//
-// LinkAccountBody.qml
-//
-// Created by Clement on 7/18/16
-// Copyright 2015 High Fidelity, Inc.
-//
-// Distributed under the Apache License, Version 2.0.
-// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-//
-
-import Hifi 1.0
-import QtQuick 2.4
-import QtQuick.Controls 1.4
-import QtQuick.Controls.Styles 1.4 as OriginalStyles
-
-import "../controls-uit"
-import "../styles-uit"
-
-Item {
- id: linkAccountBody
- clip: true
- height: parent.height
- width: parent.width
- property bool failAfterSignUp: false
-
- function login() {
- mainTextContainer.visible = false
- toggleLoading(true)
- loginDialog.login(usernameField.text, passwordField.text)
- }
-
- property bool keyboardEnabled: false
- property bool keyboardRaised: false
- property bool punctuationMode: false
-
- onKeyboardRaisedChanged: d.resize();
-
- QtObject {
- id: d
- function resize() {}
- }
-
- function toggleLoading(isLoading) {
- linkAccountSpinner.visible = isLoading
- form.visible = !isLoading
-
- if (loginDialog.isSteamRunning()) {
- additionalInformation.visible = !isLoading
- }
-
- leftButton.visible = !isLoading
- buttons.visible = !isLoading
- }
-
- BusyIndicator {
- id: linkAccountSpinner
-
- anchors {
- top: parent.top
- horizontalCenter: parent.horizontalCenter
- topMargin: hifi.dimensions.contentSpacing.y
- }
-
- visible: false
- running: true
-
- width: 48
- height: 48
- }
-
- ShortcutText {
- id: mainTextContainer
- anchors {
- top: parent.top
- left: parent.left
- margins: 0
- topMargin: hifi.dimensions.contentSpacing.y
- }
-
- visible: false
-
- text: qsTr("Username or password incorrect.")
- wrapMode: Text.WordWrap
- color: hifi.colors.redAccent
- lineHeight: 1
- lineHeightMode: Text.ProportionalHeight
- horizontalAlignment: Text.AlignHCenter
- }
-
- Column {
- id: form
- anchors {
- top: mainTextContainer.bottom
- left: parent.left
- margins: 0
- topMargin: 2 * hifi.dimensions.contentSpacing.y
- }
- spacing: 2 * hifi.dimensions.contentSpacing.y
-
- Row {
- spacing: hifi.dimensions.contentSpacing.x
-
- TextField {
- id: usernameField
- anchors {
- verticalCenter: parent.verticalCenter
- }
- width: 350
-
- label: "Username or Email"
- }
-
- ShortcutText {
- anchors {
- verticalCenter: parent.verticalCenter
- }
-
- text: "Forgot Username?"
-
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
- linkColor: hifi.colors.blueAccent
-
- onLinkActivated: loginDialog.openUrl(link)
- }
- }
- Row {
- spacing: hifi.dimensions.contentSpacing.x
-
- TextField {
- id: passwordField
- anchors {
- verticalCenter: parent.verticalCenter
- }
- width: 350
-
- label: "Password"
- echoMode: TextInput.Password
- }
-
- ShortcutText {
- anchors {
- verticalCenter: parent.verticalCenter
- }
-
- text: "Forgot Password?"
-
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
- linkColor: hifi.colors.blueAccent
-
- onLinkActivated: loginDialog.openUrl(link)
- }
- }
-
- }
-
- InfoItem {
- id: additionalInformation
- anchors {
- top: form.bottom
- left: parent.left
- margins: 0
- topMargin: hifi.dimensions.contentSpacing.y
- }
-
- visible: loginDialog.isSteamRunning()
-
- text: qsTr("Your steam account informations will not be exposed to other users.")
- wrapMode: Text.WordWrap
- color: hifi.colors.baseGrayHighlight
- lineHeight: 1
- lineHeightMode: Text.ProportionalHeight
- horizontalAlignment: Text.AlignHCenter
- }
-
- // Override ScrollingWindow's keyboard that would be at very bottom of dialog.
- Keyboard {
- raised: keyboardEnabled && keyboardRaised
- numeric: punctuationMode
- anchors {
- left: parent.left
- right: parent.right
- bottom: buttons.top
- bottomMargin: keyboardRaised ? 2 * hifi.dimensions.contentSpacing.y : 0
- }
- }
-
- Row {
- id: leftButton
- anchors {
- left: parent.left
- bottom: parent.bottom
- bottomMargin: hifi.dimensions.contentSpacing.y
- }
-
- spacing: hifi.dimensions.contentSpacing.x
- onHeightChanged: d.resize(); onWidthChanged: d.resize();
-
- Button {
- anchors.verticalCenter: parent.verticalCenter
-
- text: qsTr("Sign Up")
- visible: !loginDialog.isSteamRunning()
-
- onClicked: {
- bodyLoader.setSource("SignUpBody.qml")
- }
- }
- }
-
- Row {
- id: buttons
- anchors {
- right: parent.right
- bottom: parent.bottom
- bottomMargin: hifi.dimensions.contentSpacing.y
- }
- spacing: hifi.dimensions.contentSpacing.x
- onHeightChanged: d.resize(); onWidthChanged: d.resize();
-
- Button {
- id: linkAccountButton
- anchors.verticalCenter: parent.verticalCenter
- width: 200
-
- text: qsTr(loginDialog.isSteamRunning() ? "Link Account" : "Login")
- color: hifi.buttons.blue
-
- onClicked: linkAccountBody.login()
- }
-
- Button {
- anchors.verticalCenter: parent.verticalCenter
- text: qsTr("Cancel")
- onClicked: {
- bodyLoader.popup()
- }
- }
- }
-
- Component.onCompleted: {
- loginDialogRoot.title = qsTr("Sign Into High Fidelity")
- loginDialogRoot.iconText = "<"
- keyboardEnabled = HMD.active;
- d.resize();
-
- if (failAfterSignUp) {
- mainTextContainer.text = "Account created successfully."
- mainTextContainer.visible = true
- }
-
- usernameField.forceActiveFocus();
- }
-
- Connections {
- target: loginDialog
- onHandleLoginCompleted: {
- console.log("Login Succeeded, linking steam account")
-
- if (loginDialog.isSteamRunning()) {
- loginDialog.linkSteam()
- } else {
- bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : true })
- }
- }
- onHandleLoginFailed: {
- console.log("Login Failed")
- mainTextContainer.visible = true
- toggleLoading(false)
- }
- onHandleLinkCompleted: {
- console.log("Link Succeeded")
-
- bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : true })
- }
- onHandleLinkFailed: {
- console.log("Link Failed")
- toggleLoading(false)
- }
- }
-
- Keys.onPressed: {
- if (!visible) {
- return
- }
-
- switch (event.key) {
- case Qt.Key_Enter:
- case Qt.Key_Return:
- event.accepted = true
- linkAccountBody.login()
- break
- }
- }
-}
diff --git a/interface/resources/qml/TabletLoginDialog/SignInBody.qml b/interface/resources/qml/TabletLoginDialog/SignInBody.qml
deleted file mode 100644
index 9cdf69c7bc..0000000000
--- a/interface/resources/qml/TabletLoginDialog/SignInBody.qml
+++ /dev/null
@@ -1,109 +0,0 @@
-//
-// SignInBody.qml
-//
-// Created by Clement on 7/18/16
-// Copyright 2015 High Fidelity, Inc.
-//
-// Distributed under the Apache License, Version 2.0.
-// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-//
-
-import Hifi 1.0
-import QtQuick 2.4
-import QtQuick.Controls.Styles 1.4 as OriginalStyles
-
-import "../controls-uit"
-import "../styles-uit"
-
-Item {
- id: signInBody
- clip: true
-
- property bool required: false
-
- function login() {
- console.log("Trying to log in")
- loginDialog.loginThroughSteam()
- }
-
- function cancel() {
- bodyLoader.popup()
- }
-
- QtObject {
- id: d
- function resize() {}
- }
-
- InfoItem {
- id: mainTextContainer
- anchors {
- top: parent.top
- horizontalCenter: parent.horizontalCenter
- margins: 0
- topMargin: hifi.dimensions.contentSpacing.y
- }
-
- text: required ? qsTr("This domain's owner requires that you sign in:")
- : qsTr("Sign in to access your user account:")
- wrapMode: Text.WordWrap
- color: hifi.colors.baseGrayHighlight
- lineHeight: 2
- lineHeightMode: Text.ProportionalHeight
- horizontalAlignment: Text.AlignHCenter
- }
-
- Row {
- id: buttons
- anchors {
- top: mainTextContainer.bottom
- horizontalCenter: parent.horizontalCenter
- margins: 0
- topMargin: 2 * hifi.dimensions.contentSpacing.y
- }
- spacing: hifi.dimensions.contentSpacing.x
- onHeightChanged: d.resize(); onWidthChanged: d.resize();
-
- Button {
- anchors.verticalCenter: parent.verticalCenter
-
- width: undefined // invalidate so that the image's size sets the width
- height: undefined // invalidate so that the image's size sets the height
- focus: true
-
- style: OriginalStyles.ButtonStyle {
- background: Image {
- id: buttonImage
- source: "../../images/steam-sign-in.png"
- }
- }
- onClicked: signInBody.login()
- }
- Button {
- anchors.verticalCenter: parent.verticalCenter
-
- text: qsTr("Cancel");
-
- onClicked: signInBody.cancel()
- }
- }
-
- Component.onCompleted: {
- loginDialogRoot.title = required ? qsTr("Sign In Required")
- : qsTr("Sign In")
- loginDialogRoot.iconText = ""
- d.resize();
- }
-
- Connections {
- target: loginDialog
- onHandleLoginCompleted: {
- console.log("Login Succeeded")
- bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : true })
- }
- onHandleLoginFailed: {
- console.log("Login Failed")
- bodyLoader.setSource("CompleteProfileBody.qml")
- }
- }
-}
diff --git a/interface/resources/qml/TabletLoginDialog/SignUpBody.qml b/interface/resources/qml/TabletLoginDialog/SignUpBody.qml
deleted file mode 100644
index 2cfc0e736a..0000000000
--- a/interface/resources/qml/TabletLoginDialog/SignUpBody.qml
+++ /dev/null
@@ -1,276 +0,0 @@
-//
-// SignUpBody.qml
-//
-// Created by Stephen Birarda on 7 Dec 2016
-// Copyright 2016 High Fidelity, Inc.
-//
-// Distributed under the Apache License, Version 2.0.
-// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-//
-
-import Hifi 1.0
-import QtQuick 2.4
-import QtQuick.Controls 1.4
-import QtQuick.Controls.Styles 1.4 as OriginalStyles
-
-import "../controls-uit"
-import "../styles-uit"
-
-Item {
- id: signupBody
- clip: true
-// height: parent.height
-// width: parent.width
-
- function signup() {
- mainTextContainer.visible = false
- toggleLoading(true)
- loginDialog.signup(emailField.text, usernameField.text, passwordField.text)
- }
-
- property bool keyboardEnabled: false
- property bool keyboardRaised: false
- property bool punctuationMode: false
-
- onKeyboardRaisedChanged: d.resize();
-
- QtObject {
- id: d
- function resize() {}
- }
-
- function toggleLoading(isLoading) {
- linkAccountSpinner.visible = isLoading
- form.visible = !isLoading
-
- leftButton.visible = !isLoading
- buttons.visible = !isLoading
- }
-
- BusyIndicator {
- id: linkAccountSpinner
-
- anchors {
- top: parent.top
- horizontalCenter: parent.horizontalCenter
- topMargin: hifi.dimensions.contentSpacing.y
- }
-
- visible: false
- running: true
-
- width: 48
- height: 48
- }
-
- ShortcutText {
- id: mainTextContainer
- anchors {
- top: parent.top
- left: parent.left
- margins: 0
- topMargin: hifi.dimensions.contentSpacing.y
- }
-
- visible: false
-
- text: qsTr("There was an unknown error while creating your account.")
- wrapMode: Text.WordWrap
- color: hifi.colors.redAccent
- horizontalAlignment: Text.AlignLeft
- }
-
- Column {
- id: form
- anchors {
- top: mainTextContainer.bottom
- left: parent.left
- margins: 0
- topMargin: 2 * hifi.dimensions.contentSpacing.y
- }
- spacing: 2 * hifi.dimensions.contentSpacing.y
-
- Row {
- spacing: hifi.dimensions.contentSpacing.x
-
- TextField {
- id: emailField
- anchors {
- verticalCenter: parent.verticalCenter
- }
- width: 300
-
- label: "Email"
- }
- }
-
- Row {
- spacing: hifi.dimensions.contentSpacing.x
-
- TextField {
- id: usernameField
- anchors {
- verticalCenter: parent.verticalCenter
- }
- width: 300
-
- label: "Username"
- }
-
- ShortcutText {
- anchors {
- verticalCenter: parent.verticalCenter
- }
-
- text: qsTr("No spaces / special chars.")
-
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
-
- color: hifi.colors.blueAccent
- }
- }
-
- Row {
- spacing: hifi.dimensions.contentSpacing.x
-
- TextField {
- id: passwordField
- anchors {
- verticalCenter: parent.verticalCenter
- }
- width: 300
-
- label: "Password"
- echoMode: TextInput.Password
- }
-
- ShortcutText {
- anchors {
- verticalCenter: parent.verticalCenter
- }
-
- text: qsTr("At least 6 characters")
-
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
-
- color: hifi.colors.blueAccent
- }
- }
-
- }
-
- // Override ScrollingWindow's keyboard that would be at very bottom of dialog.
- Keyboard {
- raised: keyboardEnabled && keyboardRaised
- numeric: punctuationMode
- anchors {
- left: parent.left
- right: parent.right
- bottom: buttons.top
- bottomMargin: keyboardRaised ? 2 * hifi.dimensions.contentSpacing.y : 0
- }
- }
-
- Row {
- id: leftButton
- anchors {
- left: parent.left
- bottom: parent.bottom
- bottomMargin: hifi.dimensions.contentSpacing.y
- }
-
- spacing: hifi.dimensions.contentSpacing.x
- onHeightChanged: d.resize(); onWidthChanged: d.resize();
-
- Button {
- anchors.verticalCenter: parent.verticalCenter
-
- text: qsTr("Existing User")
-
- onClicked: {
- bodyLoader.setSource("LinkAccountBody.qml")
- }
- }
- }
-
- Row {
- id: buttons
- anchors {
- right: parent.right
- bottom: parent.bottom
- bottomMargin: hifi.dimensions.contentSpacing.y
- }
- spacing: hifi.dimensions.contentSpacing.x
- onHeightChanged: d.resize(); onWidthChanged: d.resize();
-
- Button {
- id: linkAccountButton
- anchors.verticalCenter: parent.verticalCenter
- width: 200
-
- text: qsTr("Sign Up")
- color: hifi.buttons.blue
-
- onClicked: signupBody.signup()
- }
-
- Button {
- anchors.verticalCenter: parent.verticalCenter
-
- text: qsTr("Cancel")
-
- onClicked: bodyLoader.popup()
- }
- }
-
- Component.onCompleted: {
- loginDialogRoot.title = qsTr("Create an Account")
- loginDialogRoot.iconText = "<"
- keyboardEnabled = HMD.active;
- d.resize();
-
- emailField.forceActiveFocus();
- }
-
- Connections {
- target: loginDialog
- onHandleSignupCompleted: {
- console.log("Sign Up Succeeded");
-
- // now that we have an account, login with that username and password
- loginDialog.login(usernameField.text, passwordField.text)
- }
- onHandleSignupFailed: {
- console.log("Sign Up Failed")
- toggleLoading(false)
-
- mainTextContainer.text = errorString
- mainTextContainer.visible = true
-
- d.resize();
- }
- onHandleLoginCompleted: {
- bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack": false })
- }
- onHandleLoginFailed: {
- // we failed to login, show the LoginDialog so the user will try again
- bodyLoader.setSource("LinkAccountBody.qml", { "failAfterSignUp": true })
- }
- }
-
- Keys.onPressed: {
- if (!visible) {
- return
- }
-
- switch (event.key) {
- case Qt.Key_Enter:
- case Qt.Key_Return:
- event.accepted = true
- signupBody.signup()
- break
- }
- }
-}
diff --git a/interface/resources/qml/TabletLoginDialog/UsernameCollisionBody.qml b/interface/resources/qml/TabletLoginDialog/UsernameCollisionBody.qml
deleted file mode 100644
index 9e5b01d339..0000000000
--- a/interface/resources/qml/TabletLoginDialog/UsernameCollisionBody.qml
+++ /dev/null
@@ -1,157 +0,0 @@
-//
-// UsernameCollisionBody.qml
-//
-// Created by Clement on 7/18/16
-// Copyright 2015 High Fidelity, Inc.
-//
-// Distributed under the Apache License, Version 2.0.
-// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-//
-
-import Hifi 1.0
-import QtQuick 2.4
-import QtQuick.Controls 1.4
-import QtQuick.Controls.Styles 1.4 as OriginalStyles
-
-import "../controls-uit"
-import "../styles-uit"
-
-Item {
- id: usernameCollisionBody
- clip: true
- width: parent.width
- height: parent.height
-
- function create() {
- mainTextContainer.visible = false
- loginDialog.createAccountFromStream(textField.text)
- }
-
-
- property bool keyboardEnabled: false
- property bool keyboardRaised: false
- property bool punctuationMode: false
-
- onKeyboardRaisedChanged: d.resize();
-
- QtObject {
- id: d
- function resize() {}
- }
-
- ShortcutText {
- id: mainTextContainer
- anchors {
- top: parent.top
- left: parent.left
- margins: 0
- topMargin: hifi.dimensions.contentSpacing.y
- }
-
- text: qsTr("Your Steam username is not available.")
- wrapMode: Text.WordWrap
- color: hifi.colors.redAccent
- lineHeight: 1
- lineHeightMode: Text.ProportionalHeight
- horizontalAlignment: Text.AlignHCenter
- }
-
-
- TextField {
- id: textField
- anchors {
- top: mainTextContainer.bottom
- left: parent.left
- margins: 0
- topMargin: hifi.dimensions.contentSpacing.y
- }
- width: 250
-
- placeholderText: "Choose your own"
- }
-
- // Override ScrollingWindow's keyboard that would be at very bottom of dialog.
- Keyboard {
- raised: keyboardEnabled && keyboardRaised
- numeric: punctuationMode
- anchors {
- left: parent.left
- right: parent.right
- bottom: buttons.top
- bottomMargin: keyboardRaised ? 2 * hifi.dimensions.contentSpacing.y : 0
- }
- }
-
- Row {
- id: buttons
- anchors {
- bottom: parent.bottom
- right: parent.right
- margins: 0
- topMargin: hifi.dimensions.contentSpacing.y
- }
- spacing: hifi.dimensions.contentSpacing.x
- onHeightChanged: d.resize(); onWidthChanged: d.resize();
-
- Button {
- anchors.verticalCenter: parent.verticalCenter
- width: 200
-
- text: qsTr("Create your profile")
- color: hifi.buttons.blue
-
- onClicked: usernameCollisionBody.create()
- }
-
- Button {
- anchors.verticalCenter: parent.verticalCenter
-
- text: qsTr("Cancel")
- onClicked: bodyLoader.popup()
- }
- }
-
- Component.onCompleted: {
- loginDialogRoot.title = qsTr("Complete Your Profile")
- loginDialogRoot.iconText = "<"
- keyboardEnabled = HMD.active;
- d.resize();
- }
-
- Connections {
- target: loginDialog
- onHandleCreateCompleted: {
- console.log("Create Succeeded")
-
- loginDialog.loginThroughSteam()
- }
- onHandleCreateFailed: {
- console.log("Create Failed: " + error)
-
- mainTextContainer.visible = true
- mainTextContainer.text = "\"" + textField.text + qsTr("\" is invalid or already taken.")
- }
- onHandleLoginCompleted: {
- console.log("Login Succeeded")
-
- bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : false })
- }
- onHandleLoginFailed: {
- console.log("Login Failed")
- }
- }
-
- Keys.onPressed: {
- if (!visible) {
- return
- }
-
- switch (event.key) {
- case Qt.Key_Enter:
- case Qt.Key_Return:
- event.accepted = true
- usernameCollisionBody.create()
- break
- }
- }
-}
diff --git a/interface/resources/qml/TabletLoginDialog/WelcomeBody.qml b/interface/resources/qml/TabletLoginDialog/WelcomeBody.qml
deleted file mode 100644
index 5ec259ca96..0000000000
--- a/interface/resources/qml/TabletLoginDialog/WelcomeBody.qml
+++ /dev/null
@@ -1,79 +0,0 @@
-//
-// WelcomeBody.qml
-//
-// Created by Clement on 7/18/16
-// Copyright 2015 High Fidelity, Inc.
-//
-// Distributed under the Apache License, Version 2.0.
-// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-//
-
-import Hifi 1.0
-import QtQuick 2.4
-
-import "../controls-uit"
-import "../styles-uit"
-
-Item {
- id: welcomeBody
- clip: true
-
- property bool welcomeBack: false
-
- function setTitle() {
- loginDialogRoot.title = (welcomeBack ? qsTr("Welcome back ") : qsTr("Welcome ")) + Account.username + qsTr("!")
- loginDialogRoot.iconText = ""
- d.resize();
- }
-
- QtObject {
- id: d
- function resize() {}
- }
-
- InfoItem {
- id: mainTextContainer
- anchors {
- top: parent.top
- horizontalCenter: parent.horizontalCenter
- margins: 0
- topMargin: hifi.dimensions.contentSpacing.y
- }
-
- text: qsTr("You are now signed into High Fidelity")
- wrapMode: Text.WordWrap
- color: hifi.colors.baseGrayHighlight
- lineHeight: 2
- lineHeightMode: Text.ProportionalHeight
- horizontalAlignment: Text.AlignHCenter
- }
-
- Row {
- id: buttons
- anchors {
- top: mainTextContainer.bottom
- horizontalCenter: parent.horizontalCenter
- margins: 0
- topMargin: 2 * hifi.dimensions.contentSpacing.y
- }
- spacing: hifi.dimensions.contentSpacing.x
- onHeightChanged: d.resize(); onWidthChanged: d.resize();
-
- Button {
- anchors.verticalCenter: parent.verticalCenter
-
- text: qsTr("Close");
-
- onClicked: bodyLoader.popup()
- }
- }
-
- Component.onCompleted: {
- welcomeBody.setTitle()
- }
-
- Connections {
- target: Account
- onUsernameChanged: welcomeBody.setTitle()
- }
-}
diff --git a/interface/resources/qml/controls-uit/TextField.qml b/interface/resources/qml/controls-uit/TextField.qml
index a8b2ed45a5..1cc4d0ecc1 100644
--- a/interface/resources/qml/controls-uit/TextField.qml
+++ b/interface/resources/qml/controls-uit/TextField.qml
@@ -35,6 +35,7 @@ TextField {
font.pixelSize: hifi.fontSizes.textFieldInput
font.italic: textField.text == ""
height: implicitHeight + 3 // Make surrounding box higher so that highlight is vertically centered.
+ property alias textFieldLabel: textFieldLabel
y: textFieldLabel.visible ? textFieldLabel.height + textFieldLabel.anchors.bottomMargin : 0
diff --git a/interface/resources/qml/dialogs/TabletLoginDialog.qml b/interface/resources/qml/dialogs/TabletLoginDialog.qml
index 36ca480b24..9722f31144 100644
--- a/interface/resources/qml/dialogs/TabletLoginDialog.qml
+++ b/interface/resources/qml/dialogs/TabletLoginDialog.qml
@@ -16,48 +16,66 @@ import "../controls-uit"
import "../styles-uit"
import "../windows"
+import "../LoginDialog"
+
TabletModalWindow {
- id: loginDialogRoot
+ id: realRoot
objectName: "LoginDialog"
signal sendToScript(var message);
property bool isHMD: false
property bool gotoPreviousApp: false;
color: hifi.colors.baseGray
+ title: qsTr("Sign in to High Fidelity")
+ property alias titleWidth: root.titleWidth
+ property alias punctuationMode: root.punctuationMode
+
+ //fake root for shared components expecting root here
+ property var root: QtObject {
+ id: root
+
+ property bool keyboardEnabled: false
+ property bool keyboardRaised: false
+ property bool punctuationMode: false
+
+ readonly property bool isTablet: true
+
+ property alias title: realRoot.title
+ property real width: realRoot.width
+ property real height: realRoot.height
+
+ property int titleWidth: 0
+ property string iconText: hifi.glyphs.avatar
+ property int iconSize: 35
+
+ property var pane: QtObject {
+ property real width: root.width
+ property real height: root.height
+ }
+
+ function tryDestroy() {
+ canceled()
+ }
+ }
+
+ //property int colorScheme: hifi.colorSchemes.dark
- property int colorScheme: hifi.colorSchemes.dark
- property int titleWidth: 0
- property string iconText: ""
- property int icon: hifi.icons.none
- property int iconSize: 35
MouseArea {
- width: parent.width
- height: parent.height
+ width: realRoot.width
+ height: realRoot.height
}
property bool keyboardOverride: true
- onIconChanged: updateIcon();
property var items;
property string label: ""
- onTitleWidthChanged: d.resize();
+ //onTitleWidthChanged: d.resize();
- property bool keyboardEnabled: false
- property bool keyboardRaised: false
- property bool punctuationMode: false
-
- onKeyboardRaisedChanged: d.resize();
+ //onKeyboardRaisedChanged: d.resize();
signal canceled();
- function updateIcon() {
- if (!root) {
- return;
- }
- iconText = hifi.glyphForIcon(root.icon);
- }
-
property alias bodyLoader: bodyLoader
property alias loginDialog: loginDialog
property alias hifi: hifi
@@ -65,9 +83,10 @@ TabletModalWindow {
HifiConstants { id: hifi }
onCanceled: {
- if (loginDialogRoot.Stack.view) {
- loginDialogRoot.Stack.view.pop();
- } else if (gotoPreviousApp) {
+ if (bodyLoader.active === true) {
+ //bodyLoader.active = false
+ }
+ if (gotoPreviousApp) {
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
tablet.returnToPreviousApp();
} else {
@@ -75,45 +94,81 @@ TabletModalWindow {
}
}
- LoginDialog {
- id: loginDialog
- width: parent.width
- height: parent.height
- StackView {
- id: bodyLoader
- property var item: currentItem
- property var props
- property string source: ""
+ TabletModalFrame {
+ id: mfRoot
- onCurrentItemChanged: {
- //cleanup source for future usage
- source = ""
+ width: root.width
+ height: root.height + frameMarginTop + hifi.dimensions.contentMargin.x
+
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ verticalCenter: parent.verticalCenter
+ verticalCenterOffset: -loginKeyboard.height / 2
+ }
+
+ LoginDialog {
+ id: loginDialog
+
+ anchors {
+ fill: parent
+ topMargin: parent.frameMarginTop
+ leftMargin: hifi.dimensions.contentMargin.x
+ rightMargin: hifi.dimensions.contentMargin.x
+ horizontalCenter: parent.horizontalCenter
}
- function setSource(src, props) {
- source = "../TabletLoginDialog/" + src
- bodyLoader.props = props
- }
- function popup() {
- bodyLoader.pop()
-
- //check if last screen, if yes, dialog is popped out
- if (depth === 1)
- loginDialogRoot.canceled()
- }
-
- anchors.fill: parent
- anchors.margins: 10
- onSourceChanged: {
- if (source !== "") {
- bodyLoader.push(Qt.resolvedUrl(source), props)
- }
- }
- Component.onCompleted: {
- setSource(loginDialog.isSteamRunning() ?
- "SignInBody.qml" :
- "LinkAccountBody.qml")
+ Loader {
+ id: bodyLoader
+ anchors.fill: parent
+ anchors.horizontalCenter: parent.horizontalCenter
+ source: loginDialog.isSteamRunning() ? "../LoginDialog/SignInBody.qml" : "../LoginDialog/LinkAccountBody.qml"
}
}
}
+
+ Keyboard {
+ id: loginKeyboard
+ raised: root.keyboardEnabled && root.keyboardRaised
+ numeric: root.punctuationMode
+ anchors {
+ left: parent.left
+ right: parent.right
+ bottom: parent.bottom
+ }
+ }
+
+ Keys.onPressed: {
+ if (!visible) {
+ return
+ }
+
+ if (event.modifiers === Qt.ControlModifier)
+ switch (event.key) {
+ case Qt.Key_A:
+ event.accepted = true
+ detailedText.selectAll()
+ break
+ case Qt.Key_C:
+ event.accepted = true
+ detailedText.copy()
+ break
+ case Qt.Key_Period:
+ if (Qt.platform.os === "osx") {
+ event.accepted = true
+ content.reject()
+ }
+ break
+ } else switch (event.key) {
+ case Qt.Key_Escape:
+ case Qt.Key_Back:
+ event.accepted = true
+ destroy()
+ break
+
+ case Qt.Key_Enter:
+ case Qt.Key_Return:
+ event.accepted = true
+ break
+ }
+ }
}
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 669f942f30..b7cf6fb236 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -189,7 +189,6 @@
#include "InterfaceParentFinder.h"
#include "ui/OctreeStatsProvider.h"
-#include "FrameTimingsScriptingInterface.h"
#include
#include
#include
@@ -2023,7 +2022,8 @@ void Application::cleanupBeforeQuit() {
// The cleanup process enqueues the transactions but does not process them. Calling this here will force the actual
// removal of the items.
// See https://highfidelity.fogbugz.com/f/cases/5328
- _main3DScene->processTransactionQueue();
+ _main3DScene->enqueueFrame(); // flush all the transactions
+ _main3DScene->processTransactionQueue(); // process and apply deletions
// first stop all timers directly or by invokeMethod
// depending on what thread they run in
@@ -2221,8 +2221,6 @@ void Application::initializeGL() {
update(0);
}
-FrameTimingsScriptingInterface _frameTimingsScriptingInterface;
-
extern void setupPreferences();
void Application::initializeUi() {
@@ -2383,301 +2381,105 @@ void Application::initializeUi() {
offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2);
}
-void Application::paintGL() {
- // Some plugins process message events, allowing paintGL to be called reentrantly.
- if (_aboutToQuit || _window->isMinimized()) {
- return;
- }
-
- _renderFrameCount++;
- _lastTimeRendered.start();
-
- auto lastPaintBegin = usecTimestampNow();
- PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount);
- PerformanceTimer perfTimer("paintGL");
-
- if (nullptr == _displayPlugin) {
- return;
- }
-
- DisplayPluginPointer displayPlugin;
- {
- PROFILE_RANGE(render, "/getActiveDisplayPlugin");
- displayPlugin = getActiveDisplayPlugin();
- }
-
- {
- PROFILE_RANGE(render, "/pluginBeginFrameRender");
- // If a display plugin loses it's underlying support, it
- // needs to be able to signal us to not use it
- if (!displayPlugin->beginFrameRender(_renderFrameCount)) {
- updateDisplayMode();
- return;
- }
- }
-
- // update the avatar with a fresh HMD pose
- {
- PROFILE_RANGE(render, "/updateAvatar");
- getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose());
- }
-
- auto lodManager = DependencyManager::get();
-
- RenderArgs renderArgs;
-
- float sensorToWorldScale = getMyAvatar()->getSensorToWorldScale();
- {
- PROFILE_RANGE(render, "/buildFrustrumAndArgs");
- {
- QMutexLocker viewLocker(&_viewMutex);
- // adjust near clip plane to account for sensor scaling.
- auto adjustedProjection = glm::perspective(_viewFrustum.getFieldOfView(),
- _viewFrustum.getAspectRatio(),
- DEFAULT_NEAR_CLIP * sensorToWorldScale,
- _viewFrustum.getFarClip());
- _viewFrustum.setProjection(adjustedProjection);
- _viewFrustum.calculate();
- }
- renderArgs = RenderArgs(_gpuContext, lodManager->getOctreeSizeScale(),
- lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
- RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
- {
- QMutexLocker viewLocker(&_viewMutex);
- renderArgs.setViewFrustum(_viewFrustum);
- }
- }
-
- {
- PROFILE_RANGE(render, "/resizeGL");
- PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
- bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
- PerformanceWarning warn(showWarnings, "Application::paintGL()");
- resizeGL();
- }
-
- {
- PROFILE_RANGE(render, "/gpuContextReset");
- _gpuContext->beginFrame(getHMDSensorPose());
- // Reset the gpu::Context Stages
- // Back to the default framebuffer;
- gpu::doInBatch(_gpuContext, [&](gpu::Batch& batch) {
- batch.resetStages();
- });
- }
-
-
- {
- PROFILE_RANGE(render, "/renderOverlay");
- PerformanceTimer perfTimer("renderOverlay");
- // NOTE: There is no batch associated with this renderArgs
- // the ApplicationOverlay class assumes it's viewport is setup to be the device size
- QSize size = getDeviceSize();
- renderArgs._viewport = glm::ivec4(0, 0, size.width(), size.height());
- _applicationOverlay.renderOverlay(&renderArgs);
- }
+void Application::updateCamera(RenderArgs& renderArgs) {
+ PROFILE_RANGE(render, "/updateCamera");
+ PerformanceTimer perfTimer("CameraUpdates");
glm::vec3 boomOffset;
- {
- PROFILE_RANGE(render, "/updateCamera");
- {
- PerformanceTimer perfTimer("CameraUpdates");
+ auto myAvatar = getMyAvatar();
+ boomOffset = myAvatar->getModelScale() * myAvatar->getBoomLength() * -IDENTITY_FORWARD;
- auto myAvatar = getMyAvatar();
- boomOffset = myAvatar->getModelScale() * myAvatar->getBoomLength() * -IDENTITY_FORWARD;
+ // The render mode is default or mirror if the camera is in mirror mode, assigned further below
+ renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;
- // The render mode is default or mirror if the camera is in mirror mode, assigned further below
- renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;
-
- // Always use the default eye position, not the actual head eye position.
- // 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) {
- if (isHMDMode()) {
- mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
- _myCamera.setPosition(extractTranslation(camMat));
- _myCamera.setOrientation(glmExtractRotation(camMat));
- } else {
- _myCamera.setPosition(myAvatar->getDefaultEyePosition());
- _myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation());
- }
- } 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->getOrientation() * boomOffset);
- } else {
- _myCamera.setOrientation(myAvatar->getHead()->getOrientation());
- if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
- _myCamera.setPosition(myAvatar->getDefaultEyePosition()
- + _myCamera.getOrientation() * boomOffset);
- } else {
- _myCamera.setPosition(myAvatar->getDefaultEyePosition()
- + myAvatar->getOrientation() * boomOffset);
- }
- }
- } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
- if (isHMDMode()) {
- auto mirrorBodyOrientation = myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f));
-
- glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
- // Mirror HMD yaw and roll
- glm::vec3 mirrorHmdEulers = glm::eulerAngles(hmdRotation);
- mirrorHmdEulers.y = -mirrorHmdEulers.y;
- mirrorHmdEulers.z = -mirrorHmdEulers.z;
- glm::quat mirrorHmdRotation = glm::quat(mirrorHmdEulers);
-
- glm::quat worldMirrorRotation = mirrorBodyOrientation * mirrorHmdRotation;
-
- _myCamera.setOrientation(worldMirrorRotation);
-
- glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
- // Mirror HMD lateral offsets
- hmdOffset.x = -hmdOffset.x;
-
- _myCamera.setPosition(myAvatar->getDefaultEyePosition()
- + glm::vec3(0, _raiseMirror * myAvatar->getModelScale(), 0)
- + mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror
- + mirrorBodyOrientation * hmdOffset);
- } else {
- _myCamera.setOrientation(myAvatar->getOrientation()
- * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
- _myCamera.setPosition(myAvatar->getDefaultEyePosition()
- + glm::vec3(0, _raiseMirror * myAvatar->getModelScale(), 0)
- + (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
- glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
- }
- renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
- } else if (_myCamera.getMode() == CAMERA_MODE_ENTITY) {
- EntityItemPointer cameraEntity = _myCamera.getCameraEntityPointer();
- if (cameraEntity != nullptr) {
- if (isHMDMode()) {
- glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
- _myCamera.setOrientation(cameraEntity->getRotation() * hmdRotation);
- glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
- _myCamera.setPosition(cameraEntity->getPosition() + (hmdRotation * hmdOffset));
- } else {
- _myCamera.setOrientation(cameraEntity->getRotation());
- _myCamera.setPosition(cameraEntity->getPosition());
- }
- }
+ // Always use the default eye position, not the actual head eye position.
+ // 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) {
+ if (isHMDMode()) {
+ mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
+ _myCamera.setPosition(extractTranslation(camMat));
+ _myCamera.setOrientation(glmExtractRotation(camMat));
+ }
+ else {
+ _myCamera.setPosition(myAvatar->getDefaultEyePosition());
+ _myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation());
+ }
+ }
+ 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->getOrientation() * boomOffset);
+ }
+ else {
+ _myCamera.setOrientation(myAvatar->getHead()->getOrientation());
+ if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
+ _myCamera.setPosition(myAvatar->getDefaultEyePosition()
+ + _myCamera.getOrientation() * boomOffset);
}
- // Update camera position
- if (!isHMDMode()) {
- _myCamera.update();
+ else {
+ _myCamera.setPosition(myAvatar->getDefaultEyePosition()
+ + myAvatar->getOrientation() * boomOffset);
}
}
}
+ else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
+ if (isHMDMode()) {
+ auto mirrorBodyOrientation = myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f));
- {
- PROFILE_RANGE(render, "/updateCompositor");
- getApplicationCompositor().setFrameInfo(_renderFrameCount, _myCamera.getTransform(), getMyAvatar()->getSensorToWorldMatrix());
- }
+ glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
+ // Mirror HMD yaw and roll
+ glm::vec3 mirrorHmdEulers = glm::eulerAngles(hmdRotation);
+ mirrorHmdEulers.y = -mirrorHmdEulers.y;
+ mirrorHmdEulers.z = -mirrorHmdEulers.z;
+ glm::quat mirrorHmdRotation = glm::quat(mirrorHmdEulers);
- gpu::FramebufferPointer finalFramebuffer;
- QSize finalFramebufferSize;
- {
- PROFILE_RANGE(render, "/getOutputFramebuffer");
- // Primary rendering pass
- auto framebufferCache = DependencyManager::get();
- finalFramebufferSize = framebufferCache->getFrameBufferSize();
- // Final framebuffer that will be handled to the display-plugin
- finalFramebuffer = framebufferCache->getFramebuffer();
- }
+ glm::quat worldMirrorRotation = mirrorBodyOrientation * mirrorHmdRotation;
- auto hmdInterface = DependencyManager::get();
- float ipdScale = hmdInterface->getIPDScale();
+ _myCamera.setOrientation(worldMirrorRotation);
- // scale IPD by sensorToWorldScale, to make the world seem larger or smaller accordingly.
- ipdScale *= sensorToWorldScale;
+ glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
+ // Mirror HMD lateral offsets
+ hmdOffset.x = -hmdOffset.x;
- {
- PROFILE_RANGE(render, "/mainRender");
- PerformanceTimer perfTimer("mainRender");
- renderArgs._boomOffset = boomOffset;
- // FIXME is this ever going to be different from the size previously set in the render args
- // in the overlay render?
- // Viewport is assigned to the size of the framebuffer
- renderArgs._viewport = ivec4(0, 0, finalFramebufferSize.width(), finalFramebufferSize.height());
- auto baseProjection = renderArgs.getViewFrustum().getProjection();
- if (displayPlugin->isStereo()) {
- // Stereo modes will typically have a larger projection matrix overall,
- // so we ask for the 'mono' projection matrix, which for stereo and HMD
- // plugins will imply the combined projection for both eyes.
- //
- // This is properly implemented for the Oculus plugins, but for OpenVR
- // and Stereo displays I'm not sure how to get / calculate it, so we're
- // just relying on the left FOV in each case and hoping that the
- // overall culling margin of error doesn't cause popping in the
- // right eye. There are FIXMEs in the relevant plugins
- _myCamera.setProjection(displayPlugin->getCullingProjection(baseProjection));
- renderArgs._context->enableStereo(true);
- mat4 eyeOffsets[2];
- mat4 eyeProjections[2];
-
- // FIXME we probably don't need to set the projection matrix every frame,
- // only when the display plugin changes (or in non-HMD modes when the user
- // changes the FOV manually, which right now I don't think they can.
- for_each_eye([&](Eye eye) {
- // For providing the stereo eye views, the HMD head pose has already been
- // applied to the avatar, so we need to get the difference between the head
- // pose applied to the avatar and the per eye pose, and use THAT as
- // the per-eye stereo matrix adjustment.
- mat4 eyeToHead = displayPlugin->getEyeToHeadTransform(eye);
- // Grab the translation
- vec3 eyeOffset = glm::vec3(eyeToHead[3]);
- // Apply IPD scaling
- mat4 eyeOffsetTransform = glm::translate(mat4(), eyeOffset * -1.0f * ipdScale);
- eyeOffsets[eye] = eyeOffsetTransform;
- eyeProjections[eye] = displayPlugin->getEyeProjection(eye, baseProjection);
- });
- renderArgs._context->setStereoProjections(eyeProjections);
- renderArgs._context->setStereoViews(eyeOffsets);
-
- // Configure the type of display / stereo
- renderArgs._displayMode = (isHMDMode() ? RenderArgs::STEREO_HMD : RenderArgs::STEREO_MONITOR);
+ _myCamera.setPosition(myAvatar->getDefaultEyePosition()
+ + glm::vec3(0, _raiseMirror * myAvatar->getModelScale(), 0)
+ + mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror
+ + mirrorBodyOrientation * hmdOffset);
}
- renderArgs._blitFramebuffer = finalFramebuffer;
- displaySide(&renderArgs, _myCamera);
+ else {
+ _myCamera.setOrientation(myAvatar->getOrientation()
+ * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
+ _myCamera.setPosition(myAvatar->getDefaultEyePosition()
+ + glm::vec3(0, _raiseMirror * myAvatar->getModelScale(), 0)
+ + (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
+ glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
+ }
+ renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
+ }
+ else if (_myCamera.getMode() == CAMERA_MODE_ENTITY) {
+ EntityItemPointer cameraEntity = _myCamera.getCameraEntityPointer();
+ if (cameraEntity != nullptr) {
+ if (isHMDMode()) {
+ glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
+ _myCamera.setOrientation(cameraEntity->getRotation() * hmdRotation);
+ glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
+ _myCamera.setPosition(cameraEntity->getPosition() + (hmdRotation * hmdOffset));
+ }
+ else {
+ _myCamera.setOrientation(cameraEntity->getRotation());
+ _myCamera.setPosition(cameraEntity->getPosition());
+ }
+ }
+ }
+ // Update camera position
+ if (!isHMDMode()) {
+ _myCamera.update();
}
- gpu::Batch postCompositeBatch;
- {
- PROFILE_RANGE(render, "/postComposite");
- PerformanceTimer perfTimer("postComposite");
- renderArgs._batch = &postCompositeBatch;
- renderArgs._batch->setViewportTransform(ivec4(0, 0, finalFramebufferSize.width(), finalFramebufferSize.height()));
- renderArgs._batch->setViewTransform(renderArgs.getViewFrustum().getView());
- _overlays.render3DHUDOverlays(&renderArgs);
- }
-
- auto frame = _gpuContext->endFrame();
- frame->frameIndex = _renderFrameCount;
- frame->framebuffer = finalFramebuffer;
- frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer){
- DependencyManager::get()->releaseFramebuffer(framebuffer);
- };
- frame->overlay = _applicationOverlay.getOverlayTexture();
- frame->postCompositeBatch = postCompositeBatch;
- // deliver final scene rendering commands to the display plugin
- {
- PROFILE_RANGE(render, "/pluginOutput");
- PerformanceTimer perfTimer("pluginOutput");
- _renderLoopCounter.increment();
- displayPlugin->submitFrame(frame);
- }
-
- // Reset the framebuffer and stereo state
- renderArgs._blitFramebuffer.reset();
- renderArgs._context->enableStereo(false);
-
- {
- Stats::getInstance()->setRenderDetails(renderArgs._details);
- }
-
- uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin;
- _frameTimingsScriptingInterface.addValue(lastPaintDuration);
+ renderArgs._cameraMode = (int8_t)_myCamera.getMode();
}
void Application::runTests() {
@@ -5225,6 +5027,7 @@ void Application::update(float deltaTime) {
avatarManager->postUpdate(deltaTime, getMain3DScene());
+
{
PROFILE_RANGE_EX(app, "PreRenderLambdas", 0xffff0000, (uint64_t)0);
@@ -5235,9 +5038,123 @@ void Application::update(float deltaTime) {
_postUpdateLambdas.clear();
}
+ editRenderArgs([this](AppRenderArgs& appRenderArgs) {
+ appRenderArgs._headPose= getHMDSensorPose();
+
+ auto myAvatar = getMyAvatar();
+
+ // update the avatar with a fresh HMD pose
+ {
+ PROFILE_RANGE(render, "/updateAvatar");
+ myAvatar->updateFromHMDSensorMatrix(appRenderArgs._headPose);
+ }
+
+ auto lodManager = DependencyManager::get();
+
+ float sensorToWorldScale = getMyAvatar()->getSensorToWorldScale();
+ appRenderArgs._sensorToWorldScale = sensorToWorldScale;
+ {
+ PROFILE_RANGE(render, "/buildFrustrumAndArgs");
+ {
+ QMutexLocker viewLocker(&_viewMutex);
+ // adjust near clip plane to account for sensor scaling.
+ auto adjustedProjection = glm::perspective(_viewFrustum.getFieldOfView(),
+ _viewFrustum.getAspectRatio(),
+ DEFAULT_NEAR_CLIP * sensorToWorldScale,
+ _viewFrustum.getFarClip());
+ _viewFrustum.setProjection(adjustedProjection);
+ _viewFrustum.calculate();
+ }
+ appRenderArgs._renderArgs = RenderArgs(_gpuContext, lodManager->getOctreeSizeScale(),
+ lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
+ RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
+ appRenderArgs._renderArgs._scene = getMain3DScene();
+
+ {
+ QMutexLocker viewLocker(&_viewMutex);
+ appRenderArgs._renderArgs.setViewFrustum(_viewFrustum);
+ }
+ }
+ {
+ PROFILE_RANGE(render, "/resizeGL");
+ PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
+ bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
+ PerformanceWarning warn(showWarnings, "Application::paintGL()");
+ resizeGL();
+ }
+
+ this->updateCamera(appRenderArgs._renderArgs);
+ appRenderArgs._isStereo = false;
+
+ {
+ auto hmdInterface = DependencyManager::get();
+ float ipdScale = hmdInterface->getIPDScale();
+
+ // scale IPD by sensorToWorldScale, to make the world seem larger or smaller accordingly.
+ ipdScale *= sensorToWorldScale;
+
+ auto baseProjection = appRenderArgs._renderArgs.getViewFrustum().getProjection();
+ if (getActiveDisplayPlugin()->isStereo()) {
+ // Stereo modes will typically have a larger projection matrix overall,
+ // so we ask for the 'mono' projection matrix, which for stereo and HMD
+ // plugins will imply the combined projection for both eyes.
+ //
+ // This is properly implemented for the Oculus plugins, but for OpenVR
+ // and Stereo displays I'm not sure how to get / calculate it, so we're
+ // just relying on the left FOV in each case and hoping that the
+ // overall culling margin of error doesn't cause popping in the
+ // right eye. There are FIXMEs in the relevant plugins
+ _myCamera.setProjection(getActiveDisplayPlugin()->getCullingProjection(baseProjection));
+ appRenderArgs._isStereo = true;
+
+ auto& eyeOffsets = appRenderArgs._eyeOffsets;
+ auto& eyeProjections = appRenderArgs._eyeProjections;
+
+ // FIXME we probably don't need to set the projection matrix every frame,
+ // only when the display plugin changes (or in non-HMD modes when the user
+ // changes the FOV manually, which right now I don't think they can.
+ for_each_eye([&](Eye eye) {
+ // For providing the stereo eye views, the HMD head pose has already been
+ // applied to the avatar, so we need to get the difference between the head
+ // pose applied to the avatar and the per eye pose, and use THAT as
+ // the per-eye stereo matrix adjustment.
+ mat4 eyeToHead = getActiveDisplayPlugin()->getEyeToHeadTransform(eye);
+ // Grab the translation
+ vec3 eyeOffset = glm::vec3(eyeToHead[3]);
+ // Apply IPD scaling
+ mat4 eyeOffsetTransform = glm::translate(mat4(), eyeOffset * -1.0f * ipdScale);
+ eyeOffsets[eye] = eyeOffsetTransform;
+ eyeProjections[eye] = getActiveDisplayPlugin()->getEyeProjection(eye, baseProjection);
+ });
+
+ // Configure the type of display / stereo
+ appRenderArgs._renderArgs._displayMode = (isHMDMode() ? RenderArgs::STEREO_HMD : RenderArgs::STEREO_MONITOR);
+ }
+ }
+
+ // HACK
+ // load the view frustum
+ // FIXME: This preDisplayRender call is temporary until we create a separate render::scene for the mirror rendering.
+ // Then we can move this logic into the Avatar::simulate call.
+ myAvatar->preDisplaySide(&appRenderArgs._renderArgs);
+
+ {
+ QMutexLocker viewLocker(&_viewMutex);
+ _myCamera.loadViewFrustum(_displayViewFrustum);
+ }
+
+ {
+ QMutexLocker viewLocker(&_viewMutex);
+ appRenderArgs._renderArgs.setViewFrustum(_displayViewFrustum);
+ }
+ });
+
AnimDebugDraw::getInstance().update();
DependencyManager::get()->update();
+
+ // Game loop is done, mark the end of the frame for the scene transactions and the render loop to take over
+ getMain3DScene()->enqueueFrame();
}
void Application::sendAvatarViewFrustum() {
@@ -5296,7 +5213,6 @@ int Application::sendNackPackets() {
}
});
-
return packetsSent;
}
@@ -5527,116 +5443,6 @@ void Application::copyDisplayViewFrustum(ViewFrustum& viewOut) const {
viewOut = _displayViewFrustum;
}
-void Application::copyShadowViewFrustum(ViewFrustum& viewOut) const {
- QMutexLocker viewLocker(&_viewMutex);
- viewOut = _shadowViewFrustum;
-}
-
-// WorldBox Render Data & rendering functions
-
-class WorldBoxRenderData {
-public:
- typedef render::Payload Payload;
- typedef Payload::DataPointer Pointer;
-
- int _val = 0;
- static render::ItemID _item; // unique WorldBoxRenderData
-};
-
-render::ItemID WorldBoxRenderData::_item { render::Item::INVALID_ITEM_ID };
-
-namespace render {
- template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape(); }
- template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); }
- template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) {
- if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) {
- PerformanceTimer perfTimer("worldBox");
-
- auto& batch = *args->_batch;
- DependencyManager::get()->bindSimpleProgram(batch);
- renderWorldBox(args, batch);
- }
- }
-}
-
-void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly) {
-
- // FIXME: This preDisplayRender call is temporary until we create a separate render::scene for the mirror rendering.
- // Then we can move this logic into the Avatar::simulate call.
- auto myAvatar = getMyAvatar();
- myAvatar->preDisplaySide(renderArgs);
-
- PROFILE_RANGE(render, __FUNCTION__);
- PerformanceTimer perfTimer("display");
- PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()");
-
- // load the view frustum
- {
- QMutexLocker viewLocker(&_viewMutex);
- theCamera.loadViewFrustum(_displayViewFrustum);
- }
-
- // TODO fix shadows and make them use the GPU library
-
- // The pending changes collecting the changes here
- render::Transaction transaction;
-
- // Assuming nothing gets rendered through that
- if (!selfAvatarOnly) {
- if (DependencyManager::get()->shouldRenderEntities()) {
- // render models...
- PerformanceTimer perfTimer("entities");
- PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
- "Application::displaySide() ... entities...");
-
- RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE;
-
- if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowHulls)) {
- renderDebugFlags = static_cast(renderDebugFlags |
- static_cast(RenderArgs::RENDER_DEBUG_HULLS));
- }
- renderArgs->_debugFlags = renderDebugFlags;
- //ViveControllerManager::getInstance().updateRendering(renderArgs, _main3DScene, transaction);
- }
- }
-
- // FIXME: Move this out of here!, WorldBox should be driven by the entity content just like the other entities
- // Make sure the WorldBox is in the scene
- if (!render::Item::isValidID(WorldBoxRenderData::_item)) {
- auto worldBoxRenderData = make_shared();
- auto worldBoxRenderPayload = make_shared(worldBoxRenderData);
-
- WorldBoxRenderData::_item = _main3DScene->allocateID();
-
- transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload);
- } else {
- transaction.updateItem(WorldBoxRenderData::_item,
- [](WorldBoxRenderData& payload) {
- payload._val++;
- });
- }
-
- {
- _main3DScene->enqueueTransaction(transaction);
- }
-
- // For now every frame pass the renderContext
- {
- PerformanceTimer perfTimer("EngineRun");
-
- {
- QMutexLocker viewLocker(&_viewMutex);
- renderArgs->setViewFrustum(_displayViewFrustum);
- }
- renderArgs->_cameraMode = (int8_t)theCamera.getMode(); // HACK
- renderArgs->_scene = getMain3DScene();
- _renderEngine->getRenderContext()->args = renderArgs;
-
- // Before the deferred pass, let's try to use the render engine
- _renderEngine->run();
- }
-}
-
void Application::resetSensors(bool andReload) {
DependencyManager::get()->reset();
DependencyManager::get()->reset();
@@ -7677,5 +7483,4 @@ void Application::setAvatarOverrideUrl(const QUrl& url, bool save) {
_avatarOverrideUrl = url;
_saveAvatarOverrideUrl = save;
}
-
#include "Application.moc"
diff --git a/interface/src/Application.h b/interface/src/Application.h
index f3c7f82b4b..478642e2da 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -76,6 +76,7 @@
#include
#include
#include
+#include "FrameTimingsScriptingInterface.h"
#include "Sound.h"
@@ -147,6 +148,8 @@ public:
void initializeGL();
void initializeUi();
+
+ void updateCamera(RenderArgs& renderArgs);
void paintGL();
void resizeGL();
@@ -173,7 +176,6 @@ public:
// which might be different from the viewFrustum, i.e. shadowmap
// passes, mirror window passes, etc
void copyDisplayViewFrustum(ViewFrustum& viewOut) const;
- void copyShadowViewFrustum(ViewFrustum& viewOut) const override;
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
QSharedPointer getEntities() const { return DependencyManager::get(); }
QUndoStack* getUndoStack() { return &_undoStack; }
@@ -467,8 +469,6 @@ private:
void queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions);
- void renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool isZoomed);
-
int sendNackPackets();
void sendAvatarViewFrustum();
@@ -478,7 +478,7 @@ private:
void initializeAcceptedFiles();
- void displaySide(RenderArgs* renderArgs, Camera& whichCamera, bool selfAvatarOnly = false);
+ void runRenderFrame(RenderArgs* renderArgs/*, Camera& whichCamera, bool selfAvatarOnly = false*/);
bool importJSONFromURL(const QString& urlString);
bool importSVOFromURL(const QString& urlString);
@@ -535,6 +535,8 @@ private:
RateCounter<500> _renderLoopCounter;
RateCounter<500> _gameLoopCounter;
+ FrameTimingsScriptingInterface _frameTimingsScriptingInterface;
+
QTimer _minimizedWindowTimer;
QElapsedTimer _timerStart;
QElapsedTimer _lastTimeUpdated;
@@ -550,7 +552,6 @@ private:
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels)
ViewFrustum _displayViewFrustum;
- ViewFrustum _shadowViewFrustum;
quint64 _lastQueriedTime;
OctreeQuery _octreeQuery; // NodeData derived class for querying octee cells from octree servers
@@ -621,6 +622,24 @@ private:
render::EnginePointer _renderEngine{ new render::Engine() };
gpu::ContextPointer _gpuContext; // initialized during window creation
+ mutable QMutex _renderArgsMutex{ QMutex::Recursive };
+ struct AppRenderArgs {
+ render::Args _renderArgs;
+ glm::mat4 _eyeToWorld;
+ glm::mat4 _eyeOffsets[2];
+ glm::mat4 _eyeProjections[2];
+ glm::mat4 _headPose;
+ glm::mat4 _sensorToWorld;
+ float _sensorToWorldScale { 1.0f };
+ bool _isStereo{ false };
+ };
+ AppRenderArgs _appRenderArgs;
+
+
+ using RenderArgsEditor = std::function ;
+ void editRenderArgs(RenderArgsEditor editor);
+
+
Overlays _overlays;
ApplicationOverlay _applicationOverlay;
OverlayConductor _overlayConductor;
diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp
new file mode 100644
index 0000000000..bbcd8266d7
--- /dev/null
+++ b/interface/src/Application_render.cpp
@@ -0,0 +1,240 @@
+//
+// Application_render.cpp
+// interface/src
+//
+// Copyright 2013 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 "Application.h"
+#include
+
+#include
+#include
+#include "ui/Stats.h"
+#include
+#include "Util.h"
+
+
+// Statically provided display and input plugins
+extern DisplayPluginList getDisplayPlugins();
+
+void Application::editRenderArgs(RenderArgsEditor editor) {
+ QMutexLocker renderLocker(&_renderArgsMutex);
+ editor(_appRenderArgs);
+
+}
+
+void Application::paintGL() {
+ // Some plugins process message events, allowing paintGL to be called reentrantly.
+ if (_aboutToQuit || _window->isMinimized()) {
+ return;
+ }
+
+ _renderFrameCount++;
+ _lastTimeRendered.start();
+
+ auto lastPaintBegin = usecTimestampNow();
+ PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount);
+ PerformanceTimer perfTimer("paintGL");
+
+ if (nullptr == _displayPlugin) {
+ return;
+ }
+
+ DisplayPluginPointer displayPlugin;
+ {
+ PROFILE_RANGE(render, "/getActiveDisplayPlugin");
+ displayPlugin = getActiveDisplayPlugin();
+ }
+
+ {
+ PROFILE_RANGE(render, "/pluginBeginFrameRender");
+ // If a display plugin loses it's underlying support, it
+ // needs to be able to signal us to not use it
+ if (!displayPlugin->beginFrameRender(_renderFrameCount)) {
+ updateDisplayMode();
+ return;
+ }
+ }
+
+ RenderArgs renderArgs;
+ glm::mat4 HMDSensorPose;
+ glm::mat4 eyeToWorld;
+ glm::mat4 sensorToWorld;
+
+ bool isStereo;
+ glm::mat4 stereoEyeOffsets[2];
+ glm::mat4 stereoEyeProjections[2];
+
+ {
+ QMutexLocker viewLocker(&_renderArgsMutex);
+ renderArgs = _appRenderArgs._renderArgs;
+ HMDSensorPose = _appRenderArgs._headPose;
+ eyeToWorld = _appRenderArgs._eyeToWorld;
+ sensorToWorld = _appRenderArgs._sensorToWorld;
+ isStereo = _appRenderArgs._isStereo;
+ for_each_eye([&](Eye eye) {
+ stereoEyeOffsets[eye] = _appRenderArgs._eyeOffsets[eye];
+ stereoEyeProjections[eye] = _appRenderArgs._eyeProjections[eye];
+ });
+ }
+
+ {
+ PROFILE_RANGE(render, "/gpuContextReset");
+ _gpuContext->beginFrame(HMDSensorPose);
+ // Reset the gpu::Context Stages
+ // Back to the default framebuffer;
+ gpu::doInBatch(_gpuContext, [&](gpu::Batch& batch) {
+ batch.resetStages();
+ });
+ }
+
+
+ {
+ PROFILE_RANGE(render, "/renderOverlay");
+ PerformanceTimer perfTimer("renderOverlay");
+ // NOTE: There is no batch associated with this renderArgs
+ // the ApplicationOverlay class assumes it's viewport is setup to be the device size
+ QSize size = getDeviceSize();
+ renderArgs._viewport = glm::ivec4(0, 0, size.width(), size.height());
+ _applicationOverlay.renderOverlay(&renderArgs);
+ }
+
+ {
+ PROFILE_RANGE(render, "/updateCompositor");
+ getApplicationCompositor().setFrameInfo(_renderFrameCount, eyeToWorld, sensorToWorld);
+ }
+
+ gpu::FramebufferPointer finalFramebuffer;
+ QSize finalFramebufferSize;
+ {
+ PROFILE_RANGE(render, "/getOutputFramebuffer");
+ // Primary rendering pass
+ auto framebufferCache = DependencyManager::get();
+ finalFramebufferSize = framebufferCache->getFrameBufferSize();
+ // Final framebuffer that will be handled to the display-plugin
+ finalFramebuffer = framebufferCache->getFramebuffer();
+ }
+
+ {
+ if (isStereo) {
+ renderArgs._context->enableStereo(true);
+ renderArgs._context->setStereoProjections(stereoEyeProjections);
+ renderArgs._context->setStereoViews(stereoEyeOffsets);
+ }
+
+ renderArgs._blitFramebuffer = finalFramebuffer;
+ runRenderFrame(&renderArgs);
+ }
+
+ gpu::Batch postCompositeBatch;
+ {
+ PROFILE_RANGE(render, "/postComposite");
+ PerformanceTimer perfTimer("postComposite");
+ renderArgs._batch = &postCompositeBatch;
+ renderArgs._batch->setViewportTransform(ivec4(0, 0, finalFramebufferSize.width(), finalFramebufferSize.height()));
+ renderArgs._batch->setViewTransform(renderArgs.getViewFrustum().getView());
+ _overlays.render3DHUDOverlays(&renderArgs);
+ }
+
+ auto frame = _gpuContext->endFrame();
+ frame->frameIndex = _renderFrameCount;
+ frame->framebuffer = finalFramebuffer;
+ frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) {
+ DependencyManager::get()->releaseFramebuffer(framebuffer);
+ };
+ frame->overlay = _applicationOverlay.getOverlayTexture();
+ frame->postCompositeBatch = postCompositeBatch;
+ // deliver final scene rendering commands to the display plugin
+ {
+ PROFILE_RANGE(render, "/pluginOutput");
+ PerformanceTimer perfTimer("pluginOutput");
+ _renderLoopCounter.increment();
+ displayPlugin->submitFrame(frame);
+ }
+
+ // Reset the framebuffer and stereo state
+ renderArgs._blitFramebuffer.reset();
+ renderArgs._context->enableStereo(false);
+
+ {
+ Stats::getInstance()->setRenderDetails(renderArgs._details);
+ }
+
+ uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin;
+ _frameTimingsScriptingInterface.addValue(lastPaintDuration);
+}
+
+
+// WorldBox Render Data & rendering functions
+
+class WorldBoxRenderData {
+public:
+ typedef render::Payload Payload;
+ typedef Payload::DataPointer Pointer;
+
+ int _val = 0;
+ static render::ItemID _item; // unique WorldBoxRenderData
+};
+
+render::ItemID WorldBoxRenderData::_item{ render::Item::INVALID_ITEM_ID };
+
+namespace render {
+ template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape(); }
+ template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); }
+ template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) {
+ if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) {
+ PerformanceTimer perfTimer("worldBox");
+
+ auto& batch = *args->_batch;
+ DependencyManager::get()->bindSimpleProgram(batch);
+ renderWorldBox(args, batch);
+ }
+ }
+}
+
+void Application::runRenderFrame(RenderArgs* renderArgs) {
+ PROFILE_RANGE(render, __FUNCTION__);
+ PerformanceTimer perfTimer("display");
+ PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::runRenderFrame()");
+
+ // The pending changes collecting the changes here
+ render::Transaction transaction;
+
+ if (DependencyManager::get()->shouldRenderEntities()) {
+ // render models...
+ PerformanceTimer perfTimer("entities");
+ PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
+ "Application::runRenderFrame() ... entities...");
+
+ RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE;
+
+ if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowHulls)) {
+ renderDebugFlags = static_cast(renderDebugFlags |
+ static_cast(RenderArgs::RENDER_DEBUG_HULLS));
+ }
+ renderArgs->_debugFlags = renderDebugFlags;
+ }
+
+ // Make sure the WorldBox is in the scene
+ // For the record, this one RenderItem is the first one we created and added to the scene.
+ // We could meoee that code elsewhere but you know...
+ if (!render::Item::isValidID(WorldBoxRenderData::_item)) {
+ auto worldBoxRenderData = std::make_shared();
+ auto worldBoxRenderPayload = std::make_shared(worldBoxRenderData);
+
+ WorldBoxRenderData::_item = _main3DScene->allocateID();
+
+ transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload);
+ _main3DScene->enqueueTransaction(transaction);
+ }
+
+ {
+ PerformanceTimer perfTimer("EngineRun");
+ _renderEngine->getRenderContext()->args = renderArgs;
+ _renderEngine->run();
+ }
+}
diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp
index 714723e48e..4210e76097 100644
--- a/interface/src/ui/overlays/Base3DOverlay.cpp
+++ b/interface/src/ui/overlays/Base3DOverlay.cpp
@@ -265,7 +265,6 @@ void Base3DOverlay::parentDeleted() {
}
void Base3DOverlay::update(float duration) {
-
// In Base3DOverlay, if its location or bound changed, the renderTrasnformDirty flag is true.
// then the correct transform used for rendering is computed in the update transaction and assigned.
if (_renderTransformDirty) {
diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp
index 8ce6e7f1f3..4f5ea2042f 100644
--- a/interface/src/ui/overlays/ModelOverlay.cpp
+++ b/interface/src/ui/overlays/ModelOverlay.cpp
@@ -64,7 +64,6 @@ void ModelOverlay::update(float deltatime) {
}
_isLoaded = _model->isActive();
-
if (isAnimatingSomething()) {
if (!jointsMapped()) {
mapAnimationJoints(_model->getJointNames());
diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h
index ba1ffa86c1..93deebac43 100644
--- a/interface/src/ui/overlays/ModelOverlay.h
+++ b/interface/src/ui/overlays/ModelOverlay.h
@@ -78,6 +78,8 @@ private:
bool _scaleToFit = { false };
float _loadPriority { 0.0f };
+ bool _visibleDirty { false };
+ bool _drawInFrontDirty { false };
AnimationPointer _animation;
QUrl _animationURL;
@@ -95,10 +97,6 @@ private:
QUrl _jointMappingURL;
bool _jointMappingCompleted { false };
QVector _jointMapping; // domain is index into model-joints, range is index into animation-joints
-
- bool _visibleDirty { false };
- bool _drawInFrontDirty { false };
-
};
#endif // hifi_ModelOverlay_h
diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp
index 712c728dcb..0897c26a12 100644
--- a/libraries/animation/src/Rig.cpp
+++ b/libraries/animation/src/Rig.cpp
@@ -1620,13 +1620,14 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo
}
void Rig::initAnimGraph(const QUrl& url) {
- if (_animGraphURL != url || !_animNode) {
+ if (_animGraphURL != url || (!_animNode && !_animLoading)) {
_animGraphURL = url;
_animNode.reset();
// load the anim graph
_animLoader.reset(new AnimNodeLoader(url));
+ _animLoading = true;
connect(_animLoader.get(), &AnimNodeLoader::success, [this](AnimNode::Pointer nodeIn) {
_animNode = nodeIn;
_animNode->setSkeleton(_animSkeleton);
@@ -1637,6 +1638,7 @@ void Rig::initAnimGraph(const QUrl& url) {
_userAnimState = { UserAnimState::None, "", 30.0f, false, 0.0f, 0.0f };
overrideAnimation(origState.url, origState.fps, origState.loop, origState.firstFrame, origState.lastFrame);
}
+ _animLoading = false;
emit onLoadComplete();
});
diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h
index eabc62ab75..18d49c5f1e 100644
--- a/libraries/animation/src/Rig.h
+++ b/libraries/animation/src/Rig.h
@@ -303,6 +303,7 @@ protected:
std::shared_ptr _animNode;
std::shared_ptr _animSkeleton;
std::unique_ptr _animLoader;
+ bool _animLoading { false };
AnimVariantMap _animVars;
enum class RigRole {
Idle = 0,
diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
index 0cb25a2e2f..67fcc5cc69 100644
--- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp
+++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp
@@ -260,12 +260,24 @@ void EntityTreeRenderer::update(bool simulate) {
}
}
- auto scene = _viewState->getMain3DScene();
- if (scene) {
- render::Transaction transaction;
- addPendingEntities(scene, transaction);
- updateChangedEntities(scene, transaction);
- scene->enqueueTransaction(transaction);
+ {
+ PerformanceTimer sceneTimer("scene");
+ auto scene = _viewState->getMain3DScene();
+ if (scene) {
+ render::Transaction transaction;
+ {
+ PerformanceTimer pt("add");
+ addPendingEntities(scene, transaction);
+ }
+ {
+ PerformanceTimer pt("change");
+ updateChangedEntities(scene, transaction);
+ }
+ {
+ PerformanceTimer pt("enqueue");
+ scene->enqueueTransaction(transaction);
+ }
+ }
}
}
}
@@ -1078,4 +1090,4 @@ void EntityTreeRenderer::onEntityChanged(const EntityItemID& id) {
_changedEntitiesGuard.withWriteLock([&] {
_changedEntities.insert(id);
});
-}
\ No newline at end of file
+}
diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp
index a1b7ff54de..58b8dd22bf 100644
--- a/libraries/entities/src/EntityItem.cpp
+++ b/libraries/entities/src/EntityItem.cpp
@@ -1433,7 +1433,7 @@ void EntityItem::recordCreationTime() {
const Transform EntityItem::getTransformToCenter(bool& success) const {
Transform result = getTransform(success);
if (getRegistrationPoint() != ENTITY_ITEM_HALF_VEC3) { // If it is not already centered, translate to center
- result.postTranslate(ENTITY_ITEM_HALF_VEC3 - getRegistrationPoint()); // Position to center
+ result.postTranslate((ENTITY_ITEM_HALF_VEC3 - getRegistrationPoint()) * getDimensions()); // Position to center
}
return result;
}
diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp
index 1d8cb50a4b..3ade5879c5 100644
--- a/libraries/entities/src/TextEntityItem.cpp
+++ b/libraries/entities/src/TextEntityItem.cpp
@@ -136,7 +136,7 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const
glm::vec2 xyDimensions(dimensions.x, dimensions.y);
glm::quat rotation = getRotation();
glm::vec3 position = getPosition() + rotation *
- (dimensions * (getRegistrationPoint() - ENTITY_ITEM_DEFAULT_REGISTRATION_POINT));
+ (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()));
// FIXME - should set face and surfaceNormal
return findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance);
diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp
index 61c6c8d80e..9595f2959c 100644
--- a/libraries/entities/src/WebEntityItem.cpp
+++ b/libraries/entities/src/WebEntityItem.cpp
@@ -112,7 +112,7 @@ bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const g
glm::vec3 dimensions = getDimensions();
glm::vec2 xyDimensions(dimensions.x, dimensions.y);
glm::quat rotation = getRotation();
- glm::vec3 position = getPosition() + rotation * (dimensions * (getRegistrationPoint() - ENTITY_ITEM_DEFAULT_REGISTRATION_POINT));
+ glm::vec3 position = getPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()));
if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) {
surfaceNormal = rotation * Vectors::UNIT_Z;
diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h
index 4570ead9e1..96e9f4d222 100644
--- a/libraries/render-utils/src/AbstractViewStateInterface.h
+++ b/libraries/render-utils/src/AbstractViewStateInterface.h
@@ -31,9 +31,6 @@ public:
/// copies the current view frustum for rendering the view state
virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const = 0;
- /// copies the shadow view frustum for rendering the view state
- virtual void copyShadowViewFrustum(ViewFrustum& viewOut) const = 0;
-
virtual QThread* getMainThread() = 0;
virtual PickRay computePickRay(float x, float y) const = 0;
diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp
index 4f7f9ef5c4..c22e99cbbc 100644
--- a/libraries/render-utils/src/AnimDebugDraw.cpp
+++ b/libraries/render-utils/src/AnimDebugDraw.cpp
@@ -144,6 +144,7 @@ void AnimDebugDraw::shutdown() {
if (scene && _itemID) {
render::Transaction transaction;
transaction.removeItem(_itemID);
+ render::Item::clearID(_itemID);
scene->enqueueTransaction(transaction);
}
}
@@ -316,7 +317,9 @@ void AnimDebugDraw::update() {
if (!scene) {
return;
}
-
+ if (!render::Item::isValidID(_itemID)) {
+ return;
+ }
render::Transaction transaction;
transaction.updateItem(_itemID, [&](AnimDebugDrawData& data) {
diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp
index f25cad8a6e..36f12fb1bf 100644
--- a/libraries/render-utils/src/Model.cpp
+++ b/libraries/render-utils/src/Model.cpp
@@ -241,7 +241,7 @@ void Model::updateRenderItems() {
if (model && model->isLoaded()) {
// Ensure the model geometry was not reset between frames
if (deleteGeometryCounter == model->_deleteGeometryCounter) {
-
+
const Model::MeshState& state = model->getMeshState(data._meshIndex);
Transform renderTransform = modelTransform;
if (state.clusterMatrices.size() == 1) {
diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp
index d2d3ad6de6..714be2a8c6 100644
--- a/libraries/render/src/render/Scene.cpp
+++ b/libraries/render/src/render/Scene.cpp
@@ -15,9 +15,6 @@
#include "Logging.h"
#include "TransitionStage.h"
-// Comment this to disable transitions (fades)
-#define SCENE_ENABLE_TRANSITIONS
-
using namespace render;
void Transaction::resetItem(ItemID id, const PayloadPointer& payload) {
@@ -101,16 +98,46 @@ void consolidateTransaction(TransactionQueue& queue, Transaction& singleBatch) {
queue.pop();
};
}
-
-void Scene::processTransactionQueue() {
+
+uint32_t Scene::enqueueFrame() {
PROFILE_RANGE(render, __FUNCTION__);
Transaction consolidatedTransaction;
-
{
std::unique_lock lock(_transactionQueueMutex);
consolidateTransaction(_transactionQueue, consolidatedTransaction);
}
-
+
+ uint32_t frameNumber = 0;
+ {
+ std::unique_lock lock(_transactionFramesMutex);
+ _transactionFrames.push_back(consolidatedTransaction);
+ _transactionFrameNumber++;
+ frameNumber = _transactionFrameNumber;
+ }
+
+ return frameNumber;
+}
+
+
+void Scene::processTransactionQueue() {
+ PROFILE_RANGE(render, __FUNCTION__);
+
+ TransactionFrames queuedFrames;
+ {
+ // capture the queued frames and clear the queue
+ std::unique_lock lock(_transactionFramesMutex);
+ queuedFrames = _transactionFrames;
+ _transactionFrames.clear();
+ }
+
+ // go through the queue of frames and process them
+ for (auto& frame : queuedFrames) {
+ processTransactionFrame(frame);
+ }
+}
+
+void Scene::processTransactionFrame(const Transaction& transaction) {
+ PROFILE_RANGE(render, __FUNCTION__);
{
std::unique_lock lock(_itemsMutex);
// Here we should be able to check the value of last ItemID allocated
@@ -123,32 +150,31 @@ void Scene::processTransactionQueue() {
// capture anything coming from the transaction
// resets and potential NEW items
- resetItems(consolidatedTransaction._resetItems);
+ resetItems(transaction._resetItems);
// Update the numItemsAtomic counter AFTER the reset changes went through
_numAllocatedItems.exchange(maxID);
// updates
- updateItems(consolidatedTransaction._updatedItems);
+ updateItems(transaction._updatedItems);
// removes
- removeItems(consolidatedTransaction._removedItems);
+ removeItems(transaction._removedItems);
-#ifdef SCENE_ENABLE_TRANSITIONS
// add transitions
- transitionItems(consolidatedTransaction._addedTransitions);
- reApplyTransitions(consolidatedTransaction._reAppliedTransitions);
- queryTransitionItems(consolidatedTransaction._queriedTransitions);
-#endif
+ transitionItems(transaction._addedTransitions);
+ reApplyTransitions(transaction._reAppliedTransitions);
+ queryTransitionItems(transaction._queriedTransitions);
+
// Update the numItemsAtomic counter AFTER the pending changes went through
_numAllocatedItems.exchange(maxID);
}
- if (consolidatedTransaction.touchTransactions()) {
+ if (transaction.touchTransactions()) {
std::unique_lock lock(_selectionsMutex);
// resets and potential NEW items
- resetSelections(consolidatedTransaction._resetSelections);
+ resetSelections(transaction._resetSelections);
}
}
diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h
index 3b61a20f24..fef2077897 100644
--- a/libraries/render/src/render/Scene.h
+++ b/libraries/render/src/render/Scene.h
@@ -117,6 +117,9 @@ public:
// Enqueue transaction to the scene
void enqueueTransaction(const Transaction& transaction);
+ // Enqueue end of frame transactions boundary
+ uint32_t enqueueFrame();
+
// Process the pending transactions queued
void processTransactionQueue();
@@ -162,6 +165,15 @@ protected:
std::mutex _transactionQueueMutex;
TransactionQueue _transactionQueue;
+
+ std::mutex _transactionFramesMutex;
+ using TransactionFrames = std::list;
+ TransactionFrames _transactionFrames;
+ uint32_t _transactionFrameNumber{ 0 };
+
+ // Process one transaction frame
+ void processTransactionFrame(const Transaction& transaction);
+
// The actual database
// database of items is protected for editing by a mutex
std::mutex _itemsMutex;
diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js
index 9323f651a2..70d91bf1ec 100644
--- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js
+++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js
@@ -223,7 +223,7 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
(distance > NEAR_GRAB_RADIUS * sensorScaleFactor)) {
continue;
}
- if (entityIsGrabbable(props)) {
+ if (entityIsGrabbable(props) || entityIsCloneable(props)) {
// give haptic feedback
if (props.id !== this.hapticTargetID) {
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp
index 58eb4d16f9..c70a74cd7f 100644
--- a/tests/render-perf/src/main.cpp
+++ b/tests/render-perf/src/main.cpp
@@ -443,10 +443,6 @@ protected:
viewOut = _viewFrustum;
}
- void copyShadowViewFrustum(ViewFrustum& viewOut) const override {
- viewOut = _shadowViewFrustum;
- }
-
QThread* getMainThread() override {
return QThread::currentThread();
}
@@ -1118,7 +1114,6 @@ private:
RenderThread _renderThread;
QWindowCamera _camera;
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
- ViewFrustum _shadowViewFrustum; // current state of view frustum, perspective, orientation, etc.
model::SunSkyStage _sunSkyStage;
model::LightPointer _globalLight { std::make_shared() };
bool _ready { false };