mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 21:36:47 +02:00
commit
47f18e5166
3 changed files with 146 additions and 125 deletions
|
@ -36,7 +36,6 @@ Window {
|
||||||
property var assetProxyModel: Assets.proxyModel;
|
property var assetProxyModel: Assets.proxyModel;
|
||||||
property var assetMappingsModel: Assets.mappingModel;
|
property var assetMappingsModel: Assets.mappingModel;
|
||||||
property var currentDirectory;
|
property var currentDirectory;
|
||||||
property alias currentFileUrl: fileUrlTextField.text;
|
|
||||||
|
|
||||||
Settings {
|
Settings {
|
||||||
category: "Overlay.AssetServer"
|
category: "Overlay.AssetServer"
|
||||||
|
@ -46,8 +45,8 @@ Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
assetMappingsModel.errorGettingMappings.connect(handleGetMappingsError)
|
assetMappingsModel.errorGettingMappings.connect(handleGetMappingsError);
|
||||||
reload()
|
reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
function doDeleteFile(path) {
|
function doDeleteFile(path) {
|
||||||
|
@ -241,47 +240,67 @@ Window {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function chooseClicked() {
|
|
||||||
var browser = desktop.fileDialog({
|
|
||||||
selectDirectory: false,
|
|
||||||
dir: currentDirectory
|
|
||||||
});
|
|
||||||
browser.selectedFile.connect(function(url){
|
|
||||||
fileUrlTextField.text = fileDialogHelper.urlToPath(url);
|
|
||||||
currentDirectory = browser.dir;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
property var uploadOpen: false;
|
property var uploadOpen: false;
|
||||||
|
Timer {
|
||||||
|
id: timer
|
||||||
|
}
|
||||||
function uploadClicked() {
|
function uploadClicked() {
|
||||||
if (uploadOpen) {
|
if (uploadOpen) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uploadOpen = true;
|
uploadOpen = true;
|
||||||
|
|
||||||
var fileUrl = fileUrlTextField.text
|
var fileUrl = "";
|
||||||
var shouldAddToWorld = addToWorldCheckBox.checked
|
|
||||||
|
|
||||||
var path = assetProxyModel.data(treeView.selection.currentIndex, 0x100);
|
var browser = desktop.fileDialog({
|
||||||
var directory = path ? path.slice(0, path.lastIndexOf('/') + 1) : "/";
|
selectDirectory: false,
|
||||||
var filename = fileUrl.slice(fileUrl.lastIndexOf('/') + 1);
|
dir: currentDirectory
|
||||||
|
});
|
||||||
Assets.uploadFile(fileUrl, directory + filename, function(err, path) {
|
browser.canceled.connect(function() {
|
||||||
if (err) {
|
uploadOpen = false;
|
||||||
console.log("Asset Browser - error uploading: ", fileUrl, " - error ", err);
|
});
|
||||||
var box = errorMessageBox("There was an error uploading:\n" + fileUrl + "\n" + err);
|
browser.selectedFile.connect(function(url){
|
||||||
box.selected.connect(reload);
|
var fileUrl = fileDialogHelper.urlToPath(url);
|
||||||
} else {
|
currentDirectory = browser.dir;
|
||||||
console.log("Asset Browser - finished uploading: ", fileUrl);
|
|
||||||
|
var path = assetProxyModel.data(treeView.selection.currentIndex, 0x100);
|
||||||
if (shouldAddToWorld) {
|
var directory = path ? path.slice(0, path.lastIndexOf('/') + 1) : "/";
|
||||||
addToWorld("atp:" + path);
|
var filename = fileUrl.slice(fileUrl.lastIndexOf('/') + 1);
|
||||||
}
|
|
||||||
|
Assets.uploadFile(fileUrl, directory + filename,
|
||||||
reload();
|
function() {
|
||||||
}
|
// Upload started
|
||||||
|
uploadSpinner.visible = true;
|
||||||
|
uploadButton.enabled = false;
|
||||||
|
uploadProgressLabel.text = "In progress...";
|
||||||
|
},
|
||||||
|
function(err, path) {
|
||||||
|
print(err, path);
|
||||||
|
if (!err) {
|
||||||
|
uploadProgressLabel.text = "Upload Complete";
|
||||||
|
timer.interval = 1000;
|
||||||
|
timer.repeat = false;
|
||||||
|
timer.triggered.connect(function() {
|
||||||
|
uploadSpinner.visible = false;
|
||||||
|
uploadButton.enabled = true;
|
||||||
|
uploadOpen = false;
|
||||||
|
});
|
||||||
|
timer.start();
|
||||||
|
console.log("Asset Browser - finished uploading: ", fileUrl);
|
||||||
|
reload();
|
||||||
|
} else {
|
||||||
|
if (err > 0) {
|
||||||
|
console.log("Asset Browser - error uploading: ", fileUrl, " - error ", err);
|
||||||
|
var box = errorMessageBox("There was an error uploading:\n" + fileUrl + "\n" + Assets.getErrorString(err));
|
||||||
|
box.selected.connect(reload);
|
||||||
|
}
|
||||||
|
uploadSpinner.visible = false;
|
||||||
|
uploadButton.enabled = true;
|
||||||
|
uploadOpen = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
});
|
});
|
||||||
uploadOpen = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function errorMessageBox(message) {
|
function errorMessageBox(message) {
|
||||||
|
@ -297,8 +316,9 @@ Window {
|
||||||
return treeView.selection.hasSelection()
|
return treeView.selection.hasSelection()
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Item {
|
||||||
width: pane.contentWidth
|
width: pane.contentWidth
|
||||||
|
height: pane.height
|
||||||
|
|
||||||
HifiControls.ContentSection {
|
HifiControls.ContentSection {
|
||||||
id: assetDirectory
|
id: assetDirectory
|
||||||
|
@ -386,96 +406,52 @@ Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HifiControls.Tree {
|
HifiControls.Tree {
|
||||||
id: treeView
|
id: treeView
|
||||||
height: 400
|
anchors.top: assetDirectory.bottom
|
||||||
treeModel: assetProxyModel
|
anchors.bottom: uploadSection.top
|
||||||
colorScheme: root.colorScheme
|
anchors.margins: 12
|
||||||
canEdit: true
|
anchors.bottomMargin: 0
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
anchors.left: parent.left
|
treeModel: assetProxyModel
|
||||||
anchors.right: parent.right
|
canEdit: true
|
||||||
|
colorScheme: root.colorScheme
|
||||||
|
|
||||||
modifyEl: renameEl
|
modifyEl: renameEl
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
propagateComposedEvents: true
|
propagateComposedEvents: true
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
acceptedButtons: Qt.RightButton
|
acceptedButtons: Qt.RightButton
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var index = treeView.indexAt(mouse.x, mouse.y);
|
var index = treeView.indexAt(mouse.x, mouse.y);
|
||||||
|
|
||||||
treeView.selection.setCurrentIndex(index, 0x0002);
|
treeView.selection.setCurrentIndex(index, 0x0002);
|
||||||
|
|
||||||
contextMenu.currentIndex = index;
|
contextMenu.currentIndex = index;
|
||||||
contextMenu.popup();
|
contextMenu.popup();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HifiControls.ContentSection {
|
HifiControls.ContentSection {
|
||||||
id: uploadSection
|
id: uploadSection
|
||||||
name: ""
|
name: "Upload A File"
|
||||||
spacing: hifi.dimensions.contentSpacing.y
|
spacing: hifi.dimensions.contentSpacing.y
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
HifiControls.TextField {
|
height: 130
|
||||||
id: fileUrlTextField
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: chooseButton.width + hifi.dimensions.contentSpacing.x
|
|
||||||
|
|
||||||
label: "Upload File"
|
|
||||||
placeholderText: "Paste URL or choose file"
|
|
||||||
colorScheme: root.colorScheme
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
// Take the chooseButton out of the column flow.
|
height: parent.height
|
||||||
id: chooseButtonContainer
|
width: parent.width
|
||||||
anchors.top: fileUrlTextField.top
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
HifiControls.Button {
|
|
||||||
id: chooseButton
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
text: "Choose"
|
|
||||||
color: hifi.buttons.white
|
|
||||||
colorScheme: root.colorScheme
|
|
||||||
enabled: true
|
|
||||||
|
|
||||||
width: 100
|
|
||||||
|
|
||||||
onClicked: root.chooseClicked()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HifiControls.CheckBox {
|
|
||||||
id: addToWorldCheckBox
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: uploadButton.width + hifi.dimensions.contentSpacing.x
|
|
||||||
|
|
||||||
text: "Add to world on upload"
|
|
||||||
|
|
||||||
opacity: canAddToWorld(fileUrlTextField.text) ? 1 : 0
|
|
||||||
|
|
||||||
checked: false
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
// Take the uploadButton out of the column flow.
|
|
||||||
id: uploadButtonContainer
|
|
||||||
anchors.top: addToWorldCheckBox.top
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
HifiControls.Button {
|
HifiControls.Button {
|
||||||
id: uploadButton
|
id: uploadButton
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
text: "Upload"
|
text: "Choose File"
|
||||||
color: hifi.buttons.blue
|
color: hifi.buttons.blue
|
||||||
colorScheme: root.colorScheme
|
colorScheme: root.colorScheme
|
||||||
height: 30
|
height: 30
|
||||||
|
@ -499,9 +475,44 @@ Window {
|
||||||
onTriggered: uploadClicked();
|
onTriggered: uploadClicked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: uploadSpinner
|
||||||
|
visible: false
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
width: 40
|
||||||
|
height: 32
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: image
|
||||||
|
width: 24
|
||||||
|
height: 24
|
||||||
|
source: "../images/Loading-Outer-Ring.png"
|
||||||
|
RotationAnimation on rotation {
|
||||||
|
loops: Animation.Infinite
|
||||||
|
from: 0
|
||||||
|
to: 360
|
||||||
|
duration: 2000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Image {
|
||||||
|
width: 24
|
||||||
|
height: 24
|
||||||
|
source: "../images/Loading-Inner-H.png"
|
||||||
|
}
|
||||||
|
HifiControls.Label {
|
||||||
|
id: uploadProgressLabel
|
||||||
|
anchors.left: image.right
|
||||||
|
anchors.leftMargin: 10
|
||||||
|
anchors.verticalCenter: image.verticalCenter
|
||||||
|
text: "In progress..."
|
||||||
|
colorScheme: root.colorScheme
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HifiControls.VerticalSpacer {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,11 +59,16 @@ void AssetMappingsScriptingInterface::getMapping(QString path, QJSValue callback
|
||||||
request->start();
|
request->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetMappingsScriptingInterface::uploadFile(QString path, QString mapping, QJSValue callback) {
|
void AssetMappingsScriptingInterface::uploadFile(QString path, QString mapping, QJSValue startedCallback, QJSValue completedCallback) {
|
||||||
|
static const QString helpText =
|
||||||
|
"Upload your asset to a specific folder by entering the full path. Specifying "
|
||||||
|
"a new folder name will automatically create that folder for you.";
|
||||||
|
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
auto result = offscreenUi->inputDialog(OffscreenUi::ICON_NONE, "Enter asset path:", "", mapping);
|
auto result = offscreenUi->inputDialog(OffscreenUi::ICON_INFORMATION, "Specify Asset Path", helpText, mapping);
|
||||||
|
|
||||||
if (!result.isValid()) {
|
if (!result.isValid()) {
|
||||||
|
completedCallback.call({ -1 });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mapping = result.toString();
|
mapping = result.toString();
|
||||||
|
@ -79,19 +84,22 @@ void AssetMappingsScriptingInterface::uploadFile(QString path, QString mapping,
|
||||||
auto button = offscreenUi->messageBox(OffscreenUi::ICON_QUESTION, "Overwrite File", message,
|
auto button = offscreenUi->messageBox(OffscreenUi::ICON_QUESTION, "Overwrite File", message,
|
||||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||||
if (button == QMessageBox::No) {
|
if (button == QMessageBox::No) {
|
||||||
|
completedCallback.call({ -1 });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startedCallback.call();
|
||||||
|
|
||||||
auto upload = DependencyManager::get<AssetClient>()->createUpload(path);
|
auto upload = DependencyManager::get<AssetClient>()->createUpload(path);
|
||||||
QObject::connect(upload, &AssetUpload::finished, this, [=](AssetUpload* upload, const QString& hash) mutable {
|
QObject::connect(upload, &AssetUpload::finished, this, [=](AssetUpload* upload, const QString& hash) mutable {
|
||||||
if (upload->getError() != AssetUpload::NoError) {
|
if (upload->getError() != AssetUpload::NoError) {
|
||||||
if (callback.isCallable()) {
|
if (completedCallback.isCallable()) {
|
||||||
QJSValueList args { upload->getErrorString() };
|
QJSValueList args { upload->getErrorString() };
|
||||||
callback.call(args);
|
completedCallback.call(args);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setMapping(mapping, hash, callback);
|
setMapping(mapping, hash, completedCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
upload->deleteLater();
|
upload->deleteLater();
|
||||||
|
|
|
@ -20,21 +20,23 @@
|
||||||
#include <AssetClient.h>
|
#include <AssetClient.h>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
class AssetMappingModel : public QStandardItemModel {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
Q_INVOKABLE void refresh();
|
|
||||||
|
|
||||||
bool isKnownMapping(QString path) const { return _pathToItemMap.contains(path); }
|
|
||||||
bool isKnownFolder(QString path) const;
|
|
||||||
|
|
||||||
signals:
|
class AssetMappingModel : public QStandardItemModel {
|
||||||
void errorGettingMappings(QString errorString);
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Q_INVOKABLE void refresh();
|
||||||
|
|
||||||
private:
|
bool isKnownMapping(QString path) const { return _pathToItemMap.contains(path); }
|
||||||
QHash<QString, QStandardItem*> _pathToItemMap;
|
bool isKnownFolder(QString path) const;
|
||||||
};
|
|
||||||
|
|
||||||
|
void errorGettingMappings(QString errorString);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QHash<QString, QStandardItem*> _pathToItemMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(AssetMappingModel*);
|
||||||
|
|
||||||
class AssetMappingsScriptingInterface : public QObject {
|
class AssetMappingsScriptingInterface : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -51,7 +53,7 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE void setMapping(QString path, QString hash, QJSValue callback = QJSValue());
|
Q_INVOKABLE void setMapping(QString path, QString hash, QJSValue callback = QJSValue());
|
||||||
Q_INVOKABLE void getMapping(QString path, QJSValue callback = QJSValue());
|
Q_INVOKABLE void getMapping(QString path, QJSValue callback = QJSValue());
|
||||||
Q_INVOKABLE void uploadFile(QString path, QString mapping, QJSValue callback = QJSValue());
|
Q_INVOKABLE void uploadFile(QString path, QString mapping, QJSValue startedCallback = QJSValue(), QJSValue completedCallback = QJSValue());
|
||||||
Q_INVOKABLE void deleteMappings(QStringList paths, QJSValue callback);
|
Q_INVOKABLE void deleteMappings(QStringList paths, QJSValue callback);
|
||||||
Q_INVOKABLE void deleteMapping(QString path, QJSValue callback) { deleteMappings(QStringList(path), callback = QJSValue()); }
|
Q_INVOKABLE void deleteMapping(QString path, QJSValue callback) { deleteMappings(QStringList(path), callback = QJSValue()); }
|
||||||
Q_INVOKABLE void getAllMappings(QJSValue callback = QJSValue());
|
Q_INVOKABLE void getAllMappings(QJSValue callback = QJSValue());
|
||||||
|
|
Loading…
Reference in a new issue