mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-07 12:12:39 +02:00
- error messages
- style changes
This commit is contained in:
parent
37d00d9519
commit
ecc578c2dd
12 changed files with 242 additions and 83 deletions
|
@ -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
|
||||
|
|
|
@ -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: "<a href='javascript:void'>Visit our docs</a> to learn more about using the packager."
|
||||
linkColor: "#00B4EF"
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
onLinkActivated: {
|
||||
avatarPackager.openDocs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,5 +38,4 @@ Rectangle {
|
|||
width: parent.width
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 = "";
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include <avatar/MarketplaceItemUploader.h>
|
||||
|
||||
#include <mutex>
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
#include "ui/TabletScriptingInterface.h"
|
||||
|
||||
std::once_flag setupQMLTypesFlag;
|
||||
|
@ -32,6 +31,14 @@ AvatarPackager::AvatarPackager() {
|
|||
qmlRegisterType<MarketplaceItemUploader>();
|
||||
qRegisterMetaType<AvatarPackager*>();
|
||||
qRegisterMetaType<AvatarProject*>();
|
||||
qRegisterMetaType<AvatarProjectStatus::AvatarProjectStatus>();
|
||||
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<TabletScriptingInterface>();
|
||||
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet(SYSTEM_TABLET));
|
||||
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
||||
auto tablet = dynamic_cast<TabletProxy*>(DependencyManager::get<TabletScriptingInterface>()->getTablet(SYSTEM_TABLET));
|
||||
|
||||
if (tablet->getToolbarMode()) {
|
||||
static const QUrl url{ "hifi/AvatarPackagerWindow.qml" };
|
||||
DependencyManager::get<OffscreenUi>()->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<RecentAvatarProject>();
|
||||
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) {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -22,55 +22,98 @@
|
|||
#include <ui/TabletScriptingInterface.h>
|
||||
#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<hfm::Model> 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()) {
|
||||
|
|
|
@ -22,6 +22,27 @@
|
|||
#include <QVariantHash>
|
||||
#include <QStandardPaths>
|
||||
|
||||
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;
|
||||
|
|
Loading…
Reference in a new issue