Unified · Split
| @@ -9,6 +9,8 @@ · 8 unmodified lines | ||
| 9 | 9 | // 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 | 14 | #include <thread> |
| 13 | 15 | |
| 14 | 16 | #include <QtCore/QJsonArray> |
| @@ -36,8 +38,6 @@ · 21 unmodified lines | ||
| 36 | 38 | #include "AvatarAudioStream.h" |
| 37 | 39 | #include "InjectedAudioStream.h" |
| 38 | 40 | |
| 39 | −#include "AudioMixer.h" | |
| 40 | − | |
| 41 | 41 | static const float DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE = 0.5f; // attenuation = -6dB * log2(distance) |
| 42 | 42 | static const int DISABLE_STATIC_JITTER_FRAMES = -1; |
| 43 | 43 | static const float DEFAULT_NOISE_MUTING_THRESHOLD = 1.0f; |
| @@ -18,6 +18,8 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <ThreadedAssignment.h> |
| 19 | 19 | #include <UUIDHasher.h> |
| 20 | 20 | |
| 21 | +#include <plugins/Forward.h> | |
| 22 | + | |
| 21 | 23 | #include "AudioMixerStats.h" |
| 22 | 24 | #include "AudioMixerSlavePool.h" |
| 23 | 25 | |
| @@ -9,6 +9,8 @@ · 8 unmodified lines | ||
| 9 | 9 | // 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 | 14 | #include <random> |
| 13 | 15 | |
| 14 | 16 | #include <QtCore/QDebug> |
| @@ -22,8 +24,6 @@ · 7 unmodified lines | ||
| 22 | 24 | #include "AudioLogging.h" |
| 23 | 25 | #include "AudioHelpers.h" |
| 24 | 26 | #include "AudioMixer.h" |
| 25 | −#include "AudioMixerClientData.h" | |
| 26 | − | |
| 27 | 27 | |
| 28 | 28 | AudioMixerClientData::AudioMixerClientData(const QUuid& nodeID) : |
| 29 | 29 | NodeData(nodeID), |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <AudioLimiter.h> |
| 22 | 22 | #include <UUIDHasher.h> |
| 23 | 23 | |
| 24 | +#include <plugins/Forward.h> | |
| 24 | 25 | #include <plugins/CodecPlugin.h> |
| 25 | 26 | |
| 26 | 27 | #include "PositionalAudioStream.h" |
| @@ -9,6 +9,8 @@ · 8 unmodified lines | ||
| 9 | 9 | // 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 | 14 | #include <algorithm> |
| 13 | 15 | |
| 14 | 16 | #include <glm/glm.hpp> |
| @@ -34,8 +36,6 @@ · 19 unmodified lines | ||
| 34 | 36 | #include "InjectedAudioStream.h" |
| 35 | 37 | #include "AudioHelpers.h" |
| 36 | 38 | |
| 37 | −#include "AudioMixerSlave.h" | |
| 38 | − | |
| 39 | 39 | using AudioStreamMap = AudioMixerClientData::AudioStreamMap; |
| 40 | 40 | |
| 41 | 41 | // packet helpers |
Binary file not shown.
| @@ -14,8 +14,8 @@ import "../styles-uit" · 13 unmodified lines | ||
| 14 | 14 | Item { |
| 15 | 15 | property int colorScheme: 0; |
| 16 | 16 | |
| 17 | − readonly property var topColor: [ hifi.colors.baseGrayShadow, hifi.colors.faintGray ]; | |
| 18 | − readonly property var bottomColor: [ hifi.colors.baseGrayHighlight, 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, "#89858C" ]; | |
| 19 | 19 | |
| 20 | 20 | // Size |
| 21 | 21 | height: colorScheme === 0 ? 2 : 1; |
| @@ -34,11 +34,10 @@ TextField { · 33 unmodified lines | ||
| 34 | 34 | |
| 35 | 35 | placeholderText: textField.placeholderText |
| 36 | 36 | |
| 37 | − FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; } | |
| 37 | + FontLoader { id: firaSansRegular; source: "../../fonts/FiraSans-Regular.ttf"; } | |
| 38 | 38 | FontLoader { id: hifiGlyphs; source: "../../fonts/hifi-glyphs.ttf"; } |
| 39 | − font.family: firaSansSemiBold.name | |
| 39 | + font.family: firaSansRegular.name | |
| 40 | 40 | font.pixelSize: hifi.fontSizes.textFieldInput |
| 41 | − font.italic: textField.text == "" | |
| 42 | 41 | height: implicitHeight + 3 // Make surrounding box higher so that highlight is vertically centered. |
| 43 | 42 | property alias textFieldLabel: textFieldLabel |
| 44 | 43 | |
| @@ -28,7 +28,7 @@ Rectangle { · 27 unmodified lines | ||
| 28 | 28 | id: root; |
| 29 | 29 | objectName: "checkout" |
| 30 | 30 | property string activeView: "initialize"; |
| 31 | − property bool purchasesReceived: false; | |
| 31 | + property bool ownershipStatusReceived: false; | |
| 32 | 32 | property bool balanceReceived: false; |
| 33 | 33 | property string itemName; |
| 34 | 34 | property string itemId; |
| @@ -37,11 +37,16 @@ Rectangle { · 2 unmodified lines | ||
| 37 | 37 | property double balanceAfterPurchase; |
| 38 | 38 | property bool alreadyOwned: false; |
| 39 | 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 | 47 | property bool shouldBuyWithControlledFailure: false; |
| 42 | 48 | property bool debugCheckoutSuccess: false; |
| 43 | 49 | property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified(); |
| 44 | − property bool isWearable; | |
| 45 | 50 | property string referrer; |
| 46 | 51 | // Style |
| 47 | 52 | color: hifi.colors.white; |
| @@ -85,7 +90,9 @@ Rectangle { · 37 unmodified lines | ||
| 85 | 90 | UserActivityLogger.commercePurchaseFailure(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned, result.message); |
| 86 | 91 | } else { |
| 87 | 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 | 96 | root.activeView = "checkoutSuccess"; |
| 90 | 97 | UserActivityLogger.commercePurchaseSuccess(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned); |
| 91 | 98 | } |
| @@ -97,32 +104,53 @@ Rectangle { · 5 unmodified lines | ||
| 97 | 104 | } else { |
| 98 | 105 | root.balanceReceived = true; |
| 99 | 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 | 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 | 114 | } else { |
| 108 | − root.purchasesReceived = true; | |
| 109 | − if (purchasesContains(result.data.assets, itemId)) { | |
| 110 | − root.alreadyOwned = true; | |
| 115 | + root.ownershipStatusReceived = true; | |
| 116 | + if (result.data.marketplace_item_id === root.itemId) { | |
| 117 | + root.alreadyOwned = result.data.already_owned; | |
| 111 | 118 | } else { |
| 119 | + console.log("WARNING - Received 'Already Owned' status about different Marketplace ID!"); | |
| 112 | 120 | root.alreadyOwned = false; |
| 113 | 121 | } |
| 114 | − root.setBuyText(); | |
| 122 | + root.refreshBuyUI(); | |
| 115 | 123 | } |
| 116 | 124 | } |
| 117 | 125 | } |
| 118 | 126 | |
| 119 | 127 | onItemIdChanged: { |
| 120 | − Commerce.inventory(); | |
| 128 | + root.ownershipStatusReceived = false; | |
| 129 | + Commerce.alreadyOwned(root.itemId); | |
| 121 | 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 | 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 | 156 | onItemPriceChanged: { |
| @@ -203,7 +231,7 @@ Rectangle { · 74 unmodified lines | ||
| 203 | 231 | color: hifi.colors.white; |
| 204 | 232 | |
| 205 | 233 | Component.onCompleted: { |
| 206 | − purchasesReceived = false; | |
| 234 | + ownershipStatusReceived = false; | |
| 207 | 235 | balanceReceived = false; |
| 208 | 236 | Commerce.getWalletStatus(); |
| 209 | 237 | } |
| @@ -278,6 +306,31 @@ Rectangle { · 68 unmodified lines | ||
| 278 | 306 | anchors.left: parent.left; |
| 279 | 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 | 334 | RalewayRegular { |
| 282 | 335 | id: confirmPurchaseText; |
| 283 | 336 | anchors.top: parent.top; |
| @@ -286,8 +339,8 @@ Rectangle { · 2 unmodified lines | ||
| 286 | 339 | anchors.leftMargin: 16; |
| 287 | 340 | width: paintedWidth; |
| 288 | 341 | height: paintedHeight; |
| 289 | − text: "Confirm Purchase:"; | |
| 290 | − color: hifi.colors.baseGray; | |
| 342 | + text: "Review Purchase:"; | |
| 343 | + color: hifi.colors.black; | |
| 291 | 344 | size: 28; |
| 292 | 345 | } |
| 293 | 346 | |
| @@ -400,7 +453,7 @@ Rectangle { · 106 unmodified lines | ||
| 400 | 453 | width: root.width; |
| 401 | 454 | // Anchors |
| 402 | 455 | anchors.top: separator2.bottom; |
| 403 | − anchors.topMargin: 16; | |
| 456 | + anchors.topMargin: 0; | |
| 404 | 457 | anchors.left: parent.left; |
| 405 | 458 | anchors.leftMargin: 16; |
| 406 | 459 | anchors.right: parent.right; |
| @@ -411,8 +464,8 @@ Rectangle { · 4 unmodified lines | ||
| 411 | 464 | Rectangle { |
| 412 | 465 | id: buyTextContainer; |
| 413 | 466 | visible: buyText.text !== ""; |
| 414 | − anchors.top: cancelPurchaseButton.bottom; | |
| 415 | − anchors.topMargin: 16; | |
| 467 | + anchors.top: parent.top; | |
| 468 | + anchors.topMargin: 10; | |
| 416 | 469 | anchors.left: parent.left; |
| 417 | 470 | anchors.right: parent.right; |
| 418 | 471 | height: buyText.height + 30; |
| @@ -454,32 +507,63 @@ Rectangle { · 35 unmodified lines | ||
| 454 | 507 | // Alignment |
| 455 | 508 | horizontalAlignment: Text.AlignLeft; |
| 456 | 509 | verticalAlignment: Text.AlignVCenter; |
| 510 | + } | |
| 511 | + } | |
| 457 | 512 | |
| 458 | − onLinkActivated: { | |
| 459 | − sendToScript({method: 'checkout_goToPurchases', filterText: root.itemName}); | |
| 460 | − } | |
| 513 | + // "View in My Purchases" button | |
| 514 | + HifiControlsUit.Button { | |
| 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 | 530 | // "Buy" button |
| 465 | 531 | HifiControlsUit.Button { |
| 466 | 532 | id: buyButton; |
| 467 | − enabled: (root.balanceAfterPurchase >= 0 && purchasesReceived && balanceReceived) || !itemIsJson; | |
| 468 | − color: hifi.buttons.blue; | |
| 533 | + visible: !((root.itemType === "avatar" || root.itemType === "app") && viewInMyPurchasesButton.visible) | |
| 534 | + enabled: (root.balanceAfterPurchase >= 0 && ownershipStatusReceived && balanceReceived) || (!root.isCertified); | |
| 535 | + color: viewInMyPurchasesButton.visible ? hifi.buttons.white : hifi.buttons.blue; | |
| 469 | 536 | colorScheme: hifi.colorSchemes.light; |
| 470 | − anchors.top: checkoutActionButtonsContainer.top; | |
| 471 | − anchors.topMargin: 16; | |
| 472 | − height: 40; | |
| 537 | + anchors.top: viewInMyPurchasesButton.visible ? viewInMyPurchasesButton.bottom : | |
| 538 | + (buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top); | |
| 539 | + anchors.topMargin: 10; | |
| 540 | + height: 50; | |
| 473 | 541 | anchors.left: parent.left; |
| 474 | 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 | 545 | onClicked: { |
| 477 | − if (itemIsJson) { | |
| 478 | − buyButton.enabled = false; | |
| 546 | + if (root.isCertified) { | |
| 479 | 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 | 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 | 568 | } else { |
| 485 | 569 | if (urlHandler.canHandleUrl(itemHref)) { |
| @@ -494,9 +578,9 @@ Rectangle { · 8 unmodified lines | ||
| 494 | 578 | id: cancelPurchaseButton; |
| 495 | 579 | color: hifi.buttons.noneBorderlessGray; |
| 496 | 580 | colorScheme: hifi.colorSchemes.light; |
| 497 | − anchors.top: buyButton.bottom; | |
| 498 | − anchors.topMargin: 16; | |
| 499 | − height: 40; | |
| 581 | + anchors.top: buyButton.visible ? buyButton.bottom : viewInMyPurchasesButton.bottom; | |
| 582 | + anchors.topMargin: 10; | |
| 583 | + height: 50; | |
| 500 | 584 | anchors.left: parent.left; |
| 501 | 585 | anchors.right: parent.right; |
| 502 | 586 | text: "Cancel" |
| @@ -522,31 +606,32 @@ Rectangle { · 19 unmodified lines | ||
| 522 | 606 | anchors.top: titleBarContainer.bottom; |
| 523 | 607 | anchors.bottom: root.bottom; |
| 524 | 608 | anchors.left: parent.left; |
| 525 | − anchors.leftMargin: 16; | |
| 609 | + anchors.leftMargin: 20; | |
| 526 | 610 | anchors.right: parent.right; |
| 527 | − anchors.rightMargin: 16; | |
| 611 | + anchors.rightMargin: 20; | |
| 528 | 612 | |
| 529 | 613 | RalewayRegular { |
| 530 | 614 | id: completeText; |
| 531 | 615 | anchors.top: parent.top; |
| 532 | − anchors.topMargin: 30; | |
| 616 | + anchors.topMargin: 18; | |
| 533 | 617 | anchors.left: parent.left; |
| 534 | 618 | width: paintedWidth; |
| 535 | 619 | height: paintedHeight; |
| 536 | 620 | text: "Thank you for your order!"; |
| 537 | 621 | color: hifi.colors.baseGray; |
| 538 | − size: 28; | |
| 622 | + size: 36; | |
| 539 | 623 | } |
| 540 | 624 | |
| 541 | 625 | RalewaySemiBold { |
| 542 | 626 | id: completeText2; |
| 543 | − text: "The item " + '<font color="' + hifi.colors.blueAccent + '"><a href="#">' + root.itemName + '</a></font>' + | |
| 544 | − " has been added to your Purchases and a receipt will appear in your Wallet's transaction history."; | |
| 627 | + text: "The " + (root.itemTypesText)[itemTypesArray.indexOf(root.itemType)] + | |
| 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 | 630 | // Text size |
| 546 | − size: 20; | |
| 631 | + size: 18; | |
| 547 | 632 | // Anchors |
| 548 | 633 | anchors.top: completeText.bottom; |
| 549 | − anchors.topMargin: 10; | |
| 634 | + anchors.topMargin: 15; | |
| 550 | 635 | height: paintedHeight; |
| 551 | 636 | anchors.left: parent.left; |
| 552 | 637 | anchors.right: parent.right; |
| @@ -576,7 +661,7 @@ Rectangle { · 23 unmodified lines | ||
| 576 | 661 | |
| 577 | 662 | RalewayBold { |
| 578 | 663 | anchors.fill: parent; |
| 579 | − text: "REZZED"; | |
| 664 | + text: (root.buttonTextClicked)[itemTypesArray.indexOf(root.itemType)]; | |
| 580 | 665 | size: 18; |
| 581 | 666 | color: hifi.colors.white; |
| 582 | 667 | verticalAlignment: Text.AlignVCenter; |
| @@ -592,26 +677,52 @@ Rectangle { · 9 unmodified lines | ||
| 592 | 677 | // "Rez" button |
| 593 | 678 | HifiControlsUit.Button { |
| 594 | 679 | id: rezNowButton; |
| 595 | − enabled: root.canRezCertifiedItems || root.isWearable; | |
| 596 | − buttonGlyph: hifi.glyphs.lightning; | |
| 680 | + enabled: (root.itemType === "entity" && root.canRezCertifiedItems) || | |
| 681 | + (root.itemType === "contentSet" && Entities.canReplaceContent()) || | |
| 682 | + root.itemType === "wearable" || root.itemType === "avatar"; | |
| 683 | + buttonGlyph: (root.buttonGlyph)[itemTypesArray.indexOf(root.itemType)]; | |
| 597 | 684 | color: hifi.buttons.red; |
| 598 | 685 | colorScheme: hifi.colorSchemes.light; |
| 599 | 686 | anchors.top: completeText2.bottom; |
| 600 | − anchors.topMargin: 30; | |
| 687 | + anchors.topMargin: 27; | |
| 601 | 688 | height: 50; |
| 602 | 689 | anchors.left: parent.left; |
| 603 | 690 | anchors.right: parent.right; |
| 604 | − text: root.isWearable ? "Wear It" : "Rez It" | |
| 691 | + text: (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)]; | |
| 605 | 692 | onClicked: { |
| 606 | − sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, isWearable: root.isWearable}); | |
| 607 | − rezzedNotifContainer.visible = true; | |
| 608 | − rezzedNotifContainerTimer.start(); | |
| 609 | − UserActivityLogger.commerceEntityRezzed(root.itemId, "checkout", root.isWearable ? "rez" : "wear"); | |
| 693 | + if (root.itemType === "contentSet") { | |
| 694 | + lightboxPopup.titleText = "Replace Content"; | |
| 695 | + lightboxPopup.bodyText = "Rezzing this content set will replace the existing environment and all of the items in this domain. " + | |
| 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 | 723 | RalewaySemiBold { |
| 613 | 724 | id: noPermissionText; |
| 614 | − visible: !root.canRezCertifiedItems && !root.isWearable; | |
| 725 | + visible: !root.canRezCertifiedItems && root.itemType === "entity"; | |
| 615 | 726 | text: '<font color="' + hifi.colors.redAccent + '"><a href="#">You do not have Certified Rez permissions in this domain.</a></font>' |
| 616 | 727 | // Text size |
| 617 | 728 | size: 16; |
| @@ -640,7 +751,7 @@ Rectangle { · 22 unmodified lines | ||
| 640 | 751 | } |
| 641 | 752 | RalewaySemiBold { |
| 642 | 753 | id: explainRezText; |
| 643 | − visible: !root.isWearable; | |
| 754 | + visible: root.itemType === "entity"; | |
| 644 | 755 | text: '<font color="' + hifi.colors.redAccent + '"><a href="#">What does "Rez" mean?</a></font>' |
| 645 | 756 | // Text size |
| 646 | 757 | size: 16; |
| @@ -663,9 +774,9 @@ Rectangle { · 16 unmodified lines | ||
| 663 | 774 | |
| 664 | 775 | RalewaySemiBold { |
| 665 | 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 | 778 | // Text size |
| 668 | − size: 20; | |
| 779 | + size: 18; | |
| 669 | 780 | // Anchors |
| 670 | 781 | anchors.top: explainRezText.visible ? explainRezText.bottom : (noPermissionText.visible ? noPermissionText.bottom : rezNowButton.bottom); |
| 671 | 782 | anchors.topMargin: 40; |
| @@ -685,12 +796,12 @@ Rectangle { · 13 unmodified lines | ||
| 685 | 796 | |
| 686 | 797 | RalewaySemiBold { |
| 687 | 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 | 800 | // Text size |
| 690 | − size: 20; | |
| 801 | + size: 18; | |
| 691 | 802 | // Anchors |
| 692 | 803 | anchors.top: myPurchasesLink.bottom; |
| 693 | − anchors.topMargin: 20; | |
| 804 | + anchors.topMargin: 16; | |
| 694 | 805 | height: paintedHeight; |
| 695 | 806 | anchors.left: parent.left; |
| 696 | 807 | anchors.right: parent.right; |
| @@ -708,12 +819,12 @@ Rectangle { · 11 unmodified lines | ||
| 708 | 819 | RalewayRegular { |
| 709 | 820 | id: pendingText; |
| 710 | 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 | 823 | // Text size |
| 713 | − size: 20; | |
| 824 | + size: 18; | |
| 714 | 825 | // Anchors |
| 715 | 826 | anchors.top: walletLink.bottom; |
| 716 | − anchors.topMargin: 60; | |
| 827 | + anchors.topMargin: 32; | |
| 717 | 828 | height: paintedHeight; |
| 718 | 829 | anchors.left: parent.left; |
| 719 | 830 | anchors.right: parent.right; |
| @@ -739,11 +850,10 @@ Rectangle { · 19 unmodified lines | ||
| 739 | 850 | color: hifi.buttons.noneBorderlessGray; |
| 740 | 851 | colorScheme: hifi.colorSchemes.light; |
| 741 | 852 | anchors.bottom: parent.bottom; |
| 742 | − anchors.bottomMargin: 20; | |
| 853 | + anchors.bottomMargin: 54; | |
| 743 | 854 | anchors.right: parent.right; |
| 744 | − anchors.rightMargin: 14; | |
| 745 | − width: parent.width/2 - anchors.rightMargin; | |
| 746 | − height: 60; | |
| 855 | + width: 193; | |
| 856 | + height: 44; | |
| 747 | 857 | text: "Continue Shopping"; |
| 748 | 858 | onClicked: { |
| 749 | 859 | sendToScript({method: 'checkout_continueShopping', itemId: itemId}); |
| @@ -851,7 +961,7 @@ Rectangle { · 101 unmodified lines | ||
| 851 | 961 | buyButton.color = hifi.buttons.red; |
| 852 | 962 | root.shouldBuyWithControlledFailure = true; |
| 853 | 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 | 965 | buyButton.color = hifi.buttons.blue; |
| 856 | 966 | root.shouldBuyWithControlledFailure = false; |
| 857 | 967 | } |
| @@ -883,7 +993,7 @@ Rectangle { · 25 unmodified lines | ||
| 883 | 993 | itemHref = message.params.itemHref; |
| 884 | 994 | referrer = message.params.referrer; |
| 885 | 995 | itemAuthor = message.params.itemAuthor; |
| 886 | − setBuyText(); | |
| 996 | + refreshBuyUI(); | |
| 887 | 997 | break; |
| 888 | 998 | default: |
| 889 | 999 | console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message)); |
| @@ -891,22 +1001,13 @@ Rectangle { · 1 unmodified line | ||
| 891 | 1001 | } |
| 892 | 1002 | signal sendToScript(var message); |
| 893 | 1003 | |
| 894 | − function purchasesContains(purchasesJson, id) { | |
| 895 | − for (var idx = 0; idx < purchasesJson.length; idx++) { | |
| 896 | − if(purchasesJson[idx].id === id) { | |
| 897 | − return true; | |
| 898 | − } | |
| 899 | − } | |
| 900 | − return false; | |
| 901 | − } | |
| 902 | − | |
| 903 | − function setBuyText() { | |
| 904 | − if (root.itemIsJson) { | |
| 905 | − if (root.purchasesReceived && root.balanceReceived) { | |
| 1004 | + function refreshBuyUI() { | |
| 1005 | + if (root.isCertified) { | |
| 1006 | + if (root.ownershipStatusReceived && root.balanceReceived) { | |
| 906 | 1007 | if (root.balanceAfterPurchase < 0) { |
| 907 | 1008 | if (root.alreadyOwned) { |
| 908 | − buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item again.<br>" + | |
| 909 | − '<font color="' + hifi.colors.blueAccent + '"><a href="#">View the copy you own in My Purchases</a></font></b>'; | |
| 1009 | + buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item again.</b>"; | |
| 1010 | + viewInMyPurchasesButton.visible = true; | |
| 910 | 1011 | } else { |
| 911 | 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 | 1017 | buyGlyph.size = 54; |
| 917 | 1018 | } else { |
| 918 | 1019 | if (root.alreadyOwned) { |
| 919 | − buyText.text = '<b>You already own this item.<br>Purchasing it will buy another copy.<br><font color="' | |
| 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; | |
| 1020 | + viewInMyPurchasesButton.visible = true; | |
| 925 | 1021 | } else { |
| 926 | 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 | 1034 | } else { |
| 930 | 1035 | buyText.text = ""; |
| @@ -945,8 +1050,8 @@ Rectangle { · 14 unmodified lines | ||
| 945 | 1050 | root.activeView = "checkoutSuccess"; |
| 946 | 1051 | } |
| 947 | 1052 | root.balanceReceived = false; |
| 948 | − root.purchasesReceived = false; | |
| 949 | − Commerce.inventory(); | |
| 1053 | + root.ownershipStatusReceived = false; | |
| 1054 | + Commerce.alreadyOwned(root.itemId); | |
| 950 | 1055 | Commerce.balance(); |
| 951 | 1056 | } |
| 952 | 1057 | |
| @@ -100,6 +100,10 @@ Rectangle { · 99 unmodified lines | ||
| 100 | 100 | size: 20; |
| 101 | 101 | verticalAlignment: Text.AlignTop; |
| 102 | 102 | wrapMode: Text.WordWrap; |
| 103 | + | |
| 104 | + onLinkActivated: { | |
| 105 | + sendToParent({ method: 'commerceLightboxLinkClicked', linkUrl: link }); | |
| 106 | + } | |
| 103 | 107 | } |
| 104 | 108 | |
| 105 | 109 | Item { |
| @@ -90,11 +90,11 @@ Rectangle { · 89 unmodified lines | ||
| 90 | 90 | id: introText2; |
| 91 | 91 | text: "My Purchases"; |
| 92 | 92 | // Text size |
| 93 | − size: 28; | |
| 93 | + size: 22; | |
| 94 | 94 | // Anchors |
| 95 | 95 | anchors.top: introText1.bottom; |
| 96 | 96 | anchors.left: parent.left; |
| 97 | − anchors.leftMargin: 12; | |
| 97 | + anchors.leftMargin: 24; | |
| 98 | 98 | anchors.right: parent.right; |
| 99 | 99 | height: paintedHeight; |
| 100 | 100 | // Style |
| @@ -208,6 +208,7 @@ Rectangle { · 207 unmodified lines | ||
| 208 | 208 | // able to click on a button/mouseArea underneath the popup/section. |
| 209 | 209 | MouseArea { |
| 210 | 210 | anchors.fill: parent; |
| 211 | + hoverEnabled: true; | |
| 211 | 212 | propagateComposedEvents: false; |
| 212 | 213 | } |
| 213 | 214 | |
| @@ -20,6 +20,7 @@ import "../../../styles-uit" · 19 unmodified lines | ||
| 20 | 20 | import "../../../controls-uit" as HifiControlsUit |
| 21 | 21 | import "../../../controls" as HifiControls |
| 22 | 22 | import "../wallet" as HifiWallet |
| 23 | +import TabletScriptingInterface 1.0 | |
| 23 | 24 | |
| 24 | 25 | // references XXX from root context |
| 25 | 26 | |
| @@ -29,7 +30,6 @@ Item { · 3 unmodified lines | ||
| 29 | 30 | id: root; |
| 30 | 31 | property string purchaseStatus; |
| 31 | 32 | property bool purchaseStatusChanged; |
| 32 | − property bool canRezCertifiedItems: false; | |
| 33 | 33 | property string itemName; |
| 34 | 34 | property string itemId; |
| 35 | 35 | property string itemPreviewImageUrl; |
| @@ -39,7 +39,14 @@ Item { · 3 unmodified lines | ||
| 39 | 39 | property int itemEdition; |
| 40 | 40 | property int numberSold; |
| 41 | 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 | 51 | property string originalStatusText; |
| 45 | 52 | property string originalStatusColor; |
| @@ -47,6 +54,35 @@ Item { · 1 unmodified line | ||
| 47 | 54 | height: 110; |
| 48 | 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 | 86 | onPurchaseStatusChangedChanged: { |
| 51 | 87 | if (root.purchaseStatusChanged === true && root.purchaseStatus === "confirmed") { |
| 52 | 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 | 105 | Timer { |
| 61 | 106 | id: confirmedTimer; |
| 62 | 107 | interval: 3000; |
| @@ -73,10 +118,10 @@ Item { · 10 unmodified lines | ||
| 73 | 118 | color: hifi.colors.white; |
| 74 | 119 | // Size |
| 75 | 120 | anchors.left: parent.left; |
| 76 | − anchors.leftMargin: 8; | |
| 121 | + anchors.leftMargin: 16; | |
| 77 | 122 | anchors.right: parent.right; |
| 78 | − anchors.rightMargin: 8; | |
| 79 | − anchors.top: parent.top; | |
| 123 | + anchors.rightMargin: 16; | |
| 124 | + anchors.verticalCenter: parent.verticalCenter; | |
| 80 | 125 | height: root.height - 10; |
| 81 | 126 | |
| 82 | 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 | 149 | RalewaySemiBold { |
| 101 | 150 | id: itemName; |
| 102 | 151 | anchors.top: itemPreviewImage.top; |
| 103 | 152 | anchors.topMargin: 4; |
| 104 | 153 | anchors.left: itemPreviewImage.right; |
| 105 | 154 | anchors.leftMargin: 8; |
| 106 | − anchors.right: buttonContainer.left; | |
| 107 | − anchors.rightMargin: 8; | |
| 155 | + width: !noPermissionGlyph.visible ? (buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width - anchors.leftMargin) : | |
| 156 | + Math.min(itemNameTextMetrics.tightBoundingRect.width + 2, | |
| 157 | + buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width - anchors.leftMargin - noPermissionGlyph.width + 2); | |
| 108 | 158 | height: paintedHeight; |
| 109 | 159 | // Text size |
| 110 | 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 | 271 | Item { |
| 135 | 272 | id: certificateContainer; |
| @@ -151,19 +288,19 @@ Item { · 15 unmodified lines | ||
| 151 | 288 | anchors.bottom: parent.bottom; |
| 152 | 289 | width: 32; |
| 153 | 290 | // Style |
| 154 | − color: hifi.colors.lightGray; | |
| 291 | + color: hifi.colors.black; | |
| 155 | 292 | } |
| 156 | 293 | |
| 157 | 294 | RalewayRegular { |
| 158 | 295 | id: viewCertificateText; |
| 159 | 296 | text: "VIEW CERTIFICATE"; |
| 160 | − size: 14; | |
| 297 | + size: 13; | |
| 161 | 298 | anchors.left: certificateIcon.right; |
| 162 | 299 | anchors.leftMargin: 4; |
| 163 | 300 | anchors.top: parent.top; |
| 164 | 301 | anchors.bottom: parent.bottom; |
| 165 | 302 | anchors.right: parent.right; |
| 166 | − color: hifi.colors.lightGray; | |
| 303 | + color: hifi.colors.black; | |
| 167 | 304 | } |
| 168 | 305 | |
| 169 | 306 | MouseArea { |
| @@ -173,13 +310,13 @@ Item { · 3 unmodified lines | ||
| 173 | 310 | sendToPurchases({method: 'purchases_itemCertificateClicked', itemCertificateId: root.certificateId}); |
| 174 | 311 | } |
| 175 | 312 | onEntered: { |
| 176 | − certificateIcon.color = hifi.colors.black; | |
| 177 | − viewCertificateText.color = hifi.colors.black; | |
| 178 | − } | |
| 179 | − onExited: { | |
| 180 | 313 | certificateIcon.color = hifi.colors.lightGray; |
| 181 | 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 | 330 | anchors.right: buttonContainer.left; |
| 194 | 331 | anchors.rightMargin: 2; |
| 195 | 332 | |
| 196 | − FiraSansRegular { | |
| 333 | + RalewayRegular { | |
| 197 | 334 | anchors.left: parent.left; |
| 198 | 335 | anchors.top: parent.top; |
| 199 | 336 | anchors.bottom: parent.bottom; |
| 200 | 337 | width: paintedWidth; |
| 201 | 338 | text: "#" + root.itemEdition; |
| 202 | − size: 15; | |
| 203 | − color: "#cc6a6a6a"; | |
| 339 | + size: 13; | |
| 340 | + color: hifi.colors.black; | |
| 204 | 341 | verticalAlignment: Text.AlignTop; |
| 205 | 342 | } |
| 206 | 343 | } |
| @@ -311,7 +448,7 @@ Item { · 104 unmodified lines | ||
| 311 | 448 | id: rezzedNotifContainer; |
| 312 | 449 | z: 998; |
| 313 | 450 | visible: false; |
| 314 | − color: hifi.colors.blueHighlight; | |
| 451 | + color: "#1FC6A6"; | |
| 315 | 452 | anchors.fill: buttonContainer; |
| 316 | 453 | MouseArea { |
| 317 | 454 | anchors.fill: parent; |
| @@ -321,8 +458,8 @@ Item { · 3 unmodified lines | ||
| 321 | 458 | |
| 322 | 459 | RalewayBold { |
| 323 | 460 | anchors.fill: parent; |
| 324 | − text: "REZZED"; | |
| 325 | − size: 18; | |
| 461 | + text: (root.buttonTextClicked)[itemTypesArray.indexOf(root.itemType)]; | |
| 462 | + size: 15; | |
| 326 | 463 | color: hifi.colors.white; |
| 327 | 464 | verticalAlignment: Text.AlignVCenter; |
| 328 | 465 | horizontalAlignment: Text.AlignHCenter; |
| @@ -337,25 +474,47 @@ Item { · 8 unmodified lines | ||
| 337 | 474 | |
| 338 | 475 | Button { |
| 339 | 476 | id: buttonContainer; |
| 340 | − property int color: hifi.buttons.red; | |
| 477 | + property int color: hifi.buttons.blue; | |
| 341 | 478 | property int colorScheme: hifi.colorSchemes.light; |
| 342 | 479 | |
| 343 | 480 | anchors.top: parent.top; |
| 481 | + anchors.topMargin: 4; | |
| 344 | 482 | anchors.bottom: parent.bottom; |
| 483 | + anchors.bottomMargin: 4; | |
| 345 | 484 | anchors.right: parent.right; |
| 485 | + anchors.rightMargin: 4; | |
| 346 | 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 | 503 | onClicked: { |
| 350 | − sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, isWearable: root.isWearable}); | |
| 351 | − rezzedNotifContainer.visible = true; | |
| 352 | − rezzedNotifContainerTimer.start(); | |
| 353 | − UserActivityLogger.commerceEntityRezzed(root.itemId, "purchases", root.isWearable ? "rez" : "wear"); | |
| 504 | + Tablet.playSound(TabletEnums.ButtonClick); | |
| 505 | + if (root.itemType === "contentSet") { | |
| 506 | + sendToPurchases({method: 'showReplaceContentLightbox', itemHref: root.itemHref}); | |
| 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 | 515 | style: ButtonStyle { |
| 357 | − | |
| 358 | 516 | background: Rectangle { |
| 517 | + radius: 4; | |
| 359 | 518 | gradient: Gradient { |
| 360 | 519 | GradientStop { |
| 361 | 520 | position: 0.2 |
| @@ -390,13 +549,13 @@ Item { · 28 unmodified lines | ||
| 390 | 549 | |
| 391 | 550 | label: Item { |
| 392 | 551 | HiFiGlyphs { |
| 393 | − id: lightningIcon; | |
| 394 | − text: hifi.glyphs.lightning; | |
| 552 | + id: rezIcon; | |
| 553 | + text: (root.buttonGlyph)[itemTypesArray.indexOf(root.itemType)]; | |
| 395 | 554 | // Size |
| 396 | − size: 32; | |
| 555 | + size: 60; | |
| 397 | 556 | // Anchors |
| 398 | 557 | anchors.top: parent.top; |
| 399 | − anchors.topMargin: 12; | |
| 558 | + anchors.topMargin: 0; | |
| 400 | 559 | anchors.left: parent.left; |
| 401 | 560 | anchors.right: parent.right; |
| 402 | 561 | horizontalAlignment: Text.AlignHCenter; |
| @@ -405,18 +564,19 @@ Item { · 2 unmodified lines | ||
| 405 | 564 | : hifi.buttons.disabledTextColor[control.colorScheme] |
| 406 | 565 | } |
| 407 | 566 | RalewayBold { |
| 408 | − anchors.top: lightningIcon.bottom; | |
| 409 | − anchors.topMargin: -20; | |
| 567 | + id: rezIconLabel; | |
| 568 | + anchors.top: rezIcon.bottom; | |
| 569 | + anchors.topMargin: -4; | |
| 410 | 570 | anchors.right: parent.right; |
| 411 | 571 | anchors.left: parent.left; |
| 412 | 572 | anchors.bottom: parent.bottom; |
| 413 | 573 | font.capitalization: Font.AllUppercase |
| 414 | 574 | color: enabled ? hifi.buttons.textColor[control.color] |
| 415 | 575 | : hifi.buttons.disabledTextColor[control.colorScheme] |
| 416 | − size: 16; | |
| 576 | + size: 15; | |
| 417 | 577 | verticalAlignment: Text.AlignVCenter |
| 418 | 578 | 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 | 586 | DropShadow { |
| 427 | 587 | anchors.fill: mainContainer; |
| 428 | − horizontalOffset: 3; | |
| 429 | − verticalOffset: 3; | |
| 430 | − radius: 8.0; | |
| 431 | − samples: 17; | |
| 432 | − color: "#80000000"; | |
| 588 | + horizontalOffset: 0; | |
| 589 | + verticalOffset: 4; | |
| 590 | + radius: 4.0; | |
| 591 | + samples: 9 | |
| 592 | + color: Qt.rgba(0, 0, 0, 0.25); | |
| 433 | 593 | source: mainContainer; |
| 434 | 594 | } |
| 435 | 595 | |
| @@ -32,7 +32,6 @@ Rectangle { · 31 unmodified lines | ||
| 32 | 32 | property bool securityImageResultReceived: false; |
| 33 | 33 | property bool purchasesReceived: false; |
| 34 | 34 | property bool punctuationMode: false; |
| 35 | − property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified(); | |
| 36 | 35 | property bool pendingInventoryReply: true; |
| 37 | 36 | property bool isShowingMyItems: false; |
| 38 | 37 | property bool isDebuggingFirstUseTutorial: false; |
| @@ -148,7 +147,11 @@ Rectangle { · 109 unmodified lines | ||
| 148 | 147 | |
| 149 | 148 | Connections { |
| 150 | 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 | 300 | anchors.left: parent.left; |
| 298 | 301 | anchors.leftMargin: 8; |
| 299 | 302 | anchors.right: parent.right; |
| 300 | − anchors.rightMargin: 12; | |
| 303 | + anchors.rightMargin: 16; | |
| 301 | 304 | anchors.top: parent.top; |
| 302 | 305 | anchors.topMargin: 4; |
| 303 | 306 | |
| @@ -308,11 +311,11 @@ Rectangle { · 4 unmodified lines | ||
| 308 | 311 | anchors.bottom: parent.bottom; |
| 309 | 312 | anchors.bottomMargin: 10; |
| 310 | 313 | anchors.left: parent.left; |
| 311 | − anchors.leftMargin: 4; | |
| 314 | + anchors.leftMargin: 16; | |
| 312 | 315 | width: paintedWidth; |
| 313 | 316 | text: isShowingMyItems ? "My Items" : "My Purchases"; |
| 314 | − color: hifi.colors.baseGray; | |
| 315 | − size: 28; | |
| 317 | + color: hifi.colors.black; | |
| 318 | + size: 22; | |
| 316 | 319 | } |
| 317 | 320 | |
| 318 | 321 | HifiControlsUit.TextField { |
| @@ -323,8 +326,8 @@ Rectangle { · 4 unmodified lines | ||
| 323 | 326 | hasRoundedBorder: true; |
| 324 | 327 | anchors.left: myText.right; |
| 325 | 328 | anchors.leftMargin: 16; |
| 326 | − anchors.top: parent.top; | |
| 327 | − anchors.bottom: parent.bottom; | |
| 329 | + height: 39; | |
| 330 | + anchors.verticalCenter: parent.verticalCenter; | |
| 328 | 331 | anchors.right: parent.right; |
| 329 | 332 | placeholderText: "filter items"; |
| 330 | 333 | |
| @@ -345,7 +348,7 @@ Rectangle { · 14 unmodified lines | ||
| 345 | 348 | |
| 346 | 349 | HifiControlsUit.Separator { |
| 347 | 350 | id: separator; |
| 348 | − colorScheme: 1; | |
| 351 | + colorScheme: 2; | |
| 349 | 352 | anchors.left: parent.left; |
| 350 | 353 | anchors.right: parent.right; |
| 351 | 354 | anchors.top: filterBarContainer.bottom; |
| @@ -365,69 +368,6 @@ Rectangle { · 13 unmodified lines | ||
| 365 | 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 | 371 | ListView { |
| 432 | 372 | id: purchasesContentsList; |
| 433 | 373 | visible: (root.isShowingMyItems && filteredPurchasesModel.count !== 0) || (!root.isShowingMyItems && filteredPurchasesModel.count !== 0); |
| @@ -436,13 +376,12 @@ Rectangle { · 2 unmodified lines | ||
| 436 | 376 | snapMode: ListView.SnapToItem; |
| 437 | 377 | highlightRangeMode: ListView.StrictlyEnforceRange; |
| 438 | 378 | // Anchors |
| 439 | − anchors.top: root.canRezCertifiedItems ? separator.bottom : cantRezCertified.bottom; | |
| 379 | + anchors.top: separator.bottom; | |
| 440 | 380 | anchors.topMargin: 12; |
| 441 | 381 | anchors.left: parent.left; |
| 442 | 382 | anchors.bottom: parent.bottom; |
| 443 | 383 | width: parent.width; |
| 444 | 384 | delegate: PurchasedItem { |
| 445 | − canRezCertifiedItems: root.canRezCertifiedItems; | |
| 446 | 385 | itemName: title; |
| 447 | 386 | itemId: id; |
| 448 | 387 | itemPreviewImageUrl: preview; |
| @@ -454,16 +393,31 @@ Rectangle { · 5 unmodified lines | ||
| 454 | 393 | numberSold: model.number_sold; |
| 455 | 394 | limitedRun: model.limited_run; |
| 456 | 395 | displayedItemCount: model.displayedItemCount; |
| 457 | − isWearable: model.categories.indexOf("Wearables") > -1; | |
| 458 | − anchors.topMargin: 12; | |
| 459 | − anchors.bottomMargin: 12; | |
| 396 | + permissionExplanationCardVisible: model.permissionExplanationCardVisible; | |
| 397 | + itemType: { | |
| 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 | 415 | Connections { |
| 462 | 416 | onSendToPurchases: { |
| 463 | 417 | if (msg.method === 'purchases_itemInfoClicked') { |
| 464 | 418 | sendToScript({method: 'purchases_itemInfoClicked', itemId: itemId}); |
| 465 | 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 | 421 | } else if (msg.method === 'purchases_itemCertificateClicked') { |
| 468 | 422 | inspectionCertificate.visible = true; |
| 469 | 423 | inspectionCertificate.isLightbox = true; |
| @@ -482,8 +436,51 @@ Rectangle { · 12 unmodified lines | ||
| 482 | 436 | lightboxPopup.button1text = "CLOSE"; |
| 483 | 437 | lightboxPopup.button1method = "root.visible = false;" |
| 484 | 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 | 474 | } else if (msg.method === "setFilterText") { |
| 486 | 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 | 682 | filteredPurchasesModel.clear(); |
| 686 | 683 | for (var i = 0; i < tempPurchasesModel.count; i++) { |
| 687 | 684 | filteredPurchasesModel.append(tempPurchasesModel.get(i)); |
| 685 | + filteredPurchasesModel.setProperty(i, 'permissionExplanationCardVisible', false); | |
| 688 | 686 | } |
| 689 | 687 | |
| 690 | 688 | populateDisplayedItemCounts(); |
| @@ -218,7 +218,7 @@ Item { · 217 unmodified lines | ||
| 218 | 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 | 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 | 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 | 222 | readonly property var focusedColor: [ colors.lightGray50, colors.blueAccent, colors.redAccent, colors.darkGray, colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ] |
| 223 | 223 | readonly property var disabledColorStart: [ colorStart[white], colors.baseGrayHighlight] |
| 224 | 224 | readonly property var disabledColorFinish: [ colorFinish[white], colors.baseGrayShadow] |
| @@ -354,5 +354,9 @@ Item { · 129 unmodified lines | ||
| 354 | 354 | readonly property string wallet: "\ue027" |
| 355 | 355 | readonly property string paperPlane: "\ue028" |
| 356 | 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 | } |
| @@ -6370,6 +6370,24 @@ bool Application::askToWearAvatarAttachmentUrl(const QString& url) { · 6369 unmodified lines | ||
| 6370 | 6370 | return true; |
| 6371 | 6371 | } |
| 6372 | 6372 | |
| 6373 | +void 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 | + | |
| 6373 | 6391 | bool Application::askToReplaceDomainContent(const QString& url) { |
| 6374 | 6392 | QString methodDetails; |
| 6375 | 6393 | const int MAX_CHARACTERS_PER_LINE = 90; |
| @@ -6389,21 +6407,7 @@ bool Application::askToReplaceDomainContent(const QString& url) { · 13 unmodified lines | ||
| 6389 | 6407 | QString details; |
| 6390 | 6408 | if (static_cast<QMessageBox::StandardButton>(answer.toInt()) == QMessageBox::Yes) { |
| 6391 | 6409 | // Given confirmation, send request to domain server to replace content |
| 6392 | − qCDebug(interfaceapp) << "Attempting to replace domain content: " << 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); | |
| 6410 | + replaceDomainContent(url); | |
| 6407 | 6411 | details = "SuccessfulRequestToReplaceContent"; |
| 6408 | 6412 | } else { |
| 6409 | 6413 | details = "UserDeclinedToReplaceContent"; |
| @@ -288,6 +288,8 @@ public: · 287 unmodified lines | ||
| 288 | 288 | |
| 289 | 289 | bool isServerlessMode() const { return !_serversEnabled; } |
| 290 | 290 | |
| 291 | + void replaceDomainContent(const QString& url); | |
| 292 | + | |
| 291 | 293 | signals: |
| 292 | 294 | void svoImportRequested(const QString& url); |
| 293 | 295 | |
| @@ -1479,7 +1479,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { · 1478 unmodified lines | ||
| 1479 | 1479 | }); |
| 1480 | 1480 | saveAvatarUrl(); |
| 1481 | 1481 | emit skeletonChanged(); |
| 1482 | − | |
| 1482 | + emit skeletonModelURLChanged(); | |
| 1483 | 1483 | } |
| 1484 | 1484 | |
| 1485 | 1485 | void MyAvatar::removeAvatarEntities() { |
| @@ -49,6 +49,7 @@ Handler(balance) · 48 unmodified lines | ||
| 49 | 49 | Handler(inventory) |
| 50 | 50 | Handler(transferHfcToNode) |
| 51 | 51 | Handler(transferHfcToUsername) |
| 52 | +Handler(alreadyOwned) | |
| 52 | 53 | |
| 53 | 54 | void Ledger::send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, QJsonObject request) { |
| 54 | 55 | auto accountManager = DependencyManager::get<AccountManager>(); |
| @@ -336,3 +337,12 @@ void Ledger::transferHfcToUsername(const QString& hfc_key, const QString& userna · 281 unmodified lines | ||
| 336 | 337 | auto transactionString = transactionDoc.toJson(QJsonDocument::Compact); |
| 337 | 338 | signedSend("transaction", transactionString, hfc_key, "transfer_hfc_to_user", "transferHfcToUsernameSuccess", "transferHfcToUsernameFailure"); |
| 338 | 339 | } |
| 340 | + | |
| 341 | +void 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 | +} | |
| @@ -35,6 +35,7 @@ public: · 34 unmodified lines | ||
| 35 | 35 | void certificateInfo(const QString& certificateId); |
| 36 | 36 | void transferHfcToNode(const QString& hfc_key, const QString& nodeID, const int& amount, const QString& optionalMessage); |
| 37 | 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 | 40 | enum CertificateStatus { |
| 40 | 41 | CERTIFICATE_STATUS_UNKNOWN = 0, |
| @@ -55,6 +56,7 @@ signals: · 14 unmodified lines | ||
| 55 | 56 | void certificateInfoResult(QJsonObject result); |
| 56 | 57 | void transferHfcToNodeResult(QJsonObject result); |
| 57 | 58 | void transferHfcToUsernameResult(QJsonObject result); |
| 59 | + void alreadyOwnedResult(QJsonObject result); | |
| 58 | 60 | |
| 59 | 61 | void updateCertificateStatus(const QString& certID, uint certStatus); |
| 60 | 62 | |
| @@ -79,6 +81,8 @@ public slots: · 18 unmodified lines | ||
| 79 | 81 | void transferHfcToNodeFailure(QNetworkReply& reply); |
| 80 | 82 | void transferHfcToUsernameSuccess(QNetworkReply& reply); |
| 81 | 83 | void transferHfcToUsernameFailure(QNetworkReply& reply); |
| 84 | + void alreadyOwnedSuccess(QNetworkReply& reply); | |
| 85 | + void alreadyOwnedFailure(QNetworkReply& reply); | |
| 82 | 86 | |
| 83 | 87 | private: |
| 84 | 88 | QJsonObject apiResponse(const QString& label, QNetworkReply& reply); |
| @@ -15,6 +15,8 @@ · 14 unmodified lines | ||
| 15 | 15 | #include "Ledger.h" |
| 16 | 16 | #include "Wallet.h" |
| 17 | 17 | #include <AccountManager.h> |
| 18 | +#include <Application.h> | |
| 19 | +#include <UserActivityLogger.h> | |
| 18 | 20 | |
| 19 | 21 | QmlCommerce::QmlCommerce() { |
| 20 | 22 | auto ledger = DependencyManager::get<Ledger>(); |
| @@ -28,9 +30,11 @@ QmlCommerce::QmlCommerce() { · 7 unmodified lines | ||
| 28 | 30 | connect(ledger.data(), &Ledger::accountResult, this, &QmlCommerce::accountResult); |
| 29 | 31 | connect(wallet.data(), &Wallet::walletStatusResult, this, &QmlCommerce::walletStatusResult); |
| 30 | 32 | connect(ledger.data(), &Ledger::certificateInfoResult, this, &QmlCommerce::certificateInfoResult); |
| 33 | + connect(ledger.data(), &Ledger::alreadyOwnedResult, this, &QmlCommerce::alreadyOwnedResult); | |
| 31 | 34 | connect(ledger.data(), &Ledger::updateCertificateStatus, this, &QmlCommerce::updateCertificateStatus); |
| 32 | 35 | connect(ledger.data(), &Ledger::transferHfcToNodeResult, this, &QmlCommerce::transferHfcToNodeResult); |
| 33 | 36 | connect(ledger.data(), &Ledger::transferHfcToUsernameResult, this, &QmlCommerce::transferHfcToUsernameResult); |
| 37 | + connect(ledger.data(), &Ledger::transferHfcToUsernameResult, this, &QmlCommerce::transferHfcToUsernameResult); | |
| 34 | 38 | |
| 35 | 39 | auto accountManager = DependencyManager::get<AccountManager>(); |
| 36 | 40 | connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() { |
| @@ -163,3 +167,19 @@ void QmlCommerce::transferHfcToUsername(const QString& username, const int& amou · 126 unmodified lines | ||
| 163 | 167 | QString key = keys[0]; |
| 164 | 168 | ledger->transferHfcToUsername(key, username, amount, optionalMessage); |
| 165 | 169 | } |
| 170 | + | |
| 171 | +void 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 | + | |
| 182 | +void QmlCommerce::alreadyOwned(const QString& marketplaceId) { | |
| 183 | + auto ledger = DependencyManager::get<Ledger>(); | |
| 184 | + ledger->alreadyOwned(marketplaceId); | |
| 185 | +} | |
| @@ -42,12 +42,15 @@ signals: · 41 unmodified lines | ||
| 42 | 42 | void historyResult(QJsonObject result); |
| 43 | 43 | void accountResult(QJsonObject result); |
| 44 | 44 | void certificateInfoResult(QJsonObject result); |
| 45 | + void alreadyOwnedResult(QJsonObject result); | |
| 45 | 46 | |
| 46 | 47 | void updateCertificateStatus(const QString& certID, uint certStatus); |
| 47 | 48 | |
| 48 | 49 | void transferHfcToNodeResult(QJsonObject result); |
| 49 | 50 | void transferHfcToUsernameResult(QJsonObject result); |
| 50 | 51 | |
| 52 | + void contentSetChanged(const QString& contentSetHref); | |
| 53 | + | |
| 51 | 54 | protected: |
| 52 | 55 | Q_INVOKABLE void getWalletStatus(); |
| 53 | 56 | |
| @@ -68,9 +71,13 @@ protected: · 14 unmodified lines | ||
| 68 | 71 | Q_INVOKABLE void account(); |
| 69 | 72 | |
| 70 | 73 | Q_INVOKABLE void certificateInfo(const QString& certificateId); |
| 74 | + Q_INVOKABLE void alreadyOwned(const QString& marketplaceId); | |
| 71 | 75 | |
| 72 | 76 | Q_INVOKABLE void transferHfcToNode(const QString& nodeID, const int& amount, const QString& optionalMessage); |
| 73 | 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 | 83 | #endif // hifi_QmlCommerce_h |
| @@ -38,7 +38,7 @@ class AccountServicesScriptingInterface : public QObject { · 37 unmodified lines | ||
| 38 | 38 | Q_PROPERTY(QString username READ getUsername NOTIFY myUsernameChanged) |
| 39 | 39 | Q_PROPERTY(bool loggedIn READ loggedIn NOTIFY loggedInChanged) |
| 40 | 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 | |
| 43 | 43 | public: |
| 44 | 44 | static AccountServicesScriptingInterface* getInstance(); |
| @@ -373,7 +373,7 @@ class AvatarData : public QObject, public SpatiallyNestable { · 372 unmodified lines | ||
| 373 | 373 | // The result is unique among all avatars present at the time. |
| 374 | 374 | Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName WRITE setSessionDisplayName NOTIFY sessionDisplayNameChanged) |
| 375 | 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 | 377 | Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData WRITE setAttachmentData) |
| 378 | 378 | |
| 379 | 379 | Q_PROPERTY(QStringList jointNames READ getJointNames) |
| @@ -702,6 +702,7 @@ public: · 322 unmodified lines | ||
| 702 | 702 | signals: |
| 703 | 703 | void displayNameChanged(); |
| 704 | 704 | void sessionDisplayNameChanged(); |
| 705 | + void skeletonModelURLChanged(); | |
| 705 | 706 | void lookAtSnappingChanged(bool enabled); |
| 706 | 707 | void sessionUUIDChanged(); |
| 707 | 708 | |
| @@ -16,6 +16,7 @@ ScriptAvatarData::ScriptAvatarData(AvatarSharedPointer avatarData) : · 15 unmodified lines | ||
| 16 | 16 | { |
| 17 | 17 | QObject::connect(avatarData.get(), &AvatarData::displayNameChanged, this, &ScriptAvatarData::displayNameChanged); |
| 18 | 18 | QObject::connect(avatarData.get(), &AvatarData::sessionDisplayNameChanged, this, &ScriptAvatarData::sessionDisplayNameChanged); |
| 19 | + QObject::connect(avatarData.get(), &AvatarData::skeletonModelURLChanged, this, &ScriptAvatarData::skeletonModelURLChanged); | |
| 19 | 20 | QObject::connect(avatarData.get(), &AvatarData::lookAtSnappingChanged, this, &ScriptAvatarData::lookAtSnappingChanged); |
| 20 | 21 | } |
| 21 | 22 | |
| @@ -51,7 +51,7 @@ class ScriptAvatarData : public QObject { · 50 unmodified lines | ||
| 51 | 51 | // |
| 52 | 52 | // ATTACHMENT AND JOINT PROPERTIES |
| 53 | 53 | // |
| 54 | − Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript) | |
| 54 | + Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript NOTIFY skeletonModelURLChanged) | |
| 55 | 55 | Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData) |
| 56 | 56 | Q_PROPERTY(QStringList jointNames READ getJointNames) |
| 57 | 57 | |
| @@ -132,6 +132,7 @@ public: · 74 unmodified lines | ||
| 132 | 132 | signals: |
| 133 | 133 | void displayNameChanged(); |
| 134 | 134 | void sessionDisplayNameChanged(); |
| 135 | + void skeletonModelURLChanged(); | |
| 135 | 136 | void lookAtSnappingChanged(bool enabled); |
| 136 | 137 | |
| 137 | 138 | public slots: |
| @@ -101,6 +101,11 @@ bool EntityScriptingInterface::canWriteAssets() { · 100 unmodified lines | ||
| 101 | 101 | return nodeList->getThisNodeCanWriteAssets(); |
| 102 | 102 | } |
| 103 | 103 | |
| 104 | +bool EntityScriptingInterface::canReplaceContent() { | |
| 105 | + auto nodeList = DependencyManager::get<NodeList>(); | |
| 106 | + return nodeList->getThisNodeCanReplaceContent(); | |
| 107 | +} | |
| 108 | + | |
| 104 | 109 | void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) { |
| 105 | 110 | if (_entityTree) { |
| 106 | 111 | disconnect(_entityTree.get(), &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity); |
| @@ -144,6 +144,12 @@ public slots: · 143 unmodified lines | ||
| 144 | 144 | */ |
| 145 | 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 | 153 | /**jsdoc |
| 148 | 154 | * Add a new entity with the specified properties. If `clientOnly` is true, the entity will |
| 149 | 155 | * not be sent to the server and will only be visible/accessible on the local client. |
| @@ -89,7 +89,9 @@ float evalShadowCascadeAttenuation(int cascadeIndex, ShadowSampleOffsets offsets · 88 unmodified lines | ||
| 89 | 89 | |
| 90 | 90 | float evalShadowAttenuation(vec3 worldLightDir, vec4 worldPosition, float viewDepth, vec3 worldNormal) { |
| 91 | 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 | 95 | ivec2 cascadeIndices; |
| 94 | 96 | float cascadeMix = determineShadowCascadesOnPixel(worldPosition, viewDepth, cascadeShadowCoords, cascadeIndices); |
| 95 | 97 | |
| @@ -129,6 +129,7 @@ QUrl PathUtils::expandToAppAbsolutePath(const QUrl& fileUrl) { · 128 unmodified lines | ||
| 129 | 129 | } |
| 130 | 130 | return url; |
| 131 | 131 | } |
| 132 | + | |
| 132 | 133 | const QString& PathUtils::qmlBaseUrl() { |
| 133 | 134 | static const QString staticResourcePath = resourcesUrl() + "qml/"; |
| 134 | 135 | return staticResourcePath; |
| @@ -75,11 +75,11 @@ var selectionDisplay = null; // for gridTool.js to ignore · 74 unmodified lines | ||
| 75 | 75 | tablet.pushOntoStack(MARKETPLACE_CHECKOUT_QML_PATH); |
| 76 | 76 | tablet.sendToQml({ |
| 77 | 77 | method: 'updateCheckoutQML', params: { |
| 78 | − itemId: '0d90d21c-ce7a-4990-ad18-e9d2cf991027', | |
| 79 | − itemName: 'Test Flaregun', | |
| 80 | − itemPrice: (debugError ? 10 : 17), | |
| 81 | − itemHref: 'http://mpassets.highfidelity.com/0d90d21c-ce7a-4990-ad18-e9d2cf991027-v1/flaregun.json', | |
| 82 | − categories: ["Wearables", "Miscellaneous"] | |
| 78 | + itemId: '424611a2-73d0-4c03-9087-26a6a279257b', | |
| 79 | + itemName: '2018-02-15 Finnegon', | |
| 80 | + itemPrice: (debugError ? 10 : 3), | |
| 81 | + itemHref: 'http://devmpassets.highfidelity.com/424611a2-73d0-4c03-9087-26a6a279257b-v1/finnigon.fst', | |
| 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 | 233 | return position; |
| 234 | 234 | } |
| 235 | 235 | |
| 236 | − function rezEntity(itemHref, isWearable) { | |
| 236 | + function rezEntity(itemHref, itemType) { | |
| 237 | + var isWearable = itemType === "wearable"; | |
| 237 | 238 | var success = Clipboard.importEntities(itemHref); |
| 238 | 239 | var wearableLocalPosition = null; |
| 239 | 240 | var wearableLocalRotation = null; |
| 240 | 241 | var wearableLocalDimensions = null; |
| 241 | 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 | 249 | if (isWearable) { |
| 244 | 250 | var wearableTransforms = Settings.getValue("io.highfidelity.avatarStore.checkOut.transforms"); |
| 245 | 251 | if (!wearableTransforms) { |
| @@ -545,7 +551,11 @@ var selectionDisplay = null; // for gridTool.js to ignore · 299 unmodified lines | ||
| 545 | 551 | break; |
| 546 | 552 | case 'checkout_rezClicked': |
| 547 | 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 | 559 | break; |
| 550 | 560 | case 'header_marketplaceImageClicked': |
| 551 | 561 | case 'purchases_backClicked': |