mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-10 04:53:04 +02:00
Merge pull request #14232 from kkurian/log-resource-requests-2
Display resource-access events in marketplace item tester
This commit is contained in:
commit
3cf000a71b
36 changed files with 885 additions and 298 deletions
|
@ -222,7 +222,8 @@ void Agent::requestScript() {
|
|||
return;
|
||||
}
|
||||
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(this, scriptURL);
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
this, scriptURL, true, -1, "Agent::requestScript");
|
||||
|
||||
if (!request) {
|
||||
qWarning() << "Could not create ResourceRequest for Agent script at" << scriptURL.toString();
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "AssignmentClientLogging.h"
|
||||
#include "AssignmentFactory.h"
|
||||
#include "ResourceRequestObserver.h"
|
||||
|
||||
const QString ASSIGNMENT_CLIENT_TARGET_NAME = "assignment-client";
|
||||
const long long ASSIGNMENT_REQUEST_INTERVAL_MSECS = 1 * 1000;
|
||||
|
@ -49,6 +50,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
|
|||
DependencyManager::set<tracing::Tracer>();
|
||||
DependencyManager::set<StatTracker>();
|
||||
DependencyManager::set<AccountManager>();
|
||||
DependencyManager::set<ResourceRequestObserver>();
|
||||
|
||||
auto addressManager = DependencyManager::set<AddressManager>();
|
||||
|
||||
|
|
|
@ -0,0 +1,364 @@
|
|||
//
|
||||
// ItemUnderTest
|
||||
// qml/hifi/commerce/marketplaceItemTester
|
||||
//
|
||||
// Load items not in the marketplace for testing purposes
|
||||
//
|
||||
// Created by Kerry Ivan Kurian on 2018-10-18
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.10
|
||||
import QtQuick.Controls 2.3
|
||||
import Hifi 1.0 as Hifi
|
||||
import "qrc:////qml//styles-uit" as HifiStylesUit
|
||||
import "qrc:////qml//controls-uit" as HifiControlsUit
|
||||
|
||||
Rectangle {
|
||||
id: root;
|
||||
color: hifi.colors.baseGray
|
||||
width: parent.width - 16
|
||||
height: childrenRect.height + itemHeaderContainer.anchors.topMargin + detailsContainer.anchors.topMargin
|
||||
|
||||
property var detailsExpanded: false
|
||||
|
||||
property var actions: {
|
||||
"forward": function(resource, assetType, resourceObjectId){
|
||||
switch(assetType) {
|
||||
case "application":
|
||||
Commerce.installApp(resource, true);
|
||||
break;
|
||||
case "avatar":
|
||||
MyAvatar.useFullAvatarURL(resource);
|
||||
break;
|
||||
case "content set":
|
||||
urlHandler.handleUrl("hifi://localhost/0,0,0");
|
||||
Commerce.replaceContentSet(toUrl(resource), "");
|
||||
break;
|
||||
case "entity":
|
||||
case "wearable":
|
||||
rezEntity(resource, assetType, resourceObjectId);
|
||||
break;
|
||||
default:
|
||||
print("Marketplace item tester unsupported assetType " + assetType);
|
||||
}
|
||||
},
|
||||
"trash": function(resource, assetType){
|
||||
if ("application" === assetType) {
|
||||
Commerce.uninstallApp(resource);
|
||||
}
|
||||
sendToScript({
|
||||
method: "tester_deleteResourceObject",
|
||||
objectId: resourceListModel.get(index).resourceObjectId});
|
||||
resourceListModel.remove(index);
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: itemHeaderContainer
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 8
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
width: parent.width - 16
|
||||
height: childrenRect.height
|
||||
|
||||
Item {
|
||||
id: itemNameContainer
|
||||
width: parent.width * 0.5
|
||||
height: childrenRect.height
|
||||
|
||||
HifiStylesUit.RalewaySemiBold {
|
||||
id: resourceName
|
||||
height: paintedHeight
|
||||
width: parent.width
|
||||
text: {
|
||||
var match = resource.match(/\/([^/]*)$/);
|
||||
return match ? match[1] : resource;
|
||||
}
|
||||
size: 14
|
||||
color: hifi.colors.white
|
||||
wrapMode: Text.WrapAnywhere
|
||||
}
|
||||
|
||||
HifiStylesUit.RalewayRegular {
|
||||
id: resourceUrl
|
||||
anchors.top: resourceName.bottom;
|
||||
anchors.topMargin: 4;
|
||||
height: paintedHeight
|
||||
width: parent.width
|
||||
text: resource
|
||||
size: 12
|
||||
color: hifi.colors.faintGray;
|
||||
wrapMode: Text.WrapAnywhere
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.ComboBox {
|
||||
id: comboBox
|
||||
anchors.left: itemNameContainer.right
|
||||
anchors.leftMargin: 4
|
||||
anchors.verticalCenter: itemNameContainer.verticalCenter
|
||||
height: 30
|
||||
width: parent.width * 0.3 - anchors.leftMargin
|
||||
|
||||
model: [
|
||||
"application",
|
||||
"avatar",
|
||||
"content set",
|
||||
"entity",
|
||||
"wearable",
|
||||
"unknown"
|
||||
]
|
||||
|
||||
currentIndex: (("entity or wearable" === assetType) ?
|
||||
model.indexOf("unknown") : model.indexOf(assetType))
|
||||
|
||||
Component.onCompleted: {
|
||||
onCurrentIndexChanged.connect(function() {
|
||||
assetType = model[currentIndex];
|
||||
sendToScript({
|
||||
method: "tester_updateResourceObjectAssetType",
|
||||
objectId: resourceListModel.get(index)["resourceObjectId"],
|
||||
assetType: assetType });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: actionButton
|
||||
property var glyphs: {
|
||||
"application": hifi.glyphs.install,
|
||||
"avatar": hifi.glyphs.avatar,
|
||||
"content set": hifi.glyphs.globe,
|
||||
"entity": hifi.glyphs.wand,
|
||||
"trash": hifi.glyphs.trash,
|
||||
"unknown": hifi.glyphs.circleSlash,
|
||||
"wearable": hifi.glyphs.hat
|
||||
}
|
||||
property int color: hifi.buttons.blue;
|
||||
property int colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.left: comboBox.right
|
||||
anchors.leftMargin: 4
|
||||
anchors.verticalCenter: itemNameContainer.verticalCenter
|
||||
width: parent.width * 0.10 - anchors.leftMargin
|
||||
height: width
|
||||
enabled: comboBox.model[comboBox.currentIndex] !== "unknown"
|
||||
|
||||
onClicked: {
|
||||
if (model.currentlyRecordingResources) {
|
||||
model.currentlyRecordingResources = false;
|
||||
} else {
|
||||
model.resourceAccessEventText = "";
|
||||
model.currentlyRecordingResources = true;
|
||||
root.actions["forward"](resource, comboBox.currentText, resourceObjectId);
|
||||
}
|
||||
sendToScript({
|
||||
method: "tester_updateResourceRecordingStatus",
|
||||
objectId: resourceListModel.get(index).resourceObjectId,
|
||||
status: model.currentlyRecordingResources
|
||||
});
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
radius: 4;
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: {
|
||||
if (!actionButton.enabled) {
|
||||
hifi.buttons.disabledColorStart[actionButton.colorScheme]
|
||||
} else if (actionButton.pressed) {
|
||||
hifi.buttons.pressedColor[actionButton.color]
|
||||
} else if (actionButton.hovered) {
|
||||
hifi.buttons.hoveredColor[actionButton.color]
|
||||
} else {
|
||||
hifi.buttons.colorStart[actionButton.color]
|
||||
}
|
||||
}
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: {
|
||||
if (!actionButton.enabled) {
|
||||
hifi.buttons.disabledColorFinish[actionButton.colorScheme]
|
||||
} else if (actionButton.pressed) {
|
||||
hifi.buttons.pressedColor[actionButton.color]
|
||||
} else if (actionButton.hovered) {
|
||||
hifi.buttons.hoveredColor[actionButton.color]
|
||||
} else {
|
||||
hifi.buttons.colorFinish[actionButton.color]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
HifiStylesUit.HiFiGlyphs {
|
||||
id: rezIcon;
|
||||
text: model.currentlyRecordingResources ? hifi.glyphs.scriptStop : actionButton.glyphs[comboBox.model[comboBox.currentIndex]];
|
||||
anchors.fill: parent
|
||||
size: 30;
|
||||
horizontalAlignment: Text.AlignHCenter;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
color: enabled ? hifi.buttons.textColor[actionButton.color]
|
||||
: hifi.buttons.disabledTextColor[actionButton.colorScheme]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: trashButton
|
||||
property int color: hifi.buttons.red;
|
||||
property int colorScheme: hifi.colorSchemes.dark;
|
||||
anchors.left: actionButton.right
|
||||
anchors.verticalCenter: itemNameContainer.verticalCenter
|
||||
anchors.leftMargin: 4
|
||||
width: parent.width * 0.10 - anchors.leftMargin
|
||||
height: width
|
||||
|
||||
onClicked: {
|
||||
root.actions["trash"](resource, comboBox.currentText, resourceObjectId);
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
radius: 4;
|
||||
gradient: Gradient {
|
||||
GradientStop {
|
||||
position: 0.2
|
||||
color: {
|
||||
if (!trashButton.enabled) {
|
||||
hifi.buttons.disabledColorStart[trashButton.colorScheme]
|
||||
} else if (trashButton.pressed) {
|
||||
hifi.buttons.pressedColor[trashButton.color]
|
||||
} else if (trashButton.hovered) {
|
||||
hifi.buttons.hoveredColor[trashButton.color]
|
||||
} else {
|
||||
hifi.buttons.colorStart[trashButton.color]
|
||||
}
|
||||
}
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: {
|
||||
if (!trashButton.enabled) {
|
||||
hifi.buttons.disabledColorFinish[trashButton.colorScheme]
|
||||
} else if (trashButton.pressed) {
|
||||
hifi.buttons.pressedColor[trashButton.color]
|
||||
} else if (trashButton.hovered) {
|
||||
hifi.buttons.hoveredColor[trashButton.color]
|
||||
} else {
|
||||
hifi.buttons.colorFinish[trashButton.color]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
HifiStylesUit.HiFiGlyphs {
|
||||
id: trashIcon;
|
||||
text: hifi.glyphs.trash
|
||||
anchors.fill: parent
|
||||
size: 22;
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: enabled ? hifi.buttons.textColor[trashButton.color]
|
||||
: hifi.buttons.disabledTextColor[trashButton.colorScheme]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: detailsContainer
|
||||
|
||||
width: parent.width - 16
|
||||
height: root.detailsExpanded ? 300 : 26
|
||||
anchors.top: itemHeaderContainer.bottom
|
||||
anchors.topMargin: 12
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
|
||||
HifiStylesUit.HiFiGlyphs {
|
||||
id: detailsToggle
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: -4
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: -2
|
||||
width: 22
|
||||
text: root.detailsExpanded ? hifi.glyphs.minimize : hifi.glyphs.maximize
|
||||
color: hifi.colors.white
|
||||
size: 22
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: root.detailsExpanded = !root.detailsExpanded
|
||||
}
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
id: detailsTextContainer
|
||||
anchors.top: parent.top
|
||||
anchors.left: detailsToggle.right
|
||||
anchors.leftMargin: 4
|
||||
anchors.right: parent.right
|
||||
height: detailsContainer.height - (root.detailsExpanded ? (copyToClipboardButton.height + copyToClipboardButton.anchors.topMargin) : 0)
|
||||
clip: true
|
||||
|
||||
TextArea {
|
||||
id: detailsText
|
||||
readOnly: true
|
||||
color: hifi.colors.white
|
||||
text: {
|
||||
var numUniqueResources = (model.resourceAccessEventText.split("\n").length - 1);
|
||||
if (root.detailsExpanded && numUniqueResources > 0) {
|
||||
return model.resourceAccessEventText
|
||||
} else {
|
||||
return numUniqueResources.toString() + " unique source/resource url pair" + (numUniqueResources === 1 ? "" : "s") + " recorded"
|
||||
}
|
||||
}
|
||||
font: Qt.font({ family: "Courier", pointSize: 8, weight: Font.Normal })
|
||||
wrapMode: TextEdit.NoWrap
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent;
|
||||
color: hifi.colors.baseGrayShadow;
|
||||
border.width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
if (root.detailsExpanded) {
|
||||
detailsText.selectAll();
|
||||
} else {
|
||||
root.detailsExpanded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.Button {
|
||||
id: copyToClipboardButton;
|
||||
visible: root.detailsExpanded
|
||||
color: hifi.buttons.noneBorderlessWhite
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
|
||||
anchors.top: detailsTextContainer.bottom
|
||||
anchors.topMargin: 8
|
||||
anchors.right: parent.right
|
||||
width: 160
|
||||
height: 30
|
||||
text: "Copy to Clipboard"
|
||||
|
||||
onClicked: {
|
||||
Window.copyToClipboard(detailsText.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,21 +4,19 @@
|
|||
//
|
||||
// Load items not in the marketplace for testing purposes
|
||||
//
|
||||
// Created by Zach Fox on 2018-09-05
|
||||
// Created by Kerry Ivan Kurian on 2018-09-05
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtQuick.Dialogs 1.0
|
||||
import QtQuick 2.10
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick.Controls 2.3
|
||||
import Hifi 1.0 as Hifi
|
||||
import "../../../styles-uit" as HifiStylesUit
|
||||
import "../../../controls-uit" as HifiControlsUit
|
||||
import "qrc:////qml//styles-uit" as HifiStylesUit
|
||||
import "qrc:////qml//controls-uit" as HifiControlsUit
|
||||
|
||||
|
||||
|
||||
|
@ -27,33 +25,223 @@ Rectangle {
|
|||
|
||||
property string installedApps
|
||||
property var nextResourceObjectId: 0
|
||||
signal sendToScript(var message)
|
||||
|
||||
HifiStylesUit.HifiConstants { id: hifi }
|
||||
ListModel { id: resourceListModel }
|
||||
|
||||
color: hifi.colors.white
|
||||
color: hifi.colors.darkGray
|
||||
|
||||
AnimatedImage {
|
||||
id: spinner;
|
||||
source: "spinner.gif"
|
||||
width: 74;
|
||||
height: width;
|
||||
anchors.verticalCenter: parent.verticalCenter;
|
||||
anchors.horizontalCenter: parent.horizontalCenter;
|
||||
//
|
||||
// TITLE BAR START
|
||||
//
|
||||
Item {
|
||||
id: titleBarContainer
|
||||
// Size
|
||||
width: root.width
|
||||
height: 50
|
||||
// Anchors
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
|
||||
// Title bar text
|
||||
HifiStylesUit.RalewaySemiBold {
|
||||
id: titleBarText
|
||||
text: "Marketplace Item Tester"
|
||||
// Text size
|
||||
size: 24
|
||||
// Anchors
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 16
|
||||
width: paintedWidth
|
||||
// Style
|
||||
color: hifi.colors.lightGrayText
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
// Separator
|
||||
HifiControlsUit.Separator {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 1
|
||||
}
|
||||
}
|
||||
//
|
||||
// TITLE BAR END
|
||||
//
|
||||
|
||||
Rectangle {
|
||||
id: spinner
|
||||
z: 999
|
||||
anchors.top: titleBarContainer.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: buttonContainer.top
|
||||
color: hifi.colors.darkGray
|
||||
|
||||
AnimatedImage {
|
||||
source: "spinner.gif"
|
||||
width: 74
|
||||
height: width
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: instructionsContainer
|
||||
z: 998
|
||||
color: hifi.colors.darkGray
|
||||
visible: resourceListModel.count === 0 && !spinner.visible
|
||||
anchors.top: titleBarContainer.bottom
|
||||
anchors.topMargin: 20
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 20
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 20
|
||||
anchors.bottom: buttonContainer.top
|
||||
anchors.bottomMargin: 20
|
||||
|
||||
HifiStylesUit.RalewayRegular {
|
||||
text: "Use Marketplace Item Tester to test out your items before submitting them to the Marketplace." +
|
||||
"\n\nUse one of the buttons below to load your item."
|
||||
// Text size
|
||||
size: 20
|
||||
// Anchors
|
||||
anchors.fill: parent
|
||||
// Style
|
||||
color: hifi.colors.lightGrayText
|
||||
wrapMode: Text.Wrap
|
||||
// Alignment
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: itemList
|
||||
visible: !instructionsContainer.visible
|
||||
anchors.top: titleBarContainer.bottom
|
||||
anchors.topMargin: 20
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: buttonContainer.top
|
||||
anchors.bottomMargin: 20
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
visible: !instructionsContainer.visible
|
||||
policy: ScrollBar.AlwaysOn
|
||||
parent: itemList.parent
|
||||
anchors.top: itemList.top
|
||||
anchors.right: itemList.right
|
||||
anchors.bottom: itemList.bottom
|
||||
width: 16
|
||||
}
|
||||
clip: true
|
||||
model: resourceListModel
|
||||
spacing: 8
|
||||
|
||||
delegate: ItemUnderTest { }
|
||||
}
|
||||
|
||||
Item {
|
||||
id: buttonContainer
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 12
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 12
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 12
|
||||
height: 40
|
||||
|
||||
property string currentAction
|
||||
property var actions: {
|
||||
"Load File": function() {
|
||||
buttonContainer.currentAction = "load file";
|
||||
Window.browseChanged.connect(onResourceSelected);
|
||||
Window.browseAsync("Please select a file (*.app.json *.json *.fst *.json.gz)", "", "Assets (*.app.json *.json *.fst *.json.gz)");
|
||||
},
|
||||
"Load URL": function() {
|
||||
buttonContainer.currentAction = "load url";
|
||||
Window.promptTextChanged.connect(onResourceSelected);
|
||||
Window.promptAsync("Please enter a URL", "");
|
||||
}
|
||||
}
|
||||
|
||||
function onResourceSelected(resource) {
|
||||
// It is possible that we received the present signal
|
||||
// from something other than our browserAsync window.
|
||||
// Alas, there is nothing we can do about that so charge
|
||||
// ahead as though we are sure the present signal is one
|
||||
// we expect.
|
||||
print("!!!! resource selected");
|
||||
switch(currentAction) {
|
||||
case "load file":
|
||||
Window.browseChanged.disconnect(onResourceSelected);
|
||||
break
|
||||
case "load url":
|
||||
Window.promptTextChanged.disconnect(onResourceSelected);
|
||||
break;
|
||||
}
|
||||
if (resource) {
|
||||
print("!!!! building resource object");
|
||||
var resourceObj = buildResourceObj(resource);
|
||||
print("!!!! notifying script of resource object");
|
||||
sendToScript({
|
||||
method: 'tester_newResourceObject',
|
||||
resourceObject: resourceObj
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
HifiControlsUit.Button {
|
||||
enabled: !spinner.visible
|
||||
anchors.right: parent.horizontalCenter
|
||||
anchors.rightMargin: width/4
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: hifi.buttons.blue
|
||||
fontSize: 20
|
||||
text: "Load File"
|
||||
width: parent.width / 3
|
||||
height: parent.height
|
||||
onClicked: buttonContainer.actions[text]()
|
||||
}
|
||||
|
||||
HifiControlsUit.Button {
|
||||
enabled: !spinner.visible
|
||||
anchors.left: parent.horizontalCenter
|
||||
anchors.leftMargin: width/4
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: hifi.buttons.blue
|
||||
fontSize: 20
|
||||
text: "Load URL"
|
||||
width: parent.width / 3
|
||||
height: parent.height
|
||||
onClicked: buttonContainer.actions[text]()
|
||||
}
|
||||
}
|
||||
|
||||
function fromScript(message) {
|
||||
switch (message.method) {
|
||||
case "newResourceObjectInTest":
|
||||
var resourceObject = message.resourceObject;
|
||||
resourceListModel.clear(); // REMOVE THIS once we support specific referrers
|
||||
resourceListModel.append(resourceObject);
|
||||
spinner.visible = false;
|
||||
break;
|
||||
case "nextObjectIdInTest":
|
||||
print("!!!! message from script! " + JSON.stringify(message));
|
||||
nextResourceObjectId = message.id;
|
||||
spinner.visible = false;
|
||||
break;
|
||||
case "resourceRequestEvent":
|
||||
// When we support multiple items under test simultaneously,
|
||||
// we'll have to replace "0" with the correct index.
|
||||
resourceListModel.setProperty(0, "resourceAccessEventText", message.resourceAccessEventText);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,227 +252,26 @@ Rectangle {
|
|||
resource.match(/\.json\.gz$/) ? "content set" :
|
||||
resource.match(/\.json$/) ? "entity or wearable" :
|
||||
"unknown");
|
||||
return { "id": nextResourceObjectId++,
|
||||
// Uncomment this once we support more than one item in test at the same time
|
||||
//nextResourceObjectId++;
|
||||
return { "resourceObjectId": nextResourceObjectId,
|
||||
"resource": resource,
|
||||
"assetType": assetType };
|
||||
}
|
||||
|
||||
function installResourceObj(resourceObj) {
|
||||
if ("application" === resourceObj.assetType) {
|
||||
Commerce.installApp(resourceObj.resource);
|
||||
}
|
||||
}
|
||||
|
||||
function addAllInstalledAppsToList() {
|
||||
var i, apps = Commerce.getInstalledApps().split(","), len = apps.length;
|
||||
for(i = 0; i < len - 1; ++i) {
|
||||
if (i in apps) {
|
||||
resourceListModel.append(buildResourceObj(apps[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toUrl(resource) {
|
||||
var httpPattern = /^http/i;
|
||||
return httpPattern.test(resource) ? resource : "file:///" + resource;
|
||||
}
|
||||
|
||||
function rezEntity(resource, entityType) {
|
||||
function rezEntity(resource, entityType, resourceObjectId) {
|
||||
print("!!!! tester_rezClicked");
|
||||
sendToScript({
|
||||
method: 'tester_rezClicked',
|
||||
itemHref: toUrl(resource),
|
||||
itemType: entityType});
|
||||
itemType: entityType,
|
||||
itemId: resourceObjectId });
|
||||
}
|
||||
|
||||
ListView {
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 12
|
||||
anchors.bottomMargin: 40
|
||||
anchors.rightMargin: 12
|
||||
model: resourceListModel
|
||||
spacing: 5
|
||||
interactive: false
|
||||
|
||||
delegate: RowLayout {
|
||||
anchors.left: parent.left
|
||||
width: parent.width
|
||||
spacing: 5
|
||||
|
||||
property var actions: {
|
||||
"forward": function(resource, assetType){
|
||||
switch(assetType) {
|
||||
case "application":
|
||||
Commerce.openApp(resource);
|
||||
break;
|
||||
case "avatar":
|
||||
MyAvatar.useFullAvatarURL(resource);
|
||||
break;
|
||||
case "content set":
|
||||
urlHandler.handleUrl("hifi://localhost/0,0,0");
|
||||
Commerce.replaceContentSet(toUrl(resource), "");
|
||||
break;
|
||||
case "entity":
|
||||
case "wearable":
|
||||
rezEntity(resource, assetType);
|
||||
break;
|
||||
default:
|
||||
print("Marketplace item tester unsupported assetType " + assetType);
|
||||
}
|
||||
},
|
||||
"trash": function(resource, assetType){
|
||||
if ("application" === assetType) {
|
||||
Commerce.uninstallApp(resource);
|
||||
}
|
||||
sendToScript({
|
||||
method: "tester_deleteResourceObject",
|
||||
objectId: resourceListModel.get(index).id});
|
||||
resourceListModel.remove(index);
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
Layout.preferredWidth: root.width * .6
|
||||
spacing: 5
|
||||
Text {
|
||||
text: {
|
||||
var match = resource.match(/\/([^/]*)$/);
|
||||
return match ? match[1] : resource;
|
||||
}
|
||||
font.pointSize: 12
|
||||
horizontalAlignment: Text.AlignBottom
|
||||
}
|
||||
Text {
|
||||
text: resource
|
||||
font.pointSize: 8
|
||||
width: root.width * .6
|
||||
horizontalAlignment: Text.AlignBottom
|
||||
wrapMode: Text.WrapAnywhere
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: comboBox
|
||||
|
||||
Layout.preferredWidth: root.width * .2
|
||||
|
||||
model: [
|
||||
"application",
|
||||
"avatar",
|
||||
"content set",
|
||||
"entity",
|
||||
"wearable",
|
||||
"unknown"
|
||||
]
|
||||
|
||||
currentIndex: (("entity or wearable" === assetType) ?
|
||||
model.indexOf("unknown") : model.indexOf(assetType))
|
||||
|
||||
Component.onCompleted: {
|
||||
onCurrentIndexChanged.connect(function() {
|
||||
assetType = model[currentIndex];
|
||||
sendToScript({
|
||||
method: "tester_updateResourceObjectAssetType",
|
||||
objectId: resourceListModel.get(index)["id"],
|
||||
assetType: assetType });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: [ "forward", "trash" ]
|
||||
|
||||
HifiStylesUit.HiFiGlyphs {
|
||||
property var glyphs: {
|
||||
"application": hifi.glyphs.install,
|
||||
"avatar": hifi.glyphs.avatar,
|
||||
"content set": hifi.glyphs.globe,
|
||||
"entity": hifi.glyphs.wand,
|
||||
"trash": hifi.glyphs.trash,
|
||||
"unknown": hifi.glyphs.circleSlash,
|
||||
"wearable": hifi.glyphs.hat,
|
||||
}
|
||||
text: (("trash" === modelData) ?
|
||||
glyphs.trash :
|
||||
glyphs[comboBox.model[comboBox.currentIndex]])
|
||||
size: ("trash" === modelData) ? 22 : 30
|
||||
color: hifi.colors.black
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
actions[modelData](resource, comboBox.currentText);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
headerPositioning: ListView.OverlayHeader
|
||||
header: HifiStylesUit.RalewayRegular {
|
||||
id: rootHeader
|
||||
text: "Marketplace Item Tester"
|
||||
height: 80
|
||||
width: paintedWidth
|
||||
size: 22
|
||||
color: hifi.colors.black
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 12
|
||||
}
|
||||
|
||||
footerPositioning: ListView.OverlayFooter
|
||||
footer: Row {
|
||||
id: rootActions
|
||||
spacing: 20
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
property string currentAction
|
||||
property var actions: {
|
||||
"Load File": function(){
|
||||
rootActions.currentAction = "load file";
|
||||
Window.browseChanged.connect(onResourceSelected);
|
||||
Window.browseAsync("Please select a file (*.app.json *.json *.fst *.json.gz)", "", "Assets (*.app.json *.json *.fst *.json.gz)");
|
||||
},
|
||||
"Load URL": function(){
|
||||
rootActions.currentAction = "load url";
|
||||
Window.promptTextChanged.connect(onResourceSelected);
|
||||
Window.promptAsync("Please enter a URL", "");
|
||||
}
|
||||
}
|
||||
|
||||
function onResourceSelected(resource) {
|
||||
// It is possible that we received the present signal
|
||||
// from something other than our browserAsync window.
|
||||
// Alas, there is nothing we can do about that so charge
|
||||
// ahead as though we are sure the present signal is one
|
||||
// we expect.
|
||||
switch(currentAction) {
|
||||
case "load file":
|
||||
Window.browseChanged.disconnect(onResourceSelected);
|
||||
break
|
||||
case "load url":
|
||||
Window.promptTextChanged.disconnect(onResourceSelected);
|
||||
break;
|
||||
}
|
||||
if (resource) {
|
||||
var resourceObj = buildResourceObj(resource);
|
||||
installResourceObj(resourceObj);
|
||||
sendToScript({
|
||||
method: 'tester_newResourceObject',
|
||||
resourceObject: resourceObj });
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: [ "Load File", "Load URL" ]
|
||||
HifiControlsUit.Button {
|
||||
color: hifi.buttons.blue
|
||||
fontSize: 20
|
||||
text: modelData
|
||||
width: root.width / 3
|
||||
height: 40
|
||||
onClicked: actions[text]()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
signal sendToScript(var message)
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 58 KiB |
|
@ -226,6 +226,7 @@
|
|||
#include "commerce/Ledger.h"
|
||||
#include "commerce/Wallet.h"
|
||||
#include "commerce/QmlCommerce.h"
|
||||
#include "ResourceRequestObserver.h"
|
||||
|
||||
#include "webbrowser/WebBrowserSuggestionsEngine.h"
|
||||
#include <DesktopPreviewProvider.h>
|
||||
|
@ -947,6 +948,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
DependencyManager::set<WalletScriptingInterface>();
|
||||
|
||||
DependencyManager::set<FadeEffect>();
|
||||
DependencyManager::set<ResourceRequestObserver>();
|
||||
|
||||
return previousSessionCrashed;
|
||||
}
|
||||
|
@ -3129,6 +3131,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) {
|
|||
surfaceContext->setContextProperty("ContextOverlay", DependencyManager::get<ContextOverlayInterface>().data());
|
||||
surfaceContext->setContextProperty("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("HiFiAbout", AboutUtil::getInstance());
|
||||
surfaceContext->setContextProperty("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
|
||||
|
||||
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
||||
surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
|
||||
|
@ -5022,12 +5025,12 @@ void Application::saveSettings() const {
|
|||
PluginManager::getInstance()->saveSettings();
|
||||
}
|
||||
|
||||
bool Application::importEntities(const QString& urlOrFilename) {
|
||||
bool Application::importEntities(const QString& urlOrFilename, const bool isObservable, const qint64 callerId) {
|
||||
bool success = false;
|
||||
_entityClipboard->withWriteLock([&] {
|
||||
_entityClipboard->eraseAllOctreeElements();
|
||||
|
||||
success = _entityClipboard->readFromURL(urlOrFilename);
|
||||
success = _entityClipboard->readFromURL(urlOrFilename, isObservable, callerId);
|
||||
if (success) {
|
||||
_entityClipboard->reaverageOctreeElements();
|
||||
}
|
||||
|
@ -6811,6 +6814,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
|||
scriptEngine->registerGlobalObject("Wallet", DependencyManager::get<WalletScriptingInterface>().data());
|
||||
scriptEngine->registerGlobalObject("AddressManager", DependencyManager::get<AddressManager>().data());
|
||||
scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance());
|
||||
scriptEngine->registerGlobalObject("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
|
||||
|
||||
qScriptRegisterMetaType(scriptEngine.data(), OverlayIDtoScriptValue, OverlayIDfromScriptValue);
|
||||
|
||||
|
@ -7197,7 +7201,8 @@ void Application::addAssetToWorldFromURL(QString url) {
|
|||
|
||||
addAssetToWorldInfo(filename, "Downloading model file " + filename + ".");
|
||||
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(nullptr, QUrl(url));
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
nullptr, QUrl(url), true, -1, "Application::addAssetToWorldFromURL");
|
||||
connect(request, &ResourceRequest::finished, this, &Application::addAssetToWorldFromURLRequestFinished);
|
||||
request->send();
|
||||
}
|
||||
|
|
|
@ -342,7 +342,7 @@ public slots:
|
|||
QVector<EntityItemID> pasteEntities(float x, float y, float z);
|
||||
bool exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs, const glm::vec3* givenOffset = nullptr);
|
||||
bool exportEntities(const QString& filename, float x, float y, float z, float scale);
|
||||
bool importEntities(const QString& url);
|
||||
bool importEntities(const QString& url, const bool isObservable = true, const qint64 callerId = -1);
|
||||
void updateThreadPoolCount() const;
|
||||
void updateSystemTabletMode();
|
||||
void goToErrorDomainURL(QUrl errorDomainURL);
|
||||
|
|
|
@ -53,7 +53,8 @@ void ATPAssetMigrator::loadEntityServerFile() {
|
|||
|
||||
auto migrateResources = [=](QUrl migrationURL, QJsonValueRef jsonValue, bool isModelURL) {
|
||||
auto request =
|
||||
DependencyManager::get<ResourceManager>()->createResourceRequest(this, migrationURL);
|
||||
DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
this, migrationURL, true, -1, "ATPAssetMigrator::loadEntityServerFile");
|
||||
|
||||
if (request) {
|
||||
qCDebug(asset_migrator) << "Requesting" << migrationURL << "for ATP asset migration";
|
||||
|
|
|
@ -315,7 +315,7 @@ QString QmlCommerce::getInstalledApps(const QString& justInstalledAppID) {
|
|||
return installedAppsFromMarketplace;
|
||||
}
|
||||
|
||||
bool QmlCommerce::installApp(const QString& itemHref) {
|
||||
bool QmlCommerce::installApp(const QString& itemHref, const bool& alsoOpenImmediately) {
|
||||
if (!QDir(_appsPath).exists()) {
|
||||
if (!QDir().mkdir(_appsPath)) {
|
||||
qCDebug(commerce) << "Couldn't make _appsPath directory.";
|
||||
|
@ -325,7 +325,8 @@ bool QmlCommerce::installApp(const QString& itemHref) {
|
|||
|
||||
QUrl appHref(itemHref);
|
||||
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(this, appHref);
|
||||
auto request =
|
||||
DependencyManager::get<ResourceManager>()->createResourceRequest(this, appHref, true, -1, "QmlCommerce::installApp");
|
||||
|
||||
if (!request) {
|
||||
qCDebug(commerce) << "Couldn't create resource request for app.";
|
||||
|
@ -357,13 +358,22 @@ bool QmlCommerce::installApp(const QString& itemHref) {
|
|||
QJsonObject appFileJsonObject = appFileJsonDocument.object();
|
||||
QString scriptUrl = appFileJsonObject["scriptURL"].toString();
|
||||
|
||||
if ((DependencyManager::get<ScriptEngines>()->loadScript(scriptUrl.trimmed())).isNull()) {
|
||||
qCDebug(commerce) << "Couldn't load script.";
|
||||
return false;
|
||||
// Don't try to re-load (install) a script if it's already running
|
||||
QStringList runningScripts = DependencyManager::get<ScriptEngines>()->getRunningScripts();
|
||||
if (!runningScripts.contains(scriptUrl)) {
|
||||
if ((DependencyManager::get<ScriptEngines>()->loadScript(scriptUrl.trimmed())).isNull()) {
|
||||
qCDebug(commerce) << "Couldn't load script.";
|
||||
return false;
|
||||
}
|
||||
|
||||
QFileInfo appFileInfo(appFile);
|
||||
emit appInstalled(appFileInfo.baseName());
|
||||
}
|
||||
|
||||
if (alsoOpenImmediately) {
|
||||
QmlCommerce::openApp(itemHref);
|
||||
}
|
||||
|
||||
QFileInfo appFileInfo(appFile);
|
||||
emit appInstalled(appFileInfo.baseName());
|
||||
return true;
|
||||
});
|
||||
request->send();
|
||||
|
|
|
@ -88,7 +88,7 @@ protected:
|
|||
Q_INVOKABLE void replaceContentSet(const QString& itemHref, const QString& certificateID);
|
||||
|
||||
Q_INVOKABLE QString getInstalledApps(const QString& justInstalledAppID = "");
|
||||
Q_INVOKABLE bool installApp(const QString& appHref);
|
||||
Q_INVOKABLE bool installApp(const QString& appHref, const bool& alsoOpenImmediately = false);
|
||||
Q_INVOKABLE bool uninstallApp(const QString& appHref);
|
||||
Q_INVOKABLE bool openApp(const QString& appHref);
|
||||
|
||||
|
|
|
@ -46,11 +46,17 @@ bool ClipboardScriptingInterface::exportEntities(const QString& filename, float
|
|||
return retVal;
|
||||
}
|
||||
|
||||
bool ClipboardScriptingInterface::importEntities(const QString& filename) {
|
||||
bool ClipboardScriptingInterface::importEntities(
|
||||
const QString& filename,
|
||||
const bool isObservable,
|
||||
const qint64 callerId
|
||||
) {
|
||||
bool retVal;
|
||||
BLOCKING_INVOKE_METHOD(qApp, "importEntities",
|
||||
Q_RETURN_ARG(bool, retVal),
|
||||
Q_ARG(const QString&, filename));
|
||||
Q_ARG(const QString&, filename),
|
||||
Q_ARG(const bool, isObservable),
|
||||
Q_ARG(const qint64, callerId));
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,9 +50,11 @@ public:
|
|||
* You can generate a JSON file using {@link Clipboard.exportEntities}.
|
||||
* @function Clipboard.importEntities
|
||||
* @param {string} filename Path and name of file to import.
|
||||
* @param {boolean} does the ResourceRequestObserver observe this request?
|
||||
* @param {number} optional internal id of object causing this import.
|
||||
* @returns {boolean} <code>true</code> if the import was successful, otherwise <code>false</code>.
|
||||
*/
|
||||
Q_INVOKABLE bool importEntities(const QString& filename);
|
||||
Q_INVOKABLE bool importEntities(const QString& filename, const bool isObservable = true, const qint64 callerId = -1);
|
||||
|
||||
/**jsdoc
|
||||
* Export the entities specified to a JSON file.
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "raypick/PointerScriptingInterface.h"
|
||||
#include <display-plugins/CompositorHelper.h>
|
||||
#include "AboutUtil.h"
|
||||
#include "ResourceRequestObserver.h"
|
||||
|
||||
static int MAX_WINDOW_SIZE = 4096;
|
||||
static const float METERS_TO_INCHES = 39.3701f;
|
||||
|
@ -269,6 +270,7 @@ void Web3DOverlay::setupQmlSurface(bool isTablet) {
|
|||
_webSurface->getSurfaceContext()->setContextProperty("Window", DependencyManager::get<WindowScriptingInterface>().data());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("Reticle", qApp->getApplicationCompositor().getReticleInterface());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("HiFiAbout", AboutUtil::getInstance());
|
||||
_webSurface->getSurfaceContext()->setContextProperty("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
|
||||
|
||||
// Override min fps for tablet UI, for silky smooth scrolling
|
||||
setMaxFPS(90);
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "AvatarLogging.h"
|
||||
#include "AvatarTraits.h"
|
||||
#include "ClientTraitsHandler.h"
|
||||
#include "ResourceRequestObserver.h"
|
||||
|
||||
//#define WANT_DEBUG
|
||||
|
||||
|
@ -2161,11 +2162,21 @@ void AvatarData::updateJointMappings() {
|
|||
}
|
||||
|
||||
if (_skeletonModelURL.fileName().toLower().endsWith(".fst")) {
|
||||
////
|
||||
// TODO: Should we rely upon HTTPResourceRequest for ResourceRequestObserver instead?
|
||||
// HTTPResourceRequest::doSend() covers all of the following and
|
||||
// then some. It doesn't cover the connect() call, so we may
|
||||
// want to add a HTTPResourceRequest::doSend() method that does
|
||||
// connects.
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
QNetworkRequest networkRequest = QNetworkRequest(_skeletonModelURL);
|
||||
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
||||
DependencyManager::get<ResourceRequestObserver>()->update(
|
||||
_skeletonModelURL, -1, "AvatarData::updateJointMappings");
|
||||
QNetworkReply* networkReply = networkAccessManager.get(networkRequest);
|
||||
//
|
||||
////
|
||||
connect(networkReply, &QNetworkReply::finished, this, &AvatarData::setJointMappingsFromNetworkReply);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -200,7 +200,8 @@ void EntityEditFilters::addFilter(EntityItemID entityID, QString filterURL) {
|
|||
_filterDataMap.insert(entityID, filterData);
|
||||
_lock.unlock();
|
||||
|
||||
auto scriptRequest = DependencyManager::get<ResourceManager>()->createResourceRequest(this, scriptURL);
|
||||
auto scriptRequest = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
this, scriptURL, true, -1, "EntityEditFilters::addFilter");
|
||||
if (!scriptRequest) {
|
||||
qWarning() << "Could not create ResourceRequest for Entity Edit filter script at" << scriptURL.toString();
|
||||
scriptRequestFinished(entityID);
|
||||
|
|
|
@ -953,7 +953,8 @@ bool GLTFReader::doesResourceExist(const QString& url) {
|
|||
}
|
||||
|
||||
std::tuple<bool, QByteArray> GLTFReader::requestData(QUrl& url) {
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(nullptr, url);
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
nullptr, url, true, -1, "GLTFReader::requestData");
|
||||
|
||||
if (!request) {
|
||||
return std::make_tuple(false, QByteArray());
|
||||
|
|
|
@ -443,7 +443,8 @@ void OBJReader::parseTextureLine(const QByteArray& textureLine, QByteArray& file
|
|||
}
|
||||
|
||||
std::tuple<bool, QByteArray> requestData(QUrl& url) {
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(nullptr, url);
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
nullptr, url, true, -1, "(OBJReader) requestData");
|
||||
|
||||
if (!request) {
|
||||
return std::make_tuple(false, QByteArray());
|
||||
|
|
|
@ -456,7 +456,8 @@ void NetworkTexture::makeRequest() {
|
|||
// Add a fragment to the base url so we can identify the section of the ktx being requested when debugging
|
||||
// The actual requested url is _activeUrl and will not contain the fragment
|
||||
_url.setFragment("head");
|
||||
_ktxHeaderRequest = DependencyManager::get<ResourceManager>()->createResourceRequest(this, _activeUrl);
|
||||
_ktxHeaderRequest = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
this, _activeUrl, true, -1, "NetworkTexture::makeRequest");
|
||||
|
||||
if (!_ktxHeaderRequest) {
|
||||
qCDebug(networking).noquote() << "Failed to get request for" << _url.toDisplayString();
|
||||
|
@ -617,7 +618,8 @@ void NetworkTexture::startMipRangeRequest(uint16_t low, uint16_t high) {
|
|||
|
||||
bool isHighMipRequest = low == NULL_MIP_LEVEL && high == NULL_MIP_LEVEL;
|
||||
|
||||
_ktxMipRequest = DependencyManager::get<ResourceManager>()->createResourceRequest(this, _activeUrl);
|
||||
_ktxMipRequest = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
this, _activeUrl, true, -1, "NetworkTexture::startMipRangeRequest");
|
||||
|
||||
if (!_ktxMipRequest) {
|
||||
qCWarning(networking).noquote() << "Failed to get request for" << _url.toDisplayString();
|
||||
|
|
|
@ -24,8 +24,12 @@
|
|||
|
||||
static const int DOWNLOAD_PROGRESS_LOG_INTERVAL_SECONDS = 5;
|
||||
|
||||
AssetResourceRequest::AssetResourceRequest(const QUrl& url) :
|
||||
ResourceRequest(url)
|
||||
AssetResourceRequest::AssetResourceRequest(
|
||||
const QUrl& url,
|
||||
const bool isObservable,
|
||||
const qint64 callerId,
|
||||
const QString& extra) :
|
||||
ResourceRequest(url, isObservable, callerId, extra)
|
||||
{
|
||||
_lastProgressDebug = p_high_resolution_clock::now() - std::chrono::seconds(DOWNLOAD_PROGRESS_LOG_INTERVAL_SECONDS);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,11 @@
|
|||
class AssetResourceRequest : public ResourceRequest {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AssetResourceRequest(const QUrl& url);
|
||||
AssetResourceRequest(
|
||||
const QUrl& url,
|
||||
const bool isObservable = true,
|
||||
const qint64 callerId = -1,
|
||||
const QString& extra = "");
|
||||
virtual ~AssetResourceRequest() override;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
#include "ResourceManager.h"
|
||||
|
||||
AtpReply::AtpReply(const QUrl& url, QObject* parent) :
|
||||
_resourceRequest(DependencyManager::get<ResourceManager>()->createResourceRequest(parent, url)) {
|
||||
_resourceRequest(DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
parent, url, true, -1, "AtpReply::AtpReply")) {
|
||||
setOperation(QNetworkAccessManager::GetOperation);
|
||||
|
||||
connect(_resourceRequest, &AssetResourceRequest::progress, this, &AtpReply::downloadProgress);
|
||||
|
|
|
@ -19,7 +19,12 @@
|
|||
class FileResourceRequest : public ResourceRequest {
|
||||
Q_OBJECT
|
||||
public:
|
||||
FileResourceRequest(const QUrl& url) : ResourceRequest(url) { }
|
||||
FileResourceRequest(
|
||||
const QUrl& url,
|
||||
const bool isObservable = true,
|
||||
const qint64 callerId = -1,
|
||||
const QString& extra = ""
|
||||
) : ResourceRequest(url, isObservable, callerId, extra) { }
|
||||
|
||||
protected:
|
||||
virtual void doSend() override;
|
||||
|
|
|
@ -21,7 +21,12 @@
|
|||
class HTTPResourceRequest : public ResourceRequest {
|
||||
Q_OBJECT
|
||||
public:
|
||||
HTTPResourceRequest(const QUrl& url) : ResourceRequest(url) { }
|
||||
HTTPResourceRequest(
|
||||
const QUrl& url,
|
||||
const bool isObservable = true,
|
||||
const qint64 callerId = -1,
|
||||
const QString& = ""
|
||||
) : ResourceRequest(url, isObservable, callerId) { }
|
||||
~HTTPResourceRequest();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
//
|
||||
|
||||
#include "ResourceCache.h"
|
||||
#include "ResourceRequestObserver.h"
|
||||
|
||||
#include <cfloat>
|
||||
#include <cmath>
|
||||
|
@ -340,28 +341,31 @@ QSharedPointer<Resource> ResourceCache::getResource(const QUrl& url, const QUrl&
|
|||
}
|
||||
if (resource) {
|
||||
removeUnusedResource(resource);
|
||||
return resource;
|
||||
}
|
||||
|
||||
if (!url.isValid() && !url.isEmpty() && fallback.isValid()) {
|
||||
return getResource(fallback, QUrl());
|
||||
if (!resource && !url.isValid() && !url.isEmpty() && fallback.isValid()) {
|
||||
resource = getResource(fallback, QUrl());
|
||||
}
|
||||
|
||||
resource = createResource(
|
||||
url,
|
||||
fallback.isValid() ? getResource(fallback, QUrl()) : QSharedPointer<Resource>(),
|
||||
extra);
|
||||
resource->setSelf(resource);
|
||||
resource->setCache(this);
|
||||
resource->moveToThread(qApp->thread());
|
||||
connect(resource.data(), &Resource::updateSize, this, &ResourceCache::updateTotalSize);
|
||||
{
|
||||
QWriteLocker locker(&_resourcesLock);
|
||||
_resources.insert(url, resource);
|
||||
if (!resource) {
|
||||
resource = createResource(
|
||||
url,
|
||||
fallback.isValid() ? getResource(fallback, QUrl()) : QSharedPointer<Resource>(),
|
||||
extra);
|
||||
resource->setSelf(resource);
|
||||
resource->setCache(this);
|
||||
resource->moveToThread(qApp->thread());
|
||||
connect(resource.data(), &Resource::updateSize, this, &ResourceCache::updateTotalSize);
|
||||
{
|
||||
QWriteLocker locker(&_resourcesLock);
|
||||
_resources.insert(url, resource);
|
||||
}
|
||||
removeUnusedResource(resource);
|
||||
resource->ensureLoading();
|
||||
}
|
||||
removeUnusedResource(resource);
|
||||
resource->ensureLoading();
|
||||
|
||||
DependencyManager::get<ResourceRequestObserver>()->update(
|
||||
resource->getURL(), -1, "ResourceCache::getResource");
|
||||
return resource;
|
||||
}
|
||||
|
||||
|
@ -684,7 +688,8 @@ void Resource::makeRequest() {
|
|||
|
||||
PROFILE_ASYNC_BEGIN(resource, "Resource:" + getType(), QString::number(_requestID), { { "url", _url.toString() }, { "activeURL", _activeUrl.toString() } });
|
||||
|
||||
_request = DependencyManager::get<ResourceManager>()->createResourceRequest(this, _activeUrl);
|
||||
_request = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
this, _activeUrl, true, -1, "Resource::makeRequest");
|
||||
|
||||
if (!_request) {
|
||||
qCDebug(networking).noquote() << "Failed to get request for" << _url.toDisplayString();
|
||||
|
|
|
@ -112,22 +112,28 @@ void ResourceManager::cleanup() {
|
|||
_thread.wait();
|
||||
}
|
||||
|
||||
ResourceRequest* ResourceManager::createResourceRequest(QObject* parent, const QUrl& url) {
|
||||
ResourceRequest* ResourceManager::createResourceRequest(
|
||||
QObject* parent,
|
||||
const QUrl& url,
|
||||
const bool isObservable,
|
||||
const qint64 callerId,
|
||||
const QString& extra
|
||||
) {
|
||||
auto normalizedURL = normalizeURL(url);
|
||||
auto scheme = normalizedURL.scheme();
|
||||
|
||||
ResourceRequest* request = nullptr;
|
||||
|
||||
if (scheme == URL_SCHEME_FILE || scheme == URL_SCHEME_QRC) {
|
||||
request = new FileResourceRequest(normalizedURL);
|
||||
request = new FileResourceRequest(normalizedURL, isObservable, callerId, extra);
|
||||
} else if (scheme == URL_SCHEME_HTTP || scheme == URL_SCHEME_HTTPS || scheme == URL_SCHEME_FTP) {
|
||||
request = new HTTPResourceRequest(normalizedURL);
|
||||
request = new HTTPResourceRequest(normalizedURL, isObservable, callerId, extra);
|
||||
} else if (scheme == URL_SCHEME_ATP) {
|
||||
if (!_atpSupportEnabled) {
|
||||
qCDebug(networking) << "ATP support not enabled, unable to create request for URL: " << url.url();
|
||||
return nullptr;
|
||||
}
|
||||
request = new AssetResourceRequest(normalizedURL);
|
||||
request = new AssetResourceRequest(normalizedURL, isObservable, callerId, extra);
|
||||
} else {
|
||||
qCDebug(networking) << "Unknown scheme (" << scheme << ") for URL: " << url.url();
|
||||
return nullptr;
|
||||
|
@ -163,7 +169,7 @@ bool ResourceManager::resourceExists(const QUrl& url) {
|
|||
|
||||
return reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200;
|
||||
} else if (scheme == URL_SCHEME_ATP && _atpSupportEnabled) {
|
||||
auto request = new AssetResourceRequest(url);
|
||||
auto request = new AssetResourceRequest(url, ResourceRequest::IS_NOT_OBSERVABLE);
|
||||
ByteRange range;
|
||||
range.fromInclusive = 1;
|
||||
range.toExclusive = 1;
|
||||
|
|
|
@ -34,7 +34,12 @@ public:
|
|||
QString normalizeURL(const QString& urlString);
|
||||
QUrl normalizeURL(const QUrl& url);
|
||||
|
||||
ResourceRequest* createResourceRequest(QObject* parent, const QUrl& url);
|
||||
ResourceRequest* createResourceRequest(
|
||||
QObject* parent,
|
||||
const QUrl& url,
|
||||
const bool isObservable = true,
|
||||
const qint64 callerId = -1,
|
||||
const QString& extra = "");
|
||||
|
||||
void init();
|
||||
void cleanup();
|
||||
|
|
|
@ -10,13 +10,13 @@
|
|||
//
|
||||
|
||||
#include "ResourceRequest.h"
|
||||
#include "ResourceRequestObserver.h"
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <StatTracker.h>
|
||||
|
||||
#include <QtCore/QThread>
|
||||
|
||||
ResourceRequest::ResourceRequest(const QUrl& url) : _url(url) { }
|
||||
|
||||
void ResourceRequest::send() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
|
@ -24,6 +24,10 @@ void ResourceRequest::send() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (_isObservable) {
|
||||
DependencyManager::get<ResourceRequestObserver>()->update(_url, _callerId, _extra + " => ResourceRequest::send");
|
||||
}
|
||||
|
||||
Q_ASSERT(_state == NotStarted);
|
||||
|
||||
_state = InProgress;
|
||||
|
|
|
@ -40,7 +40,20 @@ const QString STAT_FILE_RESOURCE_TOTAL_BYTES = "FILEBytesDownloaded";
|
|||
class ResourceRequest : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ResourceRequest(const QUrl& url);
|
||||
static const bool IS_OBSERVABLE = true;
|
||||
static const bool IS_NOT_OBSERVABLE = false;
|
||||
|
||||
ResourceRequest(
|
||||
const QUrl& url,
|
||||
const bool isObservable = IS_OBSERVABLE,
|
||||
const qint64 callerId = -1,
|
||||
const QString& extra = ""
|
||||
) : _url(url),
|
||||
_isObservable(isObservable),
|
||||
_callerId(callerId),
|
||||
_extra(extra)
|
||||
{ }
|
||||
|
||||
virtual ~ResourceRequest() = default;
|
||||
|
||||
enum State {
|
||||
|
@ -99,6 +112,9 @@ protected:
|
|||
bool _rangeRequestSuccessful { false };
|
||||
uint64_t _totalSizeOfResource { 0 };
|
||||
int64_t _lastRecordedBytesDownloaded { 0 };
|
||||
bool _isObservable;
|
||||
qint64 _callerId;
|
||||
QString _extra;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -734,11 +734,17 @@ QString getMarketplaceID(const QString& urlString) {
|
|||
return QString();
|
||||
}
|
||||
|
||||
bool Octree::readFromURL(const QString& urlString) {
|
||||
bool Octree::readFromURL(
|
||||
const QString& urlString,
|
||||
const bool isObservable,
|
||||
const qint64 callerId
|
||||
) {
|
||||
QString trimmedUrl = urlString.trimmed();
|
||||
QString marketplaceID = getMarketplaceID(trimmedUrl);
|
||||
auto request =
|
||||
std::unique_ptr<ResourceRequest>(DependencyManager::get<ResourceManager>()->createResourceRequest(this, trimmedUrl));
|
||||
qDebug() << "!!!!! going to createResourceRequest " << callerId;
|
||||
auto request = std::unique_ptr<ResourceRequest>(
|
||||
DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
this, trimmedUrl, isObservable, callerId, "Octree::readFromURL"));
|
||||
|
||||
if (!request) {
|
||||
return false;
|
||||
|
@ -768,7 +774,11 @@ bool Octree::readFromURL(const QString& urlString) {
|
|||
}
|
||||
|
||||
|
||||
bool Octree::readFromStream(uint64_t streamLength, QDataStream& inputStream, const QString& marketplaceID) {
|
||||
bool Octree::readFromStream(
|
||||
uint64_t streamLength,
|
||||
QDataStream& inputStream,
|
||||
const QString& marketplaceID
|
||||
) {
|
||||
// decide if this is binary SVO or JSON-formatted SVO
|
||||
QIODevice *device = inputStream.device();
|
||||
char firstChar;
|
||||
|
@ -809,7 +819,11 @@ QJsonDocument addMarketplaceIDToDocumentEntities(QJsonDocument& doc, const QStri
|
|||
|
||||
const int READ_JSON_BUFFER_SIZE = 2048;
|
||||
|
||||
bool Octree::readJSONFromStream(uint64_t streamLength, QDataStream& inputStream, const QString& marketplaceID /*=""*/) {
|
||||
bool Octree::readJSONFromStream(
|
||||
uint64_t streamLength,
|
||||
QDataStream& inputStream,
|
||||
const QString& marketplaceID /*=""*/
|
||||
) {
|
||||
// if the data is gzipped we may not have a useful bytesAvailable() result, so just keep reading until
|
||||
// we get an eof. Leave streamLength parameter for consistency.
|
||||
|
||||
|
|
|
@ -210,7 +210,7 @@ public:
|
|||
|
||||
// Octree importers
|
||||
bool readFromFile(const char* filename);
|
||||
bool readFromURL(const QString& url); // will support file urls as well...
|
||||
bool readFromURL(const QString& url, const bool isObservable = true, const qint64 callerId = -1); // will support file urls as well...
|
||||
bool readFromStream(uint64_t streamLength, QDataStream& inputStream, const QString& marketplaceID="");
|
||||
bool readSVOFromStream(uint64_t streamLength, QDataStream& inputStream);
|
||||
bool readJSONFromStream(uint64_t streamLength, QDataStream& inputStream, const QString& marketplaceID="");
|
||||
|
|
|
@ -138,7 +138,8 @@ QString FileScriptingInterface::convertUrlToPath(QUrl url) {
|
|||
// this function is not in use
|
||||
void FileScriptingInterface::downloadZip(QString path, const QString link) {
|
||||
QUrl url = QUrl(link);
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(nullptr, url);
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
nullptr, url, true, -1, "FileScriptingInterface::downloadZip");
|
||||
connect(request, &ResourceRequest::finished, this, [this, path]{
|
||||
unzipFile(path, ""); // so intellisense isn't mad
|
||||
});
|
||||
|
|
|
@ -109,7 +109,8 @@ void ScriptCache::getScriptContents(const QString& scriptOrURL, contentAvailable
|
|||
#ifdef THREAD_DEBUGGING
|
||||
qCDebug(scriptengine) << "about to call: ResourceManager::createResourceRequest(this, url); on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]";
|
||||
#endif
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(nullptr, url);
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
nullptr, url, true, -1, "ScriptCache::getScriptContents");
|
||||
Q_ASSERT(request);
|
||||
request->setCacheEnabled(!forceDownload);
|
||||
connect(request, &ResourceRequest::finished, this, [=]{ scriptContentAvailable(maxRetries); });
|
||||
|
@ -166,7 +167,8 @@ void ScriptCache::scriptContentAvailable(int maxRetries) {
|
|||
qCDebug(scriptengine) << QString("Retrying script request [%1 / %2]: %3")
|
||||
.arg(attempt).arg(maxRetries).arg(url.toString());
|
||||
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(nullptr, url);
|
||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||
nullptr, url, true, -1, "ScriptCache::scriptContentAvailable");
|
||||
Q_ASSERT(request);
|
||||
|
||||
// We've already made a request, so the cache must be disabled or it wasn't there, so enabling
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <NetworkAccessManager.h>
|
||||
#include <NetworkingConstants.h>
|
||||
|
||||
#include "ResourceRequestObserver.h"
|
||||
#include "ScriptEngine.h"
|
||||
|
||||
const QString METAVERSE_API_URL = NetworkingConstants::METAVERSE_SERVER_URL().toString() + "/api/";
|
||||
|
@ -189,7 +190,7 @@ void XMLHttpRequestClass::send(const QScriptValue& data) {
|
|||
}
|
||||
|
||||
void XMLHttpRequestClass::doSend() {
|
||||
|
||||
DependencyManager::get<ResourceRequestObserver>()->update(_url, -1, "XMLHttpRequestClass::doSend");
|
||||
_reply = NetworkAccessManager::getInstance().sendCustomRequest(_request, _method.toLatin1(), _sendData);
|
||||
connectToReply(_reply);
|
||||
|
||||
|
|
28
libraries/shared/src/ResourceRequestObserver.cpp
Normal file
28
libraries/shared/src/ResourceRequestObserver.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// ResourceAccessMonitor.h
|
||||
// libraries/networking/src
|
||||
//
|
||||
// Created by Kerry Ivan Kurian on 9/27/18.
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include "ResourceRequestObserver.h"
|
||||
|
||||
void ResourceRequestObserver::update(const QUrl& requestUrl,
|
||||
const qint64 callerId,
|
||||
const QString& extra) {
|
||||
QJsonArray array;
|
||||
QJsonObject data { { "url", requestUrl.toString() },
|
||||
{ "callerId", callerId },
|
||||
{ "extra", extra }
|
||||
};
|
||||
emit resourceRequestEvent(data.toVariantMap());
|
||||
}
|
29
libraries/shared/src/ResourceRequestObserver.h
Normal file
29
libraries/shared/src/ResourceRequestObserver.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// ResourceRequestObserver.h
|
||||
// libraries/commerce/src
|
||||
//
|
||||
// Created by Kerry Ivan Kurian on 9/27/18.
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QString>
|
||||
#include <QNetworkRequest>
|
||||
|
||||
#include "DependencyManager.h"
|
||||
|
||||
|
||||
class ResourceRequestObserver : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
void update(const QUrl& requestUrl, const qint64 callerId = -1, const QString& extra = "");
|
||||
|
||||
signals:
|
||||
void resourceRequestEvent(QVariantMap result);
|
||||
};
|
|
@ -49,6 +49,42 @@ var NO_BUTTON = 0; // QMessageBox::NoButton
|
|||
|
||||
var NO_PERMISSIONS_ERROR_MESSAGE = "Cannot download model because you can't write to \nthe domain's Asset Server.";
|
||||
|
||||
|
||||
var resourceRequestEvents = [];
|
||||
function signalResourceRequestEvent(data) {
|
||||
// Once we can tie resource request events to specific resources,
|
||||
// we will have to update the "0" in here.
|
||||
var resourceData = "from: " + data.extra + ": " + data.url.toString().replace("__NONE__,", "");
|
||||
|
||||
if (resourceObjectsInTest[0].resourceDataArray.indexOf(resourceData) === -1) {
|
||||
resourceObjectsInTest[0].resourceDataArray.push(resourceData);
|
||||
|
||||
resourceObjectsInTest[0].resourceAccessEventText += "[" + data.date.toISOString() + "] " +
|
||||
resourceData + "\n";
|
||||
|
||||
ui.tablet.sendToQml({
|
||||
method: "resourceRequestEvent",
|
||||
data: data,
|
||||
resourceAccessEventText: resourceObjectsInTest[0].resourceAccessEventText
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onResourceRequestEvent(data) {
|
||||
// Once we can tie resource request events to specific resources,
|
||||
// we will have to update the "0" in here.
|
||||
if (resourceObjectsInTest[0] && resourceObjectsInTest[0].currentlyRecordingResources) {
|
||||
var resourceRequestEvent = {
|
||||
"date": new Date(),
|
||||
"url": data.url,
|
||||
"callerId": data.callerId,
|
||||
"extra": data.extra
|
||||
};
|
||||
resourceRequestEvents.push(resourceRequestEvent);
|
||||
signalResourceRequestEvent(resourceRequestEvent);
|
||||
}
|
||||
}
|
||||
|
||||
function onMessageBoxClosed(id, button) {
|
||||
if (id === messageBox && button === CANCEL_BUTTON) {
|
||||
isDownloadBeingCancelled = true;
|
||||
|
@ -522,13 +558,18 @@ function getPositionToCreateEntity(extra) {
|
|||
return position;
|
||||
}
|
||||
|
||||
function rezEntity(itemHref, itemType) {
|
||||
function defaultFor(arg, val) {
|
||||
return typeof arg !== 'undefined' ? arg : val;
|
||||
}
|
||||
|
||||
function rezEntity(itemHref, itemType, marketplaceItemTesterId) {
|
||||
var isWearable = itemType === "wearable";
|
||||
var success = Clipboard.importEntities(itemHref);
|
||||
var success = Clipboard.importEntities(itemHref, true, marketplaceItemTesterId);
|
||||
var wearableLocalPosition = null;
|
||||
var wearableLocalRotation = null;
|
||||
var wearableLocalDimensions = null;
|
||||
var wearableDimensions = null;
|
||||
marketplaceItemTesterId = defaultFor(marketplaceItemTesterId, -1);
|
||||
|
||||
if (itemType === "contentSet") {
|
||||
console.log("Item is a content set; codepath shouldn't go here.");
|
||||
|
@ -816,7 +857,8 @@ var resourceObjectsInTest = [];
|
|||
function signalNewResourceObjectInTest(resourceObject) {
|
||||
ui.tablet.sendToQml({
|
||||
method: "newResourceObjectInTest",
|
||||
resourceObject: resourceObject });
|
||||
resourceObject: resourceObject
|
||||
});
|
||||
}
|
||||
|
||||
var onQmlMessageReceived = function onQmlMessageReceived(message) {
|
||||
|
@ -877,11 +919,15 @@ var onQmlMessageReceived = function onQmlMessageReceived(message) {
|
|||
case 'checkout_rezClicked':
|
||||
case 'purchases_rezClicked':
|
||||
case 'tester_rezClicked':
|
||||
rezEntity(message.itemHref, message.itemType);
|
||||
rezEntity(message.itemHref, message.itemType, message.itemId);
|
||||
break;
|
||||
case 'tester_newResourceObject':
|
||||
var resourceObject = message.resourceObject;
|
||||
resourceObjectsInTest[resourceObject.id] = resourceObject;
|
||||
resourceObjectsInTest = []; // REMOVE THIS once we support specific referrers
|
||||
resourceObject.currentlyRecordingResources = false;
|
||||
resourceObject.resourceAccessEventText = "";
|
||||
resourceObjectsInTest[resourceObject.resourceObjectId] = resourceObject;
|
||||
resourceObjectsInTest[resourceObject.resourceObjectId].resourceDataArray = [];
|
||||
signalNewResourceObjectInTest(resourceObject);
|
||||
break;
|
||||
case 'tester_updateResourceObjectAssetType':
|
||||
|
@ -890,6 +936,13 @@ var onQmlMessageReceived = function onQmlMessageReceived(message) {
|
|||
case 'tester_deleteResourceObject':
|
||||
delete resourceObjectsInTest[message.objectId];
|
||||
break;
|
||||
case 'tester_updateResourceRecordingStatus':
|
||||
resourceObjectsInTest[message.objectId].currentlyRecordingResources = message.status;
|
||||
if (message.status) {
|
||||
resourceObjectsInTest[message.objectId].resourceDataArray = [];
|
||||
resourceObjectsInTest[message.objectId].resourceAccessEventText = "";
|
||||
}
|
||||
break;
|
||||
case 'header_marketplaceImageClicked':
|
||||
case 'purchases_backClicked':
|
||||
openMarketplace(message.referrerURL);
|
||||
|
@ -1029,16 +1082,22 @@ var onQmlMessageReceived = function onQmlMessageReceived(message) {
|
|||
};
|
||||
|
||||
function pushResourceObjectsInTest() {
|
||||
var maxObjectId = -1;
|
||||
for (var objectId in resourceObjectsInTest) {
|
||||
signalNewResourceObjectInTest(resourceObjectsInTest[objectId]);
|
||||
maxObjectId = (maxObjectId < objectId) ? parseInt(objectId) : maxObjectId;
|
||||
var maxResourceObjectId = -1;
|
||||
var length = resourceObjectsInTest.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
if (i in resourceObjectsInTest) {
|
||||
signalNewResourceObjectInTest(resourceObjectsInTest[i]);
|
||||
var resourceObjectId = resourceObjectsInTest[i].resourceObjectId;
|
||||
maxResourceObjectId = (maxResourceObjectId < resourceObjectId) ? parseInt(resourceObjectId) : maxResourceObjectId;
|
||||
}
|
||||
}
|
||||
// N.B. Thinking about removing the following sendToQml? Be sure
|
||||
// that the marketplace item tester QML has heard from us, at least
|
||||
// so that it can indicate to the user that all of the resoruce
|
||||
// objects in test have been transmitted to it.
|
||||
ui.tablet.sendToQml({ method: "nextObjectIdInTest", id: maxObjectId + 1 });
|
||||
//ui.tablet.sendToQml({ method: "nextObjectIdInTest", id: maxResourceObjectId + 1 });
|
||||
// Since, for now, we only support 1 object in test, always send id: 0
|
||||
ui.tablet.sendToQml({ method: "nextObjectIdInTest", id: 0 });
|
||||
}
|
||||
|
||||
// Function Name: onTabletScreenChanged()
|
||||
|
@ -1193,6 +1252,7 @@ function startup() {
|
|||
ui.tablet.webEventReceived.connect(onWebEventReceived);
|
||||
Wallet.walletStatusChanged.connect(sendCommerceSettings);
|
||||
Window.messageBoxClosed.connect(onMessageBoxClosed);
|
||||
ResourceRequestObserver.resourceRequestEvent.connect(onResourceRequestEvent);
|
||||
|
||||
Wallet.refreshWalletStatus();
|
||||
}
|
||||
|
@ -1226,6 +1286,7 @@ function shutdown() {
|
|||
GlobalServices.myUsernameChanged.disconnect(onUsernameChanged);
|
||||
Entities.canWriteAssetsChanged.disconnect(onCanWriteAssetsChanged);
|
||||
ContextOverlay.contextOverlayClicked.disconnect(openInspectionCertificateQML);
|
||||
ResourceRequestObserver.resourceRequestEvent.disconnect(onResourceRequestEvent);
|
||||
|
||||
off();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue