mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 07:58:59 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into black
This commit is contained in:
commit
fd2d246f05
32 changed files with 751 additions and 613 deletions
|
@ -35,7 +35,7 @@ void ScriptableAvatar::startAnimation(const QString& url, float fps, float prior
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_animation = DependencyManager::get<AnimationCache>()->getAnimation(url);
|
_animation = DependencyManager::get<AnimationCache>()->getAnimation(url);
|
||||||
_animationDetails = AnimationDetails("", QUrl(url), fps, 0, loop, hold, false, firstFrame, lastFrame, true, firstFrame);
|
_animationDetails = AnimationDetails("", QUrl(url), fps, 0, loop, hold, false, firstFrame, lastFrame, true, firstFrame, false);
|
||||||
_maskedJoints = maskedJoints;
|
_maskedJoints = maskedJoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 643 B |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 909 B |
|
@ -29,7 +29,6 @@ Rectangle {
|
||||||
property bool purchasesReceived: false;
|
property bool purchasesReceived: false;
|
||||||
property bool balanceReceived: false;
|
property bool balanceReceived: false;
|
||||||
property bool securityImageResultReceived: false;
|
property bool securityImageResultReceived: false;
|
||||||
property bool keyFilePathIfExistsResultReceived: false;
|
|
||||||
property string itemId: "";
|
property string itemId: "";
|
||||||
property string itemHref: "";
|
property string itemHref: "";
|
||||||
property double balanceAfterPurchase: 0;
|
property double balanceAfterPurchase: 0;
|
||||||
|
@ -46,10 +45,15 @@ Rectangle {
|
||||||
root.activeView = "needsLogIn";
|
root.activeView = "needsLogIn";
|
||||||
} else if (isLoggedIn) {
|
} else if (isLoggedIn) {
|
||||||
root.activeView = "initialize";
|
root.activeView = "initialize";
|
||||||
commerce.getSecurityImage();
|
|
||||||
commerce.getKeyFilePathIfExists();
|
commerce.getKeyFilePathIfExists();
|
||||||
commerce.balance();
|
}
|
||||||
commerce.inventory();
|
}
|
||||||
|
|
||||||
|
onKeyFilePathIfExistsResult: {
|
||||||
|
if (path === "" && root.activeView !== "notSetUp") {
|
||||||
|
root.activeView = "notSetUp";
|
||||||
|
} else if (path !== "" && root.activeView === "initialize") {
|
||||||
|
commerce.getSecurityImage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,8 +61,8 @@ Rectangle {
|
||||||
securityImageResultReceived = true;
|
securityImageResultReceived = true;
|
||||||
if (!exists && root.activeView !== "notSetUp") { // "If security image is not set up"
|
if (!exists && root.activeView !== "notSetUp") { // "If security image is not set up"
|
||||||
root.activeView = "notSetUp";
|
root.activeView = "notSetUp";
|
||||||
} else if (root.securityImageResultReceived && exists && root.keyFilePathIfExistsResultReceived && root.activeView === "initialize") {
|
} else if (exists && root.activeView === "initialize") {
|
||||||
root.activeView = "checkoutMain";
|
commerce.getWalletAuthenticatedStatus();
|
||||||
} else if (exists) {
|
} else if (exists) {
|
||||||
// just set the source again (to be sure the change was noticed)
|
// just set the source again (to be sure the change was noticed)
|
||||||
securityImage.source = "";
|
securityImage.source = "";
|
||||||
|
@ -66,12 +70,17 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyFilePathIfExistsResult: {
|
onWalletAuthenticatedStatusResult: {
|
||||||
keyFilePathIfExistsResultReceived = true;
|
if (!isAuthenticated && !passphraseModal.visible) {
|
||||||
if (path === "" && root.activeView !== "notSetUp") {
|
passphraseModal.visible = true;
|
||||||
root.activeView = "notSetUp";
|
} else if (isAuthenticated) {
|
||||||
} else if (root.securityImageResultReceived && root.keyFilePathIfExistsResultReceived && path !== "" && root.activeView === "initialize") {
|
|
||||||
root.activeView = "checkoutMain";
|
root.activeView = "checkoutMain";
|
||||||
|
if (!balanceReceived) {
|
||||||
|
commerce.balance();
|
||||||
|
}
|
||||||
|
if (!purchasesReceived) {
|
||||||
|
commerce.inventory();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,8 +98,8 @@ Rectangle {
|
||||||
console.log("Failed to get balance", result.data.message);
|
console.log("Failed to get balance", result.data.message);
|
||||||
} else {
|
} else {
|
||||||
root.balanceReceived = true;
|
root.balanceReceived = true;
|
||||||
hfcBalanceText.text = (parseFloat(result.data.balance/100).toFixed(2)) + " HFC";
|
hfcBalanceText.text = result.data.balance + " HFC";
|
||||||
balanceAfterPurchase = parseFloat(result.data.balance/100) - root.itemPriceFull/100;
|
balanceAfterPurchase = result.data.balance - root.itemPriceFull;
|
||||||
root.setBuyText();
|
root.setBuyText();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,10 +119,6 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HifiWallet.SecurityImageModel {
|
|
||||||
id: securityImageModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// TITLE BAR START
|
// TITLE BAR START
|
||||||
//
|
//
|
||||||
|
@ -195,7 +200,6 @@ Rectangle {
|
||||||
securityImageResultReceived = false;
|
securityImageResultReceived = false;
|
||||||
purchasesReceived = false;
|
purchasesReceived = false;
|
||||||
balanceReceived = false;
|
balanceReceived = false;
|
||||||
keyFilePathIfExistsResultReceived = false;
|
|
||||||
commerce.getLoginStatus();
|
commerce.getLoginStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,7 +225,20 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HifiWallet.PassphraseModal {
|
||||||
|
id: passphraseModal;
|
||||||
|
visible: false;
|
||||||
|
anchors.top: titleBarContainer.bottom;
|
||||||
|
anchors.bottom: parent.bottom;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
onSendSignalToParent: {
|
||||||
|
sendToScript(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// "WALLET NOT SET UP" START
|
// "WALLET NOT SET UP" START
|
||||||
|
@ -553,7 +570,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
RalewayRegular {
|
RalewayRegular {
|
||||||
id: balanceAfterPurchaseText;
|
id: balanceAfterPurchaseText;
|
||||||
text: balanceAfterPurchase.toFixed(2) + " HFC";
|
text: balanceAfterPurchase + " HFC";
|
||||||
// Text size
|
// Text size
|
||||||
size: balanceAfterPurchaseTextLabel.size;
|
size: balanceAfterPurchaseTextLabel.size;
|
||||||
// Anchors
|
// Anchors
|
||||||
|
@ -648,7 +665,7 @@ Rectangle {
|
||||||
sendToScript({method: 'checkout_goToPurchases'});
|
sendToScript({method: 'checkout_goToPurchases'});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RalewayRegular {
|
RalewayRegular {
|
||||||
id: buyText;
|
id: buyText;
|
||||||
// Text size
|
// Text size
|
||||||
|
@ -687,7 +704,7 @@ Rectangle {
|
||||||
anchors.bottom: root.bottom;
|
anchors.bottom: root.bottom;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
|
|
||||||
RalewayRegular {
|
RalewayRegular {
|
||||||
id: completeText;
|
id: completeText;
|
||||||
text: "<b>Purchase Complete!</b><br><br>You bought <b>" + (itemNameText.text) + "</b> by <b>" + (itemAuthorText.text) + "</b>";
|
text: "<b>Purchase Complete!</b><br><br>You bought <b>" + (itemNameText.text) + "</b> by <b>" + (itemAuthorText.text) + "</b>";
|
||||||
|
@ -706,7 +723,7 @@ Rectangle {
|
||||||
horizontalAlignment: Text.AlignHCenter;
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
verticalAlignment: Text.AlignVCenter;
|
verticalAlignment: Text.AlignVCenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: checkoutSuccessActionButtonsContainer;
|
id: checkoutSuccessActionButtonsContainer;
|
||||||
// Size
|
// Size
|
||||||
|
@ -756,7 +773,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: continueShoppingButtonContainer;
|
id: continueShoppingButtonContainer;
|
||||||
// Size
|
// Size
|
||||||
|
@ -799,7 +816,7 @@ Rectangle {
|
||||||
anchors.bottom: root.bottom;
|
anchors.bottom: root.bottom;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
|
|
||||||
RalewayRegular {
|
RalewayRegular {
|
||||||
id: failureHeaderText;
|
id: failureHeaderText;
|
||||||
text: "<b>Purchase Failed.</b><br>Your Purchases and HFC balance haven't changed.";
|
text: "<b>Purchase Failed.</b><br>Your Purchases and HFC balance haven't changed.";
|
||||||
|
@ -818,7 +835,7 @@ Rectangle {
|
||||||
horizontalAlignment: Text.AlignHCenter;
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
verticalAlignment: Text.AlignVCenter;
|
verticalAlignment: Text.AlignVCenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
RalewayRegular {
|
RalewayRegular {
|
||||||
id: failureErrorText;
|
id: failureErrorText;
|
||||||
// Text size
|
// Text size
|
||||||
|
@ -836,7 +853,7 @@ Rectangle {
|
||||||
horizontalAlignment: Text.AlignHCenter;
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
verticalAlignment: Text.AlignVCenter;
|
verticalAlignment: Text.AlignVCenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: backToMarketplaceButtonContainer;
|
id: backToMarketplaceButtonContainer;
|
||||||
// Size
|
// Size
|
||||||
|
@ -892,7 +909,7 @@ Rectangle {
|
||||||
itemNameText.text = message.params.itemName;
|
itemNameText.text = message.params.itemName;
|
||||||
itemAuthorText.text = message.params.itemAuthor;
|
itemAuthorText.text = message.params.itemAuthor;
|
||||||
root.itemPriceFull = message.params.itemPrice;
|
root.itemPriceFull = message.params.itemPrice;
|
||||||
itemPriceText.text = root.itemPriceFull === 0 ? "Free" : "<b>" + (parseFloat(root.itemPriceFull/100).toFixed(2)) + " HFC</b>";
|
itemPriceText.text = root.itemPriceFull === 0 ? "Free" : "<b>" + root.itemPriceFull + " HFC</b>";
|
||||||
itemHref = message.params.itemHref;
|
itemHref = message.params.itemHref;
|
||||||
if (itemHref.indexOf('.json') === -1) {
|
if (itemHref.indexOf('.json') === -1) {
|
||||||
root.itemIsJson = false;
|
root.itemIsJson = false;
|
||||||
|
|
|
@ -28,7 +28,6 @@ Rectangle {
|
||||||
property string activeView: "initialize";
|
property string activeView: "initialize";
|
||||||
property string referrerURL: "";
|
property string referrerURL: "";
|
||||||
property bool securityImageResultReceived: false;
|
property bool securityImageResultReceived: false;
|
||||||
property bool keyFilePathIfExistsResultReceived: false;
|
|
||||||
property bool purchasesReceived: false;
|
property bool purchasesReceived: false;
|
||||||
property bool punctuationMode: false;
|
property bool punctuationMode: false;
|
||||||
// Style
|
// Style
|
||||||
|
@ -41,9 +40,15 @@ Rectangle {
|
||||||
root.activeView = "needsLogIn";
|
root.activeView = "needsLogIn";
|
||||||
} else if (isLoggedIn) {
|
} else if (isLoggedIn) {
|
||||||
root.activeView = "initialize";
|
root.activeView = "initialize";
|
||||||
commerce.getSecurityImage();
|
|
||||||
commerce.getKeyFilePathIfExists();
|
commerce.getKeyFilePathIfExists();
|
||||||
commerce.inventory();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onKeyFilePathIfExistsResult: {
|
||||||
|
if (path === "" && root.activeView !== "notSetUp") {
|
||||||
|
root.activeView = "notSetUp";
|
||||||
|
} else if (path !== "" && root.activeView === "initialize") {
|
||||||
|
commerce.getSecurityImage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,8 +56,8 @@ Rectangle {
|
||||||
securityImageResultReceived = true;
|
securityImageResultReceived = true;
|
||||||
if (!exists && root.activeView !== "notSetUp") { // "If security image is not set up"
|
if (!exists && root.activeView !== "notSetUp") { // "If security image is not set up"
|
||||||
root.activeView = "notSetUp";
|
root.activeView = "notSetUp";
|
||||||
} else if (root.securityImageResultReceived && exists && root.keyFilePathIfExistsResultReceived && root.activeView === "initialize") {
|
} else if (exists && root.activeView === "initialize") {
|
||||||
root.activeView = "purchasesMain";
|
commerce.getWalletAuthenticatedStatus();
|
||||||
} else if (exists) {
|
} else if (exists) {
|
||||||
// just set the source again (to be sure the change was noticed)
|
// just set the source again (to be sure the change was noticed)
|
||||||
securityImage.source = "";
|
securityImage.source = "";
|
||||||
|
@ -60,12 +65,12 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyFilePathIfExistsResult: {
|
onWalletAuthenticatedStatusResult: {
|
||||||
keyFilePathIfExistsResultReceived = true;
|
if (!isAuthenticated && !passphraseModal.visible) {
|
||||||
if (path === "" && root.activeView !== "notSetUp") {
|
passphraseModal.visible = true;
|
||||||
root.activeView = "notSetUp";
|
} else if (isAuthenticated) {
|
||||||
} else if (root.securityImageResultReceived && root.keyFilePathIfExistsResultReceived && path !== "" && root.activeView === "initialize") {
|
|
||||||
root.activeView = "purchasesMain";
|
root.activeView = "purchasesMain";
|
||||||
|
commerce.inventory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +171,6 @@ Rectangle {
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
securityImageResultReceived = false;
|
securityImageResultReceived = false;
|
||||||
purchasesReceived = false;
|
purchasesReceived = false;
|
||||||
keyFilePathIfExistsResultReceived = false;
|
|
||||||
commerce.getLoginStatus();
|
commerce.getLoginStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,6 +195,21 @@ Rectangle {
|
||||||
commerce.getLoginStatus();
|
commerce.getLoginStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HifiWallet.PassphraseModal {
|
||||||
|
id: passphraseModal;
|
||||||
|
visible: false;
|
||||||
|
anchors.top: titleBarContainer.bottom;
|
||||||
|
anchors.bottom: parent.bottom;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
onSendSignalToParent: {
|
||||||
|
sendToScript(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// "WALLET NOT SET UP" START
|
// "WALLET NOT SET UP" START
|
||||||
|
|
|
@ -47,11 +47,26 @@ Item {
|
||||||
HifiControlsUit.Button {
|
HifiControlsUit.Button {
|
||||||
color: hifi.buttons.black;
|
color: hifi.buttons.black;
|
||||||
colorScheme: hifi.colorSchemes.dark;
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
anchors.bottom: helpText.bottom;
|
anchors.bottom: resetButton.top;
|
||||||
|
anchors.bottomMargin: 15;
|
||||||
anchors.horizontalCenter: parent.horizontalCenter;
|
anchors.horizontalCenter: parent.horizontalCenter;
|
||||||
height: 50;
|
height: 50;
|
||||||
width: 250;
|
width: 250;
|
||||||
text: "Testing: Reset Wallet!";
|
text: "DEBUG: Clear Cached Passphrase";
|
||||||
|
onClicked: {
|
||||||
|
commerce.setPassphrase("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: resetButton;
|
||||||
|
color: hifi.buttons.red;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.bottom: helpText.bottom;
|
||||||
|
anchors.bottomMargin: 15;
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter;
|
||||||
|
height: 50;
|
||||||
|
width: 250;
|
||||||
|
text: "DEBUG: Reset Wallet!";
|
||||||
onClicked: {
|
onClicked: {
|
||||||
commerce.reset();
|
commerce.reset();
|
||||||
sendSignalToWallet({method: 'walletReset'});
|
sendSignalToWallet({method: 'walletReset'});
|
||||||
|
|
304
interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml
Normal file
304
interface/resources/qml/hifi/commerce/wallet/PassphraseModal.qml
Normal file
|
@ -0,0 +1,304 @@
|
||||||
|
//
|
||||||
|
// PassphraseModal.qml
|
||||||
|
// qml/hifi/commerce/wallet
|
||||||
|
//
|
||||||
|
// PassphraseModal
|
||||||
|
//
|
||||||
|
// Created by Zach Fox on 2017-08-31
|
||||||
|
// 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;
|
||||||
|
z: 998;
|
||||||
|
property bool keyboardRaised: false;
|
||||||
|
|
||||||
|
Hifi.QmlCommerce {
|
||||||
|
id: commerce;
|
||||||
|
|
||||||
|
onSecurityImageResult: {
|
||||||
|
passphraseModalSecurityImage.source = "";
|
||||||
|
passphraseModalSecurityImage.source = "image://security/securityImage";
|
||||||
|
}
|
||||||
|
|
||||||
|
onWalletAuthenticatedStatusResult: {
|
||||||
|
submitPassphraseInputButton.enabled = true;
|
||||||
|
if (!isAuthenticated) {
|
||||||
|
errorText.text = "Authentication failed - please try again.";
|
||||||
|
} else {
|
||||||
|
root.visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This object is always used in a popup.
|
||||||
|
// This MouseArea is used to prevent a user from being
|
||||||
|
// able to click on a button/mouseArea underneath the popup.
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent;
|
||||||
|
propagateComposedEvents: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
sendSignalToParent({method: 'disableHmdPreview'});
|
||||||
|
} else {
|
||||||
|
sendSignalToParent({method: 'maybeEnableHmdPreview'});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Background rectangle
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent;
|
||||||
|
color: "black";
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
height: 250;
|
||||||
|
color: hifi.colors.baseGray;
|
||||||
|
|
||||||
|
RalewaySemiBold {
|
||||||
|
id: instructionsText;
|
||||||
|
text: "Enter Wallet Passphrase";
|
||||||
|
size: 16;
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.topMargin: 30;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.leftMargin: 16;
|
||||||
|
width: passphraseField.width;
|
||||||
|
height: paintedHeight;
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.faintGray;
|
||||||
|
// Alignment
|
||||||
|
horizontalAlignment: Text.AlignLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.TextField {
|
||||||
|
id: passphraseField;
|
||||||
|
anchors.top: instructionsText.bottom;
|
||||||
|
anchors.topMargin: 4;
|
||||||
|
anchors.left: instructionsText.left;
|
||||||
|
width: 280;
|
||||||
|
height: 50;
|
||||||
|
echoMode: TextInput.Password;
|
||||||
|
placeholderText: "passphrase";
|
||||||
|
|
||||||
|
onFocusChanged: {
|
||||||
|
root.keyboardRaised = focus;
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent;
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
parent.focus = true;
|
||||||
|
root.keyboardRaised = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onAccepted: {
|
||||||
|
submitPassphraseInputButton.enabled = false;
|
||||||
|
commerce.setPassphrase(passphraseField.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show passphrase text
|
||||||
|
HifiControlsUit.CheckBox {
|
||||||
|
id: showPassphrase;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.left: passphraseField.left;
|
||||||
|
anchors.top: passphraseField.bottom;
|
||||||
|
anchors.topMargin: 8;
|
||||||
|
height: 30;
|
||||||
|
text: "Show passphrase as plain text";
|
||||||
|
boxSize: 24;
|
||||||
|
onClicked: {
|
||||||
|
passphraseField.echoMode = checked ? TextInput.Normal : TextInput.Password;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Security Image
|
||||||
|
Item {
|
||||||
|
id: securityImageContainer;
|
||||||
|
// Anchors
|
||||||
|
anchors.top: instructionsText.top;
|
||||||
|
anchors.left: passphraseField.right;
|
||||||
|
anchors.leftMargin: 12;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
Image {
|
||||||
|
id: passphraseModalSecurityImage;
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter;
|
||||||
|
height: 75;
|
||||||
|
width: height;
|
||||||
|
fillMode: Image.PreserveAspectFit;
|
||||||
|
mipmap: true;
|
||||||
|
source: "image://security/securityImage";
|
||||||
|
cache: false;
|
||||||
|
onVisibleChanged: {
|
||||||
|
commerce.getSecurityImage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Image {
|
||||||
|
id: passphraseModalSecurityImageOverlay;
|
||||||
|
source: "images/lockOverlay.png";
|
||||||
|
width: passphraseModalSecurityImage.width * 0.45;
|
||||||
|
height: passphraseModalSecurityImage.height * 0.45;
|
||||||
|
anchors.bottom: passphraseModalSecurityImage.bottom;
|
||||||
|
anchors.right: passphraseModalSecurityImage.right;
|
||||||
|
mipmap: true;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
// "Security image" text below pic
|
||||||
|
RalewayRegular {
|
||||||
|
text: "security image";
|
||||||
|
// Text size
|
||||||
|
size: 12;
|
||||||
|
// Anchors
|
||||||
|
anchors.top: passphraseModalSecurityImage.bottom;
|
||||||
|
anchors.topMargin: 4;
|
||||||
|
anchors.left: securityImageContainer.left;
|
||||||
|
anchors.right: securityImageContainer.right;
|
||||||
|
height: paintedHeight;
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.faintGray;
|
||||||
|
// Alignment
|
||||||
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
|
verticalAlignment: Text.AlignVCenter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error text above buttons
|
||||||
|
RalewaySemiBold {
|
||||||
|
id: errorText;
|
||||||
|
text: "";
|
||||||
|
// Text size
|
||||||
|
size: 16;
|
||||||
|
// Anchors
|
||||||
|
anchors.bottom: passphrasePopupActionButtonsContainer.top;
|
||||||
|
anchors.bottomMargin: 4;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.leftMargin: 16;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
anchors.rightMargin: 16;
|
||||||
|
height: 30;
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.redHighlight;
|
||||||
|
// Alignment
|
||||||
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
|
verticalAlignment: Text.AlignVCenter;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// ACTION BUTTONS START
|
||||||
|
//
|
||||||
|
Item {
|
||||||
|
id: passphrasePopupActionButtonsContainer;
|
||||||
|
// Size
|
||||||
|
width: root.width;
|
||||||
|
height: 50;
|
||||||
|
// Anchors
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.bottom: parent.bottom;
|
||||||
|
anchors.bottomMargin: 10;
|
||||||
|
|
||||||
|
// "Cancel" button
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: cancelPassphraseInputButton;
|
||||||
|
color: hifi.buttons.black;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.top: parent.top;
|
||||||
|
height: 40;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.leftMargin: 20;
|
||||||
|
width: parent.width/2 - anchors.leftMargin*2;
|
||||||
|
text: "Cancel"
|
||||||
|
onClicked: {
|
||||||
|
sendSignalToParent({method: 'passphrasePopup_cancelClicked'});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Submit" button
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: submitPassphraseInputButton;
|
||||||
|
color: hifi.buttons.blue;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.top: parent.top;
|
||||||
|
height: 40;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
anchors.rightMargin: 20;
|
||||||
|
width: parent.width/2 - anchors.rightMargin*2;
|
||||||
|
text: "Submit"
|
||||||
|
onClicked: {
|
||||||
|
submitPassphraseInputButton.enabled = false;
|
||||||
|
commerce.setPassphrase(passphraseField.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signal sendSignalToParent(var msg);
|
||||||
|
}
|
|
@ -40,8 +40,8 @@ Item {
|
||||||
passphrasePageSecurityImage.source = "image://security/securityImage";
|
passphrasePageSecurityImage.source = "image://security/securityImage";
|
||||||
}
|
}
|
||||||
|
|
||||||
onPassphraseSetupStatusResult: {
|
onWalletAuthenticatedStatusResult: {
|
||||||
sendMessageToLightbox({method: 'statusResult', status: passphraseIsSetup});
|
sendMessageToLightbox({method: 'statusResult', status: isAuthenticated});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,10 +58,6 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SecurityImageModel {
|
|
||||||
id: gridModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
HifiControlsUit.TextField {
|
HifiControlsUit.TextField {
|
||||||
id: passphraseField;
|
id: passphraseField;
|
||||||
anchors.top: parent.top;
|
anchors.top: parent.top;
|
||||||
|
@ -199,7 +195,7 @@ Item {
|
||||||
// Text below TextFields
|
// Text below TextFields
|
||||||
RalewaySemiBold {
|
RalewaySemiBold {
|
||||||
id: passwordReqs;
|
id: passwordReqs;
|
||||||
text: "Passphrase must be at least 4 characters";
|
text: "Passphrase must be at least 3 characters";
|
||||||
// Text size
|
// Text size
|
||||||
size: 16;
|
size: 16;
|
||||||
// Anchors
|
// Anchors
|
||||||
|
@ -256,7 +252,7 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateAndSubmitPassphrase() {
|
function validateAndSubmitPassphrase() {
|
||||||
if (passphraseField.text.length < 4) {
|
if (passphraseField.text.length < 3) {
|
||||||
setErrorText("Passphrase too short.");
|
setErrorText("Passphrase too short.");
|
||||||
return false;
|
return false;
|
||||||
} else if (passphraseField.text !== passphraseFieldAgain.text) {
|
} else if (passphraseField.text !== passphraseFieldAgain.text) {
|
||||||
|
|
|
@ -26,8 +26,6 @@ Rectangle {
|
||||||
id: root;
|
id: root;
|
||||||
|
|
||||||
property string activeView: "initialize";
|
property string activeView: "initialize";
|
||||||
property bool securityImageResultReceived: false;
|
|
||||||
property bool keyFilePathIfExistsResultReceived: false;
|
|
||||||
property bool keyboardRaised: false;
|
property bool keyboardRaised: false;
|
||||||
|
|
||||||
// Style
|
// Style
|
||||||
|
@ -40,25 +38,30 @@ Rectangle {
|
||||||
root.activeView = "needsLogIn";
|
root.activeView = "needsLogIn";
|
||||||
} else if (isLoggedIn) {
|
} else if (isLoggedIn) {
|
||||||
root.activeView = "initialize";
|
root.activeView = "initialize";
|
||||||
commerce.getSecurityImage();
|
|
||||||
commerce.getKeyFilePathIfExists();
|
commerce.getKeyFilePathIfExists();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onSecurityImageResult: {
|
onKeyFilePathIfExistsResult: {
|
||||||
securityImageResultReceived = true;
|
if (path === "" && root.activeView !== "notSetUp") {
|
||||||
if (!exists && root.activeView !== "notSetUp") { // "If security image is not set up"
|
|
||||||
root.activeView = "notSetUp";
|
root.activeView = "notSetUp";
|
||||||
} else if (root.securityImageResultReceived && exists && root.keyFilePathIfExistsResultReceived && root.activeView === "initialize") {
|
} else if (path !== "" && root.activeView === "initialize") {
|
||||||
root.activeView = "walletHome";
|
commerce.getSecurityImage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyFilePathIfExistsResult: {
|
onSecurityImageResult: {
|
||||||
keyFilePathIfExistsResultReceived = true;
|
if (!exists && root.activeView !== "notSetUp") { // "If security image is not set up"
|
||||||
if (path === "" && root.activeView !== "notSetUp") {
|
|
||||||
root.activeView = "notSetUp";
|
root.activeView = "notSetUp";
|
||||||
} else if (root.securityImageResultReceived && root.keyFilePathIfExistsResultReceived && path !== "" && root.activeView === "initialize") {
|
} else if (exists && root.activeView === "initialize") {
|
||||||
|
commerce.getWalletAuthenticatedStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onWalletAuthenticatedStatusResult: {
|
||||||
|
if (!isAuthenticated && !passphraseModal.visible) {
|
||||||
|
passphraseModal.visible = true;
|
||||||
|
} else if (isAuthenticated) {
|
||||||
root.activeView = "walletHome";
|
root.activeView = "walletHome";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +92,8 @@ Rectangle {
|
||||||
if (msg.method === 'walletSetup_cancelClicked') {
|
if (msg.method === 'walletSetup_cancelClicked') {
|
||||||
walletSetupLightbox.visible = false;
|
walletSetupLightbox.visible = false;
|
||||||
} else if (msg.method === 'walletSetup_finished') {
|
} else if (msg.method === 'walletSetup_finished') {
|
||||||
root.activeView = "walletHome";
|
root.activeView = "initialize";
|
||||||
|
commerce.getLoginStatus();
|
||||||
} else if (msg.method === 'walletSetup_raiseKeyboard') {
|
} else if (msg.method === 'walletSetup_raiseKeyboard') {
|
||||||
root.keyboardRaised = true;
|
root.keyboardRaised = true;
|
||||||
} else if (msg.method === 'walletSetup_lowerKeyboard') {
|
} else if (msg.method === 'walletSetup_lowerKeyboard') {
|
||||||
|
@ -218,6 +222,21 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PassphraseModal {
|
||||||
|
id: passphraseModal;
|
||||||
|
visible: false;
|
||||||
|
anchors.top: titleBarContainer.bottom;
|
||||||
|
anchors.bottom: parent.bottom;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
onSendSignalToParent: {
|
||||||
|
sendToScript(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NotSetUp {
|
NotSetUp {
|
||||||
id: notSetUp;
|
id: notSetUp;
|
||||||
visible: root.activeView === "notSetUp";
|
visible: root.activeView === "notSetUp";
|
||||||
|
|
|
@ -38,7 +38,7 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
onBalanceResult : {
|
onBalanceResult : {
|
||||||
balanceText.text = parseFloat(result.data.balance/100).toFixed(2);
|
balanceText.text = result.data.balance;
|
||||||
}
|
}
|
||||||
|
|
||||||
onHistoryResult : {
|
onHistoryResult : {
|
||||||
|
@ -88,13 +88,14 @@ Item {
|
||||||
height: 60;
|
height: 60;
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: hfcBalanceField;
|
id: hfcBalanceField;
|
||||||
|
color: hifi.colors.darkGray;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.bottom: parent.bottom;
|
anchors.bottom: parent.bottom;
|
||||||
height: parent.height - 15;
|
height: parent.height - 15;
|
||||||
|
|
||||||
// "HFC" balance label
|
// "HFC" balance label
|
||||||
RalewayRegular {
|
FiraSansRegular {
|
||||||
id: balanceLabel;
|
id: balanceLabel;
|
||||||
text: "HFC";
|
text: "HFC";
|
||||||
// Text size
|
// Text size
|
||||||
|
@ -106,7 +107,7 @@ Item {
|
||||||
anchors.rightMargin: 4;
|
anchors.rightMargin: 4;
|
||||||
width: paintedWidth;
|
width: paintedWidth;
|
||||||
// Style
|
// Style
|
||||||
color: hifi.colors.darkGray;
|
color: hifi.colors.lightGrayText;
|
||||||
// Alignment
|
// Alignment
|
||||||
horizontalAlignment: Text.AlignRight;
|
horizontalAlignment: Text.AlignRight;
|
||||||
verticalAlignment: Text.AlignVCenter;
|
verticalAlignment: Text.AlignVCenter;
|
||||||
|
@ -121,7 +122,7 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Balance Text
|
// Balance Text
|
||||||
FiraSansRegular {
|
FiraSansSemiBold {
|
||||||
id: balanceText;
|
id: balanceText;
|
||||||
text: "--";
|
text: "--";
|
||||||
// Text size
|
// Text size
|
||||||
|
@ -133,7 +134,7 @@ Item {
|
||||||
anchors.right: balanceLabel.left;
|
anchors.right: balanceLabel.left;
|
||||||
anchors.rightMargin: 4;
|
anchors.rightMargin: 4;
|
||||||
// Style
|
// Style
|
||||||
color: hifi.colors.darkGray;
|
color: hifi.colors.lightGrayText;
|
||||||
// Alignment
|
// Alignment
|
||||||
horizontalAlignment: Text.AlignRight;
|
horizontalAlignment: Text.AlignRight;
|
||||||
verticalAlignment: Text.AlignVCenter;
|
verticalAlignment: Text.AlignVCenter;
|
||||||
|
@ -258,7 +259,7 @@ Item {
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
width: parent.width;
|
width: parent.width;
|
||||||
height: transactionText.height + 30;
|
height: transactionText.height + 30;
|
||||||
RalewayRegular {
|
FiraSansRegular {
|
||||||
id: transactionText;
|
id: transactionText;
|
||||||
text: model.text;
|
text: model.text;
|
||||||
// Style
|
// Style
|
||||||
|
@ -272,7 +273,7 @@ Item {
|
||||||
horizontalAlignment: Text.AlignLeft;
|
horizontalAlignment: Text.AlignLeft;
|
||||||
verticalAlignment: Text.AlignVCenter;
|
verticalAlignment: Text.AlignVCenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
HifiControlsUit.Separator {
|
HifiControlsUit.Separator {
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
|
@ -288,7 +289,7 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should never be visible (since you immediately get 100 HFC)
|
// This should never be visible (since you immediately get 100 HFC)
|
||||||
RalewayRegular {
|
FiraSansRegular {
|
||||||
id: emptyTransationHistory;
|
id: emptyTransationHistory;
|
||||||
size: 24;
|
size: 24;
|
||||||
visible: !transactionHistory.visible && root.historyReceived;
|
visible: !transactionHistory.visible && root.historyReceived;
|
||||||
|
|
|
@ -39,9 +39,9 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onPassphraseSetupStatusResult: {
|
onWalletAuthenticatedStatusResult: {
|
||||||
securityImageContainer.visible = false;
|
securityImageContainer.visible = false;
|
||||||
if (passphraseIsSetup) {
|
if (isAuthenticated) {
|
||||||
privateKeysReadyContainer.visible = true;
|
privateKeysReadyContainer.visible = true;
|
||||||
} else {
|
} else {
|
||||||
choosePassphraseContainer.visible = true;
|
choosePassphraseContainer.visible = true;
|
||||||
|
@ -117,7 +117,7 @@ Rectangle {
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
anchors.rightMargin: 16;
|
anchors.rightMargin: 16;
|
||||||
height: 280;
|
height: 280;
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
onSendSignalToWallet: {
|
onSendSignalToWallet: {
|
||||||
sendSignalToWallet(msg);
|
sendSignalToWallet(msg);
|
||||||
|
@ -210,7 +210,7 @@ Rectangle {
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
commerce.getPassphraseSetupStatus();
|
commerce.getWalletAuthenticatedStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
|
#include <QTimeZone>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include "AccountManager.h"
|
#include "AccountManager.h"
|
||||||
#include "Wallet.h"
|
#include "Wallet.h"
|
||||||
|
@ -45,7 +46,6 @@ Handler(buy)
|
||||||
Handler(receiveAt)
|
Handler(receiveAt)
|
||||||
Handler(balance)
|
Handler(balance)
|
||||||
Handler(inventory)
|
Handler(inventory)
|
||||||
Handler(history)
|
|
||||||
|
|
||||||
void Ledger::send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, QJsonObject request) {
|
void Ledger::send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, QJsonObject request) {
|
||||||
auto accountManager = DependencyManager::get<AccountManager>();
|
auto accountManager = DependencyManager::get<AccountManager>();
|
||||||
|
@ -108,6 +108,64 @@ void Ledger::inventory(const QStringList& keys) {
|
||||||
keysQuery("inventory", "inventorySuccess", "inventoryFailure");
|
keysQuery("inventory", "inventorySuccess", "inventoryFailure");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString nameFromKey(const QString& key, const QStringList& publicKeys) {
|
||||||
|
if (key.isNull() || key.isEmpty()) {
|
||||||
|
return "<b>Marketplace</b>";
|
||||||
|
}
|
||||||
|
if (publicKeys.contains(key)) {
|
||||||
|
return "You";
|
||||||
|
}
|
||||||
|
return "<b>Someone</b>";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ledger::historySuccess(QNetworkReply& reply) {
|
||||||
|
// here we send a historyResult with some extra stuff in it
|
||||||
|
// Namely, the styled text we'd like to show. The issue is the
|
||||||
|
// QML cannot do that easily since it doesn't know what the wallet
|
||||||
|
// public key(s) are. Let's keep it that way
|
||||||
|
QByteArray response = reply.readAll();
|
||||||
|
QJsonObject data = QJsonDocument::fromJson(response).object();
|
||||||
|
|
||||||
|
// we will need the array of public keys from the wallet
|
||||||
|
auto wallet = DependencyManager::get<Wallet>();
|
||||||
|
auto keys = wallet->listPublicKeys();
|
||||||
|
|
||||||
|
// now we need to loop through the transactions and add fancy text...
|
||||||
|
auto historyArray = data.find("data").value().toObject().find("history").value().toArray();
|
||||||
|
QJsonArray newHistoryArray;
|
||||||
|
|
||||||
|
// TODO: do this with 0 copies if possible
|
||||||
|
for(auto it = historyArray.begin(); it != historyArray.end(); it++) {
|
||||||
|
auto valueObject = (*it).toObject();
|
||||||
|
QString from = nameFromKey(valueObject["sender_key"].toString(), keys);
|
||||||
|
QString to = nameFromKey(valueObject["recipient_key"].toString(), keys);
|
||||||
|
// turns out on my machine, toLocalTime convert to some weird timezone, yet the
|
||||||
|
// systemTimeZone is correct. To avoid a strange bug with other's systems too, lets
|
||||||
|
// be explicit
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
QDateTime createdAt = QDateTime::fromTime_t(valueObject["created_at"].toInt(), Qt::UTC);
|
||||||
|
#else
|
||||||
|
QDateTime createdAt = QDateTime::fromSecsSinceEpoch(valueObject["created_at"].toInt(), Qt::UTC);
|
||||||
|
#endif
|
||||||
|
QDateTime localCreatedAt = createdAt.toTimeZone(QTimeZone::systemTimeZone());
|
||||||
|
valueObject["text"] = QString("%1 sent %2 <b>%3 %4</b> on %5 with message \"%6\"").
|
||||||
|
arg(from, to, QString::number(valueObject["quantity"].toInt()), valueObject["asset_title"].toString(), localCreatedAt.toString(Qt::SystemLocaleShortDate), valueObject["message"].toString());
|
||||||
|
newHistoryArray.push_back(valueObject);
|
||||||
|
}
|
||||||
|
// now copy the rest of the json -- this is inefficient
|
||||||
|
// TODO: try to do this without making copies
|
||||||
|
QJsonObject newData;
|
||||||
|
newData["status"] = "success";
|
||||||
|
QJsonObject newDataData;
|
||||||
|
newDataData["history"] = newHistoryArray;
|
||||||
|
newData["data"] = newDataData;
|
||||||
|
emit historyResult(newData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ledger::historyFailure(QNetworkReply& reply) {
|
||||||
|
failResponse("history", reply);
|
||||||
|
}
|
||||||
|
|
||||||
void Ledger::history(const QStringList& keys) {
|
void Ledger::history(const QStringList& keys) {
|
||||||
keysQuery("history", "historySuccess", "historyFailure");
|
keysQuery("history", "historySuccess", "historyFailure");
|
||||||
}
|
}
|
||||||
|
@ -117,4 +175,4 @@ void Ledger::resetSuccess(QNetworkReply& reply) { apiResponse("reset", reply); }
|
||||||
void Ledger::resetFailure(QNetworkReply& reply) { failResponse("reset", reply); }
|
void Ledger::resetFailure(QNetworkReply& reply) { failResponse("reset", reply); }
|
||||||
void Ledger::reset() {
|
void Ledger::reset() {
|
||||||
send("reset_user_hfc_account", "resetSuccess", "resetFailure", QNetworkAccessManager::PutOperation, QJsonObject());
|
send("reset_user_hfc_account", "resetSuccess", "resetFailure", QNetworkAccessManager::PutOperation, QJsonObject());
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,30 @@ QmlCommerce::QmlCommerce(QQuickItem* parent) : OffscreenQmlDialog(parent) {
|
||||||
connect(wallet.data(), &Wallet::keyFilePathIfExistsResult, this, &QmlCommerce::keyFilePathIfExistsResult);
|
connect(wallet.data(), &Wallet::keyFilePathIfExistsResult, this, &QmlCommerce::keyFilePathIfExistsResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QmlCommerce::getLoginStatus() {
|
||||||
|
emit loginStatusResult(DependencyManager::get<AccountManager>()->isLoggedIn());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlCommerce::getKeyFilePathIfExists() {
|
||||||
|
auto wallet = DependencyManager::get<Wallet>();
|
||||||
|
wallet->sendKeyFilePathIfExists();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlCommerce::getWalletAuthenticatedStatus() {
|
||||||
|
auto wallet = DependencyManager::get<Wallet>();
|
||||||
|
emit walletAuthenticatedStatusResult(wallet->walletIsAuthenticatedWithPassphrase());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlCommerce::getSecurityImage() {
|
||||||
|
auto wallet = DependencyManager::get<Wallet>();
|
||||||
|
wallet->getSecurityImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlCommerce::chooseSecurityImage(const QString& imageFile) {
|
||||||
|
auto wallet = DependencyManager::get<Wallet>();
|
||||||
|
wallet->chooseSecurityImage(imageFile);
|
||||||
|
}
|
||||||
|
|
||||||
void QmlCommerce::buy(const QString& assetId, int cost, const QString& buyerUsername) {
|
void QmlCommerce::buy(const QString& assetId, int cost, const QString& buyerUsername) {
|
||||||
auto ledger = DependencyManager::get<Ledger>();
|
auto ledger = DependencyManager::get<Ledger>();
|
||||||
auto wallet = DependencyManager::get<Wallet>();
|
auto wallet = DependencyManager::get<Wallet>();
|
||||||
|
@ -60,30 +84,14 @@ void QmlCommerce::history() {
|
||||||
ledger->history(wallet->listPublicKeys());
|
ledger->history(wallet->listPublicKeys());
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlCommerce::chooseSecurityImage(const QString& imageFile) {
|
|
||||||
auto wallet = DependencyManager::get<Wallet>();
|
|
||||||
wallet->chooseSecurityImage(imageFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlCommerce::getSecurityImage() {
|
|
||||||
auto wallet = DependencyManager::get<Wallet>();
|
|
||||||
wallet->getSecurityImage();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlCommerce::getLoginStatus() {
|
|
||||||
emit loginStatusResult(DependencyManager::get<AccountManager>()->isLoggedIn());
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlCommerce::setPassphrase(const QString& passphrase) {
|
void QmlCommerce::setPassphrase(const QString& passphrase) {
|
||||||
emit passphraseSetupStatusResult(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlCommerce::getPassphraseSetupStatus() {
|
|
||||||
emit passphraseSetupStatusResult(false);
|
|
||||||
}
|
|
||||||
void QmlCommerce::getKeyFilePathIfExists() {
|
|
||||||
auto wallet = DependencyManager::get<Wallet>();
|
auto wallet = DependencyManager::get<Wallet>();
|
||||||
wallet->sendKeyFilePathIfExists();
|
if (wallet->getPassphrase() && !wallet->getPassphrase()->isEmpty()) {
|
||||||
|
wallet->changePassphrase(passphrase);
|
||||||
|
} else {
|
||||||
|
wallet->setPassphrase(passphrase);
|
||||||
|
}
|
||||||
|
getWalletAuthenticatedStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlCommerce::reset() {
|
void QmlCommerce::reset() {
|
||||||
|
@ -91,4 +99,4 @@ void QmlCommerce::reset() {
|
||||||
auto wallet = DependencyManager::get<Wallet>();
|
auto wallet = DependencyManager::get<Wallet>();
|
||||||
ledger->reset();
|
ledger->reset();
|
||||||
wallet->reset();
|
wallet->reset();
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,28 +28,32 @@ public:
|
||||||
QmlCommerce(QQuickItem* parent = nullptr);
|
QmlCommerce(QQuickItem* parent = nullptr);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
void loginStatusResult(bool isLoggedIn);
|
||||||
|
void keyFilePathIfExistsResult(const QString& path);
|
||||||
|
void securityImageResult(bool exists);
|
||||||
|
void walletAuthenticatedStatusResult(bool isAuthenticated);
|
||||||
|
|
||||||
void buyResult(QJsonObject result);
|
void buyResult(QJsonObject result);
|
||||||
// Balance and Inventory are NOT properties, because QML can't change them (without risk of failure), and
|
// Balance and Inventory are NOT properties, because QML can't change them (without risk of failure), and
|
||||||
// because we can't scalably know of out-of-band changes (e.g., another machine interacting with the block chain).
|
// because we can't scalably know of out-of-band changes (e.g., another machine interacting with the block chain).
|
||||||
void balanceResult(QJsonObject result);
|
void balanceResult(QJsonObject result);
|
||||||
void inventoryResult(QJsonObject result);
|
void inventoryResult(QJsonObject result);
|
||||||
void securityImageResult(bool exists);
|
|
||||||
void loginStatusResult(bool isLoggedIn);
|
|
||||||
void passphraseSetupStatusResult(bool passphraseIsSetup);
|
|
||||||
void historyResult(QJsonObject result);
|
void historyResult(QJsonObject result);
|
||||||
void keyFilePathIfExistsResult(const QString& path);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Q_INVOKABLE void getLoginStatus();
|
||||||
|
Q_INVOKABLE void getKeyFilePathIfExists();
|
||||||
|
Q_INVOKABLE void getSecurityImage();
|
||||||
|
Q_INVOKABLE void getWalletAuthenticatedStatus();
|
||||||
|
|
||||||
|
Q_INVOKABLE void chooseSecurityImage(const QString& imageFile);
|
||||||
|
Q_INVOKABLE void setPassphrase(const QString& passphrase);
|
||||||
|
|
||||||
Q_INVOKABLE void buy(const QString& assetId, int cost, const QString& buyerUsername = "");
|
Q_INVOKABLE void buy(const QString& assetId, int cost, const QString& buyerUsername = "");
|
||||||
Q_INVOKABLE void balance();
|
Q_INVOKABLE void balance();
|
||||||
Q_INVOKABLE void inventory();
|
Q_INVOKABLE void inventory();
|
||||||
Q_INVOKABLE void history();
|
Q_INVOKABLE void history();
|
||||||
Q_INVOKABLE void chooseSecurityImage(const QString& imageFile);
|
|
||||||
Q_INVOKABLE void getSecurityImage();
|
|
||||||
Q_INVOKABLE void getLoginStatus();
|
|
||||||
Q_INVOKABLE void setPassphrase(const QString& passphrase);
|
|
||||||
Q_INVOKABLE void getPassphraseSetupStatus();
|
|
||||||
Q_INVOKABLE void getKeyFilePathIfExists();
|
|
||||||
Q_INVOKABLE void reset();
|
Q_INVOKABLE void reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -56,16 +56,72 @@ QString imageFilePath() {
|
||||||
int passwordCallback(char* password, int maxPasswordSize, int rwFlag, void* u) {
|
int passwordCallback(char* password, int maxPasswordSize, int rwFlag, void* u) {
|
||||||
// just return a hardcoded pwd for now
|
// just return a hardcoded pwd for now
|
||||||
auto passphrase = DependencyManager::get<Wallet>()->getPassphrase();
|
auto passphrase = DependencyManager::get<Wallet>()->getPassphrase();
|
||||||
if (passphrase) {
|
if (passphrase && !passphrase->isEmpty()) {
|
||||||
strcpy(password, passphrase->toLocal8Bit().constData());
|
strcpy(password, passphrase->toLocal8Bit().constData());
|
||||||
return static_cast<int>(passphrase->size());
|
return static_cast<int>(passphrase->size());
|
||||||
} else {
|
} else {
|
||||||
// ok gotta bring up modal dialog... But right now lets just
|
// this shouldn't happen - so lets log it to tell us we have
|
||||||
// just keep it empty
|
// a problem with the flow...
|
||||||
|
qCCritical(commerce) << "no cached passphrase while decrypting!";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RSA* readKeys(const char* filename) {
|
||||||
|
FILE* fp;
|
||||||
|
RSA* key = NULL;
|
||||||
|
if ((fp = fopen(filename, "rt"))) {
|
||||||
|
// file opened successfully
|
||||||
|
qCDebug(commerce) << "opened key file" << filename;
|
||||||
|
if ((key = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL))) {
|
||||||
|
// now read private key
|
||||||
|
|
||||||
|
qCDebug(commerce) << "read public key";
|
||||||
|
|
||||||
|
if ((key = PEM_read_RSAPrivateKey(fp, &key, passwordCallback, NULL))) {
|
||||||
|
qCDebug(commerce) << "read private key";
|
||||||
|
fclose(fp);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
qCDebug(commerce) << "failed to read private key";
|
||||||
|
} else {
|
||||||
|
qCDebug(commerce) << "failed to read public key";
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
} else {
|
||||||
|
qCDebug(commerce) << "failed to open key file" << filename;
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool writeKeys(const char* filename, RSA* keys) {
|
||||||
|
FILE* fp;
|
||||||
|
bool retval = false;
|
||||||
|
if ((fp = fopen(filename, "wt"))) {
|
||||||
|
if (!PEM_write_RSAPublicKey(fp, keys)) {
|
||||||
|
fclose(fp);
|
||||||
|
qCDebug(commerce) << "failed to write public key";
|
||||||
|
QFile(QString(filename)).remove();
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PEM_write_RSAPrivateKey(fp, keys, EVP_des_ede3_cbc(), NULL, 0, passwordCallback, NULL)) {
|
||||||
|
fclose(fp);
|
||||||
|
qCDebug(commerce) << "failed to write private key";
|
||||||
|
QFile(QString(filename)).remove();
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = true;
|
||||||
|
qCDebug(commerce) << "wrote keys successfully";
|
||||||
|
fclose(fp);
|
||||||
|
} else {
|
||||||
|
qCDebug(commerce) << "failed to open key file" << filename;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// BEGIN copied code - this will be removed/changed at some point soon
|
// BEGIN copied code - this will be removed/changed at some point soon
|
||||||
// copied (without emits for various signals) from libraries/networking/src/RSAKeypairGenerator.cpp.
|
// copied (without emits for various signals) from libraries/networking/src/RSAKeypairGenerator.cpp.
|
||||||
// We will have a different implementation in practice, but this gives us a start for now
|
// We will have a different implementation in practice, but this gives us a start for now
|
||||||
|
@ -124,25 +180,9 @@ QPair<QByteArray*, QByteArray*> generateRSAKeypair() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!writeKeys(keyFilePath().toStdString().c_str(), keyPair)) {
|
||||||
// now lets persist them to files
|
qCDebug(commerce) << "couldn't save keys!";
|
||||||
// FIXME: for now I'm appending to the file if it exists. As long as we always put
|
return retval;
|
||||||
// the keys in the same order, this works fine. TODO: verify this will skip over
|
|
||||||
// anything else (like an embedded image)
|
|
||||||
FILE* fp;
|
|
||||||
if ((fp = fopen(keyFilePath().toStdString().c_str(), "at"))) {
|
|
||||||
if (!PEM_write_RSAPublicKey(fp, keyPair)) {
|
|
||||||
fclose(fp);
|
|
||||||
qCDebug(commerce) << "failed to write public key";
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!PEM_write_RSAPrivateKey(fp, keyPair, EVP_des_ede3_cbc(), NULL, 0, passwordCallback, NULL)) {
|
|
||||||
fclose(fp);
|
|
||||||
qCDebug(commerce) << "failed to write private key";
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RSA_free(keyPair);
|
RSA_free(keyPair);
|
||||||
|
@ -201,9 +241,6 @@ RSA* readPrivateKey(const char* filename) {
|
||||||
// file opened successfully
|
// file opened successfully
|
||||||
qCDebug(commerce) << "opened key file" << filename;
|
qCDebug(commerce) << "opened key file" << filename;
|
||||||
if ((key = PEM_read_RSAPrivateKey(fp, &key, passwordCallback, NULL))) {
|
if ((key = PEM_read_RSAPrivateKey(fp, &key, passwordCallback, NULL))) {
|
||||||
// cleanup
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
qCDebug(commerce) << "parsed private key file successfully";
|
qCDebug(commerce) << "parsed private key file successfully";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -215,7 +252,6 @@ RSA* readPrivateKey(const char* filename) {
|
||||||
}
|
}
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char IVEC[16] = "IAmAnIVecYay123";
|
static const unsigned char IVEC[16] = "IAmAnIVecYay123";
|
||||||
|
|
||||||
void initializeAESKeys(unsigned char* ivec, unsigned char* ckey, const QByteArray& salt) {
|
void initializeAESKeys(unsigned char* ivec, unsigned char* ckey, const QByteArray& salt) {
|
||||||
|
@ -341,6 +377,24 @@ bool Wallet::decryptFile(const QString& inputFilePath, unsigned char** outputBuf
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Wallet::walletIsAuthenticatedWithPassphrase() {
|
||||||
|
// try to read existing keys if they exist...
|
||||||
|
|
||||||
|
// FIXME: initialize OpenSSL elsewhere soon
|
||||||
|
initialize();
|
||||||
|
|
||||||
|
auto publicKey = readPublicKey(keyFilePath().toStdString().c_str());
|
||||||
|
|
||||||
|
if (publicKey.size() > 0) {
|
||||||
|
if (auto key = readPrivateKey(keyFilePath().toStdString().c_str())) {
|
||||||
|
RSA_free(key);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Wallet::createIfNeeded() {
|
bool Wallet::createIfNeeded() {
|
||||||
if (_publicKeys.count() > 0) return false;
|
if (_publicKeys.count() > 0) return false;
|
||||||
|
|
||||||
|
@ -512,3 +566,30 @@ void Wallet::reset() {
|
||||||
keyFile.remove();
|
keyFile.remove();
|
||||||
imageFile.remove();
|
imageFile.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Wallet::changePassphrase(const QString& newPassphrase) {
|
||||||
|
qCDebug(commerce) << "changing passphrase";
|
||||||
|
RSA* keys = readKeys(keyFilePath().toStdString().c_str());
|
||||||
|
if (keys) {
|
||||||
|
// we read successfully, so now write to a new temp file
|
||||||
|
// save old passphrase just in case
|
||||||
|
// TODO: force re-enter?
|
||||||
|
QString oldPassphrase = *_passphrase;
|
||||||
|
setPassphrase(newPassphrase);
|
||||||
|
QString tempFileName = QString("%1.%2").arg(keyFilePath(), QString("temp"));
|
||||||
|
if (writeKeys(tempFileName.toStdString().c_str(), keys)) {
|
||||||
|
// ok, now move the temp file to the correct spot
|
||||||
|
QFile(QString(keyFilePath())).remove();
|
||||||
|
QFile(tempFileName).rename(QString(keyFilePath()));
|
||||||
|
qCDebug(commerce) << "passphrase changed successfully";
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
qCDebug(commerce) << "couldn't write keys";
|
||||||
|
QFile(tempFileName).remove();
|
||||||
|
setPassphrase(oldPassphrase);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qCDebug(commerce) << "couldn't read keys";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -39,18 +39,21 @@ public:
|
||||||
|
|
||||||
void setPassphrase(const QString& passphrase);
|
void setPassphrase(const QString& passphrase);
|
||||||
QString* getPassphrase() { return _passphrase; }
|
QString* getPassphrase() { return _passphrase; }
|
||||||
|
bool getPassphraseIsCached() { return !(_passphrase->isEmpty()); }
|
||||||
|
bool walletIsAuthenticatedWithPassphrase();
|
||||||
|
bool changePassphrase(const QString& newPassphrase);
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void securityImageResult(bool exists) ;
|
void securityImageResult(bool exists);
|
||||||
void keyFilePathIfExistsResult(const QString& path);
|
void keyFilePathIfExistsResult(const QString& path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QStringList _publicKeys{};
|
QStringList _publicKeys{};
|
||||||
QPixmap* _securityImage { nullptr };
|
QPixmap* _securityImage { nullptr };
|
||||||
QByteArray _salt {"iamsalt!"};
|
QByteArray _salt {"iamsalt!"};
|
||||||
QString* _passphrase { new QString("pwd") };
|
QString* _passphrase { new QString("") };
|
||||||
|
|
||||||
void updateImageProvider();
|
void updateImageProvider();
|
||||||
bool encryptFile(const QString& inputFilePath, const QString& outputFilePath);
|
bool encryptFile(const QString& inputFilePath, const QString& outputFilePath);
|
||||||
|
|
|
@ -910,6 +910,8 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
|
||||||
|
|
||||||
const QVector<FBXAnimationFrame>& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy
|
const QVector<FBXAnimationFrame>& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy
|
||||||
auto& fbxJoints = _animation->getGeometry().joints;
|
auto& fbxJoints = _animation->getGeometry().joints;
|
||||||
|
auto& originalFbxJoints = _model->getFBXGeometry().joints;
|
||||||
|
bool allowTranslation = entity->getAnimationAllowTranslation();
|
||||||
int frameCount = frames.size();
|
int frameCount = frames.size();
|
||||||
if (frameCount <= 0) {
|
if (frameCount <= 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -952,7 +954,9 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) {
|
||||||
int index = _jointMapping[j];
|
int index = _jointMapping[j];
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
glm::mat4 translationMat;
|
glm::mat4 translationMat;
|
||||||
if (index < translations.size()) {
|
if (!allowTranslation){
|
||||||
|
translationMat = glm::translate(originalFbxJoints[index].translation);
|
||||||
|
} else if (index < translations.size()) {
|
||||||
translationMat = glm::translate(translations[index]);
|
translationMat = glm::translate(translations[index]);
|
||||||
}
|
}
|
||||||
glm::mat4 rotationMat;
|
glm::mat4 rotationMat;
|
||||||
|
|
|
@ -33,6 +33,7 @@ bool operator==(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b
|
||||||
|
|
||||||
void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
|
void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_URL, Animation, animation, URL, url);
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_URL, Animation, animation, URL, url);
|
||||||
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_ALLOW_TRANSLATION, Animation, animation, AllowTranslation, allowTranslation);
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FPS, Animation, animation, FPS, fps);
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FPS, Animation, animation, FPS, fps);
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame);
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame);
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_PLAYING, Animation, animation, Running, running);
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_PLAYING, Animation, animation, Running, running);
|
||||||
|
@ -46,6 +47,7 @@ void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desire
|
||||||
void AnimationPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) {
|
void AnimationPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) {
|
||||||
|
|
||||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, url, QString, setURL);
|
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, url, QString, setURL);
|
||||||
|
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, allowTranslation, bool, setAllowTranslation);
|
||||||
|
|
||||||
// legacy property support
|
// legacy property support
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationURL, QString, setURL, getURL);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationURL, QString, setURL, getURL);
|
||||||
|
@ -67,6 +69,7 @@ void AnimationPropertyGroup::copyFromScriptValue(const QScriptValue& object, boo
|
||||||
|
|
||||||
void AnimationPropertyGroup::merge(const AnimationPropertyGroup& other) {
|
void AnimationPropertyGroup::merge(const AnimationPropertyGroup& other) {
|
||||||
COPY_PROPERTY_IF_CHANGED(url);
|
COPY_PROPERTY_IF_CHANGED(url);
|
||||||
|
COPY_PROPERTY_IF_CHANGED(allowTranslation);
|
||||||
COPY_PROPERTY_IF_CHANGED(fps);
|
COPY_PROPERTY_IF_CHANGED(fps);
|
||||||
COPY_PROPERTY_IF_CHANGED(currentFrame);
|
COPY_PROPERTY_IF_CHANGED(currentFrame);
|
||||||
COPY_PROPERTY_IF_CHANGED(running);
|
COPY_PROPERTY_IF_CHANGED(running);
|
||||||
|
@ -88,6 +91,7 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) {
|
||||||
float lastFrame = getLastFrame();
|
float lastFrame = getLastFrame();
|
||||||
bool loop = getLoop();
|
bool loop = getLoop();
|
||||||
bool hold = getHold();
|
bool hold = getHold();
|
||||||
|
bool allowTranslation = getAllowTranslation();
|
||||||
|
|
||||||
QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8());
|
QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8());
|
||||||
QJsonObject settingsAsJsonObject = settingsAsJson.object();
|
QJsonObject settingsAsJsonObject = settingsAsJson.object();
|
||||||
|
@ -122,6 +126,11 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) {
|
||||||
running = settingsMap["hold"].toBool();
|
running = settingsMap["hold"].toBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settingsMap.contains("allowTranslation")) {
|
||||||
|
allowTranslation = settingsMap["allowTranslation"].toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
setAllowTranslation(allowTranslation);
|
||||||
setFPS(fps);
|
setFPS(fps);
|
||||||
setCurrentFrame(currentFrame);
|
setCurrentFrame(currentFrame);
|
||||||
setRunning(running);
|
setRunning(running);
|
||||||
|
@ -137,6 +146,7 @@ void AnimationPropertyGroup::debugDump() const {
|
||||||
qCDebug(entities) << " url:" << getURL() << " has changed:" << urlChanged();
|
qCDebug(entities) << " url:" << getURL() << " has changed:" << urlChanged();
|
||||||
qCDebug(entities) << " fps:" << getFPS() << " has changed:" << fpsChanged();
|
qCDebug(entities) << " fps:" << getFPS() << " has changed:" << fpsChanged();
|
||||||
qCDebug(entities) << "currentFrame:" << getCurrentFrame() << " has changed:" << currentFrameChanged();
|
qCDebug(entities) << "currentFrame:" << getCurrentFrame() << " has changed:" << currentFrameChanged();
|
||||||
|
qCDebug(entities) << "allowTranslation:" << getAllowTranslation() << " has changed:" << allowTranslationChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationPropertyGroup::listChangedProperties(QList<QString>& out) {
|
void AnimationPropertyGroup::listChangedProperties(QList<QString>& out) {
|
||||||
|
@ -149,6 +159,9 @@ void AnimationPropertyGroup::listChangedProperties(QList<QString>& out) {
|
||||||
if (currentFrameChanged()) {
|
if (currentFrameChanged()) {
|
||||||
out << "animation-currentFrame";
|
out << "animation-currentFrame";
|
||||||
}
|
}
|
||||||
|
if (allowTranslationChanged()) {
|
||||||
|
out << "animation-allowTranslation";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -162,6 +175,7 @@ bool AnimationPropertyGroup::appendToEditPacket(OctreePacketData* packetData,
|
||||||
bool successPropertyFits = true;
|
bool successPropertyFits = true;
|
||||||
|
|
||||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, getURL());
|
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, getURL());
|
||||||
|
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_ALLOW_TRANSLATION, getAllowTranslation());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, getFPS());
|
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, getFPS());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, getCurrentFrame());
|
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, getCurrentFrame());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, getRunning());
|
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, getRunning());
|
||||||
|
@ -181,6 +195,7 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF
|
||||||
bool somethingChanged = false;
|
bool somethingChanged = false;
|
||||||
|
|
||||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_URL, QString, setURL);
|
READ_ENTITY_PROPERTY(PROP_ANIMATION_URL, QString, setURL);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_ANIMATION_ALLOW_TRANSLATION, bool, setAllowTranslation);
|
||||||
|
|
||||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setFPS);
|
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setFPS);
|
||||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setCurrentFrame);
|
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setCurrentFrame);
|
||||||
|
@ -198,7 +213,8 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF
|
||||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_FIRST_FRAME, FirstFrame);
|
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_FIRST_FRAME, FirstFrame);
|
||||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_LAST_FRAME, LastFrame);
|
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_LAST_FRAME, LastFrame);
|
||||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_HOLD, Hold);
|
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_HOLD, Hold);
|
||||||
|
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_ALLOW_TRANSLATION, AllowTranslation);
|
||||||
|
|
||||||
processedBytes += bytesRead;
|
processedBytes += bytesRead;
|
||||||
|
|
||||||
Q_UNUSED(somethingChanged);
|
Q_UNUSED(somethingChanged);
|
||||||
|
@ -215,6 +231,7 @@ void AnimationPropertyGroup::markAllChanged() {
|
||||||
_firstFrameChanged = true;
|
_firstFrameChanged = true;
|
||||||
_lastFrameChanged = true;
|
_lastFrameChanged = true;
|
||||||
_holdChanged = true;
|
_holdChanged = true;
|
||||||
|
_allowTranslationChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityPropertyFlags AnimationPropertyGroup::getChangedProperties() const {
|
EntityPropertyFlags AnimationPropertyGroup::getChangedProperties() const {
|
||||||
|
@ -228,12 +245,14 @@ EntityPropertyFlags AnimationPropertyGroup::getChangedProperties() const {
|
||||||
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FIRST_FRAME, firstFrame);
|
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FIRST_FRAME, firstFrame);
|
||||||
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_LAST_FRAME, lastFrame);
|
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_LAST_FRAME, lastFrame);
|
||||||
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_HOLD, hold);
|
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_HOLD, hold);
|
||||||
|
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_ALLOW_TRANSLATION, allowTranslation);
|
||||||
|
|
||||||
return changedProperties;
|
return changedProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationPropertyGroup::getProperties(EntityItemProperties& properties) const {
|
void AnimationPropertyGroup::getProperties(EntityItemProperties& properties) const {
|
||||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, URL, getURL);
|
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, URL, getURL);
|
||||||
|
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, AllowTranslation, getAllowTranslation);
|
||||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, FPS, getFPS);
|
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, FPS, getFPS);
|
||||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, CurrentFrame, getCurrentFrame);
|
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, CurrentFrame, getCurrentFrame);
|
||||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, Running, getRunning);
|
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, Running, getRunning);
|
||||||
|
@ -247,6 +266,7 @@ bool AnimationPropertyGroup::setProperties(const EntityItemProperties& propertie
|
||||||
bool somethingChanged = false;
|
bool somethingChanged = false;
|
||||||
|
|
||||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, URL, url, setURL);
|
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, URL, url, setURL);
|
||||||
|
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, AllowTranslation, allowTranslation, setAllowTranslation);
|
||||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, FPS, fps, setFPS);
|
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, FPS, fps, setFPS);
|
||||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, CurrentFrame, currentFrame, setCurrentFrame);
|
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, CurrentFrame, currentFrame, setCurrentFrame);
|
||||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, Running, running, setRunning);
|
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, Running, running, setRunning);
|
||||||
|
@ -268,6 +288,7 @@ EntityPropertyFlags AnimationPropertyGroup::getEntityProperties(EncodeBitstreamP
|
||||||
requestedProperties += PROP_ANIMATION_FIRST_FRAME;
|
requestedProperties += PROP_ANIMATION_FIRST_FRAME;
|
||||||
requestedProperties += PROP_ANIMATION_LAST_FRAME;
|
requestedProperties += PROP_ANIMATION_LAST_FRAME;
|
||||||
requestedProperties += PROP_ANIMATION_HOLD;
|
requestedProperties += PROP_ANIMATION_HOLD;
|
||||||
|
requestedProperties += PROP_ANIMATION_ALLOW_TRANSLATION;
|
||||||
|
|
||||||
return requestedProperties;
|
return requestedProperties;
|
||||||
}
|
}
|
||||||
|
@ -283,6 +304,7 @@ void AnimationPropertyGroup::appendSubclassData(OctreePacketData* packetData, En
|
||||||
bool successPropertyFits = true;
|
bool successPropertyFits = true;
|
||||||
|
|
||||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, getURL());
|
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, getURL());
|
||||||
|
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_ALLOW_TRANSLATION, getAllowTranslation());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, getFPS());
|
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, getFPS());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, getCurrentFrame());
|
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, getCurrentFrame());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, getRunning());
|
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, getRunning());
|
||||||
|
@ -301,6 +323,7 @@ int AnimationPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char
|
||||||
const unsigned char* dataAt = data;
|
const unsigned char* dataAt = data;
|
||||||
|
|
||||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_URL, QString, setURL);
|
READ_ENTITY_PROPERTY(PROP_ANIMATION_URL, QString, setURL);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_ANIMATION_ALLOW_TRANSLATION, bool, setAllowTranslation);
|
||||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setFPS);
|
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setFPS);
|
||||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setCurrentFrame);
|
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setCurrentFrame);
|
||||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, setRunning);
|
READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, setRunning);
|
||||||
|
|
|
@ -85,6 +85,7 @@ public:
|
||||||
DEFINE_PROPERTY(PROP_ANIMATION_FIRST_FRAME, FirstFrame, firstFrame, float, 0.0f); // was animationSettings.firstFrame
|
DEFINE_PROPERTY(PROP_ANIMATION_FIRST_FRAME, FirstFrame, firstFrame, float, 0.0f); // was animationSettings.firstFrame
|
||||||
DEFINE_PROPERTY(PROP_ANIMATION_LAST_FRAME, LastFrame, lastFrame, float, MAXIMUM_POSSIBLE_FRAME); // was animationSettings.lastFrame
|
DEFINE_PROPERTY(PROP_ANIMATION_LAST_FRAME, LastFrame, lastFrame, float, MAXIMUM_POSSIBLE_FRAME); // was animationSettings.lastFrame
|
||||||
DEFINE_PROPERTY(PROP_ANIMATION_HOLD, Hold, hold, bool, false); // was animationSettings.hold
|
DEFINE_PROPERTY(PROP_ANIMATION_HOLD, Hold, hold, bool, false); // was animationSettings.hold
|
||||||
|
DEFINE_PROPERTY(PROP_ANIMATION_ALLOW_TRANSLATION, AllowTranslation, allowTranslation, bool, true);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend bool operator==(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b);
|
friend bool operator==(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b);
|
||||||
|
|
|
@ -1033,6 +1033,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
|
||||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame);
|
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame);
|
||||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame);
|
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame);
|
||||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold);
|
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold);
|
||||||
|
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_ALLOW_TRANSLATION, Animation, animation, AllowTranslation, allowTranslation);
|
||||||
|
|
||||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_COLOR, Skybox, skybox, Color, color);
|
ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_COLOR, Skybox, skybox, Color, color);
|
||||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_URL, Skybox, skybox, URL, url);
|
ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_URL, Skybox, skybox, URL, url);
|
||||||
|
|
|
@ -40,6 +40,7 @@ enum EntityPropertyList {
|
||||||
PROP_ANIMATION_FPS,
|
PROP_ANIMATION_FPS,
|
||||||
PROP_ANIMATION_FRAME_INDEX,
|
PROP_ANIMATION_FRAME_INDEX,
|
||||||
PROP_ANIMATION_PLAYING,
|
PROP_ANIMATION_PLAYING,
|
||||||
|
PROP_ANIMATION_ALLOW_TRANSLATION,
|
||||||
|
|
||||||
// these properties are supported by the EntityItem base class
|
// these properties are supported by the EntityItem base class
|
||||||
PROP_REGISTRATION_POINT,
|
PROP_REGISTRATION_POINT,
|
||||||
|
|
|
@ -330,6 +330,10 @@ void ModelEntityItem::setAnimationSettings(const QString& value) {
|
||||||
setAnimationHold(hold);
|
setAnimationHold(hold);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settingsMap.contains("allowTranslation")) {
|
||||||
|
bool allowTranslation = settingsMap["allowTranslation"].toBool();
|
||||||
|
setAnimationAllowTranslation(allowTranslation);
|
||||||
|
}
|
||||||
_dirtyFlags |= Simulation::DIRTY_UPDATEABLE;
|
_dirtyFlags |= Simulation::DIRTY_UPDATEABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,10 @@ public:
|
||||||
|
|
||||||
void setAnimationCurrentFrame(float value);
|
void setAnimationCurrentFrame(float value);
|
||||||
void setAnimationIsPlaying(bool value);
|
void setAnimationIsPlaying(bool value);
|
||||||
void setAnimationFPS(float value);
|
void setAnimationFPS(float value);
|
||||||
|
|
||||||
|
void setAnimationAllowTranslation(bool value) { _animationProperties.setAllowTranslation(value); };
|
||||||
|
bool getAnimationAllowTranslation() const { return _animationProperties.getAllowTranslation(); };
|
||||||
|
|
||||||
void setAnimationLoop(bool loop);
|
void setAnimationLoop(bool loop);
|
||||||
bool getAnimationLoop() const;
|
bool getAnimationLoop() const;
|
||||||
|
|
|
@ -30,7 +30,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
||||||
case PacketType::EntityEdit:
|
case PacketType::EntityEdit:
|
||||||
case PacketType::EntityData:
|
case PacketType::EntityData:
|
||||||
case PacketType::EntityPhysics:
|
case PacketType::EntityPhysics:
|
||||||
return VERSION_ENTITIES_HAS_HIGHLIGHT_SCRIPTING_INTERFACE;
|
return VERSION_ENTITIES_ANIMATION_ALLOW_TRANSLATION_PROPERTIES;
|
||||||
case PacketType::EntityQuery:
|
case PacketType::EntityQuery:
|
||||||
return static_cast<PacketVersion>(EntityQueryPacketVersion::JSONFilterWithFamilyTree);
|
return static_cast<PacketVersion>(EntityQueryPacketVersion::JSONFilterWithFamilyTree);
|
||||||
case PacketType::AvatarIdentity:
|
case PacketType::AvatarIdentity:
|
||||||
|
|
|
@ -260,6 +260,7 @@ const PacketVersion VERSION_ENTITIES_HINGE_CONSTRAINT = 69;
|
||||||
const PacketVersion VERSION_ENTITIES_BULLET_DYNAMICS = 70;
|
const PacketVersion VERSION_ENTITIES_BULLET_DYNAMICS = 70;
|
||||||
const PacketVersion VERSION_ENTITIES_HAS_SHOULD_HIGHLIGHT = 71;
|
const PacketVersion VERSION_ENTITIES_HAS_SHOULD_HIGHLIGHT = 71;
|
||||||
const PacketVersion VERSION_ENTITIES_HAS_HIGHLIGHT_SCRIPTING_INTERFACE = 72;
|
const PacketVersion VERSION_ENTITIES_HAS_HIGHLIGHT_SCRIPTING_INTERFACE = 72;
|
||||||
|
const PacketVersion VERSION_ENTITIES_ANIMATION_ALLOW_TRANSLATION_PROPERTIES = 73;
|
||||||
|
|
||||||
enum class EntityQueryPacketVersion: PacketVersion {
|
enum class EntityQueryPacketVersion: PacketVersion {
|
||||||
JSONFilter = 18,
|
JSONFilter = 18,
|
||||||
|
|
|
@ -827,10 +827,10 @@ AnimationDetails::AnimationDetails() :
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimationDetails::AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop,
|
AnimationDetails::AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop,
|
||||||
bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame) :
|
bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame, bool allowTranslation) :
|
||||||
role(role), url(url), fps(fps), priority(priority), loop(loop), hold(hold),
|
role(role), url(url), fps(fps), priority(priority), loop(loop), hold(hold),
|
||||||
startAutomatically(startAutomatically), firstFrame(firstFrame), lastFrame(lastFrame),
|
startAutomatically(startAutomatically), firstFrame(firstFrame), lastFrame(lastFrame),
|
||||||
running(running), currentFrame(currentFrame) {
|
running(running), currentFrame(currentFrame), allowTranslation(allowTranslation) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -847,6 +847,7 @@ QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const Animatio
|
||||||
obj.setProperty("lastFrame", details.lastFrame);
|
obj.setProperty("lastFrame", details.lastFrame);
|
||||||
obj.setProperty("running", details.running);
|
obj.setProperty("running", details.running);
|
||||||
obj.setProperty("currentFrame", details.currentFrame);
|
obj.setProperty("currentFrame", details.currentFrame);
|
||||||
|
obj.setProperty("allowTranslation", details.allowTranslation);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -197,7 +197,7 @@ class AnimationDetails {
|
||||||
public:
|
public:
|
||||||
AnimationDetails();
|
AnimationDetails();
|
||||||
AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop,
|
AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop,
|
||||||
bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame);
|
bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame, bool allowTranslation);
|
||||||
|
|
||||||
QString role;
|
QString role;
|
||||||
QUrl url;
|
QUrl url;
|
||||||
|
@ -210,6 +210,7 @@ public:
|
||||||
float lastFrame;
|
float lastFrame;
|
||||||
bool running;
|
bool running;
|
||||||
float currentFrame;
|
float currentFrame;
|
||||||
|
bool allowTranslation;
|
||||||
};
|
};
|
||||||
Q_DECLARE_METATYPE(AnimationDetails);
|
Q_DECLARE_METATYPE(AnimationDetails);
|
||||||
QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& event);
|
QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& event);
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
var isHmdPreviewDisabled = true;
|
var isHmdPreviewDisabled = true;
|
||||||
function fromQml(message) {
|
function fromQml(message) {
|
||||||
switch (message.method) {
|
switch (message.method) {
|
||||||
|
case 'passphrasePopup_cancelClicked':
|
||||||
case 'walletSetup_cancelClicked':
|
case 'walletSetup_cancelClicked':
|
||||||
case 'needsLogIn_cancelClicked':
|
case 'needsLogIn_cancelClicked':
|
||||||
tablet.gotoHomeScreen();
|
tablet.gotoHomeScreen();
|
||||||
|
|
|
@ -446,6 +446,10 @@
|
||||||
<input type="checkbox" id="property-model-animation-hold">
|
<input type="checkbox" id="property-model-animation-hold">
|
||||||
<label for="property-model-animation-hold">Animation hold</label>
|
<label for="property-model-animation-hold">Animation hold</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="property checkbox indent">
|
||||||
|
<input type="checkbox" id="property-model-animation-allow-translation">
|
||||||
|
<label for="property-model-animation-allow-translation">Animation Allow Translation</label>
|
||||||
|
</div>
|
||||||
<div id="animation-fps" class="property number">
|
<div id="animation-fps" class="property number">
|
||||||
<label>Animation FPS</label>
|
<label>Animation FPS</label>
|
||||||
<input type="number" id="property-model-animation-fps">
|
<input type="number" id="property-model-animation-fps">
|
||||||
|
@ -642,10 +646,6 @@
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<fieldset id="polyvox" class="major">
|
<fieldset id="polyvox" class="major">
|
||||||
<legend class="section-header spatial-group poly-vox-section property xyz">
|
<legend class="section-header spatial-group poly-vox-section property xyz">
|
||||||
Voxel volume size <span>m</span>
|
Voxel volume size <span>m</span>
|
||||||
|
|
|
@ -611,6 +611,7 @@ function loaded() {
|
||||||
var elModelAnimationLastFrame = document.getElementById("property-model-animation-last-frame");
|
var elModelAnimationLastFrame = document.getElementById("property-model-animation-last-frame");
|
||||||
var elModelAnimationLoop = document.getElementById("property-model-animation-loop");
|
var elModelAnimationLoop = document.getElementById("property-model-animation-loop");
|
||||||
var elModelAnimationHold = document.getElementById("property-model-animation-hold");
|
var elModelAnimationHold = document.getElementById("property-model-animation-hold");
|
||||||
|
var elModelAnimationAllowTranslation = document.getElementById("property-model-animation-allow-translation");
|
||||||
var elModelTextures = document.getElementById("property-model-textures");
|
var elModelTextures = document.getElementById("property-model-textures");
|
||||||
var elModelOriginalTextures = document.getElementById("property-model-original-textures");
|
var elModelOriginalTextures = document.getElementById("property-model-original-textures");
|
||||||
|
|
||||||
|
@ -926,6 +927,7 @@ function loaded() {
|
||||||
elModelAnimationLastFrame.value = properties.animation.lastFrame;
|
elModelAnimationLastFrame.value = properties.animation.lastFrame;
|
||||||
elModelAnimationLoop.checked = properties.animation.loop;
|
elModelAnimationLoop.checked = properties.animation.loop;
|
||||||
elModelAnimationHold.checked = properties.animation.hold;
|
elModelAnimationHold.checked = properties.animation.hold;
|
||||||
|
elModelAnimationAllowTranslation.checked = properties.animation.allowTranslation;
|
||||||
elModelTextures.value = properties.textures;
|
elModelTextures.value = properties.textures;
|
||||||
setTextareaScrolling(elModelTextures);
|
setTextareaScrolling(elModelTextures);
|
||||||
elModelOriginalTextures.value = properties.originalTextures;
|
elModelOriginalTextures.value = properties.originalTextures;
|
||||||
|
@ -1276,6 +1278,7 @@ function loaded() {
|
||||||
elModelAnimationLastFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'lastFrame'));
|
elModelAnimationLastFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'lastFrame'));
|
||||||
elModelAnimationLoop.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'loop'));
|
elModelAnimationLoop.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'loop'));
|
||||||
elModelAnimationHold.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'hold'));
|
elModelAnimationHold.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'hold'));
|
||||||
|
elModelAnimationAllowTranslation.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'allowTranslation'));
|
||||||
|
|
||||||
elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures'));
|
elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures'));
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
var isPreparing = false; // Explicitly track download request status.
|
var isPreparing = false; // Explicitly track download request status.
|
||||||
|
|
||||||
var confirmAllPurchases = false; // Set this to "true" to cause Checkout.qml to popup for all items, even if free
|
var confirmAllPurchases = false; // Set this to "true" to cause Checkout.qml to popup for all items, even if free
|
||||||
|
|
||||||
function injectCommonCode(isDirectoryPage) {
|
function injectCommonCode(isDirectoryPage) {
|
||||||
|
|
||||||
// Supporting styles from marketplaces.css.
|
// Supporting styles from marketplaces.css.
|
||||||
|
@ -122,7 +122,7 @@
|
||||||
|
|
||||||
function injectBuyButtonOnMainPage() {
|
function injectBuyButtonOnMainPage() {
|
||||||
var cost;
|
var cost;
|
||||||
|
|
||||||
$('.grid-item').find('#price-or-edit').find('a').each(function() {
|
$('.grid-item').find('#price-or-edit').find('a').each(function() {
|
||||||
$(this).attr('data-href', $(this).attr('href'));
|
$(this).attr('data-href', $(this).attr('href'));
|
||||||
$(this).attr('href', '#');
|
$(this).attr('href', '#');
|
||||||
|
@ -130,7 +130,7 @@
|
||||||
|
|
||||||
$(this).closest('.col-xs-3').prev().attr("class", 'col-xs-6');
|
$(this).closest('.col-xs-3').prev().attr("class", 'col-xs-6');
|
||||||
$(this).closest('.col-xs-3').attr("class", 'col-xs-6');
|
$(this).closest('.col-xs-3').attr("class", 'col-xs-6');
|
||||||
|
|
||||||
if (parseInt(cost) > 0) {
|
if (parseInt(cost) > 0) {
|
||||||
var priceElement = $(this).find('.price')
|
var priceElement = $(this).find('.price')
|
||||||
priceElement.css({ "width": "auto", "padding": "3px 5px", "height": "26px" });
|
priceElement.css({ "width": "auto", "padding": "3px 5px", "height": "26px" });
|
||||||
|
@ -138,8 +138,8 @@
|
||||||
priceElement.css({ "min-width": priceElement.width() + 10 });
|
priceElement.css({ "min-width": priceElement.width() + 10 });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$('.grid-item').find('#price-or-edit').find('a').on('click', function () {
|
$('.grid-item').find('#price-or-edit').find('a').on('click', function () {
|
||||||
buyButtonClicked($(this).closest('.grid-item').attr('data-item-id'),
|
buyButtonClicked($(this).closest('.grid-item').attr('data-item-id'),
|
||||||
$(this).closest('.grid-item').find('.item-title').text(),
|
$(this).closest('.grid-item').find('.item-title').text(),
|
||||||
|
@ -175,11 +175,12 @@
|
||||||
if (confirmAllPurchases) {
|
if (confirmAllPurchases) {
|
||||||
var href = $('#side-info').find('.btn').first().attr('href');
|
var href = $('#side-info').find('.btn').first().attr('href');
|
||||||
$('#side-info').find('.btn').first().attr('href', '#');
|
$('#side-info').find('.btn').first().attr('href', '#');
|
||||||
|
|
||||||
var cost = $('.item-cost').text();
|
var cost = $('.item-cost').text();
|
||||||
|
|
||||||
if (parseInt(cost) > 0 && $('#side-info').find('#buyItemButton').size() === 0) {
|
if (parseInt(cost) > 0 && $('#side-info').find('#buyItemButton').size() === 0) {
|
||||||
$('#side-info').find('.btn').first().html('<span class="glyphicon glyphicon-download" id="buyItemButton"></span>Own Item: ' + (parseFloat(cost / 100).toFixed(2)) + ' HFC');
|
$('#side-info').find('.btn').first().html('<span class="glyphicon glyphicon-download" id="buyItemButton"></span>Own Item: ' + cost + ' HFC');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#side-info').find('.btn').first().on('click', function () {
|
$('#side-info').find('.btn').first().on('click', function () {
|
||||||
|
@ -264,7 +265,7 @@
|
||||||
// Reference: https://clara.io/learn/sdk/api/export
|
// Reference: https://clara.io/learn/sdk/api/export
|
||||||
|
|
||||||
//var XMLHTTPREQUEST_URL = "https://clara.io/api/scenes/{uuid}/export/fbx?zip=true¢erScene=true&alignSceneGround=true&fbxUnit=Meter&fbxVersion=7&fbxEmbedTextures=true&imageFormat=WebGL";
|
//var XMLHTTPREQUEST_URL = "https://clara.io/api/scenes/{uuid}/export/fbx?zip=true¢erScene=true&alignSceneGround=true&fbxUnit=Meter&fbxVersion=7&fbxEmbedTextures=true&imageFormat=WebGL";
|
||||||
// 13 Jan 2017: Specify FBX version 5 and remove some options in order to make Clara.io site more likely to
|
// 13 Jan 2017: Specify FBX version 5 and remove some options in order to make Clara.io site more likely to
|
||||||
// be successful in generating zip files.
|
// be successful in generating zip files.
|
||||||
var XMLHTTPREQUEST_URL = "https://clara.io/api/scenes/{uuid}/export/fbx?fbxUnit=Meter&fbxVersion=5&fbxEmbedTextures=true&imageFormat=WebGL";
|
var XMLHTTPREQUEST_URL = "https://clara.io/api/scenes/{uuid}/export/fbx?fbxUnit=Meter&fbxVersion=5&fbxEmbedTextures=true&imageFormat=WebGL";
|
||||||
|
|
||||||
|
@ -447,7 +448,7 @@
|
||||||
cancelClaraDownload();
|
cancelClaraDownload();
|
||||||
} else {
|
} else {
|
||||||
var parsedJsonMessage = JSON.parse(message);
|
var parsedJsonMessage = JSON.parse(message);
|
||||||
|
|
||||||
if (parsedJsonMessage.type === "marketplaces") {
|
if (parsedJsonMessage.type === "marketplaces") {
|
||||||
if (parsedJsonMessage.action === "inspectionModeSetting") {
|
if (parsedJsonMessage.action === "inspectionModeSetting") {
|
||||||
confirmAllPurchases = !!parsedJsonMessage.data;
|
confirmAllPurchases = !!parsedJsonMessage.data;
|
||||||
|
|
|
@ -197,6 +197,7 @@
|
||||||
// Description:
|
// Description:
|
||||||
// -Called when a message is received from Checkout.qml. The "message" argument is what is sent from the Checkout QML
|
// -Called when a message is received from Checkout.qml. The "message" argument is what is sent from the Checkout QML
|
||||||
// in the format "{method, params}", like json-rpc.
|
// in the format "{method, params}", like json-rpc.
|
||||||
|
var isHmdPreviewDisabled = true;
|
||||||
function fromQml(message) {
|
function fromQml(message) {
|
||||||
switch (message.method) {
|
switch (message.method) {
|
||||||
case 'checkout_setUpClicked':
|
case 'checkout_setUpClicked':
|
||||||
|
@ -231,12 +232,20 @@
|
||||||
case 'purchases_goToMarketplaceClicked':
|
case 'purchases_goToMarketplaceClicked':
|
||||||
tablet.gotoWebScreen(MARKETPLACE_URL_INITIAL, MARKETPLACES_INJECT_SCRIPT_URL);
|
tablet.gotoWebScreen(MARKETPLACE_URL_INITIAL, MARKETPLACES_INJECT_SCRIPT_URL);
|
||||||
break;
|
break;
|
||||||
|
case 'passphrasePopup_cancelClicked':
|
||||||
case 'needsLogIn_cancelClicked':
|
case 'needsLogIn_cancelClicked':
|
||||||
tablet.gotoWebScreen(MARKETPLACE_URL_INITIAL, MARKETPLACES_INJECT_SCRIPT_URL);
|
tablet.gotoWebScreen(MARKETPLACE_URL_INITIAL, MARKETPLACES_INJECT_SCRIPT_URL);
|
||||||
break;
|
break;
|
||||||
case 'needsLogIn_loginClicked':
|
case 'needsLogIn_loginClicked':
|
||||||
openLoginWindow();
|
openLoginWindow();
|
||||||
break;
|
break;
|
||||||
|
case 'disableHmdPreview':
|
||||||
|
isHmdPreviewDisabled = Menu.isOptionChecked("Disable Preview");
|
||||||
|
Menu.setIsOptionChecked("Disable Preview", true);
|
||||||
|
break;
|
||||||
|
case 'maybeEnableHmdPreview':
|
||||||
|
Menu.setIsOptionChecked("Disable Preview", isHmdPreviewDisabled);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
print('Unrecognized message from Checkout.qml or Purchases.qml: ' + JSON.stringify(message));
|
print('Unrecognized message from Checkout.qml or Purchases.qml: ' + JSON.stringify(message));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue