diff --git a/interface/resources/qml/hifi/AvatarPackagerWindow.qml b/interface/resources/qml/hifi/AvatarPackagerWindow.qml
index 9d434ef97c..82bcd3fa40 100644
--- a/interface/resources/qml/hifi/AvatarPackagerWindow.qml
+++ b/interface/resources/qml/hifi/AvatarPackagerWindow.qml
@@ -1,15 +1,7 @@
import QtQuick 2.6
-import QtQuick.Controls 2.2
-import QtQuick.Layouts 1.3
-import QtQml.Models 2.1
-import QtGraphicalEffects 1.0
-import "../controlsUit" 1.0 as HifiControls
import "../stylesUit" 1.0
import "../windows" as Windows
-import "../controls" 1.0
-import "../dialogs"
import "avatarPackager" 1.0
-import "avatarapp" 1.0 as AvatarApp
Windows.ScrollingWindow {
id: root
diff --git a/interface/resources/qml/hifi/avatarPackager/AvatarPackagerApp.qml b/interface/resources/qml/hifi/avatarPackager/AvatarPackagerApp.qml
index 0a678dafee..fb7987ca76 100644
--- a/interface/resources/qml/hifi/avatarPackager/AvatarPackagerApp.qml
+++ b/interface/resources/qml/hifi/avatarPackager/AvatarPackagerApp.qml
@@ -3,9 +3,9 @@ import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import QtQml.Models 2.1
import QtGraphicalEffects 1.0
+import Hifi.AvatarPackager.AvatarProjectStatus 1.0
import "../../controlsUit" 1.0 as HifiControls
import "../../stylesUit" 1.0
-import "../../windows" as Windows
import "../../controls" 1.0
import "../../dialogs"
import "../avatarapp" 1.0 as AvatarApp
@@ -16,9 +16,6 @@ Item {
property alias desktopObject: avatarPackager.desktopObject
id: windowContent
- // height: pane ? pane.height : parent.width
- // width: pane ? pane.width : parent.width
-
MouseArea {
anchors.fill: parent
@@ -75,6 +72,37 @@ Item {
}
}
+ InfoBox {
+ id: errorPopup
+
+ property string errorMessage;
+
+ boxWidth: 380
+ boxHeight: 293
+
+ content: RalewayRegular {
+
+ id: bodyMessage
+
+ anchors.fill: parent
+ anchors.bottomMargin: 10
+ anchors.leftMargin: 29
+ anchors.rightMargin: 29
+
+ size: 20
+ color: "white"
+ text: errorPopup.errorMessage
+ width: parent.width
+ wrapMode: Text.WordWrap
+ }
+
+ function show(title, message) {
+ errorPopup.title = title;
+ errorMessage = message;
+ errorPopup.open();
+ }
+ }
+
Rectangle {
id: modalOverlay
anchors.fill: parent
@@ -85,8 +113,8 @@ Item {
// This mouse area captures the cursor events while the modalOverlay is active
MouseArea {
anchors.fill: parent
- propagateComposedEvents: false;
- hoverEnabled: true;
+ propagateComposedEvents: false
+ hoverEnabled: true
}
}
@@ -133,12 +161,58 @@ Item {
property var desktopObject: desktop
function openProject(path) {
- let project = AvatarPackagerCore.openAvatarProject(path);
- if (project) {
- avatarProject.reset();
- avatarPackager.state = AvatarPackagerState.project;
+ let status = AvatarPackagerCore.openAvatarProject(path);
+ if (status !== AvatarProjectStatus.SUCCESS) {
+ displayErrorMessage(status);
+ return status;
}
- return project;
+ avatarProject.reset();
+ avatarPackager.state = AvatarPackagerState.project;
+ return status;
+ }
+
+ function displayErrorMessage(status) {
+ if (status === AvatarProjectStatus.SUCCESS) {
+ return;
+ }
+ switch (status) {
+ case AvatarProjectStatus.ERROR_CREATE_PROJECT_NAME:
+ errorPopup.show("Project Folder Already Exists", "A folder with that name already exists at that location. Please choose a different project name or location.");
+ break;
+ case AvatarProjectStatus.ERROR_CREATE_CREATING_DIRECTORIES:
+ errorPopup.show("Project Folders Creation Error", "There was a problem during the creation of the Avatar Project directories. Please select a project location with write permissions.");
+ break;
+ case AvatarProjectStatus.ERROR_CREATE_FIND_MODEL:
+ errorPopup.show("Cannot Find Model File", "There was a problem while trying to find the specified model file. Please verify if it exist at the specified location.");
+ break;
+ case AvatarProjectStatus.ERROR_CREATE_OPEN_MODEL:
+ errorPopup.show("Cannot Open Model File", "There was a problem while trying to open the specified model file. Please verify if you have read permissions at the specified location.");
+ break;
+ case AvatarProjectStatus.ERROR_CREATE_READ_MODEL:
+ errorPopup.show("Error Read Model File", "There was a problem while trying to read the specified model file. Please verify if the model file is supported by High Fidelity.");
+ break;
+ case AvatarProjectStatus.ERROR_CREATE_WRITE_FST:
+ errorPopup.show("Error Writing Project File", "There was a problem while trying to write the FST file.");
+ break;
+ case AvatarProjectStatus.ERROR_OPEN_INVALID_FILE_TYPE:
+ errorPopup.show("Invalid Project Path", "The avatar packager can only open FST files.");
+ break;
+ case AvatarProjectStatus.ERROR_OPEN_PROJECT_FOLDER:
+ errorPopup.show("Project Missing", "Project folder cannot be found. Please locate the folder and copy/move it to its original location.");
+ break;
+ case AvatarProjectStatus.ERROR_OPEN_FIND_FST:
+ errorPopup.show("File Missing", "We cannot find the project file (avatar.fst) in the folder. Please locate it and move to the project folder.");
+ break;
+ case AvatarProjectStatus.ERROR_OPEN_OPEN_FST:
+ errorPopup.show("File Read Error", "We cannot read the project file (avatar.fst). Please make sure that it is not in use by another program.");
+ break;
+ case AvatarProjectStatus.ERROR_OPEN_FIND_MODEL:
+ errorPopup.show("File Missing", "We cannot find the avatar model file (.fbx) in the folder. Please locate it and move to the project folder.");
+ break;
+ default:
+ errorPopup.show("Error Message Missing", "Error message missing for status " + status);
+ }
+
}
function openDocs() {
@@ -233,10 +307,8 @@ Item {
browser.selectedFile.connect(function(fileUrl) {
let fstFilePath = fileDialogHelper.urlToPath(fileUrl);
- let currentAvatarProject = avatarPackager.openProject(fstFilePath);
- if (currentAvatarProject) {
- avatarPackager.showModalOverlay = false;
- }
+ avatarPackager.showModalOverlay = false;
+ avatarPackager.openProject(fstFilePath);
});
}
}
@@ -253,12 +325,20 @@ Item {
RalewayRegular {
size: 20
color: "white"
- text: qsTr("Use a custom avatar to express your identity")
+ text: "Use a custom avatar of your choice."
+ width: parent.width
+ wrapMode: Text.WordWrap
}
RalewayRegular {
size: 20
color: "white"
- text: qsTr("To learn more about using this tool, visit our docs")
+ text: "Visit our docs to learn more about using the packager."
+ linkColor: "#00B4EF"
+ width: parent.width
+ wrapMode: Text.WordWrap
+ onLinkActivated: {
+ avatarPackager.openDocs();
+ }
}
}
diff --git a/interface/resources/qml/hifi/avatarPackager/AvatarPackagerFooter.qml b/interface/resources/qml/hifi/avatarPackager/AvatarPackagerFooter.qml
index e1d9396e04..31e05672d2 100644
--- a/interface/resources/qml/hifi/avatarPackager/AvatarPackagerFooter.qml
+++ b/interface/resources/qml/hifi/avatarPackager/AvatarPackagerFooter.qml
@@ -38,5 +38,4 @@ Rectangle {
width: parent.width
}
}
-
-}
\ No newline at end of file
+}
diff --git a/interface/resources/qml/hifi/avatarPackager/AvatarPackagerHeader.qml b/interface/resources/qml/hifi/avatarPackager/AvatarPackagerHeader.qml
index d0b06ea15f..cd6fdb72fe 100644
--- a/interface/resources/qml/hifi/avatarPackager/AvatarPackagerHeader.qml
+++ b/interface/resources/qml/hifi/avatarPackager/AvatarPackagerHeader.qml
@@ -93,7 +93,6 @@ ShadowRectangle {
z: 200
onFocusChanged: {
if (titleArea.state === "renaming" && !titleArea.focus) {
- //titleArea.state = "";
accepted();
}
}
@@ -104,11 +103,7 @@ ShadowRectangle {
}
onAccepted: {
if (acceptableInput) {
- //AvatarPackagerCore.renameProject(text);
- console.warn(text);
AvatarPackagerCore.currentAvatarProject.name = text;
- console.warn(AvatarPackagerCore.currentAvatarProject.name);
-
}
titleArea.state = "";
}
diff --git a/interface/resources/qml/hifi/avatarPackager/AvatarProject.qml b/interface/resources/qml/hifi/avatarPackager/AvatarProject.qml
index a5a2263346..8f7a4be481 100644
--- a/interface/resources/qml/hifi/avatarPackager/AvatarProject.qml
+++ b/interface/resources/qml/hifi/avatarPackager/AvatarProject.qml
@@ -52,7 +52,7 @@ Item {
colorScheme: root.colorScheme
width: 133
height: 40
- onClicked: function() {
+ onClicked: {
uploadNew();
}
}
@@ -70,7 +70,7 @@ Item {
colorScheme: root.colorScheme
width: 134
height: 40
- onClicked: function() {
+ onClicked: {
showConfirmUploadPopup(uploadNew, uploadUpdate);
}
}
@@ -90,7 +90,7 @@ Item {
colorScheme: root.colorScheme
width: 134
height: 40
- onClicked: function() {
+ onClicked: {
showConfirmUploadPopup(uploadNew, uploadUpdate);
}
}
diff --git a/interface/resources/qml/hifi/avatarPackager/AvatarProjectUpload.qml b/interface/resources/qml/hifi/avatarPackager/AvatarProjectUpload.qml
index c1d1a98158..68f465f514 100644
--- a/interface/resources/qml/hifi/avatarPackager/AvatarProjectUpload.qml
+++ b/interface/resources/qml/hifi/avatarPackager/AvatarProjectUpload.qml
@@ -29,10 +29,11 @@ Item {
function stateChangedCallback(newState) {
if (newState >= 4) {
- root.uploader.stateChanged.disconnect(stateChangedCallback)
+ root.uploader.stateChanged.disconnect(stateChangedCallback);
backToProjectTimer.start();
}
}
+
onVisibleChanged: {
if (visible) {
root.uploader.stateChanged.connect(stateChangedCallback);
@@ -120,6 +121,7 @@ Item {
source: "../../../icons/checkmark-stroke.svg"
}
}
+
Item {
id: statusRows
@@ -169,6 +171,7 @@ Item {
color: "white"
text: "We couldn't upload your avatar at this time. Please try again later."
}
+
AvatarPackagerFooter {
id: errorFooter
diff --git a/interface/resources/qml/hifi/avatarPackager/CreateAvatarProject.qml b/interface/resources/qml/hifi/avatarPackager/CreateAvatarProject.qml
index d6f530a196..1e9a3d9e84 100644
--- a/interface/resources/qml/hifi/avatarPackager/CreateAvatarProject.qml
+++ b/interface/resources/qml/hifi/avatarPackager/CreateAvatarProject.qml
@@ -2,6 +2,8 @@ import QtQuick 2.6
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
+import Hifi.AvatarPackager.AvatarProjectStatus 1.0
+
import "../../controlsUit" 1.0 as HifiControls
import "../../stylesUit" 1.0
@@ -24,8 +26,9 @@ Item {
text: qsTr("Create")
enabled: false
onClicked: {
- if (!AvatarPackagerCore.createAvatarProject(projectLocation.text, name.text, avatarModel.text, textureFolder.text)) {
- Window.alert('Failed to create project');
+ let status = AvatarPackagerCore.createAvatarProject(projectLocation.text, name.text, avatarModel.text, textureFolder.text);
+ if (status !== AvatarProjectStatus.SUCCESS) {
+ avatarPackager.displayErrorMessage(status);
return;
}
avatarPackager.state = AvatarPackagerState.project;
diff --git a/interface/resources/qml/hifi/avatarPackager/InfoBox.qml b/interface/resources/qml/hifi/avatarPackager/InfoBox.qml
index 89f5d5c7f8..301386acfa 100644
--- a/interface/resources/qml/hifi/avatarPackager/InfoBox.qml
+++ b/interface/resources/qml/hifi/avatarPackager/InfoBox.qml
@@ -5,9 +5,9 @@ import controlsUit 1.0 as HifiControlsUit
import "../../controls" as HifiControls
Rectangle {
- id: root;
- visible: false;
- color: Qt.rgba(.34, .34, .34, 0.6);
+ id: root
+ visible: false
+ color: Qt.rgba(.34, .34, .34, 0.6)
z: 999;
anchors.fill: parent
@@ -17,6 +17,9 @@ Rectangle {
property bool closeOnClickOutside: false;
+ property alias boxWidth: mainContainer.width
+ property alias boxHeight: mainContainer.height
+
function open() {
visible = true;
}
@@ -44,15 +47,15 @@ Rectangle {
}
Rectangle {
- id: mainContainer;
+ id: mainContainer
width: Math.max(parent.width * 0.8, 400)
height: parent.height * 0.6
MouseArea {
- anchors.fill: parent;
- propagateComposedEvents: false;
- hoverEnabled: true;
+ anchors.fill: parent
+ propagateComposedEvents: false
+ hoverEnabled: true
onClicked: function(ev) {
ev.accepted = true;
}
@@ -107,6 +110,5 @@ Rectangle {
colorScheme: hifi.colorSchemes.dark;
}
}
-
}
}
diff --git a/interface/src/avatar/AvatarPackager.cpp b/interface/src/avatar/AvatarPackager.cpp
index eef574a8b5..941aff6943 100644
--- a/interface/src/avatar/AvatarPackager.cpp
+++ b/interface/src/avatar/AvatarPackager.cpp
@@ -22,7 +22,6 @@
#include
#include
-#include "scripting/HMDScriptingInterface.h"
#include "ui/TabletScriptingInterface.h"
std::once_flag setupQMLTypesFlag;
@@ -32,6 +31,14 @@ AvatarPackager::AvatarPackager() {
qmlRegisterType();
qRegisterMetaType();
qRegisterMetaType();
+ qRegisterMetaType();
+ qmlRegisterUncreatableMetaObject(
+ AvatarProjectStatus::staticMetaObject,
+ "Hifi.AvatarPackager.AvatarProjectStatus",
+ 1, 0,
+ "AvatarProjectStatus",
+ "Error: only enums"
+ );
});
recentProjectsFromVariantList(_recentProjectsSetting.get());
@@ -41,39 +48,39 @@ AvatarPackager::AvatarPackager() {
}
bool AvatarPackager::open() {
- static const QUrl url{ "hifi/AvatarPackagerWindow.qml" };
-
const auto packageModelDialogCreated = [=](QQmlContext* context, QObject* newObject) {
context->setContextProperty("AvatarPackagerCore", this);
};
static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
- auto tabletScriptingInterface = DependencyManager::get();
- auto tablet = dynamic_cast(tabletScriptingInterface->getTablet(SYSTEM_TABLET));
- auto hmd = DependencyManager::get();
+ auto tablet = dynamic_cast(DependencyManager::get()->getTablet(SYSTEM_TABLET));
if (tablet->getToolbarMode()) {
+ static const QUrl url{ "hifi/AvatarPackagerWindow.qml" };
DependencyManager::get()->show(url, "AvatarPackager", packageModelDialogCreated);
- } else {
- static const QUrl url("hifi/tablet/AvatarPackager.qml");
- if (!tablet->isPathLoaded(url)) {
- tablet->getTabletSurface()->getSurfaceContext()->setContextProperty("AvatarPackagerCore", this);
- tablet->pushOntoStack(url);
- }
+ return true;
}
- return true;
+
+ static const QUrl url{ "hifi/tablet/AvatarPackager.qml" };
+ if (!tablet->isPathLoaded(url)) {
+ tablet->getTabletSurface()->getSurfaceContext()->setContextProperty("AvatarPackagerCore", this);
+ tablet->pushOntoStack(url);
+ return true;
+ }
+
+ return false;
}
void AvatarPackager::addCurrentProjectToRecentProjects() {
const int MAX_RECENT_PROJECTS = 5;
const QString& fstPath = _currentAvatarProject->getFSTPath();
auto removeProjects = QVector();
- for (auto project : _recentProjects) {
+ for (const auto& project : _recentProjects) {
if (project.getProjectFSTPath() == fstPath) {
removeProjects.append(project);
}
}
- for (const auto removeProject : removeProjects) {
+ for (const auto& removeProject : removeProjects) {
_recentProjects.removeOne(removeProject);
}
@@ -110,14 +117,19 @@ void AvatarPackager::recentProjectsFromVariantList(QVariantList projectsVariant)
}
}
-AvatarProject* AvatarPackager::openAvatarProject(const QString& avatarProjectFSTPath) {
- setAvatarProject(AvatarProject::openAvatarProject(avatarProjectFSTPath));
- return _currentAvatarProject;
+AvatarProjectStatus::AvatarProjectStatus AvatarPackager::openAvatarProject(const QString& avatarProjectFSTPath) {
+ AvatarProjectStatus::AvatarProjectStatus status;
+ setAvatarProject(AvatarProject::openAvatarProject(avatarProjectFSTPath, status));
+ return status;
}
-AvatarProject* AvatarPackager::createAvatarProject(const QString& projectsFolder, const QString& avatarProjectName, const QString& avatarModelPath, const QString& textureFolder) {
- setAvatarProject(AvatarProject::createAvatarProject(projectsFolder, avatarProjectName, avatarModelPath, textureFolder));
- return _currentAvatarProject;
+AvatarProjectStatus::AvatarProjectStatus AvatarPackager::createAvatarProject(const QString& projectsFolder,
+ const QString& avatarProjectName,
+ const QString& avatarModelPath,
+ const QString& textureFolder) {
+ AvatarProjectStatus::AvatarProjectStatus status;
+ setAvatarProject(AvatarProject::createAvatarProject(projectsFolder, avatarProjectName, avatarModelPath, textureFolder, status));
+ return status;
}
void AvatarPackager::setAvatarProject(AvatarProject* avatarProject) {
diff --git a/interface/src/avatar/AvatarPackager.h b/interface/src/avatar/AvatarPackager.h
index 343176497f..c9c5b9d312 100644
--- a/interface/src/avatar/AvatarPackager.h
+++ b/interface/src/avatar/AvatarPackager.h
@@ -63,8 +63,12 @@ public:
AvatarPackager();
bool open();
- Q_INVOKABLE AvatarProject* createAvatarProject(const QString& projectsFolder, const QString& avatarProjectName, const QString& avatarModelPath, const QString& textureFolder);
- Q_INVOKABLE AvatarProject* openAvatarProject(const QString& avatarProjectFSTPath);
+ Q_INVOKABLE AvatarProjectStatus::AvatarProjectStatus createAvatarProject(const QString& projectsFolder,
+ const QString& avatarProjectName,
+ const QString& avatarModelPath,
+ const QString& textureFolder);
+
+ Q_INVOKABLE AvatarProjectStatus::AvatarProjectStatus openAvatarProject(const QString& avatarProjectFSTPath);
Q_INVOKABLE bool isValidNewProjectName(const QString& projectPath, const QString& projectName) { return AvatarProject::isValidNewProjectName(projectPath, projectName); }
signals:
diff --git a/interface/src/avatar/AvatarProject.cpp b/interface/src/avatar/AvatarProject.cpp
index 0c29bcf906..e049dc0ba3 100644
--- a/interface/src/avatar/AvatarProject.cpp
+++ b/interface/src/avatar/AvatarProject.cpp
@@ -22,55 +22,98 @@
#include
#include "scripting/HMDScriptingInterface.h"
-AvatarProject* AvatarProject::openAvatarProject(const QString& path) {
+AvatarProject* AvatarProject::openAvatarProject(const QString& path, AvatarProjectStatus::AvatarProjectStatus& status) {
+ status = AvatarProjectStatus::NONE;
+
if (!path.toLower().endsWith(".fst")) {
+ status = AvatarProjectStatus::ERROR_OPEN_INVALID_FILE_TYPE;
return nullptr;
}
- QFile file{ path };
+
+ QFileInfo fstFileInfo{ path };
+ if (!fstFileInfo.absoluteDir().exists()) {
+ status = AvatarProjectStatus::ERROR_OPEN_PROJECT_FOLDER;
+ return nullptr;
+ }
+
+ if (!fstFileInfo.exists()) {
+ status = AvatarProjectStatus::ERROR_OPEN_FIND_FST;
+ return nullptr;
+ }
+
+ QFile file{ fstFileInfo.filePath() };
if (!file.open(QIODevice::ReadOnly)) {
+ status = AvatarProjectStatus::ERROR_OPEN_OPEN_FST;
return nullptr;
}
+
const auto project = new AvatarProject(path, file.readAll());
+
+ QFileInfo fbxFileInfo{ project->getFBXPath() };
+ if (!fbxFileInfo.exists()) {
+ project->deleteLater();
+ status = AvatarProjectStatus::ERROR_OPEN_FIND_MODEL;
+ return nullptr;
+ }
+
QQmlEngine::setObjectOwnership(project, QQmlEngine::CppOwnership);
+ status = AvatarProjectStatus::SUCCESS;
return project;
}
-AvatarProject* AvatarProject::createAvatarProject(const QString& projectsFolder, const QString& avatarProjectName, const QString& avatarModelPath, const QString& textureFolder) {
+AvatarProject* AvatarProject::createAvatarProject(const QString& projectsFolder, const QString& avatarProjectName,
+ const QString& avatarModelPath, const QString& textureFolder,
+ AvatarProjectStatus::AvatarProjectStatus& status) {
+ status = AvatarProjectStatus::NONE;
+
if (!isValidNewProjectName(projectsFolder, avatarProjectName)) {
+ status = AvatarProjectStatus::ERROR_CREATE_PROJECT_NAME;
return nullptr;
}
+
QDir projectDir(projectsFolder + "/" + avatarProjectName);
if (!projectDir.mkpath(".")) {
+ status = AvatarProjectStatus::ERROR_CREATE_CREATING_DIRECTORIES;
return nullptr;
}
+
QDir projectTexturesDir(projectDir.path() + "/textures");
if (!projectTexturesDir.mkpath(".")) {
+ status = AvatarProjectStatus::ERROR_CREATE_CREATING_DIRECTORIES;
return nullptr;
}
+
QDir projectScriptsDir(projectDir.path() + "/scripts");
if (!projectScriptsDir.mkpath(".")) {
+ status = AvatarProjectStatus::ERROR_CREATE_CREATING_DIRECTORIES;
return nullptr;
}
+
const auto fileName = QFileInfo(avatarModelPath).fileName();
const auto newModelPath = projectDir.absoluteFilePath(fileName);
const auto newFSTPath = projectDir.absoluteFilePath("avatar.fst");
QFile::copy(avatarModelPath, newModelPath);
- QFileInfo fbxInfo(newModelPath);
- QFile fbx(fbxInfo.filePath());
- if (!fbxInfo.exists() || !fbxInfo.isFile() || !fbx.open(QIODevice::ReadOnly)) {
- // TODO: Can't open model FBX (throw error here)
+ QFileInfo fbxInfo{ newModelPath };
+ if (!fbxInfo.exists() || !fbxInfo.isFile()) {
+ status = AvatarProjectStatus::ERROR_CREATE_FIND_MODEL;
+ return nullptr;
+ }
+
+ QFile fbx{ fbxInfo.filePath() };
+ if (!fbx.open(QIODevice::ReadOnly)) {
+ status = AvatarProjectStatus::ERROR_CREATE_OPEN_MODEL;
return nullptr;
}
std::shared_ptr hfmModel;
try {
- qDebug() << "Reading FBX file : " << fbxInfo.filePath();
const QByteArray fbxContents = fbx.readAll();
hfmModel = FBXSerializer().read(fbxContents, QVariantHash(), fbxInfo.filePath());
} catch (const QString& error) {
- qDebug() << "Error reading: " << error;
+ Q_UNUSED(error)
+ status = AvatarProjectStatus::ERROR_CREATE_READ_MODEL;
return nullptr;
}
QStringList textures{};
@@ -111,9 +154,11 @@ AvatarProject* AvatarProject::createAvatarProject(const QString& projectsFolder,
fst->setName(avatarProjectName);
if (!fst->write()) {
+ status = AvatarProjectStatus::ERROR_CREATE_WRITE_FST;
return nullptr;
}
+ status = AvatarProjectStatus::SUCCESS;
return new AvatarProject(fst);
}
@@ -157,7 +202,7 @@ AvatarProject::AvatarProject(FST* fst) {
_projectPath = fileInfo.absoluteDir().absolutePath();
}
-void AvatarProject::appendDirectory(QString prefix, QDir dir) {
+void AvatarProject::appendDirectory(const QString& prefix, const QDir& dir) {
constexpr auto flags = QDir::Dirs | QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot | QDir::Hidden;
for (auto& entry : dir.entryInfoList({}, flags)) {
if (entry.isFile()) {
diff --git a/interface/src/avatar/AvatarProject.h b/interface/src/avatar/AvatarProject.h
index 469324004d..c422c14d62 100644
--- a/interface/src/avatar/AvatarProject.h
+++ b/interface/src/avatar/AvatarProject.h
@@ -22,6 +22,27 @@
#include
#include
+namespace AvatarProjectStatus {
+ Q_NAMESPACE
+ enum AvatarProjectStatus {
+ NONE,
+ SUCCESS,
+ ERROR_CREATE_PROJECT_NAME,
+ ERROR_CREATE_CREATING_DIRECTORIES,
+ ERROR_CREATE_FIND_MODEL,
+ ERROR_CREATE_OPEN_MODEL,
+ ERROR_CREATE_READ_MODEL,
+ ERROR_CREATE_WRITE_FST,
+ ERROR_OPEN_INVALID_FILE_TYPE,
+ ERROR_OPEN_PROJECT_FOLDER,
+ ERROR_OPEN_FIND_FST,
+ ERROR_OPEN_OPEN_FST,
+ ERROR_OPEN_FIND_MODEL
+ };
+ Q_ENUM_NS(AvatarProjectStatus)
+}
+
+
class AvatarProject : public QObject {
Q_OBJECT
Q_PROPERTY(FST* fst READ getFST CONSTANT)
@@ -48,16 +69,19 @@ public:
}
Q_INVOKABLE QString getProjectPath() const { return _projectPath; }
Q_INVOKABLE QString getFSTPath() const { return _fst->getPath(); }
- Q_INVOKABLE QString getFBXPath() const { return _fst->getModelPath(); }
+ Q_INVOKABLE QString getFBXPath() const {
+ return QDir::cleanPath(QDir(_projectPath).absoluteFilePath(_fst->getModelPath()));
+ }
/**
* returns the AvatarProject or a nullptr on failure.
*/
- static AvatarProject* openAvatarProject(const QString& path);
+ static AvatarProject* openAvatarProject(const QString& path, AvatarProjectStatus::AvatarProjectStatus& status);
static AvatarProject* createAvatarProject(const QString& projectsFolder,
const QString& avatarProjectName,
const QString& avatarModelPath,
- const QString& textureFolder);
+ const QString& textureFolder,
+ AvatarProjectStatus::AvatarProjectStatus& status);
static bool isValidNewProjectName(const QString& projectPath, const QString& projectName);
@@ -78,7 +102,7 @@ private:
FST* getFST() { return _fst; }
void refreshProjectFiles();
- void appendDirectory(QString prefix, QDir dir);
+ void appendDirectory(const QString& prefix, const QDir& dir);
QStringList getScriptPaths(const QDir& scriptsDir);
FST* _fst;