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
parent
2c072fc083
commit
0b2653362a
|
@ -1278,84 +1278,10 @@ void DocumentWindow::saveTo(const QString &saveAsFilename)
|
||||||
QApplication::restoreOverrideCursor();
|
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);
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
Ds3FileReader ds3Reader(":/resources/" + modelName);
|
Ds3FileReader ds3Reader(path);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
m_document->clearHistories();
|
m_document->clearHistories();
|
||||||
m_document->resetScript();
|
m_document->resetScript();
|
||||||
|
@ -1416,7 +1342,40 @@ void DocumentWindow::open()
|
||||||
}
|
}
|
||||||
QApplication::restoreOverrideCursor();
|
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()
|
void DocumentWindow::showPreferences()
|
||||||
|
@ -1435,6 +1394,11 @@ void DocumentWindow::exportObjResult()
|
||||||
if (filename.isEmpty()) {
|
if (filename.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
exportObjToFilename(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DocumentWindow::exportObjToFilename(const QString &filename)
|
||||||
|
{
|
||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
MeshLoader *resultMesh = m_document->takeResultMesh();
|
MeshLoader *resultMesh = m_document->takeResultMesh();
|
||||||
if (nullptr != resultMesh) {
|
if (nullptr != resultMesh) {
|
||||||
|
@ -1468,6 +1432,11 @@ void DocumentWindow::exportFbxResult()
|
||||||
if (filename.isEmpty()) {
|
if (filename.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
exportFbxToFilename(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DocumentWindow::exportFbxToFilename(const QString &filename)
|
||||||
|
{
|
||||||
if (!m_document->isExportReady()) {
|
if (!m_document->isExportReady()) {
|
||||||
qDebug() << "Export but document is not export ready";
|
qDebug() << "Export but document is not export ready";
|
||||||
return;
|
return;
|
||||||
|
@ -1499,6 +1468,11 @@ void DocumentWindow::exportGlbResult()
|
||||||
if (filename.isEmpty()) {
|
if (filename.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
exportGlbToFilename(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DocumentWindow::exportGlbToFilename(const QString &filename)
|
||||||
|
{
|
||||||
if (!m_document->isExportReady()) {
|
if (!m_document->isExportReady()) {
|
||||||
qDebug() << "Export but document is not export ready";
|
qDebug() << "Export but document is not export ready";
|
||||||
return;
|
return;
|
||||||
|
@ -1701,3 +1675,33 @@ void DocumentWindow::showCutFaceSettingPopup(const QPoint &globalPos, std::set<Q
|
||||||
|
|
||||||
popupMenu.exec(globalPos);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QTextBrowser>
|
#include <QTextBrowser>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <QStringList>
|
||||||
#include "document.h"
|
#include "document.h"
|
||||||
#include "modelwidget.h"
|
#include "modelwidget.h"
|
||||||
#include "exportpreviewwidget.h"
|
#include "exportpreviewwidget.h"
|
||||||
|
@ -24,6 +25,7 @@ class DocumentWindow : public QMainWindow
|
||||||
signals:
|
signals:
|
||||||
void initialized();
|
void initialized();
|
||||||
void uninialized();
|
void uninialized();
|
||||||
|
void waitingExportFinished(const QString &filename, bool succeed);
|
||||||
public:
|
public:
|
||||||
DocumentWindow();
|
DocumentWindow();
|
||||||
~DocumentWindow();
|
~DocumentWindow();
|
||||||
|
@ -43,6 +45,7 @@ public slots:
|
||||||
void saveTo(const QString &saveAsFilename);
|
void saveTo(const QString &saveAsFilename);
|
||||||
void open();
|
void open();
|
||||||
void openExample(const QString &modelName);
|
void openExample(const QString &modelName);
|
||||||
|
void openPathAs(const QString &path, const QString &asName);
|
||||||
void exportObjResult();
|
void exportObjResult();
|
||||||
void exportGlbResult();
|
void exportGlbResult();
|
||||||
void exportFbxResult();
|
void exportFbxResult();
|
||||||
|
@ -68,6 +71,11 @@ public slots:
|
||||||
void unregisterDialog(QWidget *widget);
|
void unregisterDialog(QWidget *widget);
|
||||||
void showPreferences();
|
void showPreferences();
|
||||||
void showCutFaceSettingPopup(const QPoint &globalPos, std::set<QUuid> nodeIds);
|
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:
|
private:
|
||||||
void initLockButton(QPushButton *button);
|
void initLockButton(QPushButton *button);
|
||||||
void setCurrentFilename(const QString &filename);
|
void setCurrentFilename(const QString &filename);
|
||||||
|
@ -81,6 +89,7 @@ private:
|
||||||
std::vector<QWidget *> m_dialogs;
|
std::vector<QWidget *> m_dialogs;
|
||||||
bool m_isLastMeshGenerationSucceed;
|
bool m_isLastMeshGenerationSucceed;
|
||||||
quint64 m_currentUpdatedMeshId;
|
quint64 m_currentUpdatedMeshId;
|
||||||
|
QStringList m_waitingForExportToFilenames;
|
||||||
private:
|
private:
|
||||||
QString m_currentFilename;
|
QString m_currentFilename;
|
||||||
|
|
||||||
|
|
61
src/main.cpp
61
src/main.cpp
|
@ -57,15 +57,33 @@ int main(int argc, char ** argv)
|
||||||
|
|
||||||
Theme::initAwsomeBaseSizes();
|
Theme::initAwsomeBaseSizes();
|
||||||
|
|
||||||
DocumentWindow::createDocumentWindow();
|
DocumentWindow *firstWindow = DocumentWindow::createDocumentWindow();
|
||||||
|
|
||||||
qDebug() << "Language:" << QLocale().name();
|
qDebug() << "Language:" << QLocale().name();
|
||||||
|
|
||||||
|
QStringList openFileList;
|
||||||
|
QStringList waitingExportList;
|
||||||
bool remoteIoEnabled = false;
|
bool remoteIoEnabled = false;
|
||||||
for (int i = 1; i < argc; ++i) {
|
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;
|
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) {
|
if (remoteIoEnabled) {
|
||||||
|
@ -73,5 +91,42 @@ int main(int argc, char ** argv)
|
||||||
new RemoteIoServer(53309);
|
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();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
|
@ -412,7 +412,7 @@ void ScriptRunner::run()
|
||||||
|
|
||||||
JS_FreeValue(context, globalObject);
|
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);
|
JS_EVAL_TYPE_GLOBAL);
|
||||||
if (JS_IsException(object)) {
|
if (JS_IsException(object)) {
|
||||||
JSValue exceptionValue = JS_GetException(context);
|
JSValue exceptionValue = JS_GetException(context);
|
||||||
|
|
Loading…
Reference in New Issue