Support open/export from command line

Usage example(on MacOS):
    $ ./dust3d.app/Contents/MacOS/dust3d /Users/jeremy/Desktop/test.ds3 -o /Users/jeremy/Desktop/test.glb
    $ echo $?
master
Jeremy Hu 2019-07-23 19:43:58 +09:30
parent 2c072fc083
commit 0b2653362a
4 changed files with 150 additions and 82 deletions

View File

@ -1278,84 +1278,10 @@ void DocumentWindow::saveTo(const QString &saveAsFilename)
QApplication::restoreOverrideCursor();
}
void DocumentWindow::openExample(const QString &modelName)
void DocumentWindow::openPathAs(const QString &path, const QString &asName)
{
if (!m_documentSaved) {
QMessageBox::StandardButton answer = QMessageBox::question(this,
APP_NAME,
tr("Do you really want to open example and lose the unsaved changes?"),
QMessageBox::Yes | QMessageBox::No);
if (answer != QMessageBox::Yes)
return;
}
QApplication::setOverrideCursor(Qt::WaitCursor);
Ds3FileReader ds3Reader(":/resources/" + modelName);
m_document->clearHistories();
m_document->resetScript();
m_document->reset();
m_document->saveSnapshot();
for (int i = 0; i < ds3Reader.items().size(); ++i) {
Ds3ReaderItem item = ds3Reader.items().at(i);
if (item.type == "asset") {
if (item.name.startsWith("images/")) {
QString filename = item.name.split("/")[1];
QString imageIdString = filename.split(".")[0];
QUuid imageId = QUuid(imageIdString);
if (!imageId.isNull()) {
QByteArray data;
ds3Reader.loadItem(item.name, &data);
QImage image = QImage::fromData(data, "PNG");
(void)ImageForever::add(&image, imageId);
}
}
}
}
for (int i = 0; i < ds3Reader.items().size(); ++i) {
Ds3ReaderItem item = ds3Reader.items().at(i);
if (item.type == "model") {
QByteArray data;
ds3Reader.loadItem(item.name, &data);
QXmlStreamReader stream(data);
Snapshot snapshot;
loadSkeletonFromXmlStream(&snapshot, stream);
m_document->fromSnapshot(snapshot);
m_document->saveSnapshot();
} else if (item.type == "asset") {
if (item.name == "canvas.png") {
QByteArray data;
ds3Reader.loadItem(item.name, &data);
QImage image = QImage::fromData(data, "PNG");
m_document->updateTurnaround(image);
}
}
}
QApplication::restoreOverrideCursor();
setCurrentFilename("");
}
void DocumentWindow::open()
{
if (!m_documentSaved) {
QMessageBox::StandardButton answer = QMessageBox::question(this,
APP_NAME,
tr("Do you really want to open another file and lose the unsaved changes?"),
QMessageBox::Yes | QMessageBox::No);
if (answer != QMessageBox::Yes)
return;
}
QString filename = QFileDialog::getOpenFileName(this, QString(), QString(),
tr("Dust3D Document (*.ds3)"));
if (filename.isEmpty())
return;
QApplication::setOverrideCursor(Qt::WaitCursor);
Ds3FileReader ds3Reader(filename);
Ds3FileReader ds3Reader(path);
m_document->clearHistories();
m_document->resetScript();
@ -1416,7 +1342,40 @@ void DocumentWindow::open()
}
QApplication::restoreOverrideCursor();
setCurrentFilename(filename);
setCurrentFilename(asName);
}
void DocumentWindow::openExample(const QString &modelName)
{
if (!m_documentSaved) {
QMessageBox::StandardButton answer = QMessageBox::question(this,
APP_NAME,
tr("Do you really want to open example and lose the unsaved changes?"),
QMessageBox::Yes | QMessageBox::No);
if (answer != QMessageBox::Yes)
return;
}
openPathAs(":/resources/" + modelName, "");
}
void DocumentWindow::open()
{
if (!m_documentSaved) {
QMessageBox::StandardButton answer = QMessageBox::question(this,
APP_NAME,
tr("Do you really want to open another file and lose the unsaved changes?"),
QMessageBox::Yes | QMessageBox::No);
if (answer != QMessageBox::Yes)
return;
}
QString filename = QFileDialog::getOpenFileName(this, QString(), QString(),
tr("Dust3D Document (*.ds3)"));
if (filename.isEmpty())
return;
openPathAs(filename, filename);
}
void DocumentWindow::showPreferences()
@ -1435,6 +1394,11 @@ void DocumentWindow::exportObjResult()
if (filename.isEmpty()) {
return;
}
exportObjToFilename(filename);
}
void DocumentWindow::exportObjToFilename(const QString &filename)
{
QApplication::setOverrideCursor(Qt::WaitCursor);
MeshLoader *resultMesh = m_document->takeResultMesh();
if (nullptr != resultMesh) {
@ -1468,6 +1432,11 @@ void DocumentWindow::exportFbxResult()
if (filename.isEmpty()) {
return;
}
exportFbxToFilename(filename);
}
void DocumentWindow::exportFbxToFilename(const QString &filename)
{
if (!m_document->isExportReady()) {
qDebug() << "Export but document is not export ready";
return;
@ -1499,6 +1468,11 @@ void DocumentWindow::exportGlbResult()
if (filename.isEmpty()) {
return;
}
exportGlbToFilename(filename);
}
void DocumentWindow::exportGlbToFilename(const QString &filename)
{
if (!m_document->isExportReady()) {
qDebug() << "Export but document is not export ready";
return;
@ -1701,3 +1675,33 @@ void DocumentWindow::showCutFaceSettingPopup(const QPoint &globalPos, std::set<Q
popupMenu.exec(globalPos);
}
void DocumentWindow::setExportWaitingList(const QStringList &filenames)
{
m_waitingForExportToFilenames = filenames;
}
void DocumentWindow::checkExportWaitingList()
{
if (m_waitingForExportToFilenames.empty())
return;
auto list = m_waitingForExportToFilenames;
m_waitingForExportToFilenames.clear();
bool isSucceed = m_document->isMeshGenerationSucceed();
for (const auto &filename: list) {
if (filename.endsWith(".obj")) {
exportObjToFilename(filename);
emit waitingExportFinished(filename, isSucceed);
} else if (filename.endsWith(".fbx")) {
exportFbxToFilename(filename);
emit waitingExportFinished(filename, isSucceed);
} else if (filename.endsWith(".glb")) {
exportGlbToFilename(filename);
emit waitingExportFinished(filename, isSucceed);
} else {
emit waitingExportFinished(filename, false);
}
}
}

View File

@ -8,6 +8,7 @@
#include <QAction>
#include <QTextBrowser>
#include <map>
#include <QStringList>
#include "document.h"
#include "modelwidget.h"
#include "exportpreviewwidget.h"
@ -24,6 +25,7 @@ class DocumentWindow : public QMainWindow
signals:
void initialized();
void uninialized();
void waitingExportFinished(const QString &filename, bool succeed);
public:
DocumentWindow();
~DocumentWindow();
@ -43,6 +45,7 @@ public slots:
void saveTo(const QString &saveAsFilename);
void open();
void openExample(const QString &modelName);
void openPathAs(const QString &path, const QString &asName);
void exportObjResult();
void exportGlbResult();
void exportFbxResult();
@ -68,6 +71,11 @@ public slots:
void unregisterDialog(QWidget *widget);
void showPreferences();
void showCutFaceSettingPopup(const QPoint &globalPos, std::set<QUuid> nodeIds);
void setExportWaitingList(const QStringList &filenames);
void checkExportWaitingList();
void exportObjToFilename(const QString &filename);
void exportFbxToFilename(const QString &filename);
void exportGlbToFilename(const QString &filename);
private:
void initLockButton(QPushButton *button);
void setCurrentFilename(const QString &filename);
@ -81,6 +89,7 @@ private:
std::vector<QWidget *> m_dialogs;
bool m_isLastMeshGenerationSucceed;
quint64 m_currentUpdatedMeshId;
QStringList m_waitingForExportToFilenames;
private:
QString m_currentFilename;

View File

@ -57,15 +57,33 @@ int main(int argc, char ** argv)
Theme::initAwsomeBaseSizes();
DocumentWindow::createDocumentWindow();
DocumentWindow *firstWindow = DocumentWindow::createDocumentWindow();
qDebug() << "Language:" << QLocale().name();
QStringList openFileList;
QStringList waitingExportList;
bool remoteIoEnabled = false;
for (int i = 1; i < argc; ++i) {
if ('-' == argv[i][0] && 0 == strcmp(argv[i], "-remoteio")) {
if ('-' == argv[i][0]) {
if (0 == strcmp(argv[i], "-remoteio")) {
remoteIoEnabled = true;
break;
continue;
}
if (0 == strcmp(argv[i], "-output") ||
0 == strcmp(argv[i], "-o")) {
++i;
if (i < argc)
waitingExportList.append(argv[i]);
continue;
}
qDebug() << "Unknown option:" << argv[i];
continue;
}
QString arg = argv[i];
if (arg.endsWith(".ds3")) {
openFileList.append(arg);
continue;
}
}
if (remoteIoEnabled) {
@ -73,5 +91,42 @@ int main(int argc, char ** argv)
new RemoteIoServer(53309);
}
int finishedExportFileNum = 0;
int totalExportFileNum = 0;
int succeedExportNum = 0;
if (!openFileList.empty()) {
std::vector<DocumentWindow *> windowList = {firstWindow};
for (int i = 1; i < openFileList.size(); ++i) {
windowList.push_back(DocumentWindow::createDocumentWindow());
}
if (!waitingExportList.empty() &&
openFileList.size() == 1) {
totalExportFileNum = openFileList.size() * waitingExportList.size();
for (int i = 0; i < openFileList.size(); ++i) {
QObject::connect(windowList[i], &DocumentWindow::waitingExportFinished, &app, [&](const QString &filename, bool succeed) {
qDebug() << "Export to" << filename << (succeed ? "succeed" : "failed");
++finishedExportFileNum;
if (succeed)
++succeedExportNum;
if (finishedExportFileNum == totalExportFileNum) {
if (succeedExportNum == totalExportFileNum) {
app.exit();
return;
}
app.exit(1);
return;
}
});
}
for (int i = 0; i < openFileList.size(); ++i) {
QObject::connect(windowList[i]->document(), &Document::exportReady, windowList[i], &DocumentWindow::checkExportWaitingList);
windowList[i]->setExportWaitingList(waitingExportList);
}
}
for (int i = 0; i < openFileList.size(); ++i) {
windowList[i]->openPathAs(openFileList[i], openFileList[i]);
}
}
return app.exec();
}

View File

@ -412,7 +412,7 @@ void ScriptRunner::run()
JS_FreeValue(context, globalObject);
JSValue object = JS_Eval(context, buffer.constData(), buffer.size(), "",
JSValue object = JS_Eval(context, buffer.constData(), buffer.size(), "<input>",
JS_EVAL_TYPE_GLOBAL);
if (JS_IsException(object)) {
JSValue exceptionValue = JS_GetException(context);