diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml
index 5329099df5..109e357206 100644
--- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml
+++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml
@@ -28,19 +28,31 @@ Rectangle {
property string activeView: "initialize";
property bool purchasesReceived: false;
property bool balanceReceived: false;
+ property bool securityImageResultReceived: false;
+ property bool keyFilePathIfExistsResultReceived: false;
property string itemId: "";
property string itemHref: "";
property double balanceAfterPurchase: 0;
property bool alreadyOwned: false;
property int itemPriceFull: 0;
property bool itemIsJson: true;
- property bool securityImageResultReceived: false;
- property bool keyFilePathIfExistsResultReceived: false;
// Style
color: hifi.colors.baseGray;
Hifi.QmlCommerce {
id: commerce;
+ onLoginStatusResult: {
+ if (!isLoggedIn && root.activeView !== "needsLogIn") {
+ root.activeView = "needsLogIn";
+ } else if (isLoggedIn) {
+ root.activeView = "initialize";
+ commerce.getSecurityImage();
+ commerce.getKeyFilePathIfExists();
+ commerce.balance();
+ commerce.inventory();
+ }
+ }
+
onSecurityImageResult: {
securityImageResultReceived = true;
if (!exists && root.activeView !== "notSetUp") { // "If security image is not set up"
@@ -107,6 +119,7 @@ Rectangle {
//
Item {
id: titleBarContainer;
+ visible: !needsLogIn.visible;
// Size
width: parent.width;
height: 50;
@@ -147,6 +160,16 @@ Rectangle {
cache: false;
source: "image://security/securityImage";
}
+ Image {
+ id: securityImageOverlay;
+ source: "../wallet/images/lockOverlay.png";
+ width: securityImage.width * 0.45;
+ height: securityImage.height * 0.45;
+ anchors.bottom: securityImage.bottom;
+ anchors.right: securityImage.right;
+ mipmap: true;
+ opacity: 0.9;
+ }
// Separator
HifiControlsUit.Separator {
@@ -169,10 +192,36 @@ Rectangle {
color: hifi.colors.baseGray;
Component.onCompleted: {
- commerce.getSecurityImage();
- commerce.getKeyFilePathIfExists();
+ securityImageResultReceived = false;
+ purchasesReceived = false;
+ balanceReceived = false;
+ keyFilePathIfExistsResultReceived = false;
+ commerce.getLoginStatus();
}
}
+
+ HifiWallet.NeedsLogIn {
+ id: needsLogIn;
+ visible: root.activeView === "needsLogIn";
+ anchors.top: parent.top;
+ anchors.bottom: parent.bottom;
+ anchors.left: parent.left;
+ anchors.right: parent.right;
+
+ Connections {
+ onSendSignalToWallet: {
+ sendToScript(msg);
+ }
+ }
+ }
+ Connections {
+ target: GlobalServices
+ onMyUsernameChanged: {
+ commerce.getLoginStatus();
+ }
+ }
+
+
//
// "WALLET NOT SET UP" START
@@ -268,13 +317,6 @@ Rectangle {
anchors.left: parent.left;
anchors.right: parent.right;
- onVisibleChanged: {
- if (visible) {
- commerce.balance();
- commerce.inventory();
- }
- }
-
//
// ITEM DESCRIPTION START
//
@@ -877,7 +919,7 @@ Rectangle {
if (root.purchasesReceived && root.balanceReceived) {
if (root.balanceAfterPurchase < 0) {
if (root.alreadyOwned) {
- buyText.text = "You do not have enough HFC to purchase this item again. Go to your Purchases to view the copy you own.";
+ buyText.text = "You do not have enough HFC to purchase this item again. Go to your Purchases to view the copy you own.";
} else {
buyText.text = "You do not have enough HFC to purchase this item.";
}
diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
index 5060b65e0b..bc843a140d 100644
--- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
+++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
@@ -29,12 +29,24 @@ Rectangle {
property string referrerURL: "";
property bool securityImageResultReceived: false;
property bool keyFilePathIfExistsResultReceived: false;
+ property bool purchasesReceived: false;
property bool punctuationMode: false;
// Style
color: hifi.colors.baseGray;
Hifi.QmlCommerce {
id: commerce;
+ onLoginStatusResult: {
+ if (!isLoggedIn && root.activeView !== "needsLogIn") {
+ root.activeView = "needsLogIn";
+ } else if (isLoggedIn) {
+ root.activeView = "initialize";
+ commerce.getSecurityImage();
+ commerce.getKeyFilePathIfExists();
+ commerce.inventory();
+ }
+ }
+
onSecurityImageResult: {
securityImageResultReceived = true;
if (!exists && root.activeView !== "notSetUp") { // "If security image is not set up"
@@ -58,10 +70,13 @@ Rectangle {
}
onInventoryResult: {
+ purchasesReceived = true;
if (result.status !== 'success') {
console.log("Failed to get purchases", result.message);
} else {
+ purchasesModel.clear();
purchasesModel.append(result.data.assets);
+ filteredPurchasesModel.clear();
filteredPurchasesModel.append(result.data.assets);
}
}
@@ -76,6 +91,7 @@ Rectangle {
//
Item {
id: titleBarContainer;
+ visible: !needsLogIn.visible;
// Size
height: 50;
// Anchors
@@ -116,6 +132,16 @@ Rectangle {
cache: false;
source: "image://security/securityImage";
}
+ Image {
+ id: securityImageOverlay;
+ source: "../wallet/images/lockOverlay.png";
+ width: securityImage.width * 0.45;
+ height: securityImage.height * 0.45;
+ anchors.bottom: securityImage.bottom;
+ anchors.right: securityImage.right;
+ mipmap: true;
+ opacity: 0.9;
+ }
// Separator
HifiControlsUit.Separator {
@@ -138,8 +164,31 @@ Rectangle {
color: hifi.colors.baseGray;
Component.onCompleted: {
- commerce.getSecurityImage();
- commerce.getKeyFilePathIfExists();
+ securityImageResultReceived = false;
+ purchasesReceived = false;
+ keyFilePathIfExistsResultReceived = false;
+ commerce.getLoginStatus();
+ }
+ }
+
+ HifiWallet.NeedsLogIn {
+ id: needsLogIn;
+ visible: root.activeView === "needsLogIn";
+ anchors.top: parent.top;
+ anchors.bottom: parent.bottom;
+ anchors.left: parent.left;
+ anchors.right: parent.right;
+
+ Connections {
+ onSendSignalToWallet: {
+ sendToScript(msg);
+ }
+ }
+ }
+ Connections {
+ target: GlobalServices
+ onMyUsernameChanged: {
+ commerce.getLoginStatus();
}
}
@@ -240,14 +289,7 @@ Rectangle {
anchors.top: titleBarContainer.bottom;
anchors.topMargin: 8;
anchors.bottom: actionButtonsContainer.top;
- anchors.bottomMargin: 8;
-
- onVisibleChanged: {
- if (visible) {
- commerce.balance();
- commerce.inventory();
- }
- }
+ anchors.bottomMargin: 8;
//
// FILTER BAR START
@@ -258,7 +300,9 @@ Rectangle {
height: 40;
// Anchors
anchors.left: parent.left;
+ anchors.leftMargin: 8;
anchors.right: parent.right;
+ anchors.rightMargin: 8;
anchors.top: parent.top;
anchors.topMargin: 4;
@@ -304,6 +348,7 @@ Rectangle {
ListView {
id: purchasesContentsList;
+ visible: purchasesModel.count !== 0;
clip: true;
model: filteredPurchasesModel;
// Anchors
@@ -329,6 +374,52 @@ Rectangle {
}
}
}
+
+ Item {
+ id: noPurchasesAlertContainer;
+ visible: !purchasesContentsList.visible && root.purchasesReceived;
+ anchors.top: filterBarContainer.bottom;
+ anchors.topMargin: 12;
+ anchors.left: parent.left;
+ anchors.bottom: parent.bottom;
+ width: parent.width;
+
+ // Explanitory text
+ RalewayRegular {
+ id: haventPurchasedYet;
+ text: "You haven't purchased anything yet!
Get an item from Marketplace to add it to your Purchases.";
+ // Text size
+ size: 22;
+ // Anchors
+ anchors.top: parent.top;
+ anchors.topMargin: 150;
+ anchors.left: parent.left;
+ anchors.leftMargin: 24;
+ anchors.right: parent.right;
+ anchors.rightMargin: 24;
+ height: paintedHeight;
+ // Style
+ color: hifi.colors.faintGray;
+ wrapMode: Text.WordWrap;
+ // Alignment
+ horizontalAlignment: Text.AlignHCenter;
+ }
+
+ // "Set Up" button
+ HifiControlsUit.Button {
+ color: hifi.buttons.blue;
+ colorScheme: hifi.colorSchemes.dark;
+ anchors.top: haventPurchasedYet.bottom;
+ anchors.topMargin: 20;
+ anchors.horizontalCenter: parent.horizontalCenter;
+ width: parent.width * 2 / 3;
+ height: 50;
+ text: "Visit Marketplace";
+ onClicked: {
+ sendToScript({method: 'purchases_goToMarketplaceClicked'});
+ }
+ }
+ }
}
//
// PURCHASES CONTENTS END
diff --git a/interface/resources/qml/hifi/commerce/wallet/Help.qml b/interface/resources/qml/hifi/commerce/wallet/Help.qml
index 2252cbfb59..47b3f6daf6 100644
--- a/interface/resources/qml/hifi/commerce/wallet/Help.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/Help.qml
@@ -31,6 +31,7 @@ Item {
// "Unavailable"
RalewayRegular {
+ id: helpText;
text: "Help me!";
// Anchors
anchors.fill: parent;
@@ -43,6 +44,19 @@ Item {
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
}
+ HifiControlsUit.Button {
+ color: hifi.buttons.black;
+ colorScheme: hifi.colorSchemes.dark;
+ anchors.bottom: helpText.bottom;
+ anchors.horizontalCenter: parent.horizontalCenter;
+ height: 50;
+ width: 250;
+ text: "Testing: Reset Wallet!";
+ onClicked: {
+ commerce.reset();
+ sendSignalToWallet({method: 'walletReset'});
+ }
+ }
//
// FUNCTION DEFINITIONS START
diff --git a/interface/resources/qml/hifi/commerce/wallet/NeedsLogIn.qml b/interface/resources/qml/hifi/commerce/wallet/NeedsLogIn.qml
new file mode 100644
index 0000000000..1e95aaa297
--- /dev/null
+++ b/interface/resources/qml/hifi/commerce/wallet/NeedsLogIn.qml
@@ -0,0 +1,188 @@
+//
+// NeedsLogIn.qml
+// qml/hifi/commerce/wallet
+//
+// NeedsLogIn
+//
+// Created by Zach Fox on 2017-08-18
+// 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 Hifi 1.0 as Hifi
+import QtQuick 2.5
+import QtQuick.Controls 1.4
+import "../../../styles-uit"
+import "../../../controls-uit" as HifiControlsUit
+import "../../../controls" as HifiControls
+
+// references XXX from root context
+
+Item {
+ HifiConstants { id: hifi; }
+
+ id: root;
+ Hifi.QmlCommerce {
+ id: commerce;
+ }
+
+ //
+ // LOGIN PAGE START
+ //
+ Item {
+ id: loginPageContainer;
+ // Anchors
+ anchors.fill: parent;
+
+ Item {
+ id: loginTitle;
+ // Size
+ width: parent.width;
+ height: 50;
+ // Anchors
+ anchors.left: parent.left;
+ anchors.top: parent.top;
+
+ // Title Bar text
+ RalewaySemiBold {
+ text: "HIFI COMMERCE - LOGIN";
+ // Text size
+ size: hifi.fontSizes.overlayTitle;
+ // Anchors
+ anchors.top: parent.top;
+ anchors.left: parent.left;
+ anchors.leftMargin: 16;
+ anchors.bottom: parent.bottom;
+ width: paintedWidth;
+ // Style
+ color: hifi.colors.faintGray;
+ // Alignment
+ horizontalAlignment: Text.AlignHLeft;
+ verticalAlignment: Text.AlignVCenter;
+ }
+ }
+
+ // Text below title bar
+ RalewaySemiBold {
+ id: loginTitleHelper;
+ text: "Please Log In to High Fidelity";
+ // Text size
+ size: 24;
+ // Anchors
+ anchors.top: loginTitle.bottom;
+ anchors.topMargin: 100;
+ anchors.left: parent.left;
+ anchors.leftMargin: 16;
+ anchors.right: parent.right;
+ anchors.rightMargin: 16;
+ height: 50;
+ // Style
+ color: hifi.colors.faintGray;
+ // Alignment
+ horizontalAlignment: Text.AlignHCenter;
+ verticalAlignment: Text.AlignVCenter;
+ }
+
+ // Text below helper text
+ RalewayRegular {
+ id: loginDetailText;
+ text: "To buy/sell items on the Marketplace, or to use your Wallet, you must first log in to High Fidelity.";
+ // Text size
+ size: 18;
+ // Anchors
+ anchors.top: loginTitleHelper.bottom;
+ anchors.topMargin: 25;
+ anchors.left: parent.left;
+ anchors.leftMargin: 16;
+ anchors.right: parent.right;
+ anchors.rightMargin: 16;
+ height: 50;
+ // Style
+ color: hifi.colors.faintGray;
+ wrapMode: Text.WordWrap;
+ // Alignment
+ horizontalAlignment: Text.AlignHCenter;
+ verticalAlignment: Text.AlignVCenter;
+ }
+
+
+
+ Item {
+ // Size
+ width: root.width;
+ height: 70;
+ // Anchors
+ anchors.top: loginDetailText.bottom;
+ anchors.topMargin: 40;
+ anchors.left: parent.left;
+
+ // "Cancel" button
+ HifiControlsUit.Button {
+ id: cancelButton;
+ color: hifi.buttons.black;
+ colorScheme: hifi.colorSchemes.dark;
+ anchors.top: parent.top;
+ anchors.topMargin: 3;
+ anchors.bottom: parent.bottom;
+ anchors.bottomMargin: 3;
+ anchors.left: parent.left;
+ anchors.leftMargin: 20;
+ width: parent.width/2 - anchors.leftMargin*2;
+ text: "Cancel"
+ onClicked: {
+ sendToScript({method: 'needsLogIn_cancelClicked'});
+ }
+ }
+
+ // "Set Up" button
+ HifiControlsUit.Button {
+ id: setUpButton;
+ color: hifi.buttons.blue;
+ colorScheme: hifi.colorSchemes.dark;
+ anchors.top: parent.top;
+ anchors.topMargin: 3;
+ anchors.bottom: parent.bottom;
+ anchors.bottomMargin: 3;
+ anchors.right: parent.right;
+ anchors.rightMargin: 20;
+ width: parent.width/2 - anchors.rightMargin*2;
+ text: "Log In"
+ onClicked: {
+ sendToScript({method: 'needsLogIn_loginClicked'});
+ }
+ }
+ }
+ }
+ //
+ // LOGIN PAGE END
+ //
+
+ //
+ // FUNCTION DEFINITIONS START
+ //
+ //
+ // Function Name: fromScript()
+ //
+ // Relevant Variables:
+ // None
+ //
+ // Arguments:
+ // message: The message sent from the JavaScript.
+ // Messages are in format "{method, params}", like json-rpc.
+ //
+ // Description:
+ // Called when a message is received from a script.
+ //
+ function fromScript(message) {
+ switch (message.method) {
+ default:
+ console.log('Unrecognized message from wallet.js:', JSON.stringify(message));
+ }
+ }
+ signal sendSignalToWallet(var msg);
+ //
+ // FUNCTION DEFINITIONS END
+ //
+}
diff --git a/interface/resources/qml/hifi/commerce/wallet/NotSetUp.qml b/interface/resources/qml/hifi/commerce/wallet/NotSetUp.qml
index 3efb592ba1..42b8526a8a 100644
--- a/interface/resources/qml/hifi/commerce/wallet/NotSetUp.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/NotSetUp.qml
@@ -80,7 +80,7 @@ Item {
// "Set Up" button
HifiControlsUit.Button {
- color: hifi.buttons.black;
+ color: hifi.buttons.blue;
colorScheme: hifi.colorSchemes.dark;
anchors.bottom: parent.bottom;
anchors.bottomMargin: 150;
diff --git a/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml b/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml
index 89ef851b06..39d07315d5 100644
--- a/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/PassphraseSelection.qml
@@ -45,9 +45,16 @@ Item {
}
}
+ // This will cause a bug -- if you bring up passphrase selection in HUD mode while
+ // in HMD while having HMD preview enabled, then move, then finish passphrase selection,
+ // HMD preview will stay off.
+ // TODO: Fix this unlikely bug
onVisibleChanged: {
if (visible) {
passphraseField.focus = true;
+ sendMessageToLightbox({method: 'disableHmdPreview'});
+ } else {
+ sendMessageToLightbox({method: 'maybeEnableHmdPreview'});
}
}
@@ -66,11 +73,25 @@ Item {
echoMode: TextInput.Password;
placeholderText: "passphrase";
- onVisibleChanged: {
- if (visible) {
- text = "";
+ onFocusChanged: {
+ if (focus) {
+ sendMessageToLightbox({method: 'walletSetup_raiseKeyboard'});
+ } else if (!passphraseFieldAgain.focus) {
+ sendMessageToLightbox({method: 'walletSetup_lowerKeyboard'});
}
}
+
+ MouseArea {
+ anchors.fill: parent;
+ onClicked: {
+ parent.focus = true;
+ sendMessageToLightbox({method: 'walletSetup_raiseKeyboard'});
+ }
+ }
+
+ onAccepted: {
+ passphraseFieldAgain.focus = true;
+ }
}
HifiControlsUit.TextField {
id: passphraseFieldAgain;
@@ -82,11 +103,25 @@ Item {
echoMode: TextInput.Password;
placeholderText: "re-enter passphrase";
- onVisibleChanged: {
- if (visible) {
- text = "";
+ onFocusChanged: {
+ if (focus) {
+ sendMessageToLightbox({method: 'walletSetup_raiseKeyboard'});
+ } else if (!passphraseField.focus) {
+ sendMessageToLightbox({method: 'walletSetup_lowerKeyboard'});
}
}
+
+ MouseArea {
+ anchors.fill: parent;
+ onClicked: {
+ parent.focus = true;
+ sendMessageToLightbox({method: 'walletSetup_raiseKeyboard'});
+ }
+ }
+
+ onAccepted: {
+ focus = false;
+ }
}
// Security Image
@@ -111,9 +146,19 @@ Item {
commerce.getSecurityImage();
}
}
- // "Security picture" text below pic
+ Image {
+ id: topSecurityImageOverlay;
+ source: "images/lockOverlay.png";
+ width: passphrasePageSecurityImage.width * 0.45;
+ height: passphrasePageSecurityImage.height * 0.45;
+ anchors.bottom: passphrasePageSecurityImage.bottom;
+ anchors.right: passphrasePageSecurityImage.right;
+ mipmap: true;
+ opacity: 0.9;
+ }
+ // "Security image" text below pic
RalewayRegular {
- text: "security picture";
+ text: "security image";
// Text size
size: 12;
// Anchors
@@ -228,5 +273,11 @@ Item {
errorText.text = text;
}
+ function clearPassphraseFields() {
+ passphraseField.text = "";
+ passphraseFieldAgain.text = "";
+ setErrorText("");
+ }
+
signal sendMessageToLightbox(var msg);
}
diff --git a/interface/resources/qml/hifi/commerce/wallet/PassphraseSelectionLightbox.qml b/interface/resources/qml/hifi/commerce/wallet/PassphraseSelectionLightbox.qml
index 862d1894db..608cb229b0 100644
--- a/interface/resources/qml/hifi/commerce/wallet/PassphraseSelectionLightbox.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/PassphraseSelectionLightbox.qml
@@ -27,29 +27,6 @@ Rectangle {
// Style
color: hifi.colors.baseGray;
- onVisibleChanged: {
- if (visible) {
- root.resetSubmitButton();
- }
- }
-
- Connections {
- target: passphraseSelection;
- onSendMessageToLightbox: {
- if (msg.method === 'statusResult') {
- if (msg.status) {
- // Success submitting new passphrase
- root.resetSubmitButton();
- root.visible = false;
- } else {
- // Error submitting new passphrase
- root.resetSubmitButton();
- passphraseSelection.setErrorText("Backend error");
- }
- }
- }
- }
-
//
// SECURE PASSPHRASE SELECTION START
//
@@ -113,6 +90,24 @@ Rectangle {
anchors.left: parent.left;
anchors.right: parent.right;
anchors.bottom: passphraseNavBar.top;
+
+ Connections {
+ onSendMessageToLightbox: {
+ if (msg.method === 'statusResult') {
+ if (msg.status) {
+ // Success submitting new passphrase
+ root.resetSubmitButton();
+ root.visible = false;
+ } else {
+ // Error submitting new passphrase
+ root.resetSubmitButton();
+ passphraseSelection.setErrorText("Backend error");
+ }
+ } else {
+ sendSignalToWallet(msg);
+ }
+ }
+ }
}
// Navigation Bar
@@ -168,8 +163,14 @@ Rectangle {
// SECURE PASSPHRASE SELECTION END
//
+ signal sendSignalToWallet(var msg);
+
function resetSubmitButton() {
passphraseSubmitButton.enabled = true;
passphraseSubmitButton.text = "Submit";
}
+
+ function clearPassphraseFields() {
+ passphraseSelection.clearPassphraseFields();
+ }
}
diff --git a/interface/resources/qml/hifi/commerce/wallet/Security.qml b/interface/resources/qml/hifi/commerce/wallet/Security.qml
index d0a96db3f2..b5d52d57e2 100644
--- a/interface/resources/qml/hifi/commerce/wallet/Security.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/Security.qml
@@ -13,6 +13,7 @@
import Hifi 1.0 as Hifi
import QtQuick 2.5
+import QtGraphicalEffects 1.0
import QtQuick.Controls 1.4
import "../../../styles-uit"
import "../../../controls-uit" as HifiControlsUit
@@ -35,8 +36,6 @@ Item {
topSecurityImage.source = path;
changeSecurityImageImage.source = "";
changeSecurityImageImage.source = path;
- changePassphraseImage.source = "";
- changePassphraseImage.source = path;
}
}
@@ -92,9 +91,19 @@ Item {
source: "image://security/securityImage";
cache: false;
}
- // "Security picture" text below pic
+ Image {
+ id: topSecurityImageMask;
+ source: "images/lockOverlay.png";
+ width: topSecurityImage.width * 0.45;
+ height: topSecurityImage.height * 0.45;
+ anchors.bottom: topSecurityImage.bottom;
+ anchors.right: topSecurityImage.right;
+ mipmap: true;
+ opacity: 0.9;
+ }
+ // "Security image" text below pic
RalewayRegular {
- text: "security picture";
+ text: "security image";
// Text size
size: 12;
// Anchors
@@ -148,10 +157,16 @@ Item {
anchors.left: parent.left;
height: parent.height;
width: height;
- source: "image://security/securityImage";
+ source: "images/lockOverlay.png";
fillMode: Image.PreserveAspectFit;
mipmap: true;
cache: false;
+ visible: false;
+ }
+ ColorOverlay {
+ anchors.fill: changePassphraseImage;
+ source: changePassphraseImage;
+ color: "white"
}
// "Change Passphrase" button
HifiControlsUit.Button {
diff --git a/interface/resources/qml/hifi/commerce/wallet/SecurityImageModel.qml b/interface/resources/qml/hifi/commerce/wallet/SecurityImageModel.qml
index b49f16857b..7b1434aa3c 100644
--- a/interface/resources/qml/hifi/commerce/wallet/SecurityImageModel.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/SecurityImageModel.qml
@@ -16,27 +16,27 @@ import QtQuick 2.5
ListModel {
id: root;
ListElement{
- sourcePath: "images/01cat.jpg"
+ sourcePath: "images/01.jpg"
securityImageEnumValue: 1;
}
ListElement{
- sourcePath: "images/02car.jpg"
+ sourcePath: "images/02.jpg"
securityImageEnumValue: 2;
}
ListElement{
- sourcePath: "images/03dog.jpg"
+ sourcePath: "images/03.jpg"
securityImageEnumValue: 3;
}
ListElement{
- sourcePath: "images/04stars.jpg"
+ sourcePath: "images/04.jpg"
securityImageEnumValue: 4;
}
ListElement{
- sourcePath: "images/05plane.jpg"
+ sourcePath: "images/05.jpg"
securityImageEnumValue: 5;
}
ListElement{
- sourcePath: "images/06gingerbread.jpg"
+ sourcePath: "images/06.jpg"
securityImageEnumValue: 6;
}
diff --git a/interface/resources/qml/hifi/commerce/wallet/SecurityImageSelection.qml b/interface/resources/qml/hifi/commerce/wallet/SecurityImageSelection.qml
index 7ab52b7551..5f5a3e8247 100644
--- a/interface/resources/qml/hifi/commerce/wallet/SecurityImageSelection.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/SecurityImageSelection.qml
@@ -24,16 +24,16 @@ Item {
HifiConstants { id: hifi; }
id: root;
-
- Hifi.QmlCommerce {
- id: commerce;
- onSecurityImageResult: {
- }
- }
-
+
+ // This will cause a bug -- if you bring up security image selection in HUD mode while
+ // in HMD while having HMD preview enabled, then move, then finish passphrase selection,
+ // HMD preview will stay off.
+ // TODO: Fix this unlikely bug
onVisibleChanged: {
if (visible) {
- commerce.getSecurityImage();
+ sendSignalToWallet({method: 'disableHmdPreview'});
+ } else {
+ sendSignalToWallet({method: 'maybeEnableHmdPreview'});
}
}
@@ -83,7 +83,7 @@ Item {
//
// FUNCTION DEFINITIONS START
//
- signal sendToScript(var message);
+ signal sendSignalToWallet(var msg);
function getImagePathFromImageID(imageID) {
return (imageID ? gridModel.getImagePathFromImageID(imageID) : "");
diff --git a/interface/resources/qml/hifi/commerce/wallet/SecurityImageSelectionLightbox.qml b/interface/resources/qml/hifi/commerce/wallet/SecurityImageSelectionLightbox.qml
index d4b0b82ed3..ff7156dd6c 100644
--- a/interface/resources/qml/hifi/commerce/wallet/SecurityImageSelectionLightbox.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/SecurityImageSelectionLightbox.qml
@@ -28,12 +28,6 @@ Rectangle {
// Style
color: hifi.colors.baseGray;
- onVisibleChanged: {
- if (visible) {
- root.resetSubmitButton();
- }
- }
-
Hifi.QmlCommerce {
id: commerce;
@@ -116,6 +110,12 @@ Rectangle {
anchors.right: parent.right;
anchors.rightMargin: 16;
height: 280;
+
+ Connections {
+ onSendSignalToWallet: {
+ sendSignalToWallet(msg);
+ }
+ }
}
// Text below security images
@@ -193,6 +193,8 @@ Rectangle {
// SECURITY IMAGE SELECTION END
//
+ signal sendSignalToWallet(var msg);
+
function resetSubmitButton() {
securityImageSubmitButton.enabled = true;
securityImageSubmitButton.text = "Submit";
diff --git a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml
index ae2606c0f6..53838fa58c 100644
--- a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml
@@ -28,12 +28,23 @@ Rectangle {
property string activeView: "initialize";
property bool securityImageResultReceived: false;
property bool keyFilePathIfExistsResultReceived: false;
+ property bool keyboardRaised: false;
// Style
color: hifi.colors.baseGray;
Hifi.QmlCommerce {
id: commerce;
+ onLoginStatusResult: {
+ if (!isLoggedIn && root.activeView !== "needsLogIn") {
+ root.activeView = "needsLogIn";
+ } else if (isLoggedIn) {
+ root.activeView = "initialize";
+ commerce.getSecurityImage();
+ commerce.getKeyFilePathIfExists();
+ }
+ }
+
onSecurityImageResult: {
securityImageResultReceived = true;
if (!exists && root.activeView !== "notSetUp") { // "If security image is not set up"
@@ -57,27 +68,6 @@ Rectangle {
id: securityImageModel;
}
- Connections {
- target: walletSetupLightbox;
- onSendSignalToWallet: {
- if (msg.method === 'walletSetup_cancelClicked') {
- walletSetupLightbox.visible = false;
- } else if (msg.method === 'walletSetup_finished') {
- root.activeView = "walletHome";
- } else {
- sendToScript(msg);
- }
- }
- }
- Connections {
- target: notSetUp;
- onSendSignalToWallet: {
- if (msg.method === 'setUpClicked') {
- walletSetupLightbox.visible = true;
- }
- }
- }
-
Rectangle {
id: walletSetupLightboxContainer;
visible: walletSetupLightbox.visible || passphraseSelectionLightbox.visible || securityImageSelectionLightbox.visible;
@@ -89,26 +79,60 @@ Rectangle {
WalletSetupLightbox {
id: walletSetupLightbox;
visible: false;
- z: 999;
+ z: 998;
anchors.centerIn: walletSetupLightboxContainer;
width: walletSetupLightboxContainer.width - 50;
height: walletSetupLightboxContainer.height - 50;
+
+ Connections {
+ onSendSignalToWallet: {
+ if (msg.method === 'walletSetup_cancelClicked') {
+ walletSetupLightbox.visible = false;
+ } else if (msg.method === 'walletSetup_finished') {
+ root.activeView = "walletHome";
+ } else if (msg.method === 'walletSetup_raiseKeyboard') {
+ root.keyboardRaised = true;
+ } else if (msg.method === 'walletSetup_lowerKeyboard') {
+ root.keyboardRaised = false;
+ } else {
+ sendToScript(msg);
+ }
+ }
+ }
}
PassphraseSelectionLightbox {
id: passphraseSelectionLightbox;
visible: false;
- z: 999;
+ z: 998;
anchors.centerIn: walletSetupLightboxContainer;
width: walletSetupLightboxContainer.width - 50;
height: walletSetupLightboxContainer.height - 50;
+
+ Connections {
+ onSendSignalToWallet: {
+ if (msg.method === 'walletSetup_raiseKeyboard') {
+ root.keyboardRaised = true;
+ } else if (msg.method === 'walletSetup_lowerKeyboard') {
+ root.keyboardRaised = false;
+ } else {
+ sendToScript(msg);
+ }
+ }
+ }
}
SecurityImageSelectionLightbox {
id: securityImageSelectionLightbox;
visible: false;
- z: 999;
+ z: 998;
anchors.centerIn: walletSetupLightboxContainer;
width: walletSetupLightboxContainer.width - 50;
height: walletSetupLightboxContainer.height - 50;
+
+ Connections {
+ onSendSignalToWallet: {
+ sendToScript(msg);
+ }
+ }
}
@@ -117,6 +141,7 @@ Rectangle {
//
Item {
id: titleBarContainer;
+ visible: !needsLogIn.visible;
// Size
width: parent.width;
height: 50;
@@ -168,8 +193,28 @@ Rectangle {
color: hifi.colors.baseGray;
Component.onCompleted: {
- commerce.getSecurityImage();
- commerce.getKeyFilePathIfExists();
+ commerce.getLoginStatus();
+ }
+ }
+
+ NeedsLogIn {
+ id: needsLogIn;
+ visible: root.activeView === "needsLogIn";
+ anchors.top: parent.top;
+ anchors.bottom: parent.bottom;
+ anchors.left: parent.left;
+ anchors.right: parent.right;
+
+ Connections {
+ onSendSignalToWallet: {
+ sendToScript(msg);
+ }
+ }
+ }
+ Connections {
+ target: GlobalServices
+ onMyUsernameChanged: {
+ commerce.getLoginStatus();
}
}
@@ -180,6 +225,14 @@ Rectangle {
anchors.bottom: tabButtonsContainer.top;
anchors.left: parent.left;
anchors.right: parent.right;
+
+ Connections {
+ onSendSignalToWallet: {
+ if (msg.method === 'setUpClicked') {
+ walletSetupLightbox.visible = true;
+ }
+ }
+ }
}
WalletHome {
@@ -219,14 +272,15 @@ Rectangle {
anchors.leftMargin: 16;
anchors.right: parent.right;
anchors.rightMargin: 16;
- }
- Connections {
- target: security;
- onSendSignalToWallet: {
- if (msg.method === 'walletSecurity_changePassphrase') {
- passphraseSelectionLightbox.visible = true;
- } else if (msg.method === 'walletSecurity_changeSecurityImage') {
- securityImageSelectionLightbox.visible = true;
+
+ Connections {
+ onSendSignalToWallet: {
+ if (msg.method === 'walletSecurity_changePassphrase') {
+ passphraseSelectionLightbox.visible = true;
+ passphraseSelectionLightbox.clearPassphraseFields();
+ } else if (msg.method === 'walletSecurity_changeSecurityImage') {
+ securityImageSelectionLightbox.visible = true;
+ }
}
}
}
@@ -242,6 +296,14 @@ Rectangle {
anchors.leftMargin: 16;
anchors.right: parent.right;
anchors.rightMargin: 16;
+
+ Connections {
+ onSendSignalToWallet: {
+ if (msg.method === 'walletReset') {
+ sendToScript(msg);
+ }
+ }
+ }
}
@@ -254,6 +316,7 @@ Rectangle {
//
Item {
id: tabButtonsContainer;
+ visible: !needsLogIn.visible;
property int numTabs: 5;
// Size
width: root.width;
@@ -457,6 +520,46 @@ Rectangle {
// TAB BUTTONS END
//
+ Item {
+ id: keyboardContainer;
+ z: 999;
+ visible: keyboard.raised;
+ property bool punctuationMode: false;
+ anchors {
+ bottom: parent.bottom;
+ left: parent.left;
+ right: parent.right;
+ }
+
+ Image {
+ id: lowerKeyboardButton;
+ source: "images/lowerKeyboard.png";
+ anchors.horizontalCenter: parent.horizontalCenter;
+ anchors.bottom: keyboard.top;
+ height: 30;
+ width: 120;
+
+ MouseArea {
+ anchors.fill: parent;
+
+ onClicked: {
+ root.keyboardRaised = false;
+ }
+ }
+ }
+
+ HifiControlsUit.Keyboard {
+ id: keyboard;
+ raised: HMD.mounted && root.keyboardRaised;
+ numeric: parent.punctuationMode;
+ anchors {
+ bottom: parent.bottom;
+ left: parent.left;
+ right: parent.right;
+ }
+ }
+ }
+
//
// FUNCTION DEFINITIONS START
//
diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml
index 33faacd0ab..b55f7f800a 100644
--- a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml
@@ -24,6 +24,7 @@ Item {
HifiConstants { id: hifi; }
id: root;
+ property bool historyReceived: false;
Hifi.QmlCommerce {
id: commerce;
@@ -41,9 +42,10 @@ Item {
}
onHistoryResult : {
+ historyReceived = true;
if (result.status === 'success') {
- var txt = result.data.history.map(function (h) { return h.text; }).join("
");
- transactionHistoryText.text = txt;
+ transactionHistoryModel.clear();
+ transactionHistoryModel.append(result.data.history);
}
}
}
@@ -111,6 +113,7 @@ Item {
onVisibleChanged: {
if (visible) {
+ historyReceived = false;
commerce.balance();
commerce.history();
}
@@ -182,9 +185,19 @@ Item {
cache: false;
source: "image://security/securityImage";
}
- // "Security picture" text below pic
+ Image {
+ id: securityImageOverlay;
+ source: "images/lockOverlay.png";
+ width: securityImage.width * 0.45;
+ height: securityImage.height * 0.45;
+ anchors.bottom: securityImage.bottom;
+ anchors.right: securityImage.right;
+ mipmap: true;
+ opacity: 0.9;
+ }
+ // "Security image" text below pic
RalewayRegular {
- text: "security picture";
+ text: "security image";
// Text size
size: 12;
// Anchors
@@ -208,8 +221,7 @@ Item {
anchors.topMargin: 8;
anchors.left: parent.left;
anchors.right: parent.right;
- anchors.bottom: homeMessage.visible ? homeMessage.top : root.bottom;
- anchors.bottomMargin: 10;
+ anchors.bottom: parent.bottom;
RalewayRegular {
id: recentActivityText;
@@ -224,111 +236,66 @@ Item {
// Style
color: hifi.colors.faintGray;
}
-
+ ListModel {
+ id: transactionHistoryModel;
+ }
Rectangle {
- id: transactionHistory;
anchors.top: recentActivityText.bottom;
anchors.topMargin: 4;
- anchors.bottom: toggleFullHistoryButton.top;
- anchors.bottomMargin: 8;
- anchors.left: parent.left;
- anchors.right: parent.right;
-
- // some placeholder stuff
- TextArea {
- id: transactionHistoryText;
- text: "
history unavailable
";
- textFormat: TextEdit.AutoText;
- font.pointSize: 10;
- anchors.fill: parent;
- horizontalAlignment: Text.AlignLeft;
- verticalAlignment: Text.AlignTop;
- }
- }
-
- HifiControlsUit.Button {
- id: toggleFullHistoryButton;
- color: hifi.buttons.black;
- colorScheme: hifi.colorSchemes.dark;
anchors.bottom: parent.bottom;
- anchors.right: parent.right;
- width: 250;
- height: 40;
- text: homeMessage.visible ? "See Full Transaction History" : "Collapse Transaction History";
- onClicked: {
- if (homeMessage.visible) {
- homeMessage.visible = false;
- } else {
- homeMessage.visible = true;
- }
- }
- }
- }
-
- // Item for "messages" - like "Welcome"
- Item {
- id: homeMessage;
- anchors.bottom: parent.bottom;
- anchors.left: parent.left;
- anchors.leftMargin: 20;
- anchors.right: parent.right;
- anchors.rightMargin: 20;
- height: childrenRect.height;
-
- RalewayRegular {
- id: messageText;
- text: "Welcome! Let's get you some spending money.
" +
- "Now that your account is all set up, click the button below to request your starter money. " +
- "A robot will promptly review your request and put money into your account.";
- // Text size
- size: 16;
- // Anchors
- anchors.top: parent.top;
anchors.left: parent.left;
anchors.right: parent.right;
- height: 130;
- // Style
- color: hifi.colors.faintGray;
- wrapMode: Text.WordWrap;
- // Alignment
- horizontalAlignment: Text.AlignHLeft;
- verticalAlignment: Text.AlignVCenter;
- }
+ color: "white";
- Item {
- id: homeMessageButtons;
- anchors.top: messageText.bottom;
- anchors.topMargin: 4;
- anchors.left: parent.left;
- anchors.right: parent.right;
- height: 40;
- HifiControlsUit.Button {
- id: noThanksButton;
- color: hifi.buttons.black;
- colorScheme: hifi.colorSchemes.dark;
- anchors.top: parent.top;
- anchors.bottom: parent.bottom;
- anchors.left: parent.left;
- width: 100;
- text: "No Thanks"
- onClicked: {
- messageText.text = "Okay...weird. Who doesn't like free money? If you change your mind, too bad. Sorry."
- homeMessageButtons.visible = false;
+ ListView {
+ id: transactionHistory;
+ anchors.centerIn: parent;
+ width: parent.width - 12;
+ height: parent.height - 12;
+ visible: transactionHistoryModel.count !== 0;
+ clip: true;
+ model: transactionHistoryModel;
+ delegate: Item {
+ width: parent.width;
+ height: transactionText.height + 30;
+ RalewayRegular {
+ id: transactionText;
+ text: model.text;
+ // Style
+ size: 18;
+ width: parent.width;
+ height: paintedHeight;
+ anchors.verticalCenter: parent.verticalCenter;
+ color: "black";
+ wrapMode: Text.WordWrap;
+ // Alignment
+ horizontalAlignment: Text.AlignLeft;
+ verticalAlignment: Text.AlignVCenter;
+ }
+
+ HifiControlsUit.Separator {
+ anchors.left: parent.left;
+ anchors.right: parent.right;
+ anchors.bottom: parent.bottom;
+ }
+ }
+ onAtYEndChanged: {
+ if (transactionHistory.atYEnd) {
+ console.log("User scrolled to the bottom of 'Recent Activity'.");
+ // Grab next page of results and append to model
+ }
}
}
- HifiControlsUit.Button {
- id: freeMoneyButton;
- color: hifi.buttons.black;
- colorScheme: hifi.colorSchemes.dark;
- anchors.top: parent.top;
- anchors.bottom: parent.bottom;
- anchors.right: parent.right;
- width: 210;
- text: "Free Money Please"
- onClicked: {
- messageText.text = "Go, MoneyRobots, Go!"
- homeMessageButtons.visible = false;
- }
+
+ // This should never be visible (since you immediately get 100 HFC)
+ RalewayRegular {
+ id: emptyTransationHistory;
+ size: 24;
+ visible: !transactionHistory.visible && root.historyReceived;
+ text: "Recent Activity Unavailable";
+ anchors.fill: parent;
+ horizontalAlignment: Text.AlignHCenter;
+ verticalAlignment: Text.AlignVCenter;
}
}
}
diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletSetupLightbox.qml b/interface/resources/qml/hifi/commerce/wallet/WalletSetupLightbox.qml
index bbeb77f6fa..4470ec7a75 100644
--- a/interface/resources/qml/hifi/commerce/wallet/WalletSetupLightbox.qml
+++ b/interface/resources/qml/hifi/commerce/wallet/WalletSetupLightbox.qml
@@ -24,21 +24,13 @@ Rectangle {
HifiConstants { id: hifi; }
id: root;
- property string lastPage: "login";
+ property string lastPage: "initialize";
// Style
color: hifi.colors.baseGray;
Hifi.QmlCommerce {
id: commerce;
- onLoginStatusResult: {
- if (isLoggedIn) {
- securityImageContainer.visible = true;
- } else {
- loginPageContainer.visible = true;
- }
- }
-
onSecurityImageResult: {
if (!exists && root.lastPage === "securityImage") {
// ERROR! Invalid security image.
@@ -61,151 +53,14 @@ Rectangle {
}
}
- //
- // LOGIN PAGE START
- //
- Item {
- id: loginPageContainer;
- visible: false;
- // Anchors
- anchors.fill: parent;
-
- Component.onCompleted: {
- commerce.getLoginStatus();
- }
-
- Item {
- id: loginTitle;
- // Size
- width: parent.width;
- height: 50;
- // Anchors
- anchors.left: parent.left;
- anchors.top: parent.top;
-
- // Title Bar text
- RalewaySemiBold {
- text: "WALLET SETUP - LOGIN";
- // Text size
- size: hifi.fontSizes.overlayTitle;
- // Anchors
- anchors.top: parent.top;
- anchors.left: parent.left;
- anchors.leftMargin: 16;
- anchors.bottom: parent.bottom;
- width: paintedWidth;
- // Style
- color: hifi.colors.faintGray;
- // Alignment
- horizontalAlignment: Text.AlignHLeft;
- verticalAlignment: Text.AlignVCenter;
- }
- }
-
- // Text below title bar
- RalewaySemiBold {
- id: loginTitleHelper;
- text: "Please Log In to High Fidelity";
- // Text size
- size: 24;
- // Anchors
- anchors.top: loginTitle.bottom;
- anchors.left: parent.left;
- anchors.leftMargin: 16;
- anchors.right: parent.right;
- anchors.rightMargin: 16;
- height: 50;
- // Style
- color: hifi.colors.faintGray;
- // Alignment
- horizontalAlignment: Text.AlignHLeft;
- verticalAlignment: Text.AlignVCenter;
- }
-
- // Text below helper text
- RalewaySemiBold {
- id: loginDetailText;
- text: "To set up your wallet, you must first log in to High Fidelity.";
- // Text size
- size: 18;
- // Anchors
- anchors.top: loginTitleHelper.bottom;
- anchors.topMargin: 25;
- anchors.left: parent.left;
- anchors.leftMargin: 16;
- anchors.right: parent.right;
- anchors.rightMargin: 16;
- height: 50;
- // Style
- color: hifi.colors.faintGray;
- wrapMode: Text.WordWrap;
- // Alignment
- horizontalAlignment: Text.AlignHLeft;
- verticalAlignment: Text.AlignVCenter;
- }
-
- // "Cancel" button
- HifiControlsUit.Button {
- color: hifi.buttons.black;
- colorScheme: hifi.colorSchemes.dark;
- anchors.top: loginDetailText.bottom;
- anchors.topMargin: 25;
- anchors.left: parent.left;
- anchors.leftMargin: 16;
- width: 150;
- height: 50;
- text: "Log In"
- onClicked: {
- sendSignalToWallet({method: 'walletSetup_loginClicked'});
- }
- }
-
- // Navigation Bar
- Item {
- // Size
- width: parent.width;
- height: 100;
- // Anchors:
- anchors.left: parent.left;
- anchors.bottom: parent.bottom;
-
- // "Cancel" button
- HifiControlsUit.Button {
- color: hifi.buttons.black;
- colorScheme: hifi.colorSchemes.dark;
- anchors.top: parent.top;
- anchors.topMargin: 3;
- anchors.bottom: parent.bottom;
- anchors.bottomMargin: 3;
- anchors.left: parent.left;
- anchors.leftMargin: 20;
- width: 100;
- text: "Cancel"
- onClicked: {
- sendSignalToWallet({method: 'walletSetup_cancelClicked'});
- }
- }
- }
- }
- //
- // LOGIN PAGE END
- //
-
//
// SECURITY IMAGE SELECTION START
//
Item {
id: securityImageContainer;
- visible: false;
// Anchors
anchors.fill: parent;
- onVisibleChanged: {
- if (visible) {
- commerce.getSecurityImage();
- }
- }
-
Item {
id: securityImageTitle;
// Size
@@ -262,6 +117,12 @@ Rectangle {
anchors.right: parent.right;
anchors.rightMargin: 16;
height: 280;
+
+ Connections {
+ onSendSignalToWallet: {
+ sendSignalToWallet(msg);
+ }
+ }
}
// Text below security images
@@ -329,6 +190,7 @@ Rectangle {
commerce.chooseSecurityImage(securityImagePath);
securityImageContainer.visible = false;
choosePassphraseContainer.visible = true;
+ passphraseSelection.clearPassphraseFields();
}
}
}
@@ -407,6 +269,15 @@ Rectangle {
anchors.left: parent.left;
anchors.right: parent.right;
anchors.bottom: passphraseNavBar.top;
+
+ Connections {
+ onSendMessageToLightbox: {
+ if (msg.method === 'statusResult') {
+ } else {
+ sendSignalToWallet(msg);
+ }
+ }
+ }
}
// Navigation Bar
diff --git a/interface/resources/qml/hifi/commerce/wallet/images/01cat.jpg b/interface/resources/qml/hifi/commerce/wallet/images/01.jpg
similarity index 100%
rename from interface/resources/qml/hifi/commerce/wallet/images/01cat.jpg
rename to interface/resources/qml/hifi/commerce/wallet/images/01.jpg
diff --git a/interface/resources/qml/hifi/commerce/wallet/images/02.jpg b/interface/resources/qml/hifi/commerce/wallet/images/02.jpg
new file mode 100644
index 0000000000..e210d0dc82
Binary files /dev/null and b/interface/resources/qml/hifi/commerce/wallet/images/02.jpg differ
diff --git a/interface/resources/qml/hifi/commerce/wallet/images/02car.jpg b/interface/resources/qml/hifi/commerce/wallet/images/02car.jpg
deleted file mode 100644
index 5dd8091e57..0000000000
Binary files a/interface/resources/qml/hifi/commerce/wallet/images/02car.jpg and /dev/null differ
diff --git a/interface/resources/qml/hifi/commerce/wallet/images/03dog.jpg b/interface/resources/qml/hifi/commerce/wallet/images/03.jpg
similarity index 100%
rename from interface/resources/qml/hifi/commerce/wallet/images/03dog.jpg
rename to interface/resources/qml/hifi/commerce/wallet/images/03.jpg
diff --git a/interface/resources/qml/hifi/commerce/wallet/images/04.jpg b/interface/resources/qml/hifi/commerce/wallet/images/04.jpg
new file mode 100644
index 0000000000..e2358b4dbc
Binary files /dev/null and b/interface/resources/qml/hifi/commerce/wallet/images/04.jpg differ
diff --git a/interface/resources/qml/hifi/commerce/wallet/images/04stars.jpg b/interface/resources/qml/hifi/commerce/wallet/images/04stars.jpg
deleted file mode 100644
index 8f2bf62f83..0000000000
Binary files a/interface/resources/qml/hifi/commerce/wallet/images/04stars.jpg and /dev/null differ
diff --git a/interface/resources/qml/hifi/commerce/wallet/images/05.jpg b/interface/resources/qml/hifi/commerce/wallet/images/05.jpg
new file mode 100644
index 0000000000..796acac167
Binary files /dev/null and b/interface/resources/qml/hifi/commerce/wallet/images/05.jpg differ
diff --git a/interface/resources/qml/hifi/commerce/wallet/images/05plane.jpg b/interface/resources/qml/hifi/commerce/wallet/images/05plane.jpg
deleted file mode 100644
index 6504459d8b..0000000000
Binary files a/interface/resources/qml/hifi/commerce/wallet/images/05plane.jpg and /dev/null differ
diff --git a/interface/resources/qml/hifi/commerce/wallet/images/06gingerbread.jpg b/interface/resources/qml/hifi/commerce/wallet/images/06.jpg
similarity index 100%
rename from interface/resources/qml/hifi/commerce/wallet/images/06gingerbread.jpg
rename to interface/resources/qml/hifi/commerce/wallet/images/06.jpg
diff --git a/interface/resources/qml/hifi/commerce/wallet/images/lockOverlay.png b/interface/resources/qml/hifi/commerce/wallet/images/lockOverlay.png
new file mode 100644
index 0000000000..09b2011e58
Binary files /dev/null and b/interface/resources/qml/hifi/commerce/wallet/images/lockOverlay.png differ
diff --git a/interface/resources/qml/hifi/commerce/wallet/images/lowerKeyboard.png b/interface/resources/qml/hifi/commerce/wallet/images/lowerKeyboard.png
new file mode 100644
index 0000000000..9fc88262db
Binary files /dev/null and b/interface/resources/qml/hifi/commerce/wallet/images/lowerKeyboard.png differ
diff --git a/interface/resources/qml/hifi/toolbars/ToolbarButton.qml b/interface/resources/qml/hifi/toolbars/ToolbarButton.qml
index 3d4231ced7..bbf2d019fb 100644
--- a/interface/resources/qml/hifi/toolbars/ToolbarButton.qml
+++ b/interface/resources/qml/hifi/toolbars/ToolbarButton.qml
@@ -4,6 +4,7 @@ import QtQuick.Controls 1.4
StateImage {
id: button
+ property string captionColorOverride: ""
property bool buttonEnabled: true
property bool isActive: false
property bool isEntered: false
@@ -97,7 +98,7 @@ StateImage {
Text {
id: caption
- color: button.isActive ? "#000000" : "#ffffff"
+ color: captionColorOverride !== "" ? captionColorOverride: (button.isActive ? "#000000" : "#ffffff")
text: button.isActive ? (button.isEntered ? button.activeHoverText : button.activeText) : (button.isEntered ? button.hoverText : button.text)
font.bold: false
font.pixelSize: 9
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 901b300277..458026c6a8 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -166,6 +166,7 @@
#include "scripting/WindowScriptingInterface.h"
#include "scripting/ControllerScriptingInterface.h"
#include "scripting/RatesScriptingInterface.h"
+#include "scripting/SelectionScriptingInterface.h"
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
#include "SpeechRecognizer.h"
#endif
@@ -183,7 +184,6 @@
#include "ui/UpdateDialog.h"
#include "ui/overlays/Overlays.h"
#include "ui/DomainConnectionModel.h"
-#include "ui/ImageProvider.h"
#include "Util.h"
#include "InterfaceParentFinder.h"
#include "ui/OctreeStatsProvider.h"
@@ -264,7 +264,7 @@ private:
switch ((int)event->type()) {
case ApplicationEvent::Render:
render();
- // Ensure we never back up the render events. Each render should be triggered only in response
+ // Ensure we never back up the render events. Each render should be triggered only in response
// to the NEXT render event after the last render occured
QCoreApplication::removePostedEvents(this, ApplicationEvent::Render);
return true;
@@ -676,6 +676,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
DependencyManager::set();
DependencyManager::set();
DependencyManager::set();
+ DependencyManager::set();
DependencyManager::set();
DependencyManager::set();
DependencyManager::set();
@@ -2246,8 +2247,6 @@ void Application::initializeUi() {
qApp->quit();
});
- // register the pixmap image provider (used only for security image, for now)
- engine->addImageProvider(ImageProvider::PROVIDER_NAME, new ImageProvider());
setupPreferences();
@@ -2321,6 +2320,7 @@ void Application::initializeUi() {
surfaceContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor());
surfaceContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
+ surfaceContext->setContextProperty("Selection", DependencyManager::get().data());
surfaceContext->setContextProperty("ContextOverlay", DependencyManager::get().data());
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
@@ -5187,7 +5187,7 @@ void Application::update(float deltaTime) {
}
} else {
// update the rendering without any simulation
- getEntities()->update(false);
+ getEntities()->update(false);
}
// AvatarManager update
@@ -5661,17 +5661,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
}
renderArgs->_debugFlags = renderDebugFlags;
//ViveControllerManager::getInstance().updateRendering(renderArgs, _main3DScene, transaction);
-
- RenderArgs::OutlineFlags renderOutlineFlags = RenderArgs::RENDER_OUTLINE_NONE;
- auto contextOverlayInterface = DependencyManager::get();
- if (contextOverlayInterface->getEnabled()) {
- if (DependencyManager::get()->getIsInMarketplaceInspectionMode()) {
- renderOutlineFlags = RenderArgs::RENDER_OUTLINE_MARKETPLACE_MODE;
- } else {
- renderOutlineFlags = RenderArgs::RENDER_OUTLINE_WIREFRAMES;
- }
- }
- renderArgs->_outlineFlags = renderOutlineFlags;
}
}
@@ -6138,6 +6127,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
auto entityScriptServerLog = DependencyManager::get();
scriptEngine->registerGlobalObject("EntityScriptServerLog", entityScriptServerLog.data());
scriptEngine->registerGlobalObject("AvatarInputs", AvatarInputs::getInstance());
+ scriptEngine->registerGlobalObject("Selection", DependencyManager::get().data());
scriptEngine->registerGlobalObject("ContextOverlay", DependencyManager::get().data());
qScriptRegisterMetaType(scriptEngine, OverlayIDtoScriptValue, OverlayIDfromScriptValue);
diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp
index dddfae6455..08eb79017f 100644
--- a/interface/src/commerce/Ledger.cpp
+++ b/interface/src/commerce/Ledger.cpp
@@ -111,3 +111,10 @@ void Ledger::inventory(const QStringList& keys) {
void Ledger::history(const QStringList& keys) {
keysQuery("history", "historySuccess", "historyFailure");
}
+
+// The api/failResponse is called just for the side effect of logging.
+void Ledger::resetSuccess(QNetworkReply& reply) { apiResponse("reset", reply); }
+void Ledger::resetFailure(QNetworkReply& reply) { failResponse("reset", reply); }
+void Ledger::reset() {
+ send("reset_user_hfc_account", "resetSuccess", "resetFailure", QNetworkAccessManager::PutOperation, QJsonObject());
+}
\ No newline at end of file
diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h
index 7d3fdef0c0..55b648aa4c 100644
--- a/interface/src/commerce/Ledger.h
+++ b/interface/src/commerce/Ledger.h
@@ -29,6 +29,7 @@ public:
void balance(const QStringList& keys);
void inventory(const QStringList& keys);
void history(const QStringList& keys);
+ void reset();
signals:
void buyResult(QJsonObject result);
@@ -48,6 +49,8 @@ public slots:
void inventoryFailure(QNetworkReply& reply);
void historySuccess(QNetworkReply& reply);
void historyFailure(QNetworkReply& reply);
+ void resetSuccess(QNetworkReply& reply);
+ void resetFailure(QNetworkReply& reply);
private:
QJsonObject apiResponse(const QString& label, QNetworkReply& reply);
diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp
index bf6bcc221c..655f228672 100644
--- a/interface/src/commerce/QmlCommerce.cpp
+++ b/interface/src/commerce/QmlCommerce.cpp
@@ -85,3 +85,10 @@ void QmlCommerce::getKeyFilePathIfExists() {
auto wallet = DependencyManager::get();
wallet->sendKeyFilePathIfExists();
}
+
+void QmlCommerce::reset() {
+ auto ledger = DependencyManager::get();
+ auto wallet = DependencyManager::get();
+ ledger->reset();
+ wallet->reset();
+}
\ No newline at end of file
diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h
index fd913ae4b7..deb11b7714 100644
--- a/interface/src/commerce/QmlCommerce.h
+++ b/interface/src/commerce/QmlCommerce.h
@@ -50,6 +50,7 @@ protected:
Q_INVOKABLE void setPassphrase(const QString& passphrase);
Q_INVOKABLE void getPassphraseSetupStatus();
Q_INVOKABLE void getKeyFilePathIfExists();
+ Q_INVOKABLE void reset();
};
#endif // hifi_QmlCommerce_h
diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp
index 9e04694a24..32852602d7 100644
--- a/interface/src/commerce/Wallet.cpp
+++ b/interface/src/commerce/Wallet.cpp
@@ -14,6 +14,7 @@
#include "Wallet.h"
#include "Application.h"
#include "ui/ImageProvider.h"
+#include "scripting/HMDScriptingInterface.h"
#include
#include
@@ -224,6 +225,12 @@ void initializeAESKeys(unsigned char* ivec, unsigned char* ckey, const QByteArra
memcpy(ckey, hash.data(), 32);
}
+Wallet::~Wallet() {
+ if (_securityImage) {
+ delete _securityImage;
+ }
+}
+
void Wallet::setPassphrase(const QString& passphrase) {
if (_passphrase) {
delete _passphrase;
@@ -411,6 +418,13 @@ QString Wallet::signWithKey(const QByteArray& text, const QString& key) {
return QString();
}
+void Wallet::updateImageProvider() {
+ // inform the image provider. Note it doesn't matter which one you inform, as the
+ // images are statics
+ auto engine = DependencyManager::get()->getSurfaceContext()->engine();
+ auto imageProvider = reinterpret_cast(engine->imageProvider(ImageProvider::PROVIDER_NAME));
+ imageProvider->setSecurityImage(_securityImage);
+}
void Wallet::chooseSecurityImage(const QString& filename) {
@@ -431,10 +445,7 @@ void Wallet::chooseSecurityImage(const QString& filename) {
if (encryptFile(path, imageFilePath())) {
qCDebug(commerce) << "emitting pixmap";
- // inform the image provider
- auto engine = DependencyManager::get()->getSurfaceContext()->engine();
- auto imageProvider = reinterpret_cast(engine->imageProvider(ImageProvider::PROVIDER_NAME));
- imageProvider->setSecurityImage(_securityImage);
+ updateImageProvider();
emit securityImageResult(true);
} else {
@@ -454,16 +465,15 @@ void Wallet::getSecurityImage() {
}
// decrypt and return
- if (decryptFile(imageFilePath(), &data, &dataLen)) {
+ QString filePath(imageFilePath());
+ QFileInfo fileInfo(filePath);
+ if (fileInfo.exists() && decryptFile(filePath, &data, &dataLen)) {
// create the pixmap
_securityImage = new QPixmap();
_securityImage->loadFromData(data, dataLen, "jpg");
qCDebug(commerce) << "created pixmap from encrypted file";
- // inform the image provider
- auto engine = DependencyManager::get()->getSurfaceContext()->engine();
- auto imageProvider = reinterpret_cast(engine->imageProvider(ImageProvider::PROVIDER_NAME));
- imageProvider->setSecurityImage(_securityImage);
+ updateImageProvider();
delete[] data;
emit securityImageResult(true);
@@ -481,3 +491,24 @@ void Wallet::sendKeyFilePathIfExists() {
emit keyFilePathIfExistsResult("");
}
}
+
+void Wallet::reset() {
+ _publicKeys.clear();
+
+ delete _securityImage;
+ _securityImage = nullptr;
+
+ // tell the provider we got nothing
+ updateImageProvider();
+ delete _passphrase;
+
+ // for now we need to maintain the hard-coded passphrase.
+ // FIXME: remove this line as part of wiring up the passphrase
+ // and probably set it to nullptr
+ _passphrase = new QString("pwd");
+
+ QFile keyFile(keyFilePath());
+ QFile imageFile(imageFilePath());
+ keyFile.remove();
+ imageFile.remove();
+}
diff --git a/interface/src/commerce/Wallet.h b/interface/src/commerce/Wallet.h
index b13d4368d9..4acd913181 100644
--- a/interface/src/commerce/Wallet.h
+++ b/interface/src/commerce/Wallet.h
@@ -23,6 +23,8 @@ class Wallet : public QObject, public Dependency {
SINGLETON_DEPENDENCY
public:
+
+ ~Wallet();
// These are currently blocking calls, although they might take a moment.
bool createIfNeeded();
bool generateKeyPair();
@@ -38,27 +40,19 @@ public:
void setPassphrase(const QString& passphrase);
QString* getPassphrase() { return _passphrase; }
+ void reset();
+
signals:
void securityImageResult(bool exists) ;
void keyFilePathIfExistsResult(const QString& path);
-protected:
- enum SecurityImage {
- NONE = 0,
- Cat,
- Car,
- Dog,
- Stars,
- Plane,
- Gingerbread
- };
-
private:
QStringList _publicKeys{};
QPixmap* _securityImage { nullptr };
QByteArray _salt {"iamsalt!"};
QString* _passphrase { new QString("pwd") };
+ void updateImageProvider();
bool encryptFile(const QString& inputFilePath, const QString& outputFilePath);
bool decryptFile(const QString& inputFilePath, unsigned char** outputBufferPtr, int* outputBufferLen);
};
diff --git a/interface/src/scripting/SelectionScriptingInterface.cpp b/interface/src/scripting/SelectionScriptingInterface.cpp
new file mode 100644
index 0000000000..808396c901
--- /dev/null
+++ b/interface/src/scripting/SelectionScriptingInterface.cpp
@@ -0,0 +1,195 @@
+//
+// SelectionScriptingInterface.cpp
+// interface/src/scripting
+//
+// Created by Zach Fox on 2017-08-22.
+// Copyright 2017 High Fidelity, Inc.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+#include "SelectionScriptingInterface.h"
+#include
+#include "Application.h"
+
+GameplayObjects::GameplayObjects() {
+}
+
+bool GameplayObjects::addToGameplayObjects(const QUuid& avatarID) {
+ containsData = true;
+ _avatarIDs.push_back(avatarID);
+ return true;
+}
+bool GameplayObjects::removeFromGameplayObjects(const QUuid& avatarID) {
+ _avatarIDs.erase(std::remove(_avatarIDs.begin(), _avatarIDs.end(), avatarID), _avatarIDs.end());
+ return true;
+}
+
+bool GameplayObjects::addToGameplayObjects(const EntityItemID& entityID) {
+ containsData = true;
+ _entityIDs.push_back(entityID);
+ return true;
+}
+bool GameplayObjects::removeFromGameplayObjects(const EntityItemID& entityID) {
+ _entityIDs.erase(std::remove(_entityIDs.begin(), _entityIDs.end(), entityID), _entityIDs.end());
+ return true;
+}
+
+bool GameplayObjects::addToGameplayObjects(const OverlayID& overlayID) {
+ containsData = true;
+ _overlayIDs.push_back(overlayID);
+ return true;
+}
+bool GameplayObjects::removeFromGameplayObjects(const OverlayID& overlayID) {
+ _overlayIDs.erase(std::remove(_overlayIDs.begin(), _overlayIDs.end(), overlayID), _overlayIDs.end());
+ return true;
+}
+
+
+SelectionScriptingInterface::SelectionScriptingInterface() {
+}
+
+bool SelectionScriptingInterface::addToSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id) {
+ if (itemType == "avatar") {
+ return addToGameplayObjects(listName, (QUuid)id);
+ } else if (itemType == "entity") {
+ return addToGameplayObjects(listName, (EntityItemID)id);
+ } else if (itemType == "overlay") {
+ return addToGameplayObjects(listName, (OverlayID)id);
+ }
+ return false;
+}
+bool SelectionScriptingInterface::removeFromSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id) {
+ if (itemType == "avatar") {
+ return removeFromGameplayObjects(listName, (QUuid)id);
+ } else if (itemType == "entity") {
+ return removeFromGameplayObjects(listName, (EntityItemID)id);
+ } else if (itemType == "overlay") {
+ return removeFromGameplayObjects(listName, (OverlayID)id);
+ }
+ return false;
+}
+
+template bool SelectionScriptingInterface::addToGameplayObjects(const QString& listName, T idToAdd) {
+ GameplayObjects currentList = _selectedItemsListMap.value(listName);
+ currentList.addToGameplayObjects(idToAdd);
+ _selectedItemsListMap.insert(listName, currentList);
+
+ emit selectedItemsListChanged(listName);
+ return true;
+}
+template bool SelectionScriptingInterface::removeFromGameplayObjects(const QString& listName, T idToRemove) {
+ GameplayObjects currentList = _selectedItemsListMap.value(listName);
+ if (currentList.getContainsData()) {
+ currentList.removeFromGameplayObjects(idToRemove);
+ _selectedItemsListMap.insert(listName, currentList);
+
+ emit selectedItemsListChanged(listName);
+ return true;
+ } else {
+ return false;
+ }
+}
+//
+// END HANDLING GENERIC ITEMS
+//
+
+GameplayObjects SelectionScriptingInterface::getList(const QString& listName) {
+ return _selectedItemsListMap.value(listName);
+}
+
+void SelectionScriptingInterface::printList(const QString& listName) {
+ GameplayObjects currentList = _selectedItemsListMap.value(listName);
+ if (currentList.getContainsData()) {
+
+ qDebug() << "Avatar IDs:";
+ for (auto i : currentList.getAvatarIDs()) {
+ qDebug() << i << ';';
+ }
+ qDebug() << "";
+
+ qDebug() << "Entity IDs:";
+ for (auto j : currentList.getEntityIDs()) {
+ qDebug() << j << ';';
+ }
+ qDebug() << "";
+
+ qDebug() << "Overlay IDs:";
+ for (auto k : currentList.getOverlayIDs()) {
+ qDebug() << k << ';';
+ }
+ qDebug() << "";
+ } else {
+ qDebug() << "List named" << listName << "doesn't exist.";
+ }
+}
+
+bool SelectionScriptingInterface::removeListFromMap(const QString& listName) {
+ if (_selectedItemsListMap.remove(listName)) {
+ emit selectedItemsListChanged(listName);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+SelectionToSceneHandler::SelectionToSceneHandler() {
+}
+
+void SelectionToSceneHandler::initialize(const QString& listName) {
+ _listName = listName;
+}
+
+void SelectionToSceneHandler::selectedItemsListChanged(const QString& listName) {
+ if (listName == _listName) {
+ updateSceneFromSelectedList();
+ }
+}
+
+void SelectionToSceneHandler::updateSceneFromSelectedList() {
+ auto mainScene = qApp->getMain3DScene();
+ if (mainScene) {
+ GameplayObjects thisList = DependencyManager::get()->getList(_listName);
+ render::Transaction transaction;
+ render::ItemIDs finalList;
+ render::ItemID currentID;
+ auto entityTreeRenderer = DependencyManager::get();
+ auto& overlays = qApp->getOverlays();
+
+ for (QUuid& currentAvatarID : thisList.getAvatarIDs()) {
+ auto avatar = std::static_pointer_cast(DependencyManager::get()->getAvatarBySessionID(currentAvatarID));
+ if (avatar) {
+ currentID = avatar->getRenderItemID();
+ if (currentID != render::Item::INVALID_ITEM_ID) {
+ finalList.push_back(currentID);
+ }
+ }
+ }
+
+ for (EntityItemID& currentEntityID : thisList.getEntityIDs()) {
+ currentID = entityTreeRenderer->renderableIdForEntityId(currentEntityID);
+ if (currentID != render::Item::INVALID_ITEM_ID) {
+ finalList.push_back(currentID);
+ }
+ }
+
+ for (OverlayID& currentOverlayID : thisList.getOverlayIDs()) {
+ auto overlay = overlays.getOverlay(currentOverlayID);
+ if (overlay != NULL) {
+ currentID = overlay->getRenderItemID();
+ if (currentID != render::Item::INVALID_ITEM_ID) {
+ finalList.push_back(currentID);
+ }
+ }
+ }
+
+ render::Selection selection(_listName.toStdString(), finalList);
+ transaction.resetSelection(selection);
+
+ mainScene->enqueueTransaction(transaction);
+ } else {
+ qWarning() << "SelectionToSceneHandler::updateRendererSelectedList(), Unexpected null scene, possibly during application shutdown";
+ }
+}
diff --git a/interface/src/scripting/SelectionScriptingInterface.h b/interface/src/scripting/SelectionScriptingInterface.h
new file mode 100644
index 0000000000..d1a372c5c4
--- /dev/null
+++ b/interface/src/scripting/SelectionScriptingInterface.h
@@ -0,0 +1,91 @@
+
+// SelectionScriptingInterface.h
+// interface/src/scripting
+//
+// Created by Zach Fox on 2017-08-22.
+// 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
+//
+
+#ifndef hifi_SelectionScriptingInterface_h
+#define hifi_SelectionScriptingInterface_h
+
+#include
+#include
+#include
+
+#include
+
+#include "RenderableEntityItem.h"
+#include "ui/overlays/Overlay.h"
+#include
+
+class GameplayObjects {
+public:
+ GameplayObjects();
+
+ bool getContainsData() { return containsData; }
+
+ std::vector getAvatarIDs() { return _avatarIDs; }
+ bool addToGameplayObjects(const QUuid& avatarID);
+ bool removeFromGameplayObjects(const QUuid& avatarID);
+
+ std::vector getEntityIDs() { return _entityIDs; }
+ bool addToGameplayObjects(const EntityItemID& entityID);
+ bool removeFromGameplayObjects(const EntityItemID& entityID);
+
+ std::vector getOverlayIDs() { return _overlayIDs; }
+ bool addToGameplayObjects(const OverlayID& overlayID);
+ bool removeFromGameplayObjects(const OverlayID& overlayID);
+
+private:
+ bool containsData { false };
+ std::vector _avatarIDs;
+ std::vector _entityIDs;
+ std::vector _overlayIDs;
+};
+
+
+class SelectionScriptingInterface : public QObject, public Dependency {
+ Q_OBJECT
+
+public:
+ SelectionScriptingInterface();
+
+ GameplayObjects getList(const QString& listName);
+
+ Q_INVOKABLE void printList(const QString& listName);
+ Q_INVOKABLE bool removeListFromMap(const QString& listName);
+
+ Q_INVOKABLE bool addToSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id);
+ Q_INVOKABLE bool removeFromSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id);
+
+signals:
+ void selectedItemsListChanged(const QString& listName);
+
+private:
+ QMap _selectedItemsListMap;
+
+ template bool addToGameplayObjects(const QString& listName, T idToAdd);
+ template bool removeFromGameplayObjects(const QString& listName, T idToRemove);
+};
+
+
+class SelectionToSceneHandler : public QObject {
+ Q_OBJECT
+public:
+ SelectionToSceneHandler();
+ void initialize(const QString& listName);
+
+ void updateSceneFromSelectedList();
+
+public slots:
+ void selectedItemsListChanged(const QString& listName);
+
+private:
+ QString _listName { "" };
+};
+
+#endif // hifi_SelectionScriptingInterface_h
diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp
index 46fb2df007..34aae37175 100644
--- a/interface/src/ui/overlays/ContextOverlayInterface.cpp
+++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp
@@ -13,6 +13,7 @@
#include "Application.h"
#include
+#include
static const float CONTEXT_OVERLAY_TABLET_OFFSET = 30.0f; // Degrees
static const float CONTEXT_OVERLAY_TABLET_ORIENTATION = 210.0f; // Degrees
@@ -27,6 +28,9 @@ ContextOverlayInterface::ContextOverlayInterface() {
_entityScriptingInterface = DependencyManager::get();
_hmdScriptingInterface = DependencyManager::get();
_tabletScriptingInterface = DependencyManager::get();
+ _selectionScriptingInterface = DependencyManager::get();
+
+ _selectionToSceneHandler.initialize("contextOverlayHighlightList");
_entityPropertyFlags += PROP_POSITION;
_entityPropertyFlags += PROP_ROTATION;
@@ -57,6 +61,8 @@ ContextOverlayInterface::ContextOverlayInterface() {
});
auto entityScriptingInterface = DependencyManager::get().data();
connect(entityScriptingInterface, &EntityScriptingInterface::deletingEntity, this, &ContextOverlayInterface::deletingEntity);
+
+ connect(_selectionScriptingInterface.data(), &SelectionScriptingInterface::selectedItemsListChanged, &_selectionToSceneHandler, &SelectionToSceneHandler::selectedItemsListChanged);
}
static const uint32_t LEFT_HAND_HW_ID = 1;
@@ -242,7 +248,7 @@ void ContextOverlayInterface::contextOverlays_hoverLeaveEntity(const EntityItemI
}
}
-static const QString MARKETPLACE_BASE_URL = "https://metaverse.highfidelity.com/marketplace/items/";
+static const QString MARKETPLACE_BASE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace/items/";
void ContextOverlayInterface::openMarketplace() {
// lets open the tablet and go to the current item in
@@ -260,25 +266,11 @@ void ContextOverlayInterface::openMarketplace() {
}
void ContextOverlayInterface::enableEntityHighlight(const EntityItemID& entityItemID) {
- auto entityTree = qApp->getEntities()->getTree();
- entityTree->withReadLock([&] {
- auto entityItem = entityTree->findEntityByEntityItemID(entityItemID);
- if ((entityItem != NULL) && !entityItem->getShouldHighlight()) {
- qCDebug(context_overlay) << "Setting 'shouldHighlight' to 'true' for Entity ID:" << entityItemID;
- entityItem->setShouldHighlight(true);
- }
- });
+ _selectionScriptingInterface->addToSelectedItemsList("contextOverlayHighlightList", "entity", entityItemID);
}
void ContextOverlayInterface::disableEntityHighlight(const EntityItemID& entityItemID) {
- auto entityTree = qApp->getEntities()->getTree();
- entityTree->withReadLock([&] {
- auto entityItem = entityTree->findEntityByEntityItemID(entityItemID);
- if ((entityItem != NULL) && entityItem->getShouldHighlight()) {
- qCDebug(context_overlay) << "Setting 'shouldHighlight' to 'false' for Entity ID:" << entityItemID;
- entityItem->setShouldHighlight(false);
- }
- });
+ _selectionScriptingInterface->removeFromSelectedItemsList("contextOverlayHighlightList", "entity", entityItemID);
}
void ContextOverlayInterface::deletingEntity(const EntityItemID& entityID) {
diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h
index b386de08cc..c14262029e 100644
--- a/interface/src/ui/overlays/ContextOverlayInterface.h
+++ b/interface/src/ui/overlays/ContextOverlayInterface.h
@@ -25,6 +25,7 @@
#include "ui/overlays/Image3DOverlay.h"
#include "ui/overlays/Overlays.h"
#include "scripting/HMDScriptingInterface.h"
+#include "scripting/SelectionScriptingInterface.h"
#include "EntityTree.h"
#include "ContextOverlayLogging.h"
@@ -42,6 +43,7 @@ class ContextOverlayInterface : public QObject, public Dependency {
EntityPropertyFlags _entityPropertyFlags;
QSharedPointer _hmdScriptingInterface;
QSharedPointer _tabletScriptingInterface;
+ QSharedPointer _selectionScriptingInterface;
OverlayID _contextOverlayID { UNKNOWN_OVERLAY_ID };
std::shared_ptr _contextOverlay { nullptr };
public:
@@ -81,6 +83,8 @@ private:
void disableEntityHighlight(const EntityItemID& entityItemID);
void deletingEntity(const EntityItemID& entityItemID);
+
+ SelectionToSceneHandler _selectionToSceneHandler;
};
#endif // hifi_ContextOverlayInterface_h
diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h
index 75d9afeb90..e4eb02b817 100644
--- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h
+++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h
@@ -242,6 +242,7 @@ public:
void addToScene(AvatarSharedPointer self, const render::ScenePointer& scene);
void ensureInScene(AvatarSharedPointer self, const render::ScenePointer& scene);
bool isInScene() const { return render::Item::isValidID(_renderItemID); }
+ render::ItemID getRenderItemID() { return _renderItemID; }
bool isMoving() const { return _moving; }
void setPhysicsCallback(AvatarPhysicsCallback cb);
diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h
index 429bb629c6..0950974347 100644
--- a/libraries/entities-renderer/src/EntityTreeRenderer.h
+++ b/libraries/entities-renderer/src/EntityTreeRenderer.h
@@ -147,6 +147,7 @@ public slots:
void setDisplayModelBounds(bool value) { _displayModelBounds = value; }
void setPrecisionPicking(bool value) { _setPrecisionPickingOperator(_mouseRayPickID, value); }
EntityRendererPointer renderableForEntityId(const EntityItemID& id) const;
+ render::ItemID renderableIdForEntityId(const EntityItemID& id) const;
protected:
virtual OctreePointer createTree() override {
@@ -156,7 +157,6 @@ protected:
}
private:
- render::ItemID renderableIdForEntityId(const EntityItemID& id) const;
EntityRendererPointer renderableForEntity(const EntityItemPointer& entity) const { return renderableForEntityId(entity->getID()); }
render::ItemID renderableIdForEntity(const EntityItemPointer& entity) const { return renderableIdForEntityId(entity->getID()); }
diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
index 5ec0a1408a..277f6898d1 100644
--- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp
@@ -1080,7 +1080,6 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
}
_marketplaceEntity = entity->getMarketplaceID().length() != 0;
- _shouldHighlight = entity->getShouldHighlight();
_animating = entity->isAnimatingSomething();
withWriteLock([&] {
@@ -1207,17 +1206,6 @@ void ModelEntityRenderer::doRender(RenderArgs* args) {
model = _model;
});
- // this simple logic should say we set showingEntityHighlight to true whenever we are in marketplace mode and we have a marketplace id, or
- // whenever we are not set to none and shouldHighlight is true.
- bool showingEntityHighlight = ((bool)(args->_outlineFlags & (int)RenderArgs::RENDER_OUTLINE_MARKETPLACE_MODE) && _marketplaceEntity != 0) ||
- (args->_outlineFlags != RenderArgs::RENDER_OUTLINE_NONE && _shouldHighlight);
- if (showingEntityHighlight) {
- static glm::vec4 yellowColor(1.0f, 1.0f, 0.0f, 1.0f);
- gpu::Batch& batch = *args->_batch;
- batch.setModelTransform(_modelTransform); // we want to include the scale as well
- DependencyManager::get()->renderWireCubeInstance(args, batch, yellowColor);
- }
-
if (_model && _model->didVisualGeometryRequestFail()) {
static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f);
gpu::Batch& batch = *args->_batch;
diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp
index 6b57c79713..107af837fe 100644
--- a/libraries/entities/src/EntityItem.cpp
+++ b/libraries/entities/src/EntityItem.cpp
@@ -95,7 +95,6 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
requestedProperties += PROP_LOCKED;
requestedProperties += PROP_USER_DATA;
requestedProperties += PROP_MARKETPLACE_ID;
- requestedProperties += PROP_SHOULD_HIGHLIGHT;
requestedProperties += PROP_NAME;
requestedProperties += PROP_HREF;
requestedProperties += PROP_DESCRIPTION;
@@ -241,7 +240,6 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
APPEND_ENTITY_PROPERTY(PROP_LOCKED, getLocked());
APPEND_ENTITY_PROPERTY(PROP_USER_DATA, getUserData());
APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, getMarketplaceID());
- APPEND_ENTITY_PROPERTY(PROP_SHOULD_HIGHLIGHT, getShouldHighlight());
APPEND_ENTITY_PROPERTY(PROP_NAME, getName());
APPEND_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, getCollisionSoundURL());
APPEND_ENTITY_PROPERTY(PROP_HREF, getHref());
@@ -793,10 +791,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
READ_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
}
- if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_SHOULD_HIGHLIGHT) {
- READ_ENTITY_PROPERTY(PROP_SHOULD_HIGHLIGHT, bool, setShouldHighlight);
- }
-
READ_ENTITY_PROPERTY(PROP_NAME, QString, setName);
READ_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL);
READ_ENTITY_PROPERTY(PROP_HREF, QString, setHref);
@@ -2777,20 +2771,6 @@ void EntityItem::setMarketplaceID(const QString& value) {
});
}
-bool EntityItem::getShouldHighlight() const {
- bool result;
- withReadLock([&] {
- result = _shouldHighlight;
- });
- return result;
-}
-
-void EntityItem::setShouldHighlight(const bool value) {
- withWriteLock([&] {
- _shouldHighlight = value;
- });
-}
-
uint32_t EntityItem::getDirtyFlags() const {
uint32_t result;
withReadLock([&] {
diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp
index 1bd75f78d4..20b541f563 100644
--- a/libraries/entities/src/EntityItemProperties.cpp
+++ b/libraries/entities/src/EntityItemProperties.cpp
@@ -289,7 +289,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_RADIUS_START, radiusStart);
CHECK_PROPERTY_CHANGE(PROP_RADIUS_FINISH, radiusFinish);
CHECK_PROPERTY_CHANGE(PROP_MARKETPLACE_ID, marketplaceID);
- CHECK_PROPERTY_CHANGE(PROP_SHOULD_HIGHLIGHT, shouldHighlight);
CHECK_PROPERTY_CHANGE(PROP_NAME, name);
CHECK_PROPERTY_CHANGE(PROP_BACKGROUND_MODE, backgroundMode);
CHECK_PROPERTY_CHANGE(PROP_SOURCE_URL, sourceUrl);
@@ -407,7 +406,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCKED, locked);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_USER_DATA, userData);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MARKETPLACE_ID, marketplaceID);
- COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SHOULD_HIGHLIGHT, shouldHighlight);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_NAME, name);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLLISION_SOUND_URL, collisionSoundURL);
@@ -984,7 +982,6 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
ADD_PROPERTY_TO_MAP(PROP_RADIUS_START, RadiusStart, radiusStart, float);
ADD_PROPERTY_TO_MAP(PROP_RADIUS_FINISH, RadiusFinish, radiusFinish, float);
ADD_PROPERTY_TO_MAP(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString);
- ADD_PROPERTY_TO_MAP(PROP_SHOULD_HIGHLIGHT, ShouldHighlight, shouldHighlight, bool);
ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_COLOR, KeyLightColor, keyLightColor, xColor);
ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_INTENSITY, KeyLightIntensity, keyLightIntensity, float);
ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_AMBIENT_INTENSITY, KeyLightAmbientIntensity, keyLightAmbientIntensity, float);
@@ -1337,7 +1334,6 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
APPEND_ENTITY_PROPERTY(PROP_SHAPE, properties.getShape());
}
APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, properties.getMarketplaceID());
- APPEND_ENTITY_PROPERTY(PROP_SHOULD_HIGHLIGHT, properties.getShouldHighlight());
APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName());
APPEND_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, properties.getCollisionSoundURL());
APPEND_ENTITY_PROPERTY(PROP_ACTION_DATA, properties.getActionData());
@@ -1636,7 +1632,6 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
}
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
- READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHOULD_HIGHLIGHT, bool, setShouldHighlight);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ACTION_DATA, QByteArray, setActionData);
@@ -1751,7 +1746,6 @@ void EntityItemProperties::markAllChanged() {
//_alphaFinishChanged = true;
_marketplaceIDChanged = true;
- _shouldHighlightChanged = true;
_keyLight.markAllChanged();
diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h
index b04c3e7dc7..dd8ce952d3 100644
--- a/libraries/entities/src/EntityItemProperties.h
+++ b/libraries/entities/src/EntityItemProperties.h
@@ -171,7 +171,6 @@ public:
DEFINE_PROPERTY(PROP_RADIUS_FINISH, RadiusFinish, radiusFinish, float, particle::DEFAULT_RADIUS_FINISH);
DEFINE_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, EmitterShouldTrail, emitterShouldTrail, bool, particle::DEFAULT_EMITTER_SHOULD_TRAIL);
DEFINE_PROPERTY_REF(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString, ENTITY_ITEM_DEFAULT_MARKETPLACE_ID);
- DEFINE_PROPERTY_REF(PROP_SHOULD_HIGHLIGHT, ShouldHighlight, shouldHighlight, bool, ENTITY_ITEM_DEFAULT_SHOULD_HIGHLIGHT);
DEFINE_PROPERTY_GROUP(KeyLight, keyLight, KeyLightPropertyGroup);
DEFINE_PROPERTY_REF(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3, PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE);
DEFINE_PROPERTY_REF(PROP_VOXEL_DATA, VoxelData, voxelData, QByteArray, PolyVoxEntityItem::DEFAULT_VOXEL_DATA);
diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h
index 43d0e33ba6..d52c5d9aab 100644
--- a/libraries/entities/src/EntityItemPropertiesDefaults.h
+++ b/libraries/entities/src/EntityItemPropertiesDefaults.h
@@ -27,7 +27,6 @@ const glm::vec3 ENTITY_ITEM_HALF_VEC3 = glm::vec3(0.5f);
const bool ENTITY_ITEM_DEFAULT_LOCKED = false;
const QString ENTITY_ITEM_DEFAULT_USER_DATA = QString("");
const QString ENTITY_ITEM_DEFAULT_MARKETPLACE_ID = QString("");
-const bool ENTITY_ITEM_DEFAULT_SHOULD_HIGHLIGHT = false;
const QUuid ENTITY_ITEM_DEFAULT_SIMULATOR_ID = QUuid();
const float ENTITY_ITEM_DEFAULT_ALPHA = 1.0f;
diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h
index 9600d0d4fe..b3cfc143c2 100644
--- a/libraries/entities/src/EntityPropertyFlags.h
+++ b/libraries/entities/src/EntityPropertyFlags.h
@@ -78,7 +78,6 @@ enum EntityPropertyList {
PROP_COMPOUND_SHAPE_URL, // used by Model + zones entities
PROP_MARKETPLACE_ID, // all entities
- PROP_SHOULD_HIGHLIGHT, // all entities
PROP_ACCELERATION, // all entities
PROP_SIMULATION_OWNER, // formerly known as PROP_SIMULATOR_ID
PROP_NAME, // all entities
diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp
index f44beb6d74..c9961cc53a 100644
--- a/libraries/networking/src/udt/PacketHeaders.cpp
+++ b/libraries/networking/src/udt/PacketHeaders.cpp
@@ -30,7 +30,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketType::EntityEdit:
case PacketType::EntityData:
case PacketType::EntityPhysics:
- return VERSION_ENTITIES_HAS_SHOULD_HIGHLIGHT;
+ return VERSION_ENTITIES_HAS_HIGHLIGHT_SCRIPTING_INTERFACE;
case PacketType::EntityQuery:
return static_cast(EntityQueryPacketVersion::JSONFilterWithFamilyTree);
case PacketType::AvatarIdentity:
diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h
index e8b74a74d5..3ba2b96dfc 100644
--- a/libraries/networking/src/udt/PacketHeaders.h
+++ b/libraries/networking/src/udt/PacketHeaders.h
@@ -259,6 +259,7 @@ const PacketVersion VERSION_ENTITIES_ZONE_FILTERS = 68;
const PacketVersion VERSION_ENTITIES_HINGE_CONSTRAINT = 69;
const PacketVersion VERSION_ENTITIES_BULLET_DYNAMICS = 70;
const PacketVersion VERSION_ENTITIES_HAS_SHOULD_HIGHLIGHT = 71;
+const PacketVersion VERSION_ENTITIES_HAS_HIGHLIGHT_SCRIPTING_INTERFACE = 72;
enum class EntityQueryPacketVersion: PacketVersion {
JSONFilter = 18,
diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp
index 68c0250bec..27abc8c282 100644
--- a/libraries/render-utils/src/RenderDeferredTask.cpp
+++ b/libraries/render-utils/src/RenderDeferredTask.cpp
@@ -210,6 +210,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
}
task.addJob("DrawZoneStack", deferredFrameTransform);
+
+ // Render.getConfig("RenderMainView.DrawSelectionBounds").enabled = true
+ const auto selectedMetas = task.addJob("PassTestSelection", metas, "contextOverlayHighlightList");
+ task.addJob("DrawSelectionBounds", selectedMetas);
}
// AA job to be revisited
diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h
index 12f9506286..7070a4def5 100644
--- a/libraries/render/src/render/Args.h
+++ b/libraries/render/src/render/Args.h
@@ -63,12 +63,6 @@ namespace render {
public:
enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, MIRROR_RENDER_MODE, SECONDARY_CAMERA_RENDER_MODE };
enum DisplayMode { MONO, STEREO_MONITOR, STEREO_HMD };
- enum OutlineFlags {
- RENDER_OUTLINE_NONE = 0,
- RENDER_OUTLINE_WIREFRAMES = 1,
- RENDER_OUTLINE_MARKETPLACE_MODE = 2,
- RENDER_OUTLINE_SHADER = 4
- };
enum DebugFlags {
RENDER_DEBUG_NONE = 0,
RENDER_DEBUG_HULLS = 1
@@ -115,7 +109,6 @@ namespace render {
int _boundaryLevelAdjust { 0 };
RenderMode _renderMode { DEFAULT_RENDER_MODE };
DisplayMode _displayMode { MONO };
- OutlineFlags _outlineFlags{ RENDER_OUTLINE_NONE };
DebugFlags _debugFlags { RENDER_DEBUG_NONE };
gpu::Batch* _batch = nullptr;
diff --git a/interface/src/ui/ImageProvider.cpp b/libraries/ui/src/ui/ImageProvider.cpp
similarity index 56%
rename from interface/src/ui/ImageProvider.cpp
rename to libraries/ui/src/ui/ImageProvider.cpp
index 4925cdf1e9..c74ed0cb44 100644
--- a/interface/src/ui/ImageProvider.cpp
+++ b/libraries/ui/src/ui/ImageProvider.cpp
@@ -10,13 +10,39 @@
//
#include "ImageProvider.h"
-#include
+
+#include
+#include
const QString ImageProvider::PROVIDER_NAME = "security";
+QReadWriteLock ImageProvider::_rwLock;
+QPixmap* ImageProvider::_securityImage = nullptr;
+
+ImageProvider::~ImageProvider() {
+ QWriteLocker lock(&_rwLock);
+ if (_securityImage) {
+ delete _securityImage;
+ _securityImage = nullptr;
+ }
+}
+
+void ImageProvider::setSecurityImage(const QPixmap* pixmap) {
+ // no need to delete old one, that is managed by the wallet
+ QWriteLocker lock(&_rwLock);
+ if (_securityImage) {
+ delete _securityImage;
+ }
+ if (pixmap) {
+ _securityImage = new QPixmap(*pixmap);
+ } else {
+ _securityImage = nullptr;
+ }
+}
QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize& requestedSize) {
// adjust the internal pixmap to have the requested size
+ QReadLocker lock(&_rwLock);
if (id == "securityImage" && _securityImage) {
*size = _securityImage->size();
if (requestedSize.width() > 0 && requestedSize.height() > 0) {
diff --git a/interface/src/ui/ImageProvider.h b/libraries/ui/src/ui/ImageProvider.h
similarity index 79%
rename from interface/src/ui/ImageProvider.h
rename to libraries/ui/src/ui/ImageProvider.h
index c0b620585a..0093b60655 100644
--- a/interface/src/ui/ImageProvider.h
+++ b/libraries/ui/src/ui/ImageProvider.h
@@ -13,19 +13,20 @@
#define hifi_ImageProvider_h
#include
+#include
class ImageProvider: public QQuickImageProvider {
public:
static const QString PROVIDER_NAME;
ImageProvider() : QQuickImageProvider(QQuickImageProvider::Pixmap) {}
-
+ virtual ~ImageProvider();
QPixmap requestPixmap(const QString& id, QSize* size, const QSize& requestedSize) override;
- void setSecurityImage(QPixmap* pixmap) { _securityImage = pixmap; }
-
+ void setSecurityImage(const QPixmap* pixmap);
protected:
- QPixmap* _securityImage { nullptr };
+ static QReadWriteLock _rwLock;
+ static QPixmap* _securityImage;
};
diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
index be9a15b416..84466f41b0 100644
--- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp
+++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
@@ -6,6 +6,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "OffscreenQmlSurface.h"
+#include "ImageProvider.h"
// Has to come before Qt GL includes
#include
@@ -184,7 +185,7 @@ private:
GLuint texture = textureAndFence.first;
uvec2 size = _textureSizes[texture];
auto sizeKey = uvec2ToUint64(size);
- // Textures can be returned after all surfaces of the given size have been destroyed,
+ // Textures can be returned after all surfaces of the given size have been destroyed,
// in which case we just destroy the texture
if (!_textures.count(sizeKey)) {
destroy(textureAndFence);
@@ -305,6 +306,9 @@ static size_t globalEngineRefCount{ 0 };
#endif
void initializeQmlEngine(QQmlEngine* engine, QQuickWindow* window) {
+ // register the pixmap image provider (used only for security image, for now)
+ engine->addImageProvider(ImageProvider::PROVIDER_NAME, new ImageProvider());
+
engine->setNetworkAccessManagerFactory(new QmlNetworkAccessManagerFactory);
auto importList = engine->importPathList();
importList.insert(importList.begin(), PathUtils::resourcesPath());
@@ -464,8 +468,8 @@ std::function OffscreenQmlSurface::getDiscardLambda() {
}
bool OffscreenQmlSurface::allowNewFrame(uint8_t fps) {
- // If we already have a pending texture, don't render another one
- // i.e. don't render faster than the consumer context, since it wastes
+ // If we already have a pending texture, don't render another one
+ // i.e. don't render faster than the consumer context, since it wastes
// GPU cycles on producing output that will never be seen
if (0 != _latestTextureAndFence.first) {
return false;
@@ -526,6 +530,7 @@ void OffscreenQmlSurface::create() {
// Create a QML engine.
auto qmlEngine = acquireEngine(_quickWindow);
+
_qmlContext = new QQmlContext(qmlEngine->rootContext());
_qmlContext->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow()));
diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js
index 7f24e7f634..a7b7b50379 100644
--- a/scripts/system/commerce/wallet.js
+++ b/scripts/system/commerce/wallet.js
@@ -53,14 +53,27 @@
// Description:
// -Called when a message is received from SpectatorCamera.qml. The "message" argument is what is sent from the QML
// in the format "{method, params}", like json-rpc. See also sendToQml().
+ var isHmdPreviewDisabled = true;
function fromQml(message) {
switch (message.method) {
case 'walletSetup_cancelClicked':
+ case 'needsLogIn_cancelClicked':
tablet.gotoHomeScreen();
break;
- case 'walletSetup_loginClicked':
+ case 'needsLogIn_loginClicked':
openLoginWindow();
break;
+ case 'disableHmdPreview':
+ isHmdPreviewDisabled = Menu.isOptionChecked("Disable Preview");
+ Menu.setIsOptionChecked("Disable Preview", true);
+ break;
+ case 'maybeEnableHmdPreview':
+ Menu.setIsOptionChecked("Disable Preview", isHmdPreviewDisabled);
+ break;
+ case 'walletReset':
+ onButtonClicked();
+ onButtonClicked();
+ break;
default:
print('Unrecognized message from QML:', JSON.stringify(message));
}
diff --git a/scripts/system/edit.js b/scripts/system/edit.js
index 7ee6c64858..8b61226235 100644
--- a/scripts/system/edit.js
+++ b/scripts/system/edit.js
@@ -405,9 +405,11 @@ var toolBar = (function () {
}
});
- var createButtonIconRsrc = ((Entities.canRez() || Entities.canRezTmp()) ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON);
+ var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp());
+ var createButtonIconRsrc = (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON);
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
activeButton = tablet.addButton({
+ captionColorOverride: hasRezPermissions ? "" : "#888888",
icon: createButtonIconRsrc,
activeIcon: "icons/tablet-icons/edit-a.svg",
text: "CREATE",
@@ -789,6 +791,7 @@ function handleDomainChange() {
var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp());
createButton.editProperties({
icon: (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON),
+ captionColorOverride: (hasRezPermissions ? "" : "#888888"),
});
}
diff --git a/scripts/system/html/js/marketplacesInject.js b/scripts/system/html/js/marketplacesInject.js
index 62a4dcf369..28d116d3ec 100644
--- a/scripts/system/html/js/marketplacesInject.js
+++ b/scripts/system/html/js/marketplacesInject.js
@@ -127,9 +127,15 @@
$(this).attr('data-href', $(this).attr('href'));
$(this).attr('href', '#');
cost = $(this).closest('.col-xs-3').find('.item-cost').text();
+
+ $(this).closest('.col-xs-3').prev().attr("class", 'col-xs-6');
+ $(this).closest('.col-xs-3').attr("class", 'col-xs-6');
if (parseInt(cost) > 0) {
- $(this).find('.price').text("BUY");
+ var priceElement = $(this).find('.price')
+ priceElement.css({ "width": "auto", "padding": "3px 5px", "height": "26px" });
+ priceElement.text(parseFloat(cost / 100).toFixed(2) + ' HFC');
+ priceElement.css({ "min-width": priceElement.width() + 10 });
}
});
@@ -160,23 +166,23 @@
// Try this here in case it works (it will if the user just pressed the "back" button,
// since that doesn't trigger another AJAX request.
- injectBuyButtonOnMainPage;
+ injectBuyButtonOnMainPage();
addPurchasesButton();
}
}
function injectHiFiItemPageCode() {
if (confirmAllPurchases) {
- var href = $('#side-info').find('.btn').attr('href');
- $('#side-info').find('.btn').attr('href', '#');
+ var href = $('#side-info').find('.btn').first().attr('href');
+ $('#side-info').find('.btn').first().attr('href', '#');
var cost = $('.item-cost').text();
- if (parseInt(cost) > 0) {
- $('#side-info').find('.btn').html('Buy Item ');
+ if (parseInt(cost) > 0 && $('#side-info').find('#buyItemButton').size() === 0) {
+ $('#side-info').find('.btn').first().html('Own Item: ' + (parseFloat(cost / 100).toFixed(2)) + ' HFC');
}
- $('#side-info').find('.btn').on('click', function () {
+ $('#side-info').find('.btn').first().on('click', function () {
buyButtonClicked(window.location.pathname.split("/")[3],
$('#top-center').find('h1').text(),
$('#creator').find('.value').text(),
diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js
index 7b479cdcad..7d1aaee157 100644
--- a/scripts/system/marketplaces/marketplaces.js
+++ b/scripts/system/marketplaces/marketplaces.js
@@ -228,6 +228,15 @@
case 'purchases_backClicked':
tablet.gotoWebScreen(message.referrerURL, MARKETPLACES_INJECT_SCRIPT_URL);
break;
+ case 'purchases_goToMarketplaceClicked':
+ tablet.gotoWebScreen(MARKETPLACE_URL_INITIAL, MARKETPLACES_INJECT_SCRIPT_URL);
+ break;
+ case 'needsLogIn_cancelClicked':
+ tablet.gotoWebScreen(MARKETPLACE_URL_INITIAL, MARKETPLACES_INJECT_SCRIPT_URL);
+ break;
+ case 'needsLogIn_loginClicked':
+ openLoginWindow();
+ break;
default:
print('Unrecognized message from Checkout.qml or Purchases.qml: ' + JSON.stringify(message));
}