History

Merge branch 'serverless-domains' into serverless-domains

Dante Ruiz committed 8 years ago

Commit 364081d2 parents 7ea4042 9b8c92531 files · +597 −249Browse files

Unified · Split

31 files
  1. assignment-client/src/audio/AudioMixer.cpp +2 −2
  2. assignment-client/src/audio/AudioMixer.h +2 −0
  3. assignment-client/src/audio/AudioMixerClientData.cpp +2 −2
  4. assignment-client/src/audio/AudioMixerClientData.h +1 −0
  5. assignment-client/src/audio/AudioMixerSlave.cpp +2 −2
  6. interface/resources/fonts/hifi-glyphs.ttf +0 −0
  7. interface/resources/qml/controls-uit/Separator.qml +2 −2
  8. interface/resources/qml/controls-uit/TextField.qml +2 −3
  9. interface/resources/qml/hifi/commerce/checkout/Checkout.qml +195 −90
  10. interface/resources/qml/hifi/commerce/common/CommerceLightbox.qml +4 −0
  11. interface/resources/qml/hifi/commerce/common/FirstUseTutorial.qml +2 −2
  12. interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml +1 −0
  13. interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +201 −41
  14. interface/resources/qml/hifi/commerce/purchases/Purchases.qml +76 −78
  15. interface/resources/qml/styles-uit/HifiConstants.qml +5 −1
  16. interface/src/Application.cpp +19 −15
  17. interface/src/Application.h +2 −0
  18. interface/src/avatar/MyAvatar.cpp +1 −1
  19. interface/src/commerce/Ledger.cpp +10 −0
  20. interface/src/commerce/Ledger.h +4 −0
  21. interface/src/commerce/QmlCommerce.cpp +20 −0
  22. interface/src/commerce/QmlCommerce.h +7 −0
  23. interface/src/scripting/AccountServicesScriptingInterface.h +1 −1
  24. libraries/avatars/src/AvatarData.h +2 −1
  25. libraries/avatars/src/ScriptAvatarData.cpp +1 −0
  26. libraries/avatars/src/ScriptAvatarData.h +2 −1
  27. libraries/entities/src/EntityScriptingInterface.cpp +5 −0
  28. libraries/entities/src/EntityScriptingInterface.h +6 −0
  29. libraries/render-utils/src/Shadow.slh +3 −1
  30. libraries/shared/src/PathUtils.cpp +1 −0
  31. scripts/system/marketplaces/marketplaces.js +17 −7
assignment-client/src/audio/AudioMixer.cpp+2−2
@@ -9,6 +9,8 @@ · 8 unmodified lines
9// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html9// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10//10//
11 11
12#include "AudioMixer.h"
13
12#include <thread>14#include <thread>
13 15
14#include <QtCore/QJsonArray>16#include <QtCore/QJsonArray>
@@ -36,8 +38,6 @@ · 21 unmodified lines
36#include "AvatarAudioStream.h"38#include "AvatarAudioStream.h"
37#include "InjectedAudioStream.h"39#include "InjectedAudioStream.h"
38 40
39#include "AudioMixer.h"
40
41static const float DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE = 0.5f; // attenuation = -6dB * log2(distance)41static const float DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE = 0.5f; // attenuation = -6dB * log2(distance)
42static const int DISABLE_STATIC_JITTER_FRAMES = -1;42static const int DISABLE_STATIC_JITTER_FRAMES = -1;
43static const float DEFAULT_NOISE_MUTING_THRESHOLD = 1.0f;43static const float DEFAULT_NOISE_MUTING_THRESHOLD = 1.0f;
assignment-client/src/audio/AudioMixer.h+2−0
@@ -18,6 +18,8 @@ · 17 unmodified lines
18#include <ThreadedAssignment.h>18#include <ThreadedAssignment.h>
19#include <UUIDHasher.h>19#include <UUIDHasher.h>
20 20
21#include <plugins/Forward.h>
22
21#include "AudioMixerStats.h"23#include "AudioMixerStats.h"
22#include "AudioMixerSlavePool.h"24#include "AudioMixerSlavePool.h"
23 25
assignment-client/src/audio/AudioMixerClientData.cpp+2−2
@@ -9,6 +9,8 @@ · 8 unmodified lines
9// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html9// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10//10//
11 11
12#include "AudioMixerClientData.h"
13
12#include <random>14#include <random>
13 15
14#include <QtCore/QDebug>16#include <QtCore/QDebug>
@@ -22,8 +24,6 @@ · 7 unmodified lines
22#include "AudioLogging.h"24#include "AudioLogging.h"
23#include "AudioHelpers.h"25#include "AudioHelpers.h"
24#include "AudioMixer.h"26#include "AudioMixer.h"
25#include "AudioMixerClientData.h"
26
27 27
28AudioMixerClientData::AudioMixerClientData(const QUuid& nodeID) :28AudioMixerClientData::AudioMixerClientData(const QUuid& nodeID) :
29 NodeData(nodeID),29 NodeData(nodeID),
assignment-client/src/audio/AudioMixerClientData.h+1−0
@@ -21,6 +21,7 @@ · 20 unmodified lines
21#include <AudioLimiter.h>21#include <AudioLimiter.h>
22#include <UUIDHasher.h>22#include <UUIDHasher.h>
23 23
24#include <plugins/Forward.h>
24#include <plugins/CodecPlugin.h>25#include <plugins/CodecPlugin.h>
25 26
26#include "PositionalAudioStream.h"27#include "PositionalAudioStream.h"
assignment-client/src/audio/AudioMixerSlave.cpp+2−2
@@ -9,6 +9,8 @@ · 8 unmodified lines
9// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html9// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10//10//
11 11
12#include "AudioMixerSlave.h"
13
12#include <algorithm>14#include <algorithm>
13 15
14#include <glm/glm.hpp>16#include <glm/glm.hpp>
@@ -34,8 +36,6 @@ · 19 unmodified lines
34#include "InjectedAudioStream.h"36#include "InjectedAudioStream.h"
35#include "AudioHelpers.h"37#include "AudioHelpers.h"
36 38
37#include "AudioMixerSlave.h"
38
39using AudioStreamMap = AudioMixerClientData::AudioStreamMap;39using AudioStreamMap = AudioMixerClientData::AudioStreamMap;
40 40
41// packet helpers41// packet helpers
interface/resources/fonts/hifi-glyphs.ttf+0−0

Binary file not shown.

interface/resources/qml/controls-uit/Separator.qml+2−2
@@ -14,8 +14,8 @@ import "../styles-uit" · 13 unmodified lines
14Item {14Item {
15 property int colorScheme: 0;15 property int colorScheme: 0;
16 16
17 readonly property var topColor: [ hifi.colors.baseGrayShadow, hifi.colors.faintGray ];17 readonly property var topColor: [ hifi.colors.baseGrayShadow, hifi.colors.faintGray, "#89858C" ];
18 readonly property var bottomColor: [ hifi.colors.baseGrayHighlight, hifi.colors.faintGray ];18 readonly property var bottomColor: [ hifi.colors.baseGrayHighlight, hifi.colors.faintGray, "#89858C" ];
19 19
20 // Size20 // Size
21 height: colorScheme === 0 ? 2 : 1;21 height: colorScheme === 0 ? 2 : 1;
interface/resources/qml/controls-uit/TextField.qml+2−3
@@ -34,11 +34,10 @@ TextField { · 33 unmodified lines
34 34
35 placeholderText: textField.placeholderText35 placeholderText: textField.placeholderText
36 36
37 FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; }37 FontLoader { id: firaSansRegular; source: "../../fonts/FiraSans-Regular.ttf"; }
38 FontLoader { id: hifiGlyphs; source: "../../fonts/hifi-glyphs.ttf"; }38 FontLoader { id: hifiGlyphs; source: "../../fonts/hifi-glyphs.ttf"; }
39 font.family: firaSansSemiBold.name39 font.family: firaSansRegular.name
40 font.pixelSize: hifi.fontSizes.textFieldInput40 font.pixelSize: hifi.fontSizes.textFieldInput
41 font.italic: textField.text == ""
42 height: implicitHeight + 3 // Make surrounding box higher so that highlight is vertically centered.41 height: implicitHeight + 3 // Make surrounding box higher so that highlight is vertically centered.
43 property alias textFieldLabel: textFieldLabel42 property alias textFieldLabel: textFieldLabel
44 43
interface/resources/qml/hifi/commerce/checkout/Checkout.qml+195−90
@@ -28,7 +28,7 @@ Rectangle { · 27 unmodified lines
28 id: root;28 id: root;
29 objectName: "checkout"29 objectName: "checkout"
30 property string activeView: "initialize";30 property string activeView: "initialize";
31 property bool purchasesReceived: false;31 property bool ownershipStatusReceived: false;
32 property bool balanceReceived: false;32 property bool balanceReceived: false;
33 property string itemName;33 property string itemName;
34 property string itemId;34 property string itemId;
@@ -37,11 +37,16 @@ Rectangle { · 2 unmodified lines
37 property double balanceAfterPurchase;37 property double balanceAfterPurchase;
38 property bool alreadyOwned: false;38 property bool alreadyOwned: false;
39 property int itemPrice: -1;39 property int itemPrice: -1;
40 property bool itemIsJson: true;40 property bool isCertified;
41 property string itemType;
42 property var itemTypesArray: ["entity", "wearable", "contentSet", "app", "avatar"];
43 property var itemTypesText: ["entity", "wearable", "content set", "app", "avatar"];
44 property var buttonTextNormal: ["REZ", "WEAR", "REPLACE CONTENT SET", "INSTALL", "WEAR"];
45 property var buttonTextClicked: ["REZZED!", "WORN!", "CONTENT SET REPLACED!", "INSTALLED!", "AVATAR CHANGED!"]
46 property var buttonGlyph: [hifi.glyphs.wand, hifi.glyphs.hat, hifi.glyphs.globe, hifi.glyphs.install, hifi.glyphs.avatar];
41 property bool shouldBuyWithControlledFailure: false;47 property bool shouldBuyWithControlledFailure: false;
42 property bool debugCheckoutSuccess: false;48 property bool debugCheckoutSuccess: false;
43 property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified();49 property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified();
44 property bool isWearable;
45 property string referrer;50 property string referrer;
46 // Style51 // Style
47 color: hifi.colors.white;52 color: hifi.colors.white;
@@ -85,7 +90,9 @@ Rectangle { · 37 unmodified lines
85 UserActivityLogger.commercePurchaseFailure(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned, result.message);90 UserActivityLogger.commercePurchaseFailure(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned, result.message);
86 } else {91 } else {
87 root.itemHref = result.data.download_url;92 root.itemHref = result.data.download_url;
88 root.isWearable = result.data.categories.indexOf("Wearables") > -1;93 if (result.data.categories.indexOf("Wearables") > -1) {
94 root.itemType = "wearable";
95 }
89 root.activeView = "checkoutSuccess";96 root.activeView = "checkoutSuccess";
90 UserActivityLogger.commercePurchaseSuccess(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned);97 UserActivityLogger.commercePurchaseSuccess(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned);
91 }98 }
@@ -97,32 +104,53 @@ Rectangle { · 5 unmodified lines
97 } else {104 } else {
98 root.balanceReceived = true;105 root.balanceReceived = true;
99 root.balanceAfterPurchase = result.data.balance - root.itemPrice;106 root.balanceAfterPurchase = result.data.balance - root.itemPrice;
100 root.setBuyText();107 root.refreshBuyUI();
101 }108 }
102 }109 }
103 110
104 onInventoryResult: {111 onAlreadyOwnedResult: {
105 if (result.status !== 'success') {112 if (result.status !== 'success') {
106 console.log("Failed to get purchases", result.data.message);113 console.log("Failed to get Already Owned status", result.data.message);
107 } else {114 } else {
108 root.purchasesReceived = true;115 root.ownershipStatusReceived = true;
109 if (purchasesContains(result.data.assets, itemId)) {116 if (result.data.marketplace_item_id === root.itemId) {
110 root.alreadyOwned = true;117 root.alreadyOwned = result.data.already_owned;
111 } else {118 } else {
119 console.log("WARNING - Received 'Already Owned' status about different Marketplace ID!");
112 root.alreadyOwned = false;120 root.alreadyOwned = false;
113 }121 }
114 root.setBuyText();122 root.refreshBuyUI();
115 }123 }
116 }124 }
117 }125 }
118 126
119 onItemIdChanged: {127 onItemIdChanged: {
120 Commerce.inventory();128 root.ownershipStatusReceived = false;
129 Commerce.alreadyOwned(root.itemId);
121 itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg";130 itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg";
122 }131 }
123 132
124 onItemHrefChanged: {133 onItemHrefChanged: {
125 itemIsJson = root.itemHref.endsWith('.json');134 if (root.itemHref.indexOf(".fst") > -1) {
135 root.itemType = "avatar";
136 } else if (root.itemHref.indexOf('.json.gz') > -1) {
137 root.itemType = "contentSet";
138 } else if (root.itemHref.indexOf('.app.json') > -1) {
139 root.itemType = "app";
140 } else if (root.itemHref.indexOf('.json') > -1) {
141 root.itemType = "entity"; // "wearable" type handled later
142 } else {
143 console.log("WARNING - Item type is UNKNOWN!");
144 root.itemType = "entity";
145 }
146 }
147
148 onItemTypeChanged: {
149 if (root.itemType === "entity" || root.itemType === "wearable" || root.itemType === "contentSet" || root.itemType === "avatar") {
150 root.isCertified = true;
151 } else {
152 root.isCertified = false;
153 }
126 }154 }
127 155
128 onItemPriceChanged: {156 onItemPriceChanged: {
@@ -203,7 +231,7 @@ Rectangle { · 74 unmodified lines
203 color: hifi.colors.white;231 color: hifi.colors.white;
204 232
205 Component.onCompleted: {233 Component.onCompleted: {
206 purchasesReceived = false;234 ownershipStatusReceived = false;
207 balanceReceived = false;235 balanceReceived = false;
208 Commerce.getWalletStatus();236 Commerce.getWalletStatus();
209 }237 }
@@ -278,6 +306,31 @@ Rectangle { · 68 unmodified lines
278 anchors.left: parent.left;306 anchors.left: parent.left;
279 anchors.right: parent.right;307 anchors.right: parent.right;
280 308
309 Rectangle {
310 id: loading;
311 z: 997;
312 visible: !root.ownershipStatusReceived || !root.balanceReceived;
313 anchors.fill: parent;
314 color: Qt.rgba(0.0, 0.0, 0.0, 0.7);
315
316 // This object is always used in a popup.
317 // This MouseArea is used to prevent a user from being
318 // able to click on a button/mouseArea underneath the popup/section.
319 MouseArea {
320 anchors.fill: parent;
321 hoverEnabled: true;
322 propagateComposedEvents: false;
323 }
324
325 AnimatedImage {
326 source: "../common/images/loader.gif"
327 width: 96;
328 height: width;
329 anchors.verticalCenter: parent.verticalCenter;
330 anchors.horizontalCenter: parent.horizontalCenter;
331 }
332 }
333
281 RalewayRegular {334 RalewayRegular {
282 id: confirmPurchaseText;335 id: confirmPurchaseText;
283 anchors.top: parent.top;336 anchors.top: parent.top;
@@ -286,8 +339,8 @@ Rectangle { · 2 unmodified lines
286 anchors.leftMargin: 16;339 anchors.leftMargin: 16;
287 width: paintedWidth;340 width: paintedWidth;
288 height: paintedHeight;341 height: paintedHeight;
289 text: "Confirm Purchase:";342 text: "Review Purchase:";
290 color: hifi.colors.baseGray;343 color: hifi.colors.black;
291 size: 28;344 size: 28;
292 }345 }
293 346
@@ -400,7 +453,7 @@ Rectangle { · 106 unmodified lines
400 width: root.width;453 width: root.width;
401 // Anchors454 // Anchors
402 anchors.top: separator2.bottom;455 anchors.top: separator2.bottom;
403 anchors.topMargin: 16;456 anchors.topMargin: 0;
404 anchors.left: parent.left;457 anchors.left: parent.left;
405 anchors.leftMargin: 16;458 anchors.leftMargin: 16;
406 anchors.right: parent.right;459 anchors.right: parent.right;
@@ -411,8 +464,8 @@ Rectangle { · 4 unmodified lines
411 Rectangle {464 Rectangle {
412 id: buyTextContainer;465 id: buyTextContainer;
413 visible: buyText.text !== "";466 visible: buyText.text !== "";
414 anchors.top: cancelPurchaseButton.bottom;467 anchors.top: parent.top;
415 anchors.topMargin: 16;468 anchors.topMargin: 10;
416 anchors.left: parent.left;469 anchors.left: parent.left;
417 anchors.right: parent.right;470 anchors.right: parent.right;
418 height: buyText.height + 30;471 height: buyText.height + 30;
@@ -454,32 +507,63 @@ Rectangle { · 35 unmodified lines
454 // Alignment507 // Alignment
455 horizontalAlignment: Text.AlignLeft;508 horizontalAlignment: Text.AlignLeft;
456 verticalAlignment: Text.AlignVCenter;509 verticalAlignment: Text.AlignVCenter;
510 }
511 }
457 512
458 onLinkActivated: {513 // "View in My Purchases" button
459 sendToScript({method: 'checkout_goToPurchases', filterText: root.itemName});514 HifiControlsUit.Button {
460 }515 id: viewInMyPurchasesButton;
516 visible: false;
517 color: hifi.buttons.blue;
518 colorScheme: hifi.colorSchemes.light;
519 anchors.top: buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top;
520 anchors.topMargin: 10;
521 height: 50;
522 anchors.left: parent.left;
523 anchors.right: parent.right;
524 text: "VIEW THIS ITEM IN MY PURCHASES";
525 onClicked: {
526 sendToScript({method: 'checkout_goToPurchases', filterText: root.itemName});
461 }527 }
462 }528 }
463 529
464 // "Buy" button530 // "Buy" button
465 HifiControlsUit.Button {531 HifiControlsUit.Button {
466 id: buyButton;532 id: buyButton;
467 enabled: (root.balanceAfterPurchase >= 0 && purchasesReceived && balanceReceived) || !itemIsJson;533 visible: !((root.itemType === "avatar" || root.itemType === "app") && viewInMyPurchasesButton.visible)
468 color: hifi.buttons.blue;534 enabled: (root.balanceAfterPurchase >= 0 && ownershipStatusReceived && balanceReceived) || (!root.isCertified);
535 color: viewInMyPurchasesButton.visible ? hifi.buttons.white : hifi.buttons.blue;
469 colorScheme: hifi.colorSchemes.light;536 colorScheme: hifi.colorSchemes.light;
470 anchors.top: checkoutActionButtonsContainer.top;537 anchors.top: viewInMyPurchasesButton.visible ? viewInMyPurchasesButton.bottom :
471 anchors.topMargin: 16;538 (buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top);
472 height: 40;539 anchors.topMargin: 10;
540 height: 50;
473 anchors.left: parent.left;541 anchors.left: parent.left;
474 anchors.right: parent.right;542 anchors.right: parent.right;
475 text: (itemIsJson ? ((purchasesReceived && balanceReceived) ? "Confirm Purchase" : "--") : "Get Item");543 text: ((root.isCertified) ? ((ownershipStatusReceived && balanceReceived) ?
544 (viewInMyPurchasesButton.visible ? "Buy It Again" : "Confirm Purchase") : "--") : "Get Item");
476 onClicked: {545 onClicked: {
477 if (itemIsJson) {546 if (root.isCertified) {
478 buyButton.enabled = false;
479 if (!root.shouldBuyWithControlledFailure) {547 if (!root.shouldBuyWithControlledFailure) {
480 Commerce.buy(itemId, itemPrice);548 if (root.itemType === "contentSet" && !Entities.canReplaceContent()) {
549 lightboxPopup.titleText = "Purchase Content Set";
550 lightboxPopup.bodyText = "You will not be able to replace this domain's content with <b>" + root.itemName +
551 " </b>until the server owner gives you 'Replace Content' permissions.<br><br>Are you sure you want to purchase this content set?";
552 lightboxPopup.button1text = "CANCEL";
553 lightboxPopup.button1method = "root.visible = false;"
554 lightboxPopup.button2text = "CONFIRM";
555 lightboxPopup.button2method = "Commerce.buy('" + root.itemId + "', " + root.itemPrice + ");" +
556 "root.visible = false; buyButton.enabled = false; loading.visible = true;";
557 lightboxPopup.visible = true;
558 } else {
559 buyButton.enabled = false;
560 loading.visible = true;
561 Commerce.buy(root.itemId, root.itemPrice);
562 }
481 } else {563 } else {
482 Commerce.buy(itemId, itemPrice, true);564 buyButton.enabled = false;
565 loading.visible = true;
566 Commerce.buy(root.itemId, root.itemPrice, true);
483 }567 }
484 } else {568 } else {
485 if (urlHandler.canHandleUrl(itemHref)) {569 if (urlHandler.canHandleUrl(itemHref)) {
@@ -494,9 +578,9 @@ Rectangle { · 8 unmodified lines
494 id: cancelPurchaseButton;578 id: cancelPurchaseButton;
495 color: hifi.buttons.noneBorderlessGray;579 color: hifi.buttons.noneBorderlessGray;
496 colorScheme: hifi.colorSchemes.light;580 colorScheme: hifi.colorSchemes.light;
497 anchors.top: buyButton.bottom;581 anchors.top: buyButton.visible ? buyButton.bottom : viewInMyPurchasesButton.bottom;
498 anchors.topMargin: 16;582 anchors.topMargin: 10;
499 height: 40;583 height: 50;
500 anchors.left: parent.left;584 anchors.left: parent.left;
501 anchors.right: parent.right;585 anchors.right: parent.right;
502 text: "Cancel"586 text: "Cancel"
@@ -522,31 +606,32 @@ Rectangle { · 19 unmodified lines
522 anchors.top: titleBarContainer.bottom;606 anchors.top: titleBarContainer.bottom;
523 anchors.bottom: root.bottom;607 anchors.bottom: root.bottom;
524 anchors.left: parent.left;608 anchors.left: parent.left;
525 anchors.leftMargin: 16;609 anchors.leftMargin: 20;
526 anchors.right: parent.right;610 anchors.right: parent.right;
527 anchors.rightMargin: 16;611 anchors.rightMargin: 20;
528 612
529 RalewayRegular {613 RalewayRegular {
530 id: completeText;614 id: completeText;
531 anchors.top: parent.top;615 anchors.top: parent.top;
532 anchors.topMargin: 30;616 anchors.topMargin: 18;
533 anchors.left: parent.left;617 anchors.left: parent.left;
534 width: paintedWidth;618 width: paintedWidth;
535 height: paintedHeight;619 height: paintedHeight;
536 text: "Thank you for your order!";620 text: "Thank you for your order!";
537 color: hifi.colors.baseGray;621 color: hifi.colors.baseGray;
538 size: 28;622 size: 36;
539 }623 }
540 624
541 RalewaySemiBold {625 RalewaySemiBold {
542 id: completeText2;626 id: completeText2;
543 text: "The item " + '<font color="' + hifi.colors.blueAccent + '"><a href="#">' + root.itemName + '</a></font>' +627 text: "The " + (root.itemTypesText)[itemTypesArray.indexOf(root.itemType)] +
544 " has been added to your Purchases and a receipt will appear in your Wallet's transaction history.";628 ' <font color="' + hifi.colors.blueAccent + '"><a href="#">' + root.itemName + '</a></font>' +
629 " has been added to your Purchases and a receipt will appear in your Wallet's transaction history.";
545 // Text size630 // Text size
546 size: 20;631 size: 18;
547 // Anchors632 // Anchors
548 anchors.top: completeText.bottom;633 anchors.top: completeText.bottom;
549 anchors.topMargin: 10;634 anchors.topMargin: 15;
550 height: paintedHeight;635 height: paintedHeight;
551 anchors.left: parent.left;636 anchors.left: parent.left;
552 anchors.right: parent.right;637 anchors.right: parent.right;
@@ -576,7 +661,7 @@ Rectangle { · 23 unmodified lines
576 661
577 RalewayBold {662 RalewayBold {
578 anchors.fill: parent;663 anchors.fill: parent;
579 text: "REZZED";664 text: (root.buttonTextClicked)[itemTypesArray.indexOf(root.itemType)];
580 size: 18;665 size: 18;
581 color: hifi.colors.white;666 color: hifi.colors.white;
582 verticalAlignment: Text.AlignVCenter;667 verticalAlignment: Text.AlignVCenter;
@@ -592,26 +677,52 @@ Rectangle { · 9 unmodified lines
592 // "Rez" button677 // "Rez" button
593 HifiControlsUit.Button {678 HifiControlsUit.Button {
594 id: rezNowButton;679 id: rezNowButton;
595 enabled: root.canRezCertifiedItems || root.isWearable;680 enabled: (root.itemType === "entity" && root.canRezCertifiedItems) ||
596 buttonGlyph: hifi.glyphs.lightning;681 (root.itemType === "contentSet" && Entities.canReplaceContent()) ||
682 root.itemType === "wearable" || root.itemType === "avatar";
683 buttonGlyph: (root.buttonGlyph)[itemTypesArray.indexOf(root.itemType)];
597 color: hifi.buttons.red;684 color: hifi.buttons.red;
598 colorScheme: hifi.colorSchemes.light;685 colorScheme: hifi.colorSchemes.light;
599 anchors.top: completeText2.bottom;686 anchors.top: completeText2.bottom;
600 anchors.topMargin: 30;687 anchors.topMargin: 27;
601 height: 50;688 height: 50;
602 anchors.left: parent.left;689 anchors.left: parent.left;
603 anchors.right: parent.right;690 anchors.right: parent.right;
604 text: root.isWearable ? "Wear It" : "Rez It"691 text: (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)];
605 onClicked: {692 onClicked: {
606 sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, isWearable: root.isWearable});693 if (root.itemType === "contentSet") {
607 rezzedNotifContainer.visible = true;694 lightboxPopup.titleText = "Replace Content";
608 rezzedNotifContainerTimer.start();695 lightboxPopup.bodyText = "Rezzing this content set will replace the existing environment and all of the items in this domain. " +
609 UserActivityLogger.commerceEntityRezzed(root.itemId, "checkout", root.isWearable ? "rez" : "wear");696 "If you want to save the state of the content in this domain, create a backup before proceeding.<br><br>" +
697 "For more information about backing up and restoring content, " +
698 "<a href='https://docs.highfidelity.com/create-and-explore/start-working-in-your-sandbox/restoring-sandbox-content'>" +
699 "click here to open info on your desktop browser.";
700 lightboxPopup.button1text = "CANCEL";
701 lightboxPopup.button1method = "root.visible = false;"
702 lightboxPopup.button2text = "CONFIRM";
703 lightboxPopup.button2method = "Commerce.replaceContentSet('" + root.itemHref + "');" +
704 "root.visible = false;rezzedNotifContainer.visible = true; rezzedNotifContainerTimer.start();" +
705 "UserActivityLogger.commerceEntityRezzed('" + root.itemId + "', 'checkout', '" + root.itemType + "');";
706 lightboxPopup.visible = true;
707 } else if (root.itemType === "avatar") {
708 lightboxPopup.titleText = "Change Avatar";
709 lightboxPopup.bodyText = "This will change your current avatar to " + root.itemName + " while retaining your wearables.";
710 lightboxPopup.button1text = "CANCEL";
711 lightboxPopup.button1method = "root.visible = false;"
712 lightboxPopup.button2text = "CONFIRM";
713 lightboxPopup.button2method = "MyAvatar.useFullAvatarURL('" + root.itemHref + "'); root.visible = false;";
714 lightboxPopup.visible = true;
715 } else {
716 sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, itemType: root.itemType});
717 rezzedNotifContainer.visible = true;
718 rezzedNotifContainerTimer.start();
719 UserActivityLogger.commerceEntityRezzed(root.itemId, "checkout", root.itemType);
720 }
610 }721 }
611 }722 }
612 RalewaySemiBold {723 RalewaySemiBold {
613 id: noPermissionText;724 id: noPermissionText;
614 visible: !root.canRezCertifiedItems && !root.isWearable;725 visible: !root.canRezCertifiedItems && root.itemType === "entity";
615 text: '<font color="' + hifi.colors.redAccent + '"><a href="#">You do not have Certified Rez permissions in this domain.</a></font>'726 text: '<font color="' + hifi.colors.redAccent + '"><a href="#">You do not have Certified Rez permissions in this domain.</a></font>'
616 // Text size727 // Text size
617 size: 16;728 size: 16;
@@ -640,7 +751,7 @@ Rectangle { · 22 unmodified lines
640 }751 }
641 RalewaySemiBold {752 RalewaySemiBold {
642 id: explainRezText;753 id: explainRezText;
643 visible: !root.isWearable;754 visible: root.itemType === "entity";
644 text: '<font color="' + hifi.colors.redAccent + '"><a href="#">What does "Rez" mean?</a></font>'755 text: '<font color="' + hifi.colors.redAccent + '"><a href="#">What does "Rez" mean?</a></font>'
645 // Text size756 // Text size
646 size: 16;757 size: 16;
@@ -663,9 +774,9 @@ Rectangle { · 16 unmodified lines
663 774
664 RalewaySemiBold {775 RalewaySemiBold {
665 id: myPurchasesLink;776 id: myPurchasesLink;
666 text: '<font color="' + hifi.colors.blueAccent + '"><a href="#">View this item in My Purchases</a></font>';777 text: '<font color="' + hifi.colors.primaryHighlight + '"><a href="#">View this item in My Purchases</a></font>';
667 // Text size778 // Text size
668 size: 20;779 size: 18;
669 // Anchors780 // Anchors
670 anchors.top: explainRezText.visible ? explainRezText.bottom : (noPermissionText.visible ? noPermissionText.bottom : rezNowButton.bottom);781 anchors.top: explainRezText.visible ? explainRezText.bottom : (noPermissionText.visible ? noPermissionText.bottom : rezNowButton.bottom);
671 anchors.topMargin: 40;782 anchors.topMargin: 40;
@@ -685,12 +796,12 @@ Rectangle { · 13 unmodified lines
685 796
686 RalewaySemiBold {797 RalewaySemiBold {
687 id: walletLink;798 id: walletLink;
688 text: '<font color="' + hifi.colors.blueAccent + '"><a href="#">View receipt in Wallet</a></font>';799 text: '<font color="' + hifi.colors.primaryHighlight + '"><a href="#">View receipt in Wallet</a></font>';
689 // Text size800 // Text size
690 size: 20;801 size: 18;
691 // Anchors802 // Anchors
692 anchors.top: myPurchasesLink.bottom;803 anchors.top: myPurchasesLink.bottom;
693 anchors.topMargin: 20;804 anchors.topMargin: 16;
694 height: paintedHeight;805 height: paintedHeight;
695 anchors.left: parent.left;806 anchors.left: parent.left;
696 anchors.right: parent.right;807 anchors.right: parent.right;
@@ -708,12 +819,12 @@ Rectangle { · 11 unmodified lines
708 RalewayRegular {819 RalewayRegular {
709 id: pendingText;820 id: pendingText;
710 text: 'Your item is marked "pending" while your purchase is being confirmed. ' +821 text: 'Your item is marked "pending" while your purchase is being confirmed. ' +
711 '<font color="' + hifi.colors.blueAccent + '"><a href="#">Learn More</a></font>';822 '<b><font color="' + hifi.colors.primaryHighlight + '"><a href="#">Learn More</a></font></b>';
712 // Text size823 // Text size
713 size: 20;824 size: 18;
714 // Anchors825 // Anchors
715 anchors.top: walletLink.bottom;826 anchors.top: walletLink.bottom;
716 anchors.topMargin: 60;827 anchors.topMargin: 32;
717 height: paintedHeight;828 height: paintedHeight;
718 anchors.left: parent.left;829 anchors.left: parent.left;
719 anchors.right: parent.right;830 anchors.right: parent.right;
@@ -739,11 +850,10 @@ Rectangle { · 19 unmodified lines
739 color: hifi.buttons.noneBorderlessGray;850 color: hifi.buttons.noneBorderlessGray;
740 colorScheme: hifi.colorSchemes.light;851 colorScheme: hifi.colorSchemes.light;
741 anchors.bottom: parent.bottom;852 anchors.bottom: parent.bottom;
742 anchors.bottomMargin: 20;853 anchors.bottomMargin: 54;
743 anchors.right: parent.right;854 anchors.right: parent.right;
744 anchors.rightMargin: 14;855 width: 193;
745 width: parent.width/2 - anchors.rightMargin;856 height: 44;
746 height: 60;
747 text: "Continue Shopping";857 text: "Continue Shopping";
748 onClicked: {858 onClicked: {
749 sendToScript({method: 'checkout_continueShopping', itemId: itemId});859 sendToScript({method: 'checkout_continueShopping', itemId: itemId});
@@ -851,7 +961,7 @@ Rectangle { · 101 unmodified lines
851 buyButton.color = hifi.buttons.red;961 buyButton.color = hifi.buttons.red;
852 root.shouldBuyWithControlledFailure = true;962 root.shouldBuyWithControlledFailure = true;
853 } else {963 } else {
854 buyButton.text = (itemIsJson ? ((purchasesReceived && balanceReceived) ? (root.alreadyOwned ? "Buy Another" : "Buy"): "--") : "Get Item");964 buyButton.text = (root.isCertified ? ((ownershipStatusReceived && balanceReceived) ? (root.alreadyOwned ? "Buy Another" : "Buy"): "--") : "Get Item");
855 buyButton.color = hifi.buttons.blue;965 buyButton.color = hifi.buttons.blue;
856 root.shouldBuyWithControlledFailure = false;966 root.shouldBuyWithControlledFailure = false;
857 }967 }
@@ -883,7 +993,7 @@ Rectangle { · 25 unmodified lines
883 itemHref = message.params.itemHref;993 itemHref = message.params.itemHref;
884 referrer = message.params.referrer;994 referrer = message.params.referrer;
885 itemAuthor = message.params.itemAuthor;995 itemAuthor = message.params.itemAuthor;
886 setBuyText();996 refreshBuyUI();
887 break;997 break;
888 default:998 default:
889 console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message));999 console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message));
@@ -891,22 +1001,13 @@ Rectangle { · 1 unmodified line
891 }1001 }
892 signal sendToScript(var message);1002 signal sendToScript(var message);
893 1003
894 function purchasesContains(purchasesJson, id) {1004 function refreshBuyUI() {
895 for (var idx = 0; idx < purchasesJson.length; idx++) {1005 if (root.isCertified) {
896 if(purchasesJson[idx].id === id) {1006 if (root.ownershipStatusReceived && root.balanceReceived) {
897 return true;
898 }
899 }
900 return false;
901 }
902
903 function setBuyText() {
904 if (root.itemIsJson) {
905 if (root.purchasesReceived && root.balanceReceived) {
906 if (root.balanceAfterPurchase < 0) {1007 if (root.balanceAfterPurchase < 0) {
907 if (root.alreadyOwned) {1008 if (root.alreadyOwned) {
908 buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item again.<br>" +1009 buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item again.</b>";
909 '<font color="' + hifi.colors.blueAccent + '"><a href="#">View the copy you own in My Purchases</a></font></b>';1010 viewInMyPurchasesButton.visible = true;
910 } else {1011 } else {
911 buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item.</b>";1012 buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item.</b>";
912 }1013 }
@@ -916,15 +1017,19 @@ Rectangle { · 3 unmodified lines
916 buyGlyph.size = 54;1017 buyGlyph.size = 54;
917 } else {1018 } else {
918 if (root.alreadyOwned) {1019 if (root.alreadyOwned) {
919 buyText.text = '<b>You already own this item.<br>Purchasing it will buy another copy.<br><font color="'1020 viewInMyPurchasesButton.visible = true;
920 + hifi.colors.blueAccent + '"><a href="#">View this item in My Purchases</a></font></b>';
921 buyTextContainer.color = "#FFD6AD";
922 buyTextContainer.border.color = "#FAC07D";
923 buyGlyph.text = hifi.glyphs.alert;
924 buyGlyph.size = 46;
925 } else {1021 } else {
926 buyText.text = "";1022 buyText.text = "";
927 }1023 }
1024
1025 if (root.itemType === "contentSet" && !Entities.canReplaceContent()) {
1026 buyText.text = "The domain owner must enable 'Replace Content' permissions for you in this " +
1027 "<b>domain's server settings</b> before you can replace this domain's content with <b>" + root.itemName + "</b>";
1028 buyTextContainer.color = "#FFC3CD";
1029 buyTextContainer.border.color = "#F3808F";
1030 buyGlyph.text = hifi.glyphs.alert;
1031 buyGlyph.size = 54;
1032 }
928 }1033 }
929 } else {1034 } else {
930 buyText.text = "";1035 buyText.text = "";
@@ -945,8 +1050,8 @@ Rectangle { · 14 unmodified lines
945 root.activeView = "checkoutSuccess";1050 root.activeView = "checkoutSuccess";
946 }1051 }
947 root.balanceReceived = false;1052 root.balanceReceived = false;
948 root.purchasesReceived = false;1053 root.ownershipStatusReceived = false;
949 Commerce.inventory();1054 Commerce.alreadyOwned(root.itemId);
950 Commerce.balance();1055 Commerce.balance();
951 }1056 }
952 1057
interface/resources/qml/hifi/commerce/common/CommerceLightbox.qml+4−0
@@ -100,6 +100,10 @@ Rectangle { · 99 unmodified lines
100 size: 20;100 size: 20;
101 verticalAlignment: Text.AlignTop;101 verticalAlignment: Text.AlignTop;
102 wrapMode: Text.WordWrap;102 wrapMode: Text.WordWrap;
103
104 onLinkActivated: {
105 sendToParent({ method: 'commerceLightboxLinkClicked', linkUrl: link });
106 }
103 }107 }
104 108
105 Item {109 Item {
interface/resources/qml/hifi/commerce/common/FirstUseTutorial.qml+2−2
@@ -90,11 +90,11 @@ Rectangle { · 89 unmodified lines
90 id: introText2;90 id: introText2;
91 text: "My Purchases";91 text: "My Purchases";
92 // Text size92 // Text size
93 size: 28;93 size: 22;
94 // Anchors94 // Anchors
95 anchors.top: introText1.bottom;95 anchors.top: introText1.bottom;
96 anchors.left: parent.left;96 anchors.left: parent.left;
97 anchors.leftMargin: 12;97 anchors.leftMargin: 24;
98 anchors.right: parent.right;98 anchors.right: parent.right;
99 height: paintedHeight;99 height: paintedHeight;
100 // Style100 // Style
interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml+1−0
@@ -208,6 +208,7 @@ Rectangle { · 207 unmodified lines
208 // able to click on a button/mouseArea underneath the popup/section.208 // able to click on a button/mouseArea underneath the popup/section.
209 MouseArea {209 MouseArea {
210 anchors.fill: parent;210 anchors.fill: parent;
211 hoverEnabled: true;
211 propagateComposedEvents: false;212 propagateComposedEvents: false;
212 }213 }
213 214
interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml+201−41
@@ -20,6 +20,7 @@ import "../../../styles-uit" · 19 unmodified lines
20import "../../../controls-uit" as HifiControlsUit20import "../../../controls-uit" as HifiControlsUit
21import "../../../controls" as HifiControls21import "../../../controls" as HifiControls
22import "../wallet" as HifiWallet22import "../wallet" as HifiWallet
23import TabletScriptingInterface 1.0
23 24
24// references XXX from root context25// references XXX from root context
25 26
@@ -29,7 +30,6 @@ Item { · 3 unmodified lines
29 id: root;30 id: root;
30 property string purchaseStatus;31 property string purchaseStatus;
31 property bool purchaseStatusChanged;32 property bool purchaseStatusChanged;
32 property bool canRezCertifiedItems: false;
33 property string itemName;33 property string itemName;
34 property string itemId;34 property string itemId;
35 property string itemPreviewImageUrl;35 property string itemPreviewImageUrl;
@@ -39,7 +39,14 @@ Item { · 3 unmodified lines
39 property int itemEdition;39 property int itemEdition;
40 property int numberSold;40 property int numberSold;
41 property int limitedRun;41 property int limitedRun;
42 property bool isWearable;42 property string itemType;
43 property var itemTypesArray: ["entity", "wearable", "contentSet", "app", "avatar"];
44 property var buttonTextNormal: ["REZ", "WEAR", "REPLACE", "INSTALL", "WEAR"];
45 property var buttonTextClicked: ["REZZED", "WORN", "REPLACED", "INSTALLED", "WORN"]
46 property var buttonGlyph: [hifi.glyphs.wand, hifi.glyphs.hat, hifi.glyphs.globe, hifi.glyphs.install, hifi.glyphs.avatar];
47 property bool showConfirmation: false;
48 property bool hasPermissionToRezThis;
49 property bool permissionExplanationCardVisible;
43 50
44 property string originalStatusText;51 property string originalStatusText;
45 property string originalStatusColor;52 property string originalStatusColor;
@@ -47,6 +54,35 @@ Item { · 1 unmodified line
47 height: 110;54 height: 110;
48 width: parent.width;55 width: parent.width;
49 56
57 Connections {
58 target: Commerce;
59
60 onContentSetChanged: {
61 if (contentSetHref === root.itemHref) {
62 showConfirmation = true;
63 }
64 }
65 }
66
67 Connections {
68 target: MyAvatar;
69
70 onSkeletonModelURLChanged: {
71 if (skeletonModelURL === root.itemHref) {
72 showConfirmation = true;
73 }
74 }
75 }
76
77 onItemTypeChanged: {
78 if ((itemType === "entity" && (!Entities.canRezCertified() && !Entities.canRezTmpCertified())) ||
79 (itemType === "contentSet" && !Entities.canReplaceContent())) {
80 root.hasPermissionToRezThis = false;
81 } else {
82 root.hasPermissionToRezThis = true;
83 }
84 }
85
50 onPurchaseStatusChangedChanged: {86 onPurchaseStatusChangedChanged: {
51 if (root.purchaseStatusChanged === true && root.purchaseStatus === "confirmed") {87 if (root.purchaseStatusChanged === true && root.purchaseStatus === "confirmed") {
52 root.originalStatusText = statusText.text;88 root.originalStatusText = statusText.text;
@@ -57,6 +93,15 @@ Item { · 4 unmodified lines
57 }93 }
58 }94 }
59 95
96 onShowConfirmationChanged: {
97 if (root.showConfirmation) {
98 rezzedNotifContainer.visible = true;
99 rezzedNotifContainerTimer.start();
100 UserActivityLogger.commerceEntityRezzed(root.itemId, "purchases", root.itemType);
101 root.showConfirmation = false;
102 }
103 }
104
60 Timer {105 Timer {
61 id: confirmedTimer;106 id: confirmedTimer;
62 interval: 3000;107 interval: 3000;
@@ -73,10 +118,10 @@ Item { · 10 unmodified lines
73 color: hifi.colors.white;118 color: hifi.colors.white;
74 // Size119 // Size
75 anchors.left: parent.left;120 anchors.left: parent.left;
76 anchors.leftMargin: 8;121 anchors.leftMargin: 16;
77 anchors.right: parent.right;122 anchors.right: parent.right;
78 anchors.rightMargin: 8;123 anchors.rightMargin: 16;
79 anchors.top: parent.top;124 anchors.verticalCenter: parent.verticalCenter;
80 height: root.height - 10;125 height: root.height - 10;
81 126
82 Image {127 Image {
@@ -96,15 +141,20 @@ Item { · 13 unmodified lines
96 }141 }
97 }142 }
98 143
99 144 TextMetrics {
145 id: itemNameTextMetrics;
146 font: itemName.font;
147 text: itemName.text;
148 }
100 RalewaySemiBold {149 RalewaySemiBold {
101 id: itemName;150 id: itemName;
102 anchors.top: itemPreviewImage.top;151 anchors.top: itemPreviewImage.top;
103 anchors.topMargin: 4;152 anchors.topMargin: 4;
104 anchors.left: itemPreviewImage.right;153 anchors.left: itemPreviewImage.right;
105 anchors.leftMargin: 8;154 anchors.leftMargin: 8;
106 anchors.right: buttonContainer.left;155 width: !noPermissionGlyph.visible ? (buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width - anchors.leftMargin) :
107 anchors.rightMargin: 8;156 Math.min(itemNameTextMetrics.tightBoundingRect.width + 2,
157 buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width - anchors.leftMargin - noPermissionGlyph.width + 2);
108 height: paintedHeight;158 height: paintedHeight;
109 // Text size159 // Text size
110 size: 24;160 size: 24;
@@ -130,6 +180,93 @@ Item { · 19 unmodified lines
130 }180 }
131 }181 }
132 }182 }
183 HiFiGlyphs {
184 id: noPermissionGlyph;
185 visible: !root.hasPermissionToRezThis;
186 anchors.verticalCenter: itemName.verticalCenter;
187 anchors.left: itemName.right;
188 anchors.leftMargin: itemName.truncated ? -10 : -2;
189 text: hifi.glyphs.info;
190 // Size
191 size: 40;
192 width: 32;
193 // Style
194 color: hifi.colors.redAccent;
195
196 MouseArea {
197 anchors.fill: parent;
198 hoverEnabled: true;
199
200 onEntered: {
201 noPermissionGlyph.color = hifi.colors.redHighlight;
202 }
203 onExited: {
204 noPermissionGlyph.color = hifi.colors.redAccent;
205 }
206 onClicked: {
207 root.sendToPurchases({ method: 'openPermissionExplanationCard' });
208 }
209 }
210 }
211 Rectangle {
212 id: permissionExplanationCard;
213 z: 995;
214 visible: root.permissionExplanationCardVisible;
215 anchors.fill: parent;
216 color: hifi.colors.white;
217
218 RalewayRegular {
219 id: permissionExplanationText;
220 text: {
221 if (root.itemType === "contentSet") {
222 "You do not have 'Replace Content' permissions in this domain. <a href='#replaceContentPermission'>Learn more</a>";
223 } else if (root.itemType === "entity") {
224 "You do not have 'Rez Certified' permissions in this domain. <a href='#rezCertifiedPermission'>Learn more</a>";
225 } else {
226 ""
227 }
228 }
229 size: 16;
230 anchors.left: parent.left;
231 anchors.leftMargin: 30;
232 anchors.top: parent.top;
233 anchors.bottom: parent.bottom;
234 anchors.right: permissionExplanationGlyph.left;
235 color: hifi.colors.baseGray;
236 wrapMode: Text.WordWrap;
237 verticalAlignment: Text.AlignVCenter;
238
239 onLinkActivated: {
240 sendToPurchases({method: 'showPermissionsExplanation', itemType: root.itemType});
241 }
242 }
243 // "Close" button
244 HiFiGlyphs {
245 id: permissionExplanationGlyph;
246 text: hifi.glyphs.close;
247 color: hifi.colors.baseGray;
248 size: 26;
249 anchors.top: parent.top;
250 anchors.bottom: parent.bottom;
251 anchors.right: parent.right;
252 width: 77;
253 horizontalAlignment: Text.AlignHCenter;
254 verticalAlignment: Text.AlignVCenter;
255 MouseArea {
256 anchors.fill: parent;
257 hoverEnabled: true;
258 onEntered: {
259 parent.text = hifi.glyphs.closeInverted;
260 }
261 onExited: {
262 parent.text = hifi.glyphs.close;
263 }
264 onClicked: {
265 root.sendToPurchases({ method: 'openPermissionExplanationCard', closeAll: true });
266 }
267 }
268 }
269 }
133 270
134 Item {271 Item {
135 id: certificateContainer;272 id: certificateContainer;
@@ -151,19 +288,19 @@ Item { · 15 unmodified lines
151 anchors.bottom: parent.bottom;288 anchors.bottom: parent.bottom;
152 width: 32;289 width: 32;
153 // Style290 // Style
154 color: hifi.colors.lightGray;291 color: hifi.colors.black;
155 }292 }
156 293
157 RalewayRegular {294 RalewayRegular {
158 id: viewCertificateText;295 id: viewCertificateText;
159 text: "VIEW CERTIFICATE";296 text: "VIEW CERTIFICATE";
160 size: 14;297 size: 13;
161 anchors.left: certificateIcon.right;298 anchors.left: certificateIcon.right;
162 anchors.leftMargin: 4;299 anchors.leftMargin: 4;
163 anchors.top: parent.top;300 anchors.top: parent.top;
164 anchors.bottom: parent.bottom;301 anchors.bottom: parent.bottom;
165 anchors.right: parent.right;302 anchors.right: parent.right;
166 color: hifi.colors.lightGray;303 color: hifi.colors.black;
167 }304 }
168 305
169 MouseArea {306 MouseArea {
@@ -173,13 +310,13 @@ Item { · 3 unmodified lines
173 sendToPurchases({method: 'purchases_itemCertificateClicked', itemCertificateId: root.certificateId});310 sendToPurchases({method: 'purchases_itemCertificateClicked', itemCertificateId: root.certificateId});
174 }311 }
175 onEntered: {312 onEntered: {
176 certificateIcon.color = hifi.colors.black;
177 viewCertificateText.color = hifi.colors.black;
178 }
179 onExited: {
180 certificateIcon.color = hifi.colors.lightGray;313 certificateIcon.color = hifi.colors.lightGray;
181 viewCertificateText.color = hifi.colors.lightGray;314 viewCertificateText.color = hifi.colors.lightGray;
182 }315 }
316 onExited: {
317 certificateIcon.color = hifi.colors.black;
318 viewCertificateText.color = hifi.colors.black;
319 }
183 }320 }
184 }321 }
185 322
@@ -193,14 +330,14 @@ Item { · 7 unmodified lines
193 anchors.right: buttonContainer.left;330 anchors.right: buttonContainer.left;
194 anchors.rightMargin: 2;331 anchors.rightMargin: 2;
195 332
196 FiraSansRegular {333 RalewayRegular {
197 anchors.left: parent.left;334 anchors.left: parent.left;
198 anchors.top: parent.top;335 anchors.top: parent.top;
199 anchors.bottom: parent.bottom;336 anchors.bottom: parent.bottom;
200 width: paintedWidth;337 width: paintedWidth;
201 text: "#" + root.itemEdition;338 text: "#" + root.itemEdition;
202 size: 15;339 size: 13;
203 color: "#cc6a6a6a";340 color: hifi.colors.black;
204 verticalAlignment: Text.AlignTop;341 verticalAlignment: Text.AlignTop;
205 }342 }
206 }343 }
@@ -311,7 +448,7 @@ Item { · 104 unmodified lines
311 id: rezzedNotifContainer;448 id: rezzedNotifContainer;
312 z: 998;449 z: 998;
313 visible: false;450 visible: false;
314 color: hifi.colors.blueHighlight;451 color: "#1FC6A6";
315 anchors.fill: buttonContainer;452 anchors.fill: buttonContainer;
316 MouseArea {453 MouseArea {
317 anchors.fill: parent;454 anchors.fill: parent;
@@ -321,8 +458,8 @@ Item { · 3 unmodified lines
321 458
322 RalewayBold {459 RalewayBold {
323 anchors.fill: parent;460 anchors.fill: parent;
324 text: "REZZED";461 text: (root.buttonTextClicked)[itemTypesArray.indexOf(root.itemType)];
325 size: 18;462 size: 15;
326 color: hifi.colors.white;463 color: hifi.colors.white;
327 verticalAlignment: Text.AlignVCenter;464 verticalAlignment: Text.AlignVCenter;
328 horizontalAlignment: Text.AlignHCenter;465 horizontalAlignment: Text.AlignHCenter;
@@ -337,25 +474,47 @@ Item { · 8 unmodified lines
337 474
338 Button {475 Button {
339 id: buttonContainer;476 id: buttonContainer;
340 property int color: hifi.buttons.red;477 property int color: hifi.buttons.blue;
341 property int colorScheme: hifi.colorSchemes.light;478 property int colorScheme: hifi.colorSchemes.light;
342 479
343 anchors.top: parent.top;480 anchors.top: parent.top;
481 anchors.topMargin: 4;
344 anchors.bottom: parent.bottom;482 anchors.bottom: parent.bottom;
483 anchors.bottomMargin: 4;
345 anchors.right: parent.right;484 anchors.right: parent.right;
485 anchors.rightMargin: 4;
346 width: height;486 width: height;
347 enabled: (root.canRezCertifiedItems || root.isWearable) && root.purchaseStatus !== "invalidated";487 enabled: root.hasPermissionToRezThis &&
488 root.purchaseStatus !== "invalidated" &&
489 MyAvatar.skeletonModelURL !== root.itemHref;
490
491 onHoveredChanged: {
492 if (hovered) {
493 Tablet.playSound(TabletEnums.ButtonHover);
494 }
495 }
496
497 onFocusChanged: {
498 if (focus) {
499 Tablet.playSound(TabletEnums.ButtonHover);
500 }
501 }
348 502
349 onClicked: {503 onClicked: {
350 sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, isWearable: root.isWearable});504 Tablet.playSound(TabletEnums.ButtonClick);
351 rezzedNotifContainer.visible = true;505 if (root.itemType === "contentSet") {
352 rezzedNotifContainerTimer.start();506 sendToPurchases({method: 'showReplaceContentLightbox', itemHref: root.itemHref});
353 UserActivityLogger.commerceEntityRezzed(root.itemId, "purchases", root.isWearable ? "rez" : "wear");507 } else if (root.itemType === "avatar") {
508 sendToPurchases({method: 'showChangeAvatarLightbox', itemName: root.itemName, itemHref: root.itemHref});
509 } else {
510 sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, itemType: root.itemType});
511 root.showConfirmation = true;
512 }
354 }513 }
355 514
356 style: ButtonStyle {515 style: ButtonStyle {
357
358 background: Rectangle {516 background: Rectangle {
517 radius: 4;
359 gradient: Gradient {518 gradient: Gradient {
360 GradientStop {519 GradientStop {
361 position: 0.2520 position: 0.2
@@ -390,13 +549,13 @@ Item { · 28 unmodified lines
390 549
391 label: Item {550 label: Item {
392 HiFiGlyphs {551 HiFiGlyphs {
393 id: lightningIcon;552 id: rezIcon;
394 text: hifi.glyphs.lightning;553 text: (root.buttonGlyph)[itemTypesArray.indexOf(root.itemType)];
395 // Size554 // Size
396 size: 32;555 size: 60;
397 // Anchors556 // Anchors
398 anchors.top: parent.top;557 anchors.top: parent.top;
399 anchors.topMargin: 12;558 anchors.topMargin: 0;
400 anchors.left: parent.left;559 anchors.left: parent.left;
401 anchors.right: parent.right;560 anchors.right: parent.right;
402 horizontalAlignment: Text.AlignHCenter;561 horizontalAlignment: Text.AlignHCenter;
@@ -405,18 +564,19 @@ Item { · 2 unmodified lines
405 : hifi.buttons.disabledTextColor[control.colorScheme]564 : hifi.buttons.disabledTextColor[control.colorScheme]
406 }565 }
407 RalewayBold {566 RalewayBold {
408 anchors.top: lightningIcon.bottom;567 id: rezIconLabel;
409 anchors.topMargin: -20;568 anchors.top: rezIcon.bottom;
569 anchors.topMargin: -4;
410 anchors.right: parent.right;570 anchors.right: parent.right;
411 anchors.left: parent.left;571 anchors.left: parent.left;
412 anchors.bottom: parent.bottom;572 anchors.bottom: parent.bottom;
413 font.capitalization: Font.AllUppercase573 font.capitalization: Font.AllUppercase
414 color: enabled ? hifi.buttons.textColor[control.color]574 color: enabled ? hifi.buttons.textColor[control.color]
415 : hifi.buttons.disabledTextColor[control.colorScheme]575 : hifi.buttons.disabledTextColor[control.colorScheme]
416 size: 16;576 size: 15;
417 verticalAlignment: Text.AlignVCenter577 verticalAlignment: Text.AlignVCenter
418 horizontalAlignment: Text.AlignHCenter578 horizontalAlignment: Text.AlignHCenter
419 text: root.isWearable ? "Wear It" : "Rez It"579 text: MyAvatar.skeletonModelURL === root.itemHref ? "CURRENT" : (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)];
420 }580 }
421 }581 }
422 }582 }
@@ -425,11 +585,11 @@ Item { · 2 unmodified lines
425 585
426 DropShadow {586 DropShadow {
427 anchors.fill: mainContainer;587 anchors.fill: mainContainer;
428 horizontalOffset: 3;588 horizontalOffset: 0;
429 verticalOffset: 3;589 verticalOffset: 4;
430 radius: 8.0;590 radius: 4.0;
431 samples: 17;591 samples: 9
432 color: "#80000000";592 color: Qt.rgba(0, 0, 0, 0.25);
433 source: mainContainer;593 source: mainContainer;
434 }594 }
435 595
interface/resources/qml/hifi/commerce/purchases/Purchases.qml+76−78
@@ -32,7 +32,6 @@ Rectangle { · 31 unmodified lines
32 property bool securityImageResultReceived: false;32 property bool securityImageResultReceived: false;
33 property bool purchasesReceived: false;33 property bool purchasesReceived: false;
34 property bool punctuationMode: false;34 property bool punctuationMode: false;
35 property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified();
36 property bool pendingInventoryReply: true;35 property bool pendingInventoryReply: true;
37 property bool isShowingMyItems: false;36 property bool isShowingMyItems: false;
38 property bool isDebuggingFirstUseTutorial: false;37 property bool isDebuggingFirstUseTutorial: false;
@@ -148,7 +147,11 @@ Rectangle { · 109 unmodified lines
148 147
149 Connections {148 Connections {
150 onSendToParent: {149 onSendToParent: {
151 sendToScript(msg);150 if (msg.method === 'commerceLightboxLinkClicked') {
151 Qt.openUrlExternally(msg.linkUrl);
152 } else {
153 sendToScript(msg);
154 }
152 }155 }
153 }156 }
154 }157 }
@@ -297,7 +300,7 @@ Rectangle { · 142 unmodified lines
297 anchors.left: parent.left;300 anchors.left: parent.left;
298 anchors.leftMargin: 8;301 anchors.leftMargin: 8;
299 anchors.right: parent.right;302 anchors.right: parent.right;
300 anchors.rightMargin: 12;303 anchors.rightMargin: 16;
301 anchors.top: parent.top;304 anchors.top: parent.top;
302 anchors.topMargin: 4;305 anchors.topMargin: 4;
303 306
@@ -308,11 +311,11 @@ Rectangle { · 4 unmodified lines
308 anchors.bottom: parent.bottom;311 anchors.bottom: parent.bottom;
309 anchors.bottomMargin: 10;312 anchors.bottomMargin: 10;
310 anchors.left: parent.left;313 anchors.left: parent.left;
311 anchors.leftMargin: 4;314 anchors.leftMargin: 16;
312 width: paintedWidth;315 width: paintedWidth;
313 text: isShowingMyItems ? "My Items" : "My Purchases";316 text: isShowingMyItems ? "My Items" : "My Purchases";
314 color: hifi.colors.baseGray;317 color: hifi.colors.black;
315 size: 28;318 size: 22;
316 }319 }
317 320
318 HifiControlsUit.TextField {321 HifiControlsUit.TextField {
@@ -323,8 +326,8 @@ Rectangle { · 4 unmodified lines
323 hasRoundedBorder: true;326 hasRoundedBorder: true;
324 anchors.left: myText.right;327 anchors.left: myText.right;
325 anchors.leftMargin: 16;328 anchors.leftMargin: 16;
326 anchors.top: parent.top;329 height: 39;
327 anchors.bottom: parent.bottom;330 anchors.verticalCenter: parent.verticalCenter;
328 anchors.right: parent.right;331 anchors.right: parent.right;
329 placeholderText: "filter items";332 placeholderText: "filter items";
330 333
@@ -345,7 +348,7 @@ Rectangle { · 14 unmodified lines
345 348
346 HifiControlsUit.Separator {349 HifiControlsUit.Separator {
347 id: separator;350 id: separator;
348 colorScheme: 1;351 colorScheme: 2;
349 anchors.left: parent.left;352 anchors.left: parent.left;
350 anchors.right: parent.right;353 anchors.right: parent.right;
351 anchors.top: filterBarContainer.bottom;354 anchors.top: filterBarContainer.bottom;
@@ -365,69 +368,6 @@ Rectangle { · 13 unmodified lines
365 id: filteredPurchasesModel;368 id: filteredPurchasesModel;
366 }369 }
367 370
368 Rectangle {
369 id: cantRezCertified;
370 visible: !root.canRezCertifiedItems;
371 color: "#FFC3CD";
372 radius: 4;
373 border.color: hifi.colors.redAccent;
374 border.width: 1;
375 anchors.top: separator.bottom;
376 anchors.topMargin: 12;
377 anchors.left: parent.left;
378 anchors.leftMargin: 16;
379 anchors.right: parent.right;
380 anchors.rightMargin: 16;
381 height: 80;
382
383 HiFiGlyphs {
384 id: lightningIcon;
385 text: hifi.glyphs.lightning;
386 // Size
387 size: 36;
388 // Anchors
389 anchors.top: parent.top;
390 anchors.topMargin: 18;
391 anchors.left: parent.left;
392 anchors.leftMargin: 12;
393 horizontalAlignment: Text.AlignHCenter;
394 // Style
395 color: hifi.colors.lightGray;
396 }
397
398 RalewayRegular {
399 text: "You don't have permission to rez certified items in this domain. " +
400 '<b><font color="' + hifi.colors.blueAccent + '"><a href="#">Learn More</a></font></b>';
401 // Text size
402 size: 18;
403 // Anchors
404 anchors.top: parent.top;
405 anchors.topMargin: 4;
406 anchors.left: lightningIcon.right;
407 anchors.leftMargin: 8;
408 anchors.right: parent.right;
409 anchors.rightMargin: 8;
410 anchors.bottom: parent.bottom;
411 anchors.bottomMargin: 4;
412 // Style
413 color: hifi.colors.baseGray;
414 wrapMode: Text.WordWrap;
415 // Alignment
416 verticalAlignment: Text.AlignVCenter;
417
418 onLinkActivated: {
419 lightboxPopup.titleText = "Rez Permission Required";
420 lightboxPopup.bodyText = "You don't have permission to rez certified items in this domain.<br><br>" +
421 "Use the <b>GOTO app</b> to visit another domain or <b>go to your own sandbox.</b>";
422 lightboxPopup.button1text = "CLOSE";
423 lightboxPopup.button1method = "root.visible = false;"
424 lightboxPopup.button2text = "OPEN GOTO";
425 lightboxPopup.button2method = "sendToParent({method: 'purchases_openGoTo'});";
426 lightboxPopup.visible = true;
427 }
428 }
429 }
430
431 ListView {371 ListView {
432 id: purchasesContentsList;372 id: purchasesContentsList;
433 visible: (root.isShowingMyItems && filteredPurchasesModel.count !== 0) || (!root.isShowingMyItems && filteredPurchasesModel.count !== 0);373 visible: (root.isShowingMyItems && filteredPurchasesModel.count !== 0) || (!root.isShowingMyItems && filteredPurchasesModel.count !== 0);
@@ -436,13 +376,12 @@ Rectangle { · 2 unmodified lines
436 snapMode: ListView.SnapToItem;376 snapMode: ListView.SnapToItem;
437 highlightRangeMode: ListView.StrictlyEnforceRange;377 highlightRangeMode: ListView.StrictlyEnforceRange;
438 // Anchors378 // Anchors
439 anchors.top: root.canRezCertifiedItems ? separator.bottom : cantRezCertified.bottom;379 anchors.top: separator.bottom;
440 anchors.topMargin: 12;380 anchors.topMargin: 12;
441 anchors.left: parent.left;381 anchors.left: parent.left;
442 anchors.bottom: parent.bottom;382 anchors.bottom: parent.bottom;
443 width: parent.width;383 width: parent.width;
444 delegate: PurchasedItem {384 delegate: PurchasedItem {
445 canRezCertifiedItems: root.canRezCertifiedItems;
446 itemName: title;385 itemName: title;
447 itemId: id;386 itemId: id;
448 itemPreviewImageUrl: preview;387 itemPreviewImageUrl: preview;
@@ -454,16 +393,31 @@ Rectangle { · 5 unmodified lines
454 numberSold: model.number_sold;393 numberSold: model.number_sold;
455 limitedRun: model.limited_run;394 limitedRun: model.limited_run;
456 displayedItemCount: model.displayedItemCount;395 displayedItemCount: model.displayedItemCount;
457 isWearable: model.categories.indexOf("Wearables") > -1;396 permissionExplanationCardVisible: model.permissionExplanationCardVisible;
458 anchors.topMargin: 12;397 itemType: {
459 anchors.bottomMargin: 12;398 if (model.root_file_url.indexOf(".fst") > -1) {
399 "avatar";
400 } else if (model.categories.indexOf("Wearables") > -1) {
401 "wearable";
402 } else if (model.root_file_url.endsWith('.json.gz')) {
403 "contentSet";
404 } else if (model.root_file_url.endsWith('.app.json')) {
405 "app";
406 } else if (model.root_file_url.endsWith('.json')) {
407 "entity";
408 } else {
409 "unknown";
410 }
411 }
412 anchors.topMargin: 10;
413 anchors.bottomMargin: 10;
460 414
461 Connections {415 Connections {
462 onSendToPurchases: {416 onSendToPurchases: {
463 if (msg.method === 'purchases_itemInfoClicked') {417 if (msg.method === 'purchases_itemInfoClicked') {
464 sendToScript({method: 'purchases_itemInfoClicked', itemId: itemId});418 sendToScript({method: 'purchases_itemInfoClicked', itemId: itemId});
465 } else if (msg.method === "purchases_rezClicked") {419 } else if (msg.method === "purchases_rezClicked") {
466 sendToScript({method: 'purchases_rezClicked', itemHref: itemHref, isWearable: isWearable});420 sendToScript({method: 'purchases_rezClicked', itemHref: itemHref, itemType: itemType});
467 } else if (msg.method === 'purchases_itemCertificateClicked') {421 } else if (msg.method === 'purchases_itemCertificateClicked') {
468 inspectionCertificate.visible = true;422 inspectionCertificate.visible = true;
469 inspectionCertificate.isLightbox = true;423 inspectionCertificate.isLightbox = true;
@@ -482,8 +436,51 @@ Rectangle { · 12 unmodified lines
482 lightboxPopup.button1text = "CLOSE";436 lightboxPopup.button1text = "CLOSE";
483 lightboxPopup.button1method = "root.visible = false;"437 lightboxPopup.button1method = "root.visible = false;"
484 lightboxPopup.visible = true;438 lightboxPopup.visible = true;
439 } else if (msg.method === "showReplaceContentLightbox") {
440 lightboxPopup.titleText = "Replace Content";
441 lightboxPopup.bodyText = "Rezzing this content set will replace the existing environment and all of the items in this domain. " +
442 "If you want to save the state of the content in this domain, create a backup before proceeding.<br><br>" +
443 "For more information about backing up and restoring content, " +
444 "<a href='https://docs.highfidelity.com/create-and-explore/start-working-in-your-sandbox/restoring-sandbox-content'>" +
445 "click here to open info on your desktop browser.";
446 lightboxPopup.button1text = "CANCEL";
447 lightboxPopup.button1method = "root.visible = false;"
448 lightboxPopup.button2text = "CONFIRM";
449 lightboxPopup.button2method = "Commerce.replaceContentSet('" + msg.itemHref + "'); root.visible = false;";
450 lightboxPopup.visible = true;
451 } else if (msg.method === "showChangeAvatarLightbox") {
452 lightboxPopup.titleText = "Change Avatar";
453 lightboxPopup.bodyText = "This will change your current avatar to " + msg.itemName + " while retaining your wearables.";
454 lightboxPopup.button1text = "CANCEL";
455 lightboxPopup.button1method = "root.visible = false;"
456 lightboxPopup.button2text = "CONFIRM";
457 lightboxPopup.button2method = "MyAvatar.useFullAvatarURL('" + msg.itemHref + "'); root.visible = false;";
458 lightboxPopup.visible = true;
459 } else if (msg.method === "showPermissionsExplanation") {
460 if (msg.itemType === "entity") {
461 lightboxPopup.titleText = "Rez Certified Permission";
462 lightboxPopup.bodyText = "You don't have permission to rez certified items in this domain.<br><br>" +
463 "Use the <b>GOTO app</b> to visit another domain or <b>go to your own sandbox.</b>";
464 lightboxPopup.button2text = "OPEN GOTO";
465 lightboxPopup.button2method = "sendToParent({method: 'purchases_openGoTo'});";
466 } else if (msg.itemType === "contentSet") {
467 lightboxPopup.titleText = "Replace Content Permission";
468 lightboxPopup.bodyText = "You do not have the permission 'Replace Content' in this <b>domain's server settings</b>. The domain owner " +
469 "must enable it for you before you can replace content sets in this domain.";
470 }
471 lightboxPopup.button1text = "CLOSE";
472 lightboxPopup.button1method = "root.visible = false;"
473 lightboxPopup.visible = true;
485 } else if (msg.method === "setFilterText") {474 } else if (msg.method === "setFilterText") {
486 filterBar.text = msg.filterText;475 filterBar.text = msg.filterText;
476 } else if (msg.method === "openPermissionExplanationCard") {
477 for (var i = 0; i < filteredPurchasesModel.count; i++) {
478 if (i !== index || msg.closeAll) {
479 filteredPurchasesModel.setProperty(i, "permissionExplanationCardVisible", false);
480 } else {
481 filteredPurchasesModel.setProperty(i, "permissionExplanationCardVisible", true);
482 }
483 }
487 }484 }
488 }485 }
489 }486 }
@@ -685,6 +682,7 @@ Rectangle { · 195 unmodified lines
685 filteredPurchasesModel.clear();682 filteredPurchasesModel.clear();
686 for (var i = 0; i < tempPurchasesModel.count; i++) {683 for (var i = 0; i < tempPurchasesModel.count; i++) {
687 filteredPurchasesModel.append(tempPurchasesModel.get(i));684 filteredPurchasesModel.append(tempPurchasesModel.get(i));
685 filteredPurchasesModel.setProperty(i, 'permissionExplanationCardVisible', false);
688 }686 }
689 687
690 populateDisplayedItemCounts();688 populateDisplayedItemCounts();
interface/resources/qml/styles-uit/HifiConstants.qml+5−1
@@ -218,7 +218,7 @@ Item { · 217 unmodified lines
218 readonly property var colorStart: [ colors.white, colors.primaryHighlight, "#d42043", "#343434", Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0) ]218 readonly property var colorStart: [ colors.white, colors.primaryHighlight, "#d42043", "#343434", Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0) ]
219 readonly property var colorFinish: [ colors.lightGrayText, colors.blueAccent, "#94132e", colors.black, Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0) ]219 readonly property var colorFinish: [ colors.lightGrayText, colors.blueAccent, "#94132e", colors.black, Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0) ]
220 readonly property var hoveredColor: [ colorStart[white], colorStart[blue], colorStart[red], colorFinish[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ]220 readonly property var hoveredColor: [ colorStart[white], colorStart[blue], colorStart[red], colorFinish[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ]
221 readonly property var pressedColor: [ colorFinish[white], colorFinish[blue], colorFinish[red], colorStart[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ]221 readonly property var pressedColor: [ colorFinish[white], colorFinish[blue], colorFinish[red], colorStart[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colors.lightGrayText ]
222 readonly property var focusedColor: [ colors.lightGray50, colors.blueAccent, colors.redAccent, colors.darkGray, colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ]222 readonly property var focusedColor: [ colors.lightGray50, colors.blueAccent, colors.redAccent, colors.darkGray, colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ]
223 readonly property var disabledColorStart: [ colorStart[white], colors.baseGrayHighlight]223 readonly property var disabledColorStart: [ colorStart[white], colors.baseGrayHighlight]
224 readonly property var disabledColorFinish: [ colorFinish[white], colors.baseGrayShadow]224 readonly property var disabledColorFinish: [ colorFinish[white], colors.baseGrayShadow]
@@ -354,5 +354,9 @@ Item { · 129 unmodified lines
354 readonly property string wallet: "\ue027"354 readonly property string wallet: "\ue027"
355 readonly property string paperPlane: "\ue028"355 readonly property string paperPlane: "\ue028"
356 readonly property string passphrase: "\ue029"356 readonly property string passphrase: "\ue029"
357 readonly property string globe: "\ue02c"
358 readonly property string wand: "\ue02d"
359 readonly property string hat: "\ue02e"
360 readonly property string install: "\ue02f"
357 }361 }
358}362}
interface/src/Application.cpp+19−15
@@ -6370,6 +6370,24 @@ bool Application::askToWearAvatarAttachmentUrl(const QString& url) { · 6369 unmodified lines
6370 return true;6370 return true;
6371}6371}
6372 6372
6373void Application::replaceDomainContent(const QString& url) {
6374 qCDebug(interfaceapp) << "Attempting to replace domain content: " << url;
6375 QByteArray urlData(url.toUtf8());
6376 auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
6377 limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) {
6378 return node->getType() == NodeType::EntityServer && node->getActiveSocket();
6379 }, [&urlData, limitedNodeList](const SharedNodePointer& octreeNode) {
6380 auto octreeFilePacket = NLPacket::create(PacketType::OctreeFileReplacementFromUrl, urlData.size(), true);
6381 octreeFilePacket->write(urlData);
6382 limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode);
6383 });
6384 auto addressManager = DependencyManager::get<AddressManager>();
6385 addressManager->handleLookupString(DOMAIN_SPAWNING_POINT);
6386 QString newHomeAddress = addressManager->getHost() + DOMAIN_SPAWNING_POINT;
6387 qCDebug(interfaceapp) << "Setting new home bookmark to: " << newHomeAddress;
6388 DependencyManager::get<LocationBookmarks>()->setHomeLocationToAddress(newHomeAddress);
6389}
6390
6373bool Application::askToReplaceDomainContent(const QString& url) {6391bool Application::askToReplaceDomainContent(const QString& url) {
6374 QString methodDetails;6392 QString methodDetails;
6375 const int MAX_CHARACTERS_PER_LINE = 90;6393 const int MAX_CHARACTERS_PER_LINE = 90;
@@ -6389,21 +6407,7 @@ bool Application::askToReplaceDomainContent(const QString& url) { · 13 unmodified lines
6389 QString details;6407 QString details;
6390 if (static_cast<QMessageBox::StandardButton>(answer.toInt()) == QMessageBox::Yes) {6408 if (static_cast<QMessageBox::StandardButton>(answer.toInt()) == QMessageBox::Yes) {
6391 // Given confirmation, send request to domain server to replace content6409 // Given confirmation, send request to domain server to replace content
6392 qCDebug(interfaceapp) << "Attempting to replace domain content: " << url;6410 replaceDomainContent(url);
6393 QByteArray urlData(url.toUtf8());
6394 auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
6395 limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) {
6396 return node->getType() == NodeType::EntityServer && node->getActiveSocket();
6397 }, [&urlData, limitedNodeList](const SharedNodePointer& octreeNode) {
6398 auto octreeFilePacket = NLPacket::create(PacketType::OctreeFileReplacementFromUrl, urlData.size(), true);
6399 octreeFilePacket->write(urlData);
6400 limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode);
6401 });
6402 auto addressManager = DependencyManager::get<AddressManager>();
6403 addressManager->handleLookupString(DOMAIN_SPAWNING_POINT);
6404 QString newHomeAddress = addressManager->getHost() + DOMAIN_SPAWNING_POINT;
6405 qCDebug(interfaceapp) << "Setting new home bookmark to: " << newHomeAddress;
6406 DependencyManager::get<LocationBookmarks>()->setHomeLocationToAddress(newHomeAddress);
6407 details = "SuccessfulRequestToReplaceContent";6411 details = "SuccessfulRequestToReplaceContent";
6408 } else {6412 } else {
6409 details = "UserDeclinedToReplaceContent";6413 details = "UserDeclinedToReplaceContent";
interface/src/Application.h+2−0
@@ -288,6 +288,8 @@ public: · 287 unmodified lines
288 288
289 bool isServerlessMode() const { return !_serversEnabled; }289 bool isServerlessMode() const { return !_serversEnabled; }
290 290
291 void replaceDomainContent(const QString& url);
292
291signals:293signals:
292 void svoImportRequested(const QString& url);294 void svoImportRequested(const QString& url);
293 295
interface/src/avatar/MyAvatar.cpp+1−1
@@ -1479,7 +1479,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { · 1478 unmodified lines
1479 });1479 });
1480 saveAvatarUrl();1480 saveAvatarUrl();
1481 emit skeletonChanged();1481 emit skeletonChanged();
1482 1482 emit skeletonModelURLChanged();
1483}1483}
1484 1484
1485void MyAvatar::removeAvatarEntities() {1485void MyAvatar::removeAvatarEntities() {
interface/src/commerce/Ledger.cpp+10−0
@@ -49,6 +49,7 @@ Handler(balance) · 48 unmodified lines
49Handler(inventory)49Handler(inventory)
50Handler(transferHfcToNode)50Handler(transferHfcToNode)
51Handler(transferHfcToUsername)51Handler(transferHfcToUsername)
52Handler(alreadyOwned)
52 53
53void Ledger::send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, QJsonObject request) {54void Ledger::send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, QJsonObject request) {
54 auto accountManager = DependencyManager::get<AccountManager>();55 auto accountManager = DependencyManager::get<AccountManager>();
@@ -336,3 +337,12 @@ void Ledger::transferHfcToUsername(const QString& hfc_key, const QString& userna · 281 unmodified lines
336 auto transactionString = transactionDoc.toJson(QJsonDocument::Compact);337 auto transactionString = transactionDoc.toJson(QJsonDocument::Compact);
337 signedSend("transaction", transactionString, hfc_key, "transfer_hfc_to_user", "transferHfcToUsernameSuccess", "transferHfcToUsernameFailure");338 signedSend("transaction", transactionString, hfc_key, "transfer_hfc_to_user", "transferHfcToUsernameSuccess", "transferHfcToUsernameFailure");
338}339}
340
341void Ledger::alreadyOwned(const QString& marketplaceId) {
342 auto wallet = DependencyManager::get<Wallet>();
343 QString endpoint = "already_owned";
344 QJsonObject request;
345 request["public_keys"] = QJsonArray::fromStringList(wallet->listPublicKeys());
346 request["marketplace_item_id"] = marketplaceId;
347 send(endpoint, "alreadyOwnedSuccess", "alreadyOwnedFailure", QNetworkAccessManager::PutOperation, AccountManagerAuth::Required, request);
348}
interface/src/commerce/Ledger.h+4−0
@@ -35,6 +35,7 @@ public: · 34 unmodified lines
35 void certificateInfo(const QString& certificateId);35 void certificateInfo(const QString& certificateId);
36 void transferHfcToNode(const QString& hfc_key, const QString& nodeID, const int& amount, const QString& optionalMessage);36 void transferHfcToNode(const QString& hfc_key, const QString& nodeID, const int& amount, const QString& optionalMessage);
37 void transferHfcToUsername(const QString& hfc_key, const QString& username, const int& amount, const QString& optionalMessage);37 void transferHfcToUsername(const QString& hfc_key, const QString& username, const int& amount, const QString& optionalMessage);
38 void alreadyOwned(const QString& marketplaceId);
38 39
39 enum CertificateStatus {40 enum CertificateStatus {
40 CERTIFICATE_STATUS_UNKNOWN = 0,41 CERTIFICATE_STATUS_UNKNOWN = 0,
@@ -55,6 +56,7 @@ signals: · 14 unmodified lines
55 void certificateInfoResult(QJsonObject result);56 void certificateInfoResult(QJsonObject result);
56 void transferHfcToNodeResult(QJsonObject result);57 void transferHfcToNodeResult(QJsonObject result);
57 void transferHfcToUsernameResult(QJsonObject result);58 void transferHfcToUsernameResult(QJsonObject result);
59 void alreadyOwnedResult(QJsonObject result);
58 60
59 void updateCertificateStatus(const QString& certID, uint certStatus);61 void updateCertificateStatus(const QString& certID, uint certStatus);
60 62
@@ -79,6 +81,8 @@ public slots: · 18 unmodified lines
79 void transferHfcToNodeFailure(QNetworkReply& reply);81 void transferHfcToNodeFailure(QNetworkReply& reply);
80 void transferHfcToUsernameSuccess(QNetworkReply& reply);82 void transferHfcToUsernameSuccess(QNetworkReply& reply);
81 void transferHfcToUsernameFailure(QNetworkReply& reply);83 void transferHfcToUsernameFailure(QNetworkReply& reply);
84 void alreadyOwnedSuccess(QNetworkReply& reply);
85 void alreadyOwnedFailure(QNetworkReply& reply);
82 86
83private:87private:
84 QJsonObject apiResponse(const QString& label, QNetworkReply& reply);88 QJsonObject apiResponse(const QString& label, QNetworkReply& reply);
interface/src/commerce/QmlCommerce.cpp+20−0
@@ -15,6 +15,8 @@ · 14 unmodified lines
15#include "Ledger.h"15#include "Ledger.h"
16#include "Wallet.h"16#include "Wallet.h"
17#include <AccountManager.h>17#include <AccountManager.h>
18#include <Application.h>
19#include <UserActivityLogger.h>
18 20
19QmlCommerce::QmlCommerce() {21QmlCommerce::QmlCommerce() {
20 auto ledger = DependencyManager::get<Ledger>();22 auto ledger = DependencyManager::get<Ledger>();
@@ -28,9 +30,11 @@ QmlCommerce::QmlCommerce() { · 7 unmodified lines
28 connect(ledger.data(), &Ledger::accountResult, this, &QmlCommerce::accountResult);30 connect(ledger.data(), &Ledger::accountResult, this, &QmlCommerce::accountResult);
29 connect(wallet.data(), &Wallet::walletStatusResult, this, &QmlCommerce::walletStatusResult);31 connect(wallet.data(), &Wallet::walletStatusResult, this, &QmlCommerce::walletStatusResult);
30 connect(ledger.data(), &Ledger::certificateInfoResult, this, &QmlCommerce::certificateInfoResult);32 connect(ledger.data(), &Ledger::certificateInfoResult, this, &QmlCommerce::certificateInfoResult);
33 connect(ledger.data(), &Ledger::alreadyOwnedResult, this, &QmlCommerce::alreadyOwnedResult);
31 connect(ledger.data(), &Ledger::updateCertificateStatus, this, &QmlCommerce::updateCertificateStatus);34 connect(ledger.data(), &Ledger::updateCertificateStatus, this, &QmlCommerce::updateCertificateStatus);
32 connect(ledger.data(), &Ledger::transferHfcToNodeResult, this, &QmlCommerce::transferHfcToNodeResult);35 connect(ledger.data(), &Ledger::transferHfcToNodeResult, this, &QmlCommerce::transferHfcToNodeResult);
33 connect(ledger.data(), &Ledger::transferHfcToUsernameResult, this, &QmlCommerce::transferHfcToUsernameResult);36 connect(ledger.data(), &Ledger::transferHfcToUsernameResult, this, &QmlCommerce::transferHfcToUsernameResult);
37 connect(ledger.data(), &Ledger::transferHfcToUsernameResult, this, &QmlCommerce::transferHfcToUsernameResult);
34 38
35 auto accountManager = DependencyManager::get<AccountManager>();39 auto accountManager = DependencyManager::get<AccountManager>();
36 connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() {40 connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() {
@@ -163,3 +167,19 @@ void QmlCommerce::transferHfcToUsername(const QString& username, const int& amou · 126 unmodified lines
163 QString key = keys[0];167 QString key = keys[0];
164 ledger->transferHfcToUsername(key, username, amount, optionalMessage);168 ledger->transferHfcToUsername(key, username, amount, optionalMessage);
165}169}
170
171void QmlCommerce::replaceContentSet(const QString& itemHref) {
172 qApp->replaceDomainContent(itemHref);
173 QJsonObject messageProperties = {
174 { "status", "SuccessfulRequestToReplaceContent" },
175 { "content_set_url", itemHref }
176 };
177 UserActivityLogger::getInstance().logAction("replace_domain_content", messageProperties);
178
179 emit contentSetChanged(itemHref);
180}
181
182void QmlCommerce::alreadyOwned(const QString& marketplaceId) {
183 auto ledger = DependencyManager::get<Ledger>();
184 ledger->alreadyOwned(marketplaceId);
185}
interface/src/commerce/QmlCommerce.h+7−0
@@ -42,12 +42,15 @@ signals: · 41 unmodified lines
42 void historyResult(QJsonObject result);42 void historyResult(QJsonObject result);
43 void accountResult(QJsonObject result);43 void accountResult(QJsonObject result);
44 void certificateInfoResult(QJsonObject result);44 void certificateInfoResult(QJsonObject result);
45 void alreadyOwnedResult(QJsonObject result);
45 46
46 void updateCertificateStatus(const QString& certID, uint certStatus);47 void updateCertificateStatus(const QString& certID, uint certStatus);
47 48
48 void transferHfcToNodeResult(QJsonObject result);49 void transferHfcToNodeResult(QJsonObject result);
49 void transferHfcToUsernameResult(QJsonObject result);50 void transferHfcToUsernameResult(QJsonObject result);
50 51
52 void contentSetChanged(const QString& contentSetHref);
53
51protected:54protected:
52 Q_INVOKABLE void getWalletStatus();55 Q_INVOKABLE void getWalletStatus();
53 56
@@ -68,9 +71,13 @@ protected: · 14 unmodified lines
68 Q_INVOKABLE void account();71 Q_INVOKABLE void account();
69 72
70 Q_INVOKABLE void certificateInfo(const QString& certificateId);73 Q_INVOKABLE void certificateInfo(const QString& certificateId);
74 Q_INVOKABLE void alreadyOwned(const QString& marketplaceId);
71 75
72 Q_INVOKABLE void transferHfcToNode(const QString& nodeID, const int& amount, const QString& optionalMessage);76 Q_INVOKABLE void transferHfcToNode(const QString& nodeID, const int& amount, const QString& optionalMessage);
73 Q_INVOKABLE void transferHfcToUsername(const QString& username, const int& amount, const QString& optionalMessage);77 Q_INVOKABLE void transferHfcToUsername(const QString& username, const int& amount, const QString& optionalMessage);
78
79
80 Q_INVOKABLE void replaceContentSet(const QString& itemHref);
74};81};
75 82
76#endif // hifi_QmlCommerce_h83#endif // hifi_QmlCommerce_h
interface/src/scripting/AccountServicesScriptingInterface.h+1−1
@@ -38,7 +38,7 @@ class AccountServicesScriptingInterface : public QObject { · 37 unmodified lines
38 Q_PROPERTY(QString username READ getUsername NOTIFY myUsernameChanged)38 Q_PROPERTY(QString username READ getUsername NOTIFY myUsernameChanged)
39 Q_PROPERTY(bool loggedIn READ loggedIn NOTIFY loggedInChanged)39 Q_PROPERTY(bool loggedIn READ loggedIn NOTIFY loggedInChanged)
40 Q_PROPERTY(QString findableBy READ getFindableBy WRITE setFindableBy NOTIFY findableByChanged)40 Q_PROPERTY(QString findableBy READ getFindableBy WRITE setFindableBy NOTIFY findableByChanged)
41 Q_PROPERTY(QUrl metaverseServerURL READ getMetaverseServerURL)41 Q_PROPERTY(QUrl metaverseServerURL READ getMetaverseServerURL CONSTANT)
42 42
43public:43public:
44 static AccountServicesScriptingInterface* getInstance();44 static AccountServicesScriptingInterface* getInstance();
libraries/avatars/src/AvatarData.h+2−1
@@ -373,7 +373,7 @@ class AvatarData : public QObject, public SpatiallyNestable { · 372 unmodified lines
373 // The result is unique among all avatars present at the time.373 // The result is unique among all avatars present at the time.
374 Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName WRITE setSessionDisplayName NOTIFY sessionDisplayNameChanged)374 Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName WRITE setSessionDisplayName NOTIFY sessionDisplayNameChanged)
375 Q_PROPERTY(bool lookAtSnappingEnabled MEMBER _lookAtSnappingEnabled NOTIFY lookAtSnappingChanged)375 Q_PROPERTY(bool lookAtSnappingEnabled MEMBER _lookAtSnappingEnabled NOTIFY lookAtSnappingChanged)
376 Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript)376 Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript NOTIFY skeletonModelURLChanged)
377 Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData WRITE setAttachmentData)377 Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData WRITE setAttachmentData)
378 378
379 Q_PROPERTY(QStringList jointNames READ getJointNames)379 Q_PROPERTY(QStringList jointNames READ getJointNames)
@@ -702,6 +702,7 @@ public: · 322 unmodified lines
702signals:702signals:
703 void displayNameChanged();703 void displayNameChanged();
704 void sessionDisplayNameChanged();704 void sessionDisplayNameChanged();
705 void skeletonModelURLChanged();
705 void lookAtSnappingChanged(bool enabled);706 void lookAtSnappingChanged(bool enabled);
706 void sessionUUIDChanged();707 void sessionUUIDChanged();
707 708
libraries/avatars/src/ScriptAvatarData.cpp+1−0
@@ -16,6 +16,7 @@ ScriptAvatarData::ScriptAvatarData(AvatarSharedPointer avatarData) : · 15 unmodified lines
16{16{
17 QObject::connect(avatarData.get(), &AvatarData::displayNameChanged, this, &ScriptAvatarData::displayNameChanged);17 QObject::connect(avatarData.get(), &AvatarData::displayNameChanged, this, &ScriptAvatarData::displayNameChanged);
18 QObject::connect(avatarData.get(), &AvatarData::sessionDisplayNameChanged, this, &ScriptAvatarData::sessionDisplayNameChanged);18 QObject::connect(avatarData.get(), &AvatarData::sessionDisplayNameChanged, this, &ScriptAvatarData::sessionDisplayNameChanged);
19 QObject::connect(avatarData.get(), &AvatarData::skeletonModelURLChanged, this, &ScriptAvatarData::skeletonModelURLChanged);
19 QObject::connect(avatarData.get(), &AvatarData::lookAtSnappingChanged, this, &ScriptAvatarData::lookAtSnappingChanged);20 QObject::connect(avatarData.get(), &AvatarData::lookAtSnappingChanged, this, &ScriptAvatarData::lookAtSnappingChanged);
20}21}
21 22
libraries/avatars/src/ScriptAvatarData.h+2−1
@@ -51,7 +51,7 @@ class ScriptAvatarData : public QObject { · 50 unmodified lines
51 //51 //
52 // ATTACHMENT AND JOINT PROPERTIES52 // ATTACHMENT AND JOINT PROPERTIES
53 //53 //
54 Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript)54 Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript NOTIFY skeletonModelURLChanged)
55 Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData)55 Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData)
56 Q_PROPERTY(QStringList jointNames READ getJointNames)56 Q_PROPERTY(QStringList jointNames READ getJointNames)
57 57
@@ -132,6 +132,7 @@ public: · 74 unmodified lines
132signals:132signals:
133 void displayNameChanged();133 void displayNameChanged();
134 void sessionDisplayNameChanged();134 void sessionDisplayNameChanged();
135 void skeletonModelURLChanged();
135 void lookAtSnappingChanged(bool enabled);136 void lookAtSnappingChanged(bool enabled);
136 137
137public slots:138public slots:
libraries/entities/src/EntityScriptingInterface.cpp+5−0
@@ -101,6 +101,11 @@ bool EntityScriptingInterface::canWriteAssets() { · 100 unmodified lines
101 return nodeList->getThisNodeCanWriteAssets();101 return nodeList->getThisNodeCanWriteAssets();
102}102}
103 103
104bool EntityScriptingInterface::canReplaceContent() {
105 auto nodeList = DependencyManager::get<NodeList>();
106 return nodeList->getThisNodeCanReplaceContent();
107}
108
104void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) {109void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) {
105 if (_entityTree) {110 if (_entityTree) {
106 disconnect(_entityTree.get(), &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity);111 disconnect(_entityTree.get(), &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity);
libraries/entities/src/EntityScriptingInterface.h+6−0
@@ -144,6 +144,12 @@ public slots: · 143 unmodified lines
144 */144 */
145 Q_INVOKABLE bool canWriteAssets();145 Q_INVOKABLE bool canWriteAssets();
146 146
147 /**jsdoc
148 * @function Entities.canReplaceContent
149 * @return {bool} `true` if the DomainServer will allow this Node/Avatar to replace the domain's content set
150 */
151 Q_INVOKABLE bool canReplaceContent();
152
147 /**jsdoc153 /**jsdoc
148 * Add a new entity with the specified properties. If `clientOnly` is true, the entity will154 * Add a new entity with the specified properties. If `clientOnly` is true, the entity will
149 * not be sent to the server and will only be visible/accessible on the local client.155 * not be sent to the server and will only be visible/accessible on the local client.
libraries/render-utils/src/Shadow.slh+3−1
@@ -89,7 +89,9 @@ float evalShadowCascadeAttenuation(int cascadeIndex, ShadowSampleOffsets offsets · 88 unmodified lines
89 89
90float evalShadowAttenuation(vec3 worldLightDir, vec4 worldPosition, float viewDepth, vec3 worldNormal) {90float evalShadowAttenuation(vec3 worldLightDir, vec4 worldPosition, float viewDepth, vec3 worldNormal) {
91 ShadowSampleOffsets offsets = evalShadowFilterOffsets(worldPosition);91 ShadowSampleOffsets offsets = evalShadowFilterOffsets(worldPosition);
92 vec4 cascadeShadowCoords[2] = { vec4(0), vec4(0) };92 vec4 cascadeShadowCoords[2];
93 cascadeShadowCoords[0] = vec4(0);
94 cascadeShadowCoords[1] = vec4(0);
93 ivec2 cascadeIndices;95 ivec2 cascadeIndices;
94 float cascadeMix = determineShadowCascadesOnPixel(worldPosition, viewDepth, cascadeShadowCoords, cascadeIndices);96 float cascadeMix = determineShadowCascadesOnPixel(worldPosition, viewDepth, cascadeShadowCoords, cascadeIndices);
95 97
libraries/shared/src/PathUtils.cpp+1−0
@@ -129,6 +129,7 @@ QUrl PathUtils::expandToAppAbsolutePath(const QUrl& fileUrl) { · 128 unmodified lines
129 }129 }
130 return url;130 return url;
131}131}
132
132const QString& PathUtils::qmlBaseUrl() {133const QString& PathUtils::qmlBaseUrl() {
133 static const QString staticResourcePath = resourcesUrl() + "qml/";134 static const QString staticResourcePath = resourcesUrl() + "qml/";
134 return staticResourcePath;135 return staticResourcePath;
scripts/system/marketplaces/marketplaces.js+17−7
@@ -75,11 +75,11 @@ var selectionDisplay = null; // for gridTool.js to ignore · 74 unmodified lines
75 tablet.pushOntoStack(MARKETPLACE_CHECKOUT_QML_PATH);75 tablet.pushOntoStack(MARKETPLACE_CHECKOUT_QML_PATH);
76 tablet.sendToQml({76 tablet.sendToQml({
77 method: 'updateCheckoutQML', params: {77 method: 'updateCheckoutQML', params: {
78 itemId: '0d90d21c-ce7a-4990-ad18-e9d2cf991027',78 itemId: '424611a2-73d0-4c03-9087-26a6a279257b',
79 itemName: 'Test Flaregun',79 itemName: '2018-02-15 Finnegon',
80 itemPrice: (debugError ? 10 : 17),80 itemPrice: (debugError ? 10 : 3),
81 itemHref: 'http://mpassets.highfidelity.com/0d90d21c-ce7a-4990-ad18-e9d2cf991027-v1/flaregun.json',81 itemHref: 'http://devmpassets.highfidelity.com/424611a2-73d0-4c03-9087-26a6a279257b-v1/finnigon.fst',
82 categories: ["Wearables", "Miscellaneous"]82 categories: ["Miscellaneous"]
83 }83 }
84 });84 });
85 }85 }
@@ -233,13 +233,19 @@ var selectionDisplay = null; // for gridTool.js to ignore · 147 unmodified lines
233 return position;233 return position;
234 }234 }
235 235
236 function rezEntity(itemHref, isWearable) {236 function rezEntity(itemHref, itemType) {
237 var isWearable = itemType === "wearable";
237 var success = Clipboard.importEntities(itemHref);238 var success = Clipboard.importEntities(itemHref);
238 var wearableLocalPosition = null;239 var wearableLocalPosition = null;
239 var wearableLocalRotation = null;240 var wearableLocalRotation = null;
240 var wearableLocalDimensions = null;241 var wearableLocalDimensions = null;
241 var wearableDimensions = null;242 var wearableDimensions = null;
242 243
244 if (itemType === "contentSet") {
245 console.log("Item is a content set; codepath shouldn't go here.")
246 return;
247 }
248
243 if (isWearable) {249 if (isWearable) {
244 var wearableTransforms = Settings.getValue("io.highfidelity.avatarStore.checkOut.transforms");250 var wearableTransforms = Settings.getValue("io.highfidelity.avatarStore.checkOut.transforms");
245 if (!wearableTransforms) {251 if (!wearableTransforms) {
@@ -545,7 +551,11 @@ var selectionDisplay = null; // for gridTool.js to ignore · 299 unmodified lines
545 break;551 break;
546 case 'checkout_rezClicked':552 case 'checkout_rezClicked':
547 case 'purchases_rezClicked':553 case 'purchases_rezClicked':
548 rezEntity(message.itemHref, message.isWearable);554 if (message.itemType === "app") {
555 console.log("How did you get here? You can't buy apps yet!");
556 } else {
557 rezEntity(message.itemHref, message.itemType);
558 }
549 break;559 break;
550 case 'header_marketplaceImageClicked':560 case 'header_marketplaceImageClicked':
551 case 'purchases_backClicked':561 case 'purchases_backClicked':