diff --git a/interface/resources/icons/+android/avatar-a.svg b/interface/resources/icons/+android/avatar-a.svg
new file mode 100755
index 0000000000..165b39943e
--- /dev/null
+++ b/interface/resources/icons/+android/avatar-a.svg
@@ -0,0 +1,38 @@
+
+
+
+
diff --git a/interface/resources/icons/+android/avatar-i.svg b/interface/resources/icons/+android/avatar-i.svg
new file mode 100755
index 0000000000..c1557487ea
--- /dev/null
+++ b/interface/resources/icons/+android/avatar-i.svg
@@ -0,0 +1,38 @@
+
+
+
+
diff --git a/interface/resources/icons/+android/bubble-a.svg b/interface/resources/icons/+android/bubble-a.svg
new file mode 100644
index 0000000000..fccc9c07ff
--- /dev/null
+++ b/interface/resources/icons/+android/bubble-a.svg
@@ -0,0 +1,1022 @@
+
+
+
+
\ No newline at end of file
diff --git a/interface/resources/icons/+android/bubble-i.svg b/interface/resources/icons/+android/bubble-i.svg
new file mode 100644
index 0000000000..80c97d2704
--- /dev/null
+++ b/interface/resources/icons/+android/bubble-i.svg
@@ -0,0 +1,1022 @@
+
+
+
+
\ No newline at end of file
diff --git a/interface/resources/icons/+android/button-a.svg b/interface/resources/icons/+android/button-a.svg
new file mode 100644
index 0000000000..d469154775
--- /dev/null
+++ b/interface/resources/icons/+android/button-a.svg
@@ -0,0 +1,949 @@
+
+
+
+
diff --git a/interface/resources/icons/+android/button.svg b/interface/resources/icons/+android/button.svg
new file mode 100644
index 0000000000..8c19332064
--- /dev/null
+++ b/interface/resources/icons/+android/button.svg
@@ -0,0 +1,949 @@
+
+
+
+
diff --git a/interface/resources/icons/+android/login-a.svg b/interface/resources/icons/+android/login-a.svg
new file mode 100755
index 0000000000..8a7f097ed7
--- /dev/null
+++ b/interface/resources/icons/+android/login-a.svg
@@ -0,0 +1,990 @@
+
+
+
+
diff --git a/interface/resources/icons/+android/login-i.svg b/interface/resources/icons/+android/login-i.svg
new file mode 100755
index 0000000000..6f011e1d13
--- /dev/null
+++ b/interface/resources/icons/+android/login-i.svg
@@ -0,0 +1,990 @@
+
+
+
+
diff --git a/interface/resources/icons/+android/tick.svg b/interface/resources/icons/+android/tick.svg
new file mode 100644
index 0000000000..2c451c0994
--- /dev/null
+++ b/interface/resources/icons/+android/tick.svg
@@ -0,0 +1,950 @@
+
+
+
+
diff --git a/interface/resources/qml/+android/AddressBarDialog.qml b/interface/resources/qml/+android/AddressBarDialog.qml
index 0b12301561..50552f0d3b 100644
--- a/interface/resources/qml/+android/AddressBarDialog.qml
+++ b/interface/resources/qml/+android/AddressBarDialog.qml
@@ -33,7 +33,8 @@ Item {
bar.visible = shown;
sendToScript({method: 'shownChanged', params: { shown: shown }});
if (shown) {
- updateLocationText(false);
+ addressLine.text="";
+ updateLocationText(addressLine.text.length > 0);
}
}
@@ -43,7 +44,7 @@ Item {
}
Component.onCompleted: {
- updateLocationText(false);
+ updateLocationText(addressLine.text.length > 0);
}
HifiConstants { id: hifi }
@@ -75,33 +76,33 @@ Item {
HifiStyles.RalewayRegular {
id: notice
text: "YOUR LOCATION"
- font.pixelSize: hifi.fonts.pixelSize * 2.15;
+ font.pixelSize: (hifi.fonts.pixelSize * 2.15)*(android.dimen.atLeast1440p?1:.75);
color: "#2CD7FF"
anchors {
bottom: addressBackground.top
- bottomMargin: 45
+ bottomMargin: android.dimen.atLeast1440p?45:34
left: addressBackground.left
- leftMargin: 60
+ leftMargin: android.dimen.atLeast1440p?60:45
}
}
- property int inputAreaHeight: 210
+ property int inputAreaHeight: android.dimen.atLeast1440p?210:156
property int inputAreaStep: (height - inputAreaHeight) / 2
ToolbarButton {
id: homeButton
- y: 280
+ y: android.dimen.atLeast1440p?280:210
imageURL: "../../icons/home.svg"
onClicked: {
addressBarDialog.loadHome();
bar.shown = false;
}
anchors {
- leftMargin: 75
+ leftMargin: android.dimen.atLeast1440p?75:56
left: parent.left
}
- size: 150
+ size: android.dimen.atLeast1440p?150:150//112
}
ToolbarButton {
@@ -110,10 +111,10 @@ Item {
onClicked: addressBarDialog.loadBack();
anchors {
left: homeButton.right
- leftMargin: 70
+ leftMargin: android.dimen.atLeast1440p?70:52
verticalCenter: homeButton.verticalCenter
}
- size: 150
+ size: android.dimen.atLeast1440p?150:150
}
ToolbarButton {
id: forwardArrow;
@@ -121,16 +122,16 @@ Item {
onClicked: addressBarDialog.loadForward();
anchors {
left: backArrow.right
- leftMargin: 60
+ leftMargin: android.dimen.atLeast1440p?60:45
verticalCenter: homeButton.verticalCenter
}
- size: 150
+ size: android.dimen.atLeast1440p?150:150
}
HifiStyles.FiraSansRegular {
id: location;
font.pixelSize: addressLine.font.pixelSize;
- color: "gray";
+ color: "lightgray";
clip: true;
anchors.fill: addressLine;
visible: addressLine.text.length === 0
@@ -139,24 +140,24 @@ Item {
Rectangle {
id: addressBackground
- x: 780
- y: 280
- width: 1440
- height: 150
+ x: android.dimen.atLeast1440p?780:585
+ y: android.dimen.atLeast1440p?280:235 // tweaking by hand
+ width: android.dimen.atLeast1440p?1270:952
+ height: android.dimen.atLeast1440p?150:112
color: "#FFFFFF"
}
TextInput {
id: addressLine
focus: true
- x: 870
- y: 450
- width: 1350
- height: 120
+ x: android.dimen.atLeast1440p?870:652
+ y: android.dimen.atLeast1440p?300:245 // tweaking by hand
+ width: android.dimen.atLeast1440p?1200:900
+ height: android.dimen.atLeast1440p?120:90
inputMethodHints: Qt.ImhNoPredictiveText
//helperText: "Hint is here"
anchors {
- verticalCenter: homeButton.verticalCenter
+ //verticalCenter: addressBackground.verticalCenter
}
font.pixelSize: hifi.fonts.pixelSize * 3.75
onTextChanged: {
diff --git a/interface/resources/qml/+android/LoginDialog.qml b/interface/resources/qml/+android/LoginDialog.qml
new file mode 100644
index 0000000000..9eb2c74147
--- /dev/null
+++ b/interface/resources/qml/+android/LoginDialog.qml
@@ -0,0 +1,93 @@
+//
+// LoginDialog.qml
+//
+// Created by David Rowe on 3 Jun 2015
+// 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"
+import "windows"
+
+import "LoginDialog"
+
+ModalWindow {
+ id: root
+ HifiConstants { id: hifi }
+
+ objectName: "LoginDialog"
+ implicitWidth: 1560
+ implicitHeight: 450
+ y:0
+ destroyOnCloseButton: true
+ destroyOnHidden: true
+ visible: true
+
+ property string iconText: ""
+ property int iconSize: 105
+
+ property string title: ""
+ property int titleWidth: 0
+
+ keyboardOverride: true // Disable ModalWindow's keyboard.
+
+ function tryDestroy() {
+ root.destroy()
+ }
+
+ LoginDialog {
+ id: loginDialog
+
+ Loader {
+ id: bodyLoader
+ source: loginDialog.isSteamRunning() ? "LoginDialog/+android/SignInBody.qml" : "LoginDialog/+android/LinkAccountBody.qml"
+ }
+ }
+
+ Component.onCompleted: {
+ this.anchors.centerIn = undefined;
+ this.y=150;
+ this.x=(parent.width - this.width)/2;
+ }
+
+ 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/resources/qml/LoginDialog/+android/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/+android/LinkAccountBody.qml
new file mode 100644
index 0000000000..7eced0c751
--- /dev/null
+++ b/interface/resources/qml/LoginDialog/+android/LinkAccountBody.qml
@@ -0,0 +1,290 @@
+//
+// 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: 300
+ width: root.pane.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
+ readonly property int minWidth: 1440
+ readonly property int maxWidth: 3840
+ readonly property int minHeight: 150
+ readonly property int maxHeight: 660
+
+ 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;
+
+ if (additionalInformation.visible) {
+ targetWidth = Math.max(targetWidth, additionalInformation.width);
+ targetHeight += hifi.dimensions.contentSpacing.y + additionalInformation.height
+ }
+
+ parent.width = root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth));
+ parent.height = 420;
+ /*root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight))
+ + (keyboardEnabled && keyboardRaised ? (200 + 2 * hifi.dimensions.contentSpacing.y) : hifi.dimensions.contentSpacing.y);*/
+ }
+ }
+
+ 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: 144
+ height: 144
+ }
+
+ ShortcutText {
+ id: mainTextContainer
+ anchors {
+ top: parent.top
+ left: parent.left
+ margins: 0
+ topMargin: hifi.dimensions.contentSpacing.y / 2
+ }
+
+ 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: 0 // hifi.dimensions.contentSpacing.y
+ }
+ spacing: hifi.dimensions.contentSpacing.y / 2
+
+ TextField {
+ id: usernameField
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: 1080
+ placeholderText: qsTr("Username or Email")
+ }
+
+ TextField {
+ id: passwordField
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: 1080
+
+ placeholderText: qsTr("Password")
+ echoMode: TextInput.Password
+ }
+ }
+
+ 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: 3
+ 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
+ top: form.bottom
+ topMargin: hifi.dimensions.contentSpacing.y / 2
+ }
+
+ 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
+ top: form.bottom
+ topMargin: hifi.dimensions.contentSpacing.y / 2
+ }
+ spacing: hifi.dimensions.contentSpacing.x
+ onHeightChanged: d.resize(); onWidthChanged: d.resize();
+
+ Button {
+ id: linkAccountButton
+ anchors.verticalCenter: parent.verticalCenter
+
+ text: qsTr(loginDialog.isSteamRunning() ? "Link Account" : "Login")
+ color: hifi.buttons.blue
+
+ onClicked: {
+ Qt.inputMethod.hide();
+ linkAccountBody.login();
+ }
+ }
+
+ Button {
+ anchors.verticalCenter: parent.verticalCenter
+
+ text: qsTr("Cancel")
+
+ onClicked: {
+ Qt.inputMethod.hide();
+ root.destroy();
+ }
+ }
+ }
+
+ Component.onCompleted: {
+ root.title = qsTr("Sign Into High Fidelity")
+ root.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 })
+ bodyLoader.item.width = root.pane.width
+ bodyLoader.item.height = root.pane.height
+ }
+ }
+ onHandleLoginFailed: {
+ console.log("Login Failed")
+ mainTextContainer.visible = true
+ toggleLoading(false)
+ }
+ onHandleLinkCompleted: {
+ console.log("Link Succeeded")
+
+ bodyLoader.setSource("../WelcomeBody.qml", { "welcomeBack" : true })
+ bodyLoader.item.width = root.pane.width
+ bodyLoader.item.height = root.pane.height
+ }
+ 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/LoginDialog/+android/SignUpBody.qml b/interface/resources/qml/LoginDialog/+android/SignUpBody.qml
new file mode 100644
index 0000000000..3a44a8d741
--- /dev/null
+++ b/interface/resources/qml/LoginDialog/+android/SignUpBody.qml
@@ -0,0 +1,297 @@
+//
+// 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: root.pane.height
+ width: root.pane.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
+ readonly property int minWidth: 960
+ readonly property int maxWidth: 2560
+ readonly property int minHeight: 240
+ readonly property int maxHeight: 1480
+
+ 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;
+
+ parent.width = root.width = Math.max(d.minWidth, Math.min(d.maxWidth, targetWidth));
+ //parent.height = 650;
+ parent.height = root.height = Math.max(d.minHeight, Math.min(d.maxHeight, targetHeight));
+
+ }
+ }
+
+ 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: 0; // 2 * hifi.dimensions.contentSpacing.y
+ }
+ spacing: hifi.dimensions.contentSpacing.y / 2
+
+ Row {
+ spacing: hifi.dimensions.contentSpacing.x
+
+ TextField {
+ id: emailField
+ anchors {
+ verticalCenter: parent.verticalCenter
+ }
+ width: 780
+
+ placeholderText: "Email"
+ }
+ }
+
+ Row {
+ spacing: hifi.dimensions.contentSpacing.x
+
+ TextField {
+ id: usernameField
+ anchors {
+ verticalCenter: parent.verticalCenter
+ }
+ width: 780
+
+ placeholderText: "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: 780
+
+ placeholderText: "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
+ top: form.bottom
+ topMargin: hifi.dimensions.contentSpacing.y// / 2
+ }
+
+ 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
+ top: form.bottom
+ topMargin: hifi.dimensions.contentSpacing.y / 2
+ }
+ spacing: hifi.dimensions.contentSpacing.x
+ onHeightChanged: d.resize(); onWidthChanged: d.resize();
+
+ Button {
+ id: linkAccountButton
+ anchors.verticalCenter: parent.verticalCenter
+
+ 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;
+ 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 })
+ bodyLoader.item.width = root.pane.width
+ bodyLoader.item.height = root.pane.height
+ }
+ 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
+ }
+ }
+
+ 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/controls-uit/+android/ImageButton.qml b/interface/resources/qml/controls-uit/+android/ImageButton.qml
new file mode 100644
index 0000000000..5ebf7cd3e9
--- /dev/null
+++ b/interface/resources/qml/controls-uit/+android/ImageButton.qml
@@ -0,0 +1,82 @@
+//
+// ImageButton.qml
+// interface/resources/qml/controls-uit
+//
+// Created by Gabriel Calero & Cristian Duarte on 12 Oct 2017
+// Copyright 2017 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+import QtQuick 2.5
+import QtQuick.Layouts 1.3
+import "../styles-uit" as HifiStyles
+
+Item {
+ id: button
+
+ property string text: ""
+ property string source : ""
+ property string hoverSource : ""
+ property real fontSize: 10
+ property string fontColor: "#FFFFFF"
+ property string hoverFontColor: "#000000"
+
+ signal clicked();
+
+ Rectangle {
+ color: "transparent"
+ anchors.fill: parent
+ Image {
+ id: image
+ anchors.fill: parent
+ source: button.source
+ }
+
+ HifiStyles.FiraSansRegular {
+ id: buttonText
+ anchors.centerIn: parent
+ text: button.text
+ color: button.fontColor
+ font.pixelSize: button.fontSize
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: button.clicked();
+ onEntered: {
+ button.state = "hover state";
+ }
+ onExited: {
+ button.state = "base state";
+ }
+ }
+
+
+ }
+ states: [
+ State {
+ name: "hover state"
+ PropertyChanges {
+ target: image
+ source: button.hoverSource
+ }
+ PropertyChanges {
+ target: buttonText
+ color: button.hoverFontColor
+ }
+ },
+ State {
+ name: "base state"
+ PropertyChanges {
+ target: image
+ source: button.source
+ }
+ PropertyChanges {
+ target: buttonText
+ color: button.fontColor
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/interface/resources/qml/controls-uit/Button.qml b/interface/resources/qml/controls-uit/Button.qml
index 926e9c4fe5..e2b6097553 100644
--- a/interface/resources/qml/controls-uit/Button.qml
+++ b/interface/resources/qml/controls-uit/Button.qml
@@ -22,7 +22,7 @@ Original.Button {
property int colorScheme: hifi.colorSchemes.light
property string buttonGlyph: "";
- width: 120
+ width: hifi.dimensions.buttonWidth
height: hifi.dimensions.controlLineHeight
HifiConstants { id: hifi }
diff --git a/interface/resources/qml/desktop/+android/FocusHack.qml b/interface/resources/qml/desktop/+android/FocusHack.qml
new file mode 100644
index 0000000000..38253fdec1
--- /dev/null
+++ b/interface/resources/qml/desktop/+android/FocusHack.qml
@@ -0,0 +1,26 @@
+//
+// FocusHack.qml
+//
+// Created by Bradley Austin Davis on 21 Jan 2015
+// 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 QtQuick 2.5
+
+FocusScope {
+ id: root
+ objectName: "FocusHack"
+
+ TextInput {
+ id: textInput;
+ focus: true
+ width: 10; height: 10
+ onActiveFocusChanged: root.destroy()
+ }
+
+ function start() {
+ }
+}
diff --git a/interface/resources/qml/hifi/+android/AvatarOption.qml b/interface/resources/qml/hifi/+android/AvatarOption.qml
new file mode 100644
index 0000000000..e7056baa36
--- /dev/null
+++ b/interface/resources/qml/hifi/+android/AvatarOption.qml
@@ -0,0 +1,117 @@
+//
+// AvatarOption.qml
+// interface/resources/qml/hifi/android
+//
+// Created by Cristian Duarte & Gabriel Calero on 12 Oct 2017
+// Copyright 2017 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+import QtQuick.Layouts 1.3
+import QtQuick 2.5
+import "../controls-uit" as HifiControlsUit
+
+ColumnLayout {
+ id: itemRoot
+
+ property string type: "";
+
+ property string thumbnailUrl: "";
+ property string avatarUrl: "";
+ property string avatarName: "";
+ property bool avatarSelected: false;
+
+ property string methodName: "";
+ property string actionText: "";
+
+ spacing: 4*3
+ signal sendToParentQml(var message);
+
+ Image {
+ id: itemImage
+ Layout.preferredWidth: 250*3
+ Layout.preferredHeight: 140*3
+ source: thumbnailUrl
+ asynchronous: true
+ fillMode: Image.PreserveAspectFit
+
+ MouseArea {
+ id: itemArea
+ anchors.fill: parent
+ hoverEnabled: true
+ enabled: true
+ onClicked: {
+ if (type=="avatar") {
+ if (!avatarSelected) sendToParentQml({ method: "selectAvatar", params: { avatarUrl: avatarUrl } });
+ } else {
+ sendToParentQml({ method: methodName, params: { } });
+ }
+ }
+ }
+
+ }
+
+ Text {
+ id: itemName
+ text: avatarName
+ color: "#FFFFFF"
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ anchors.horizontalCenter: itemImage.horizontalCenter
+ font.pointSize: 5*3
+ wrapMode: Text.WordWrap
+ width: parent
+ MouseArea {
+ id: itemNameArea
+ anchors.fill: parent
+ hoverEnabled: true
+ enabled: true
+ onClicked: {
+ if (type=="avatar") {
+ if (!avatarSelected) sendToParentQml({ method: "selectAvatar", params: { avatarUrl: avatarUrl } });
+ } else {
+ sendToParentQml({ method: methodName, params: { } });
+ }
+ }
+ }
+ }
+
+ HifiControlsUit.ImageButton {
+ width: 140*3
+ height: 35*3
+ text: type=="extra"? actionText: "CHOOSE"
+ source: "../../../../icons/button.svg"
+ hoverSource: "../../../../icons/button-a.svg"
+ fontSize: 18*3
+ fontColor: "#2CD8FF"
+ hoverFontColor: "#FFFFFF"
+ anchors {
+ horizontalCenter: itemName.horizontalCenter
+ }
+ visible: !avatarSelected
+ onClicked: {
+ if (type=="avatar") {
+ if (!avatarSelected) sendToParentQml({ method: "selectAvatar", params: { avatarUrl: avatarUrl } });
+ } else {
+ sendToParentQml({ method: methodName, params: { } });
+ }
+ }
+ }
+
+ Image {
+ id: tickImage
+ width: 35*3
+ height: 35*3
+ source: "../../../icons/tick.svg"
+ anchors {
+ horizontalCenter: itemName.horizontalCenter
+ }
+ visible: avatarSelected
+ }
+
+ Component.onCompleted:{
+ sendToParentQml.connect(sendToScript);
+ }
+}
\ No newline at end of file
diff --git a/interface/resources/qml/hifi/+android/HifiConstants.qml b/interface/resources/qml/hifi/+android/HifiConstants.qml
index ee6d92ed38..fbdf60dcb0 100644
--- a/interface/resources/qml/hifi/+android/HifiConstants.qml
+++ b/interface/resources/qml/hifi/+android/HifiConstants.qml
@@ -10,6 +10,7 @@
//
import QtQuick 2.4
+import QtQuick.Window 2.2
Item {
@@ -20,26 +21,27 @@ Item {
Item {
id: dimen
- readonly property real windowLessWidth: 126
- readonly property real windowLessHeight: 64
+ readonly property bool atLeast1440p: Screen.width >= 2560 && Screen.height >= 1440
+ readonly property real windowLessWidth: atLeast1440p?378:284
+ readonly property real windowLessHeight: atLeast1440p?192:144
readonly property real windowZ: 100
- readonly property real headerHeight: 276
+ readonly property real headerHeight: atLeast1440p?276:207
- readonly property real headerIconPosX: 90
- readonly property real headerIconPosY: 108
- readonly property real headerIconWidth: 111
- readonly property real headerIconHeight: 111
- readonly property real headerIconTitleDistance: 151
+ readonly property real headerIconPosX: atLeast1440p?90:67
+ readonly property real headerIconPosY: atLeast1440p?108:81
+ readonly property real headerIconWidth: atLeast1440p?111:83
+ readonly property real headerIconHeight: atLeast1440p?111:83
+ readonly property real headerIconTitleDistance: atLeast1440p?151:113
- readonly property real headerHideWidth: 150
- readonly property real headerHideHeight: 150
- readonly property real headerHideRightMargin: 110
- readonly property real headerHideTopMargin: 90
- readonly property real headerHideIconWidth: 70
- readonly property real headerHideIconHeight: 45
- readonly property real headerHideTextTopMargin: 36
+ readonly property real headerHideWidth: atLeast1440p?150:112
+ readonly property real headerHideHeight: atLeast1440p?150:112
+ readonly property real headerHideRightMargin: atLeast1440p?110:82
+ readonly property real headerHideTopMargin: atLeast1440p?90:67
+ readonly property real headerHideIconWidth: atLeast1440p?70:52
+ readonly property real headerHideIconHeight: atLeast1440p?45:33
+ readonly property real headerHideTextTopMargin: atLeast1440p?36:27
readonly property real botomHudWidth: 366
readonly property real botomHudHeight: 180
diff --git a/interface/resources/qml/hifi/+android/avatarSelection.qml b/interface/resources/qml/hifi/+android/avatarSelection.qml
new file mode 100644
index 0000000000..3090204308
--- /dev/null
+++ b/interface/resources/qml/hifi/+android/avatarSelection.qml
@@ -0,0 +1,175 @@
+//
+// avatarSelection.qml
+// interface/resources/qml/android
+//
+// Created by Gabriel Calero & Cristian Duarte on 21 Sep 2017
+// Copyright 2017 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+import QtQuick 2.5
+import QtQuick.Layouts 1.3
+import Hifi 1.0
+
+import "../../styles"
+import "."
+import ".."
+import ".." as QmlHifi
+import "../../styles-uit" as HifiStyles
+
+
+Item {
+
+ id: top
+
+ HifiConstants { id: android }
+ width: parent ? parent.width - android.dimen.windowLessWidth : 0
+ height: parent ? parent.height - android.dimen.windowLessHeight : 0
+ z: android.dimen.windowZ
+ anchors { horizontalCenter: parent.horizontalCenter; bottom: parent.bottom }
+
+ signal sendToScript(var message);
+
+ property bool shown: true
+
+ onShownChanged: {
+ top.visible = shown;
+ }
+
+
+ HifiConstants { id: hifi }
+ HifiStyles.HifiConstants { id: hifiStyleConstants }
+
+ property int cardWidth: 250 *3;
+ property int cardHeight: 240 *3;
+ property int gap: 14 *3;
+
+ property var avatarsArray: [];
+ property var extraOptionsArray: [];
+
+ function hide() {
+ shown = false;
+ sendToScript ({ method: "hide" });
+ }
+
+ Rectangle {
+
+ width: parent ? parent.width : 0
+ height: parent ? parent.height : 0
+
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: android.color.gradientTop }
+ GradientStop { position: 1.0; color: android.color.gradientBottom }
+ }
+
+ QmlHifi.WindowHeader {
+ id: header
+ iconSource: "../../../../icons/avatar-i.svg"
+ titleText: "AVATAR"
+ }
+
+ ListModel { id: avatars }
+
+ ListView {
+ id: scroll
+ height: 250*3
+ property int stackedCardShadowHeight: 10*3;
+ spacing: gap;
+ clip: true;
+ anchors {
+ left: parent.left
+ right: parent.right
+ top: header.bottom
+ topMargin: gap
+ leftMargin: gap
+ rightMargin: gap
+ }
+ model: avatars;
+ orientation: ListView.Horizontal;
+ delegate: QmlHifi.AvatarOption {
+ type: model.type;
+ thumbnailUrl: model.thumbnailUrl;
+ avatarUrl: model.avatarUrl;
+ avatarName: model.avatarName;
+ avatarSelected: model.avatarSelected;
+ methodName: model.methodName;
+ actionText: model.actionText;
+ }
+ highlightMoveDuration: -1;
+ highlightMoveVelocity: -1;
+ }
+
+ }
+
+ function escapeRegExp(str) {
+ return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
+ }
+ function replaceAll(str, find, replace) {
+ return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
+ }
+
+ function refreshSelected(selectedAvatarUrl) {
+ // URL as ID?
+ avatarsArray.forEach(function (avatarData) {
+ avatarData.avatarSelected = (selectedAvatarUrl == avatarData.avatarUrl);
+ console.log('[avatarSelection] avatar : ', avatarData.avatarName, ' is selected? ' , avatarData.avatarSelected);
+ });
+ }
+
+ function addAvatar(name, thumbnailUrl, avatarUrl) {
+ avatarsArray.push({
+ type: "avatar",
+ thumbnailUrl: thumbnailUrl,
+ avatarUrl: avatarUrl,
+ avatarName: name,
+ avatarSelected: false,
+ methodName: "",
+ actionText: ""
+ });
+ }
+
+ function showAvatars() {
+ avatars.clear();
+ avatarsArray.forEach(function (avatarData) {
+ avatars.append(avatarData);
+ console.log('[avatarSelection] adding avatar to model: ', JSON.stringify(avatarData));
+ });
+ extraOptionsArray.forEach(function (extraData) {
+ avatars.append(extraData);
+ console.log('[avatarSelection] adding extra option to model: ', JSON.stringify(extraData));
+ });
+ }
+
+ function addExtraOption(showName, thumbnailUrl, methodNameWhenClicked, actionText) {
+ extraOptionsArray.push({
+ type: "extra",
+ thumbnailUrl: thumbnailUrl,
+ avatarUrl: "",
+ avatarName: showName,
+ avatarSelected: false,
+ methodName: methodNameWhenClicked,
+ actionText: actionText
+ });
+ }
+
+ function fromScript(message) {
+ //console.log("[CHAT] fromScript " + JSON.stringify(message));
+ switch (message.type) {
+ case "addAvatar":
+ addAvatar(message.name, message.thumbnailUrl, message.avatarUrl);
+ break;
+ case "addExtraOption":
+ //(showName, thumbnailUrl, methodNameWhenClicked, actionText)
+ addExtraOption(message.showName, message.thumbnailUrl, message.methodNameWhenClicked, message.actionText);
+ break;
+ case "refreshSelected":
+ refreshSelected(message.selectedAvatarUrl);
+ break;
+ case "showAvatars":
+ showAvatars();
+ break;
+ default:
+ }
+ }
+}
\ No newline at end of file
diff --git a/interface/resources/qml/hifi/+android/bottombar.qml b/interface/resources/qml/hifi/+android/bottombar.qml
index 2a34b7fe19..e861d441d9 100644
--- a/interface/resources/qml/hifi/+android/bottombar.qml
+++ b/interface/resources/qml/hifi/+android/bottombar.qml
@@ -41,6 +41,15 @@ Item {
Styles.HifiConstants { id: hifi }
HifiConstants { id: android }
+ MouseArea {
+ anchors.fill: parent
+ onEntered: {
+ Controller.setVPadEnabled(false);
+ }
+ onExited: {
+ Controller.setVPadEnabled(true);
+ }
+ }
Rectangle {
id: background
diff --git a/interface/resources/qml/hifi/+android/button.qml b/interface/resources/qml/hifi/+android/button.qml
index ec7af2ab92..4822b6bf33 100644
--- a/interface/resources/qml/hifi/+android/button.qml
+++ b/interface/resources/qml/hifi/+android/button.qml
@@ -40,6 +40,8 @@ Item {
property bool isActive: false
signal clicked()
+ signal entered()
+ signal exited()
onIsActiveChanged: {
if (button.isEntered) {
@@ -118,6 +120,7 @@ Item {
}
onEntered: {
button.isEntered = true;
+ button.entered();
if (button.isActive) {
button.state = "hover active state";
} else {
@@ -126,6 +129,7 @@ Item {
}
onExited: {
button.isEntered = false;
+ button.exited()
if (button.isActive) {
button.state = "active state";
} else {
diff --git a/interface/resources/qml/hifi/+android/modesbar.qml b/interface/resources/qml/hifi/+android/modesbar.qml
index 8ce455c2c1..552ca80778 100644
--- a/interface/resources/qml/hifi/+android/modesbar.qml
+++ b/interface/resources/qml/hifi/+android/modesbar.qml
@@ -25,8 +25,8 @@ Item {
}
Component.onCompleted: {
- width = 330;
- height = 330;
+ width = 300 + 30; // That 30 is extra regardless the qty of items shown
+ height = 300 + 30;
x=Window.innerWidth - width;
}
@@ -40,6 +40,12 @@ Item {
var keys = Object.keys(properties).forEach(function (key) {
button[key] = properties[key];
});
+ button.entered.connect(function() {
+ Controller.setVPadEnabled(false);
+ });
+ button.exited.connect(function() {
+ Controller.setVPadEnabled(true);
+ });
return button;
} else if( component.status == Component.Error) {
console.log("Load button errors " + component.errorString());
@@ -60,10 +66,10 @@ Item {
function fromScript(message) {
switch (message.type) {
case "allButtonsShown":
- modesbar.height = flowMain.children.length * 100 + 10;
+ modesbar.height = flowMain.children.length * 300 + 30; // That 30 is extra regardless the qty of items shown
break;
case "inactiveButtonsHidden":
- modesbar.height = 100 + 10;
+ modesbar.height = 300 + 30;
break;
default:
break;
diff --git a/interface/resources/qml/styles-uit/+android/HifiConstants.qml b/interface/resources/qml/styles-uit/+android/HifiConstants.qml
new file mode 100644
index 0000000000..d5fab57501
--- /dev/null
+++ b/interface/resources/qml/styles-uit/+android/HifiConstants.qml
@@ -0,0 +1,358 @@
+//
+// HiFiConstants.qml
+//
+// Created by Bradley Austin Davis on 28 Apr 2015
+// 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 QtQuick 2.5
+import QtQuick.Window 2.2
+
+Item {
+ readonly property alias colors: colors
+ readonly property alias colorSchemes: colorSchemes
+ readonly property alias dimensions: dimensions
+ readonly property alias fontSizes: fontSizes
+ readonly property alias glyphs: glyphs
+ readonly property alias icons: icons
+ readonly property alias buttons: buttons
+ readonly property alias effects: effects
+
+ function glyphForIcon(icon) {
+ // Translates icon enum to glyph char.
+ var glyph;
+ switch (icon) {
+ case hifi.icons.information:
+ glyph = hifi.glyphs.info;
+ break;
+ case hifi.icons.question:
+ glyph = hifi.glyphs.question;
+ break;
+ case hifi.icons.warning:
+ glyph = hifi.glyphs.alert;
+ break;
+ case hifi.icons.critical:
+ glyph = hifi.glyphs.error;
+ break;
+ case hifi.icons.placemark:
+ glyph = hifi.glyphs.placemark;
+ break;
+ default:
+ glyph = hifi.glyphs.noIcon;
+ }
+ return glyph;
+ }
+
+ Item {
+ id: colors
+
+ // Base colors
+ readonly property color baseGray: "#393939"
+ readonly property color darkGray: "#121212"
+ readonly property color baseGrayShadow: "#252525"
+ readonly property color baseGrayHighlight: "#575757"
+ readonly property color lightGray: "#6a6a6a"
+ readonly property color lightGrayText: "#afafaf"
+ readonly property color faintGray: "#e3e3e3"
+ readonly property color primaryHighlight: "#00b4ef"
+ readonly property color blueHighlight: "#00b4ef"
+ readonly property color blueAccent: "#0093C5"
+ readonly property color redHighlight: "#EA4C5F"
+ readonly property color redAccent: "#C62147"
+ readonly property color greenHighlight: "#1ac567"
+ readonly property color greenShadow: "#359D85"
+ readonly property color orangeHighlight: "#FFC49C"
+ readonly property color orangeAccent: "#FF6309"
+ readonly property color indigoHighlight: "#C0D2FF"
+ readonly property color indigoAccent: "#9495FF"
+ readonly property color magentaHighlight: "#EF93D1"
+ readonly property color magentaAccent: "#A2277C"
+ readonly property color checkboxCheckedRed: "#FF0000"
+ readonly property color checkboxCheckedBorderRed: "#D00000"
+ readonly property color lightBlueHighlight: "#d6f6ff"
+
+ // Semitransparent
+ readonly property color darkGray30: "#4d121212"
+ readonly property color darkGray0: "#00121212"
+ readonly property color baseGrayShadow60: "#99252525"
+ readonly property color baseGrayShadow50: "#80252525"
+ readonly property color baseGrayShadow25: "#40252525"
+ readonly property color baseGrayHighlight40: "#66575757"
+ readonly property color baseGrayHighlight15: "#26575757"
+ readonly property color lightGray50: "#806a6a6a"
+ readonly property color lightGrayText80: "#ccafafaf"
+ readonly property color faintGray80: "#cce3e3e3"
+ readonly property color faintGray50: "#80e3e3e3"
+
+ // Other colors
+ readonly property color white: "#ffffff"
+ readonly property color gray: "#808080"
+ readonly property color black: "#000000"
+ readonly property color locked: "#252525"
+ // Semitransparent
+ readonly property color white50: "#80ffffff"
+ readonly property color white30: "#4dffffff"
+ readonly property color white25: "#40ffffff"
+ readonly property color transparent: "#00ffffff"
+
+ // Control specific colors
+ readonly property color tableRowLightOdd: "#fafafa"
+ readonly property color tableRowLightEven: "#eeeeee" // Equivavlent to "#1a575757" over #e3e3e3 background
+ readonly property color tableRowDarkOdd: "#2e2e2e" // Equivalent to "#80393939" over #404040 background
+ readonly property color tableRowDarkEven: "#1c1c1c" // Equivalent to "#a6181818" over #404040 background
+ readonly property color tableBackgroundLight: tableRowLightEven
+ readonly property color tableBackgroundDark: tableRowDarkEven
+ readonly property color tableScrollHandleLight: "#DDDDDD"
+ readonly property color tableScrollHandleDark: "#707070"
+ readonly property color tableScrollBackgroundLight: tableRowLightOdd
+ readonly property color tableScrollBackgroundDark: "#323232"
+ readonly property color checkboxLightStart: "#ffffff"
+ readonly property color checkboxLightFinish: "#afafaf"
+ readonly property color checkboxDarkStart: "#7d7d7d"
+ readonly property color checkboxDarkFinish: "#6b6a6b"
+ readonly property color checkboxChecked: primaryHighlight
+ readonly property color checkboxCheckedBorder: "#36cdff"
+ readonly property color sliderGutterLight: "#d4d4d4"
+ readonly property color sliderGutterDark: "#252525"
+ readonly property color sliderBorderLight: "#afafaf"
+ readonly property color sliderBorderDark: "#7d7d7d"
+ readonly property color sliderLightStart: "#ffffff"
+ readonly property color sliderLightFinish: "#afafaf"
+ readonly property color sliderDarkStart: "#7d7d7d"
+ readonly property color sliderDarkFinish: "#6b6a6b"
+ readonly property color dropDownPressedLight: "#d4d4d4"
+ readonly property color dropDownPressedDark: "#afafaf"
+ readonly property color dropDownLightStart: "#ffffff"
+ readonly property color dropDownLightFinish: "#afafaf"
+ readonly property color dropDownDarkStart: "#7d7d7d"
+ readonly property color dropDownDarkFinish: "#6b6a6b"
+ readonly property color textFieldLightBackground: "#d4d4d4"
+ readonly property color tabBackgroundDark: "#252525"
+ readonly property color tabBackgroundLight: "#d4d4d4"
+ }
+
+ Item {
+ id: colorSchemes
+ readonly property int light: 0
+ readonly property int dark: 1
+ readonly property int faintGray: 2
+ }
+
+ Item {
+ id: dimensions
+ readonly property bool largeScreen: Screen.width >= 1920 && Screen.height >= 1080
+ readonly property real borderRadius: largeScreen ? 7.5 : 5.0
+ readonly property real borderWidth: largeScreen ? 2 : 1
+ readonly property vector2d contentMargin: Qt.vector2d(21, 21)
+ readonly property vector2d contentSpacing: Qt.vector2d(11, 14)
+ readonly property real labelPadding: 40
+ readonly property real textPadding: 8
+ readonly property real sliderHandleSize: 18
+ readonly property real sliderGrooveHeight: 8
+ readonly property real frameIconSize: 22
+ readonly property real spinnerSize: 50
+ readonly property real tablePadding: 12
+ readonly property real tableRowHeight: largeScreen ? 26 : 23
+ readonly property real tableHeaderHeight: 29
+ readonly property vector2d modalDialogMargin: Qt.vector2d(50, 30)
+ readonly property real modalDialogTitleHeight: 120
+ readonly property real controlLineHeight: 84 // Height of spinbox control on 1920 x 1080 monitor
+ readonly property real controlInterlineHeight: 21 // 75% of controlLineHeight
+ readonly property vector2d menuPadding: Qt.vector2d(14, 102)
+ readonly property real scrollbarBackgroundWidth: 20
+ readonly property real scrollbarHandleWidth: scrollbarBackgroundWidth - 2
+ readonly property real tabletMenuHeader: 90
+ readonly property real buttonWidth: 360
+ }
+
+ Item {
+ id: fontSizes // In pixels
+ readonly property real overlayTitle: dimensions.largeScreen ? 54 : 42
+ readonly property real tabName: dimensions.largeScreen ? 12 : 10
+ readonly property real sectionName: dimensions.largeScreen ? 36 : 30
+ readonly property real inputLabel: dimensions.largeScreen ? 14 : 10
+ readonly property real textFieldInput: dimensions.largeScreen ? 48 : 36
+ readonly property real textFieldInputLabel: dimensions.largeScreen ? 13 : 9
+ readonly property real textFieldSearchIcon: dimensions.largeScreen ? 30 : 24
+ readonly property real tableHeading: dimensions.largeScreen ? 12 : 10
+ readonly property real tableHeadingIcon: dimensions.largeScreen ? 60 : 33
+ readonly property real tableText: dimensions.largeScreen ? 15 : 12
+ readonly property real buttonLabel: dimensions.largeScreen ? 42 : 27
+ readonly property real iconButton: dimensions.largeScreen ? 13 : 9
+ readonly property real listItem: dimensions.largeScreen ? 15 : 11
+ readonly property real tabularData: dimensions.largeScreen ? 15 : 11
+ readonly property real logs: dimensions.largeScreen ? 16 : 12
+ readonly property real code: dimensions.largeScreen ? 16 : 12
+ readonly property real rootMenu: dimensions.largeScreen ? 15 : 11
+ readonly property real rootMenuDisclosure: dimensions.largeScreen ? 20 : 16
+ readonly property real menuItem: dimensions.largeScreen ? 45 : 33
+ readonly property real shortcutText: dimensions.largeScreen ? 39 : 27
+ readonly property real carat: dimensions.largeScreen ? 38 : 30
+ readonly property real disclosureButton: dimensions.largeScreen ? 30 : 22
+ }
+
+ Item {
+ id: icons
+ // Values per OffscreenUi::Icon
+ readonly property int none: 0
+ readonly property int question: 1
+ readonly property int information: 2
+ readonly property int warning: 3
+ readonly property int critical: 4
+ readonly property int placemark: 5
+ }
+
+ Item {
+ id: buttons
+ readonly property int white: 0
+ readonly property int blue: 1
+ readonly property int red: 2
+ readonly property int black: 3
+ readonly property int none: 4
+ readonly property int noneBorderless: 5
+ readonly property int noneBorderlessWhite: 6
+ readonly property int noneBorderlessGray: 7
+ readonly property var textColor: [ colors.darkGray, colors.white, colors.white, colors.white, colors.white, colors.blueAccent, colors.white, colors.darkGray ]
+ readonly property var colorStart: [ colors.white, colors.primaryHighlight, "#d42043", "#343434", Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0) ]
+ readonly property var colorFinish: [ colors.lightGrayText, colors.blueAccent, "#94132e", colors.black, Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0) ]
+ readonly property var hoveredColor: [ colorStart[white], colorStart[blue], colorStart[red], colorFinish[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ]
+ readonly property var pressedColor: [ colorFinish[white], colorFinish[blue], colorFinish[red], colorStart[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ]
+ readonly property var disabledColorStart: [ colorStart[white], colors.baseGrayHighlight]
+ readonly property var disabledColorFinish: [ colorFinish[white], colors.baseGrayShadow]
+ readonly property var disabledTextColor: [ colors.lightGrayText, colors.baseGrayShadow]
+ readonly property int radius: 15
+ }
+
+ QtObject {
+ id: effects
+ readonly property int fadeInDuration: 300
+ }
+ Item {
+ id: glyphs
+ readonly property string noIcon: ""
+ readonly property string hmd: "b"
+ readonly property string screen: "c"
+ readonly property string keyboard: "d"
+ readonly property string handControllers: "e"
+ readonly property string headphonesMic: "f"
+ readonly property string gamepad: "g"
+ readonly property string headphones: "h"
+ readonly property string mic: "i"
+ readonly property string upload: "j"
+ readonly property string script: "k"
+ readonly property string text: "l"
+ readonly property string cube: "m"
+ readonly property string sphere: "n"
+ readonly property string zone: "o"
+ readonly property string light: "p"
+ readonly property string web: "q"
+ readonly property string web2: "r"
+ readonly property string edit: "s"
+ readonly property string market: "t"
+ readonly property string directory: "u"
+ readonly property string menu: "v"
+ readonly property string close: "w"
+ readonly property string closeInverted: "x"
+ readonly property string pin: "y"
+ readonly property string pinInverted: "z"
+ readonly property string resizeHandle: "A"
+ readonly property string disclosureExpand: "B"
+ readonly property string reloadSmall: "a"
+ readonly property string closeSmall: "C"
+ readonly property string forward: "D"
+ readonly property string backward: "E"
+ readonly property string reload: "F"
+ readonly property string unmuted: "G"
+ readonly property string muted: "H"
+ readonly property string minimize: "I"
+ readonly property string maximize: "J"
+ readonly property string maximizeInverted: "K"
+ readonly property string disclosureButtonExpand: "L"
+ readonly property string disclosureButtonCollapse: "M"
+ readonly property string scriptStop: "N"
+ readonly property string scriptReload: "O"
+ readonly property string scriptRun: "P"
+ readonly property string scriptNew: "Q"
+ readonly property string hifiForum: "2"
+ readonly property string hifiLogoSmall: "S"
+ readonly property string avatar1: "T"
+ readonly property string placemark: "U"
+ readonly property string box: "V"
+ readonly property string community: "0"
+ readonly property string grabHandle: "X"
+ readonly property string search: "Y"
+ readonly property string disclosureCollapse: "Z"
+ readonly property string scriptUpload: "R"
+ readonly property string code: "W"
+ readonly property string avatar: "<"
+ readonly property string arrowsH: ":"
+ readonly property string arrowsV: ";"
+ readonly property string arrows: "`"
+ readonly property string compress: "!"
+ readonly property string expand: "\""
+ readonly property string placemark1: "#"
+ readonly property string circle: "$"
+ readonly property string handPointer: "9"
+ readonly property string plusSquareO: "%"
+ readonly property string sliders: "&"
+ readonly property string square: "'"
+ readonly property string alignCenter: "8"
+ readonly property string alignJustify: ")"
+ readonly property string alignLeft: "*"
+ readonly property string alignRight: "^"
+ readonly property string bars: "7"
+ readonly property string circleSlash: ","
+ readonly property string sync: "()"
+ readonly property string key: "-"
+ readonly property string link: "."
+ readonly property string location: "/"
+ readonly property string caratR: "3"
+ readonly property string caratL: "4"
+ readonly property string caratDn: "5"
+ readonly property string caratUp: "6"
+ readonly property string folderLg: ">"
+ readonly property string folderSm: "?"
+ readonly property string levelUp: "1"
+ readonly property string info: "["
+ readonly property string question: "]"
+ readonly property string alert: "+"
+ readonly property string home: "_"
+ readonly property string error: "="
+ readonly property string settings: "@"
+ readonly property string trash: "{"
+ readonly property string objectGroup: "\ue000"
+ readonly property string cm: "}"
+ readonly property string msvg79: "~"
+ readonly property string deg: "\\"
+ readonly property string px: "|"
+ readonly property string editPencil: "\ue00d"
+ readonly property string vol_0: "\ue00e"
+ readonly property string vol_1: "\ue00f"
+ readonly property string vol_2: "\ue010"
+ readonly property string vol_3: "\ue011"
+ readonly property string vol_4: "\ue012"
+ readonly property string vol_x_0: "\ue013"
+ readonly property string vol_x_1: "\ue014"
+ readonly property string vol_x_2: "\ue015"
+ readonly property string vol_x_3: "\ue016"
+ readonly property string vol_x_4: "\ue017"
+ readonly property string source: "\ue01c"
+ readonly property string playback_play: "\ue01d"
+ readonly property string stop_square: "\ue01e"
+ readonly property string avatarTPose: "\ue01f"
+ readonly property string lock: "\ue006"
+ readonly property string checkmark: "\ue020"
+ readonly property string leftRightArrows: "\ue021"
+ readonly property string hfc: "\ue022"
+ readonly property string home2: "\ue023"
+ readonly property string walletKey: "\ue024"
+ readonly property string lightning: "\ue025"
+ readonly property string securityImage: "\ue026"
+ readonly property string wallet: "\ue027"
+ readonly property string paperPlane: "\ue028"
+ readonly property string passphrase: "\ue029"
+ }
+}
diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml
index 5da587ea57..53920759b1 100644
--- a/interface/resources/qml/styles-uit/HifiConstants.qml
+++ b/interface/resources/qml/styles-uit/HifiConstants.qml
@@ -165,6 +165,7 @@ Item {
readonly property real scrollbarBackgroundWidth: 20
readonly property real scrollbarHandleWidth: scrollbarBackgroundWidth - 2
readonly property real tabletMenuHeader: 90
+ readonly property real buttonWidth: 120
}
Item {
diff --git a/interface/resources/qml/windows/Frame.qml b/interface/resources/qml/windows/Frame.qml
index c3b8399e01..4391c902ed 100644
--- a/interface/resources/qml/windows/Frame.qml
+++ b/interface/resources/qml/windows/Frame.qml
@@ -43,7 +43,8 @@ Item {
Text {
id: debugZ
visible: DebugQML
- text: window ? "Z: " + window.z : ""
+ color: "red"
+ text: (window ? "Z: " + window.z : "") + DebugQMLFile
y: window ? window.height + 4 : 0
}
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index b4d1bf4c0a..ea060c2923 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -5968,6 +5968,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
scriptEngine->registerGlobalObject("ContextOverlay", DependencyManager::get().data());
scriptEngine->registerGlobalObject("Wallet", DependencyManager::get().data());
+ scriptEngine->registerGlobalObject("App", this);
+
qScriptRegisterMetaType(scriptEngine.data(), OverlayIDtoScriptValue, OverlayIDfromScriptValue);
DependencyManager::get()->registerMetaTypes(scriptEngine.data());
diff --git a/interface/src/Application.h b/interface/src/Application.h
index 8f0690bda1..5161c62a65 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -389,6 +389,8 @@ public slots:
const QString getPreferredCursor() const { return _preferredCursor.get(); }
void setPreferredCursor(const QString& cursor);
+ Q_INVOKABLE bool askBeforeSetAvatarUrl(const QString& avatarUrl) { return askToSetAvatarUrl(avatarUrl); }
+
private slots:
void showDesktop();
void clearDomainOctreeDetails();
diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp
index 8e1e6c2fba..53683870df 100644
--- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp
+++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp
@@ -127,6 +127,10 @@ void TouchscreenVirtualPadDevice::debugPoints(const QTouchEvent* event, QString
void TouchscreenVirtualPadDevice::touchBeginEvent(const QTouchEvent* event) {
// touch begin here is a big begin -> begins both pads? maybe it does nothing
debugPoints(event, " BEGIN ++++++++++++++++");
+ auto& virtualPadManager = VirtualPad::Manager::instance();
+ if (!virtualPadManager.isEnabled()) {
+ return;
+ }
KeyboardMouseDevice::enableTouch(false);
QScreen* eventScreen = event->window()->screen();
_screenWidthCenter = eventScreen->size().width() / 2;
@@ -138,6 +142,10 @@ void TouchscreenVirtualPadDevice::touchBeginEvent(const QTouchEvent* event) {
}
void TouchscreenVirtualPadDevice::touchEndEvent(const QTouchEvent* event) {
+ auto& virtualPadManager = VirtualPad::Manager::instance();
+ if (!virtualPadManager.isEnabled()) {
+ return;
+ }
// touch end here is a big reset -> resets both pads
_touchPointCount = 0;
KeyboardMouseDevice::enableTouch(true);
@@ -148,6 +156,12 @@ void TouchscreenVirtualPadDevice::touchEndEvent(const QTouchEvent* event) {
}
void TouchscreenVirtualPadDevice::touchUpdateEvent(const QTouchEvent* event) {
+ auto& virtualPadManager = VirtualPad::Manager::instance();
+ if (!virtualPadManager.isEnabled()) {
+ touchLeftEnd();
+ touchRightEnd();
+ return;
+ }
_touchPointCount = event->touchPoints().count();
const QList& tPoints = event->touchPoints();
@@ -224,6 +238,10 @@ void TouchscreenVirtualPadDevice::touchRightEnd() {
}
void TouchscreenVirtualPadDevice::touchGestureEvent(const QGestureEvent* event) {
+ auto& virtualPadManager = VirtualPad::Manager::instance();
+ if (!virtualPadManager.isEnabled()) {
+ return;
+ }
if (QGesture* gesture = event->gesture(Qt::PinchGesture)) {
QPinchGesture* pinch = static_cast(gesture);
_pinchScale = pinch->totalScaleFactor();
diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp
index 4829e5c85b..144671fca8 100755
--- a/libraries/render-utils/src/RenderForwardTask.cpp
+++ b/libraries/render-utils/src/RenderForwardTask.cpp
@@ -37,6 +37,7 @@ using namespace render;
extern void initForwardPipelines(ShapePlumber& plumber,
const render::ShapePipeline::BatchSetter& batchSetter,
const render::ShapePipeline::ItemSetter& itemSetter);
+extern void initOverlay3DPipelines(render::ShapePlumber& plumber, bool depthTest = false);
void RenderForwardTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
auto items = input.get();
@@ -45,6 +46,7 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
// Prepare the ShapePipelines
ShapePlumberPointer shapePlumber = std::make_shared();
initForwardPipelines(*shapePlumber, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter());
+ initOverlay3DPipelines(*shapePlumber);
// Extract opaques / transparents / lights / metas / overlays / background
const auto& opaques = items.get0()[RenderFetchCullSortTask::OPAQUE_SHAPE];
diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp
index 221f5013bf..287978bbd3 100644
--- a/libraries/ui/src/OffscreenUi.cpp
+++ b/libraries/ui/src/OffscreenUi.cpp
@@ -658,8 +658,10 @@ void OffscreenUi::createDesktop(const QUrl& url) {
#ifdef DEBUG
getSurfaceContext()->setContextProperty("DebugQML", QVariant(true));
+ getSurfaceContext()->setContextProperty("DebugQMLFile", QVariant(url.toString()));
#else
getSurfaceContext()->setContextProperty("DebugQML", QVariant(false));
+ getSurfaceContext()->setContextProperty("DebugQMLFile", QVariant(""));
#endif
load(url, [=](QQmlContext* context, QObject* newObject) {
diff --git a/scripts/system/+android/avatarSelection.js b/scripts/system/+android/avatarSelection.js
new file mode 100644
index 0000000000..be58f61ac2
--- /dev/null
+++ b/scripts/system/+android/avatarSelection.js
@@ -0,0 +1,159 @@
+"use strict";
+//
+// avatarSelection.js
+// scripts/system/
+//
+// Created by Gabriel Calero & Cristian Duarte on 21 Sep 2017
+// Copyright 2017 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+var window;
+
+var logEnabled = true;
+var isVisible = false;
+
+function printd(str) {
+ if (logEnabled)
+ print("[avatarSelection.js] " + str);
+}
+
+function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml.
+ var data;
+ printd("fromQml " + JSON.stringify(message));
+ switch (message.method) {
+ case 'selectAvatar':
+ // use this message.params.avatarUrl
+ printd("Selected Avatar: [" + message.params.avatarUrl + "]");
+ App.askBeforeSetAvatarUrl(message.params.avatarUrl);
+ break;
+ case 'openAvatarMarket':
+ // good
+ App.openUrl("https://metaverse.highfidelity.com/marketplace?category=avatars");
+ break;
+ case 'hide':
+ module.exports.onHidden();
+ break;
+ default:
+ print('[avatarSelection.js] Unrecognized message from avatarSelection.qml:', JSON.stringify(message));
+ }
+}
+
+function sendToQml(message) {
+ if (!window) {
+ print("[avatarSelection.js] There is no window object");
+ return;
+ }
+ window.sendToQml(message);
+}
+
+function refreshSelected(currentAvatarURL) {
+ sendToQml({
+ type: "refreshSelected",
+ selectedAvatarUrl: currentAvatarURL
+ });
+
+ sendToQml({
+ type: "showAvatars"
+ });
+}
+
+function init() {
+ if (!window) {
+ print("[avatarSelection.js] There is no window object for init()");
+ return;
+ }
+ var DEFAULT_AVATAR_URL = "http://mpassets.highfidelity.com/7fe80a1e-f445-4800-9e89-40e677b03bee-v3/mannequin.fst";
+ sendToQml({
+ type: "addAvatar",
+ name: "Wooden Mannequin",
+ thumbnailUrl: "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/7fe80a1e-f445-4800-9e89-40e677b03bee/thumbnail/hifi-mp-7fe80a1e-f445-4800-9e89-40e677b03bee.jpg",
+ avatarUrl: DEFAULT_AVATAR_URL
+ });
+ sendToQml({
+ type: "addAvatar",
+ name: "Cody",
+ thumbnailUrl: "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/8c859fca-4cbd-4e82-aad1-5f4cb0ca5d53/thumbnail/hifi-mp-8c859fca-4cbd-4e82-aad1-5f4cb0ca5d53.jpg",
+ avatarUrl: "http://mpassets.highfidelity.com/8c859fca-4cbd-4e82-aad1-5f4cb0ca5d53-v1/cody.fst"
+ });
+ sendToQml({
+ type: "addAvatar",
+ name: "Mixamo Will",
+ thumbnailUrl: "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/d029ae8d-2905-4eb7-ba46-4bd1b8cb9d73/thumbnail/hifi-mp-d029ae8d-2905-4eb7-ba46-4bd1b8cb9d73.jpg",
+ avatarUrl: "http://mpassets.highfidelity.com/d029ae8d-2905-4eb7-ba46-4bd1b8cb9d73-v1/4618d52e711fbb34df442b414da767bb.fst"
+ });
+ sendToQml({
+ type: "addAvatar",
+ name: "Albert",
+ thumbnailUrl: "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/1e57c395-612e-4acd-9561-e79dbda0bc49/thumbnail/hifi-mp-1e57c395-612e-4acd-9561-e79dbda0bc49.jpg",
+ avatarUrl: "http://mpassets.highfidelity.com/1e57c395-612e-4acd-9561-e79dbda0bc49-v1/albert.fst"
+ });
+ /* We need to implement the wallet, so let's skip this for the moment
+ sendToQml({
+ type: "addExtraOption",
+ showName: "More choices",
+ thumbnailUrl: "../../../images/moreAvatars.png",
+ methodNameWhenClicked: "openAvatarMarket",
+ actionText: "MARKETPLACE"
+ });
+ */
+ var currentAvatarURL = Settings.getValue('Avatar/fullAvatarURL', DEFAULT_AVATAR_URL);
+ printd("Default Avatar: [" + DEFAULT_AVATAR_URL + "]");
+ printd("Current Avatar: [" + currentAvatarURL + "]");
+ if (!currentAvatarURL || 0 === currentAvatarURL.length) {
+ currentAvatarURL = DEFAULT_AVATAR_URL;
+ }
+ refreshSelected(currentAvatarURL);
+}
+
+module.exports = {
+ init: function() {
+ window = new QmlFragment({
+ qml: "hifi/avatarSelection.qml",
+ visible: false
+ });
+ /*,
+ visible: false*/
+ if (window) {
+ window.fromQml.connect(fromQml);
+ }
+ init();
+ },
+ show: function() {
+ if (window) {
+ window.setVisible(true);
+ isVisible = true;
+ }
+ },
+ hide: function() {
+ if (window) {
+ window.setVisible(false);
+ }
+ isVisible = false;
+ },
+ destroy: function() {
+ if (window) {
+ window.fromQml.disconnect(fromQml);
+ window.close();
+ window = null;
+ }
+ },
+ isVisible: function() {
+ return isVisible;
+ },
+ width: function() {
+ return window ? window.size.x : 0;
+ },
+ height: function() {
+ return window ? window.size.y : 0;
+ },
+ position: function() {
+ return window && isVisible ? window.position : null;
+ },
+ refreshSelectedAvatar: function(currentAvatarURL) {
+ refreshSelected(currentAvatarURL);
+ },
+ onHidden: function() { }
+};
diff --git a/scripts/system/+android/bottombar.js b/scripts/system/+android/bottombar.js
index e58840ad6f..5f82886c8a 100644
--- a/scripts/system/+android/bottombar.js
+++ b/scripts/system/+android/bottombar.js
@@ -14,8 +14,12 @@
var bottombar;
var bottomHudOptionsBar;
var gotoBtn;
+var avatarBtn;
+var bubbleBtn;
+var loginBtn;
var gotoScript = Script.require('./goto.js');
+var avatarSelection = Script.require('./avatarSelection.js');
var logEnabled = false;
@@ -34,15 +38,20 @@ function init() {
hideAddressBar();
}
});
+ avatarSelection.init();
+ App.fullAvatarURLChanged.connect(processedNewAvatar);
setupBottomBar();
setupBottomHudOptionsBar();
raiseBottomBar();
+ GlobalServices.connected.connect(handleLogin);
+ GlobalServices.disconnected.connect(handleLogout);
}
function shutdown() {
+ App.fullAvatarURLChanged.disconnect(processedNewAvatar);
}
function setupBottomBar() {
@@ -60,6 +69,32 @@ function setupBottomBar() {
}
});
+ avatarBtn = bottombar.addButton({
+ icon: "icons/avatar-i.svg",
+ activeIcon: "icons/avatar-a.svg",
+ bgOpacity: 0,
+ height: 240,
+ width: 294,
+ hoverBgOpacity: 0,
+ activeBgOpacity: 0,
+ activeHoverBgOpacity: 0,
+ iconSize: 108,
+ textSize: 45,
+ text: "AVATAR"
+ });
+ avatarBtn.clicked.connect(function() {
+ printd("Avatar button clicked");
+ if (!avatarSelection.isVisible()) {
+ showAvatarSelection();
+ } else {
+ hideAvatarSelection();
+ }
+ });
+ avatarSelection.onHidden = function() {
+ if (avatarBtn) {
+ avatarBtn.isActive = false;
+ }
+ };
gotoBtn = bottombar.addButton({
icon: "icons/goto-i.svg",
@@ -69,7 +104,7 @@ function setupBottomBar() {
activeBgOpacity: 0,
activeHoverBgOpacity: 0,
height: 240,
- width: 300,
+ width: 294,
iconSize: 108,
textSize: 45,
text: "GO TO"
@@ -83,6 +118,42 @@ function setupBottomBar() {
}
});
+ bubbleBtn = bottombar.addButton({
+ icon: "icons/bubble-i.svg",
+ activeIcon: "icons/bubble-a.svg",
+ bgOpacity: 0,
+ hoverBgOpacity: 0,
+ activeBgOpacity: 0,
+ activeHoverBgOpacity: 0,
+ height: 240,
+ width: 294,
+ iconSize: 108,
+ textSize: 45,
+ text: "BUBBLE"
+ });
+
+ bubbleBtn.clicked.connect(function() {
+ Users.toggleIgnoreRadius();
+ bubbleBtn.editProperties({isActive: Users.getIgnoreRadiusEnabled()});
+ });
+
+ loginBtn = bottombar.addButton({
+ icon: "icons/login-i.svg",
+ activeIcon: "icons/login-a.svg",
+ height: 240,
+ width: 294,
+ iconSize: 108,
+ textSize: 45,
+ text: Account.isLoggedIn() ? "LOG OUT" : "LOG IN"
+ });
+ loginBtn.clicked.connect(function() {
+ if (!Account.isLoggedIn()) {
+ Account.checkAndSignalForAccessToken();
+ } else {
+ Menu.triggerOption("Login / Sign Up");
+ }
+ });
+
// TODO: setup all the buttons or provide a dynamic interface
raiseBottomBar();
@@ -148,10 +219,43 @@ function hideAddressBar() {
gotoBtn.isActive = false;
}
+function showAvatarSelection() {
+ avatarSelection.show();
+ avatarBtn.isActive = true;
+}
+function hideAvatarSelection() {
+ avatarSelection.hide();
+ avatarBtn.isActive = false;
+}
+
+// TODO: Move to avatarSelection.js and make it possible to hide the window from there AND switch the button state here too
+function processedNewAvatar(url, modelName) {
+ avatarSelection.refreshSelectedAvatar(url);
+ hideAvatarSelection();
+}
+
+function handleLogin() {
+ Script.setTimeout(function() {
+ if (Account.isLoggedIn()) {
+ MyAvatar.displayName=Account.getUsername();
+ }
+ }, 2000);
+ if (loginBtn) {
+ loginBtn.editProperties({text: "LOG OUT"});
+ }
+}
+function handleLogout() {
+ MyAvatar.displayName="";
+ if (loginBtn) {
+ loginBtn.editProperties({text: "LOG IN"});
+ }
+}
Script.scriptEnding.connect(function () {
shutdown();
+ GlobalServices.connected.disconnect(handleLogin);
+ GlobalServices.disconnected.disconnect(handleLogout);
});
init();
diff --git a/scripts/system/+android/radar.js b/scripts/system/+android/radar.js
index 9fa07178f6..54e1e51945 100644
--- a/scripts/system/+android/radar.js
+++ b/scripts/system/+android/radar.js
@@ -29,12 +29,13 @@ var MOVE_BY = 1;
// Swipe/Drag vars
var PINCH_INCREMENT_FIRST = 0.4; // 0.1 meters zoom in - out
var PINCH_INCREMENT = 0.4; // 0.1 meters zoom in - out
-var RADAR_HEIGHT_MAX_PLUS_AVATAR = 40;
+var RADAR_HEIGHT_MAX_PLUS_AVATAR = 80;
var RADAR_HEIGHT_MIN_PLUS_AVATAR = 2;
-var RADAR_CAMERA_DISTANCE_TO_ICONS = 0.5; // Icons are near the camera to prevent the LOD manager dismissing them
+var RADAR_CAMERA_DISTANCE_TO_ICONS = 1.5; // Icons are near the camera to prevent the LOD manager dismissing them
var RADAR_ICONS_APPARENT_DISTANCE_TO_AVATAR_BASE = 1; // How much above the avatar base should the icon appear
-var AVATAR_DISPLAY_NAME_HEIGHT = 38;
-var AVATAR_DISPLAY_NAME_CHAR_WIDTH = 18;
+var AVATAR_DISPLAY_NAME_HEIGHT = 106;
+var AVATAR_DISPLAY_NAME_CHAR_WIDTH = 48;
+var AVATAR_DISPLAY_NAME_FONT_SIZE = 50;
var lastDragAt;
var lastDeltaDrag;
@@ -734,14 +735,15 @@ function saveAvatarData(QUuid) {
if (avatarsData[QUuid] != undefined) {
avatarsData[QUuid].position = avat.position;
} else {
- var avatarIcon = Overlays.addOverlay("image3d", {
- subImage: { x: 0, y: 0, width: 150, height: 142},
- url: getAvatarIconForUser(QUuid),
- dimensions: ICON_ENTITY_DEFAULT_DIMENSIONS,
- visible: false,
- ignoreRayIntersection: false,
- orientation: Quat.fromPitchYawRollDegrees(-90,0,0)
- });
+ var avatarIcon = Overlays.addOverlay("circle3d", {
+ color: uniqueColor.convertHexToRGB(uniqueColor.getColor(QUuid)),
+ dimensions: ICON_ENTITY_DEFAULT_DIMENSIONS,
+ rotation: Quat.fromPitchYawRollDegrees(90, 0, 0),
+ innerRadius: 1.8,
+ outerRadius: 2,
+ isSolid: true,
+ visible: false
+ });
var needRefresh = !avat || !avat.displayName;
var displayName = avat && avat.displayName ? avat.displayName : "Unknown";
@@ -752,7 +754,7 @@ function saveAvatarData(QUuid) {
color: { red: 255, green: 255, blue: 255},
backgroundAlpha: 0.0,
textRaiseColor: { red: 0, green: 0, blue: 0},
- font: {size: 68, bold: true},
+ font: {size: AVATAR_DISPLAY_NAME_FONT_SIZE, bold: true},
visible: false,
text: displayName,
textAlignCenter: true
@@ -809,19 +811,24 @@ function avatarRemoved(QUuid) {
********************************************************************************************************/
var myAvatarIcon;
var myAvatarName;
-
+function distanceForCameraHeight(h) {
+ if (h < 30) return 1;
+ if (h < 40) return 2;
+ if (h < 50) return 2.5;
+ return 5;
+}
function renderMyAvatarIcon() {
+ var commonY = Camera.position.y - distanceForCameraHeight(Camera.position.y);
var iconPos = findLineToHeightIntersectionCoords( MyAvatar.position.x,
MyAvatar.position.y + RADAR_ICONS_APPARENT_DISTANCE_TO_AVATAR_BASE,
MyAvatar.position.z,
Camera.position.x, Camera.position.y, Camera.position.z,
- Camera.position.y - RADAR_CAMERA_DISTANCE_TO_ICONS);
+ commonY);
if (!iconPos) { printd("avatarmy icon pos null"); return;}
var iconDimensions = avatarIconPlaneDimensions();
var avatarPos = MyAvatar.position;
var cameraPos = Camera.position;
- var commonY = Camera.position.y - RADAR_CAMERA_DISTANCE_TO_ICONS;
var borderPoints = [
computePointAtPlaneY(0, 0, commonY),
computePointAtPlaneY(Window.innerWidth, Window.innerHeight, commonY)
@@ -833,25 +840,26 @@ function renderMyAvatarIcon() {
var x = (p1.x - borderPoints[0].x) * (Window.innerWidth) / (borderPoints[1].x - borderPoints[0].x);
var y = (p1.z - borderPoints[0].z) * (Window.innerHeight) / (borderPoints[1].z - borderPoints[0].z);
- if (!myAvatarIcon && MyAvatar.sessionUUID) {
- myAvatarIcon = Overlays.addOverlay("image3d", {
- subImage: { x: 0, y: 0, width: 150, height: 142},
- url: getAvatarIconForUser(MyAvatar.sessionUUID),
- dimensions: ICON_ENTITY_DEFAULT_DIMENSIONS,
- visible: false,
- ignoreRayIntersection: false,
- orientation: Quat.fromPitchYawRollDegrees(-90,0,0)
- });
+ if (!myAvatarIcon && MyAvatar.SELF_ID) {
+ myAvatarIcon = Overlays.addOverlay("circle3d", {
+ color: uniqueColor.convertHexToRGB(uniqueColor.getColor(MyAvatar.SELF_ID)),
+ dimensions: ICON_ENTITY_DEFAULT_DIMENSIONS,
+ rotation: Quat.fromPitchYawRollDegrees(90, 0, 0),
+ innerRadius: 1.8,
+ outerRadius: 2,
+ isSolid: true,
+ visible: false
+ });
}
if (!myAvatarName) {
myAvatarName = Overlays.addOverlay("text", {
- width: 40,
+ width: 100,
height: AVATAR_DISPLAY_NAME_HEIGHT,
textAlignCenter: true,
color: { red: 255, green: 255, blue: 255},
backgroundAlpha: 0.0,
- font: {size: 68, bold: true},
+ font: {size: AVATAR_DISPLAY_NAME_FONT_SIZE, bold: true},
textRaiseColor: { red: 0, green: 0, blue: 0},
visible: false,
text: "Me"
@@ -896,7 +904,7 @@ function hideAllAvatarIcons() {
function renderAllOthersAvatarIcons() {
var avatarPos;
var iconDimensions = avatarIconPlaneDimensions();
- var commonY = Camera.position.y - RADAR_CAMERA_DISTANCE_TO_ICONS;
+ var commonY = Camera.position.y - distanceForCameraHeight(Camera.position.y);
var borderPoints = [
computePointAtPlaneY(0, 0, commonY),
computePointAtPlaneY(Window.innerWidth, Window.innerHeight, commonY)
@@ -907,18 +915,18 @@ function renderAllOthersAvatarIcons() {
if (AvatarList.getAvatar(QUuid) != null) {
avatarPos = AvatarList.getAvatar(QUuid).position;
- var cameraPos = Camera.position;
- var p1 = findLineToHeightIntersectionCoords(avatarPos.x, avatarPos.y, avatarPos.z,
+ var cameraPos = Camera.position;
+ var p1 = findLineToHeightIntersectionCoords(avatarPos.x, avatarPos.y, avatarPos.z,
cameraPos.x, cameraPos.y, cameraPos.z,
commonY);
- var x = (p1.x - borderPoints[0].x) * (Window.innerWidth) / (borderPoints[1].x - borderPoints[0].x);
- var y = (p1.z - borderPoints[0].z) * (Window.innerHeight) / (borderPoints[1].z - borderPoints[0].z);
+ var x = (p1.x - borderPoints[0].x) * (Window.innerWidth) / (borderPoints[1].x - borderPoints[0].x);
+ var y = (p1.z - borderPoints[0].z) * (Window.innerHeight) / (borderPoints[1].z - borderPoints[0].z);
if (avatarsData[QUuid].icon != undefined) {
var iconPos = findLineToHeightIntersectionCoords( avatarPos.x, avatarPos.y + RADAR_ICONS_APPARENT_DISTANCE_TO_AVATAR_BASE, avatarPos.z,
Camera.position.x, Camera.position.y, Camera.position.z,
- Camera.position.y - RADAR_CAMERA_DISTANCE_TO_ICONS);
+ commonY);
if (!iconPos) { print ("avatar icon pos bad for " + QUuid); continue; }
if (avatarsData[QUuid].needRefresh) {
var avat = AvatarList.getAvatar(QUuid);
@@ -1100,6 +1108,8 @@ function startRadar() {
Camera.orientation = Quat.fromPitchYawRollDegrees(-90,0,0);
radar = true;
+ Controller.setVPadEnabled(false); // this was done before in CompositeExtra in the DisplayPlugin (Checking for camera not independent, not radar mode)
+
connectRadarModeEvents();
}
@@ -1108,6 +1118,8 @@ function endRadar() {
Camera.mode = "first person";
radar = false;
+ Controller.setVPadEnabled(true);
+
disconnectRadarModeEvents();
hideAllEntitiesIcons();
hideAllAvatarIcons();
diff --git a/scripts/system/+android/uniqueColor.js b/scripts/system/+android/uniqueColor.js
index c296b6c87d..a2741642d2 100644
--- a/scripts/system/+android/uniqueColor.js
+++ b/scripts/system/+android/uniqueColor.js
@@ -41,6 +41,14 @@ function getColorForId(uuid) {
module.exports = {
getColor: function(id) {
- return getColorForId(id);
+ return getColorForId(id);
+ },
+ convertHexToRGB: function(hex) {
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ return result ? {
+ red: parseInt(result[1], 16),
+ green: parseInt(result[2], 16),
+ blue: parseInt(result[3], 16)
+ } : null;
}
};