Add project file(.ds3) reader and writer
parent
130ffdae79
commit
ff19efa188
|
@ -10,9 +10,6 @@ HEADERS += src/mainwindow.h
|
||||||
SOURCES += src/modelingwidget.cpp
|
SOURCES += src/modelingwidget.cpp
|
||||||
HEADERS += src/modelingwidget.h
|
HEADERS += src/modelingwidget.h
|
||||||
|
|
||||||
SOURCES += src/skeletoneditwidget.cpp
|
|
||||||
HEADERS += src/skeletoneditwidget.h
|
|
||||||
|
|
||||||
SOURCES += src/skeletoneditgraphicsview.cpp
|
SOURCES += src/skeletoneditgraphicsview.cpp
|
||||||
HEADERS += src/skeletoneditgraphicsview.h
|
HEADERS += src/skeletoneditgraphicsview.h
|
||||||
|
|
||||||
|
@ -31,8 +28,8 @@ HEADERS += src/turnaroundloader.h
|
||||||
SOURCES += src/skeletonwidget.cpp
|
SOURCES += src/skeletonwidget.cpp
|
||||||
HEADERS += src/skeletonwidget.h
|
HEADERS += src/skeletonwidget.h
|
||||||
|
|
||||||
SOURCES += src/combineeditwidget.cpp
|
SOURCES += src/ds3file.cpp
|
||||||
HEADERS += src/combineeditwidget.h
|
HEADERS += src/ds3file.h
|
||||||
|
|
||||||
SOURCES += src/theme.cpp
|
SOURCES += src/theme.cpp
|
||||||
HEADERS += src/theme.h
|
HEADERS += src/theme.h
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
#include <QGridLayout>
|
|
||||||
#include "combineeditwidget.h"
|
|
||||||
|
|
||||||
CombineEditWidget::CombineEditWidget(QWidget *parent) :
|
|
||||||
QFrame(parent)
|
|
||||||
{
|
|
||||||
m_modelingWidget = new ModelingWidget(this);
|
|
||||||
|
|
||||||
QGridLayout *mainLayout = new QGridLayout;
|
|
||||||
mainLayout->addWidget(m_modelingWidget, 0, 0, 1, 1);
|
|
||||||
|
|
||||||
setLayout(mainLayout);
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelingWidget *CombineEditWidget::modelingWidget()
|
|
||||||
{
|
|
||||||
return m_modelingWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CombineEditWidget::resizeEvent(QResizeEvent *event)
|
|
||||||
{
|
|
||||||
QFrame::resizeEvent(event);
|
|
||||||
emit sizeChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
#ifndef COMBINE_EDIT_WIDGET_H
|
|
||||||
#define COMBINE_EDIT_WIDGET_H
|
|
||||||
#include <QFrame>
|
|
||||||
#include "modelingwidget.h"
|
|
||||||
|
|
||||||
class CombineEditWidget : public QFrame
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
signals:
|
|
||||||
void sizeChanged();
|
|
||||||
public:
|
|
||||||
CombineEditWidget(QWidget *parent = 0);
|
|
||||||
ModelingWidget *modelingWidget();
|
|
||||||
protected:
|
|
||||||
void resizeEvent(QResizeEvent *event);
|
|
||||||
private:
|
|
||||||
ModelingWidget *m_modelingWidget;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QXmlStreamReader>
|
||||||
|
#include "ds3file.h"
|
||||||
|
|
||||||
|
QString Ds3FileReader::m_applicationName = QString("DUST3D");
|
||||||
|
QString Ds3FileReader::m_fileFormatVersion = QString("1.0");
|
||||||
|
QString Ds3FileReader::m_headFormat = QString("xml");
|
||||||
|
|
||||||
|
QString Ds3FileReader::readFirstLine()
|
||||||
|
{
|
||||||
|
QString firstLine;
|
||||||
|
QFile file(m_filename);
|
||||||
|
if (file.open(QIODevice::ReadOnly)) {
|
||||||
|
QTextStream in(&file);
|
||||||
|
if (!in.atEnd()) {
|
||||||
|
firstLine = in.readLine();
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
return firstLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ds3FileReader::Ds3FileReader(const QString &filename) :
|
||||||
|
m_headerIsGood(false),
|
||||||
|
m_binaryOffset(0)
|
||||||
|
{
|
||||||
|
m_filename = filename;
|
||||||
|
QString firstLine = readFirstLine();
|
||||||
|
QStringList tokens = firstLine.split(" ");
|
||||||
|
if (tokens.length() < 4) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tokens[0] != Ds3FileReader::m_applicationName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tokens[1] != Ds3FileReader::m_fileFormatVersion) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tokens[2] != Ds3FileReader::m_headFormat) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_binaryOffset = tokens[3].toLongLong();
|
||||||
|
QFile file(m_filename);
|
||||||
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QString header = QString::fromUtf8(file.read(m_binaryOffset).constData()).mid(firstLine.size()).trimmed();
|
||||||
|
QXmlStreamReader xml(header);
|
||||||
|
bool ds3TagEntered = false;
|
||||||
|
while (!xml.atEnd()) {
|
||||||
|
xml.readNext();
|
||||||
|
if (xml.isStartElement()) {
|
||||||
|
if (xml.name() == "ds3") {
|
||||||
|
ds3TagEntered = true;
|
||||||
|
m_headerIsGood = true;
|
||||||
|
} else {
|
||||||
|
if (ds3TagEntered) {
|
||||||
|
Ds3ReaderItem readerItem;
|
||||||
|
readerItem.type = xml.name().toString().trimmed();
|
||||||
|
readerItem.name = xml.attributes().value("name").toString().trimmed();
|
||||||
|
readerItem.offset = xml.attributes().value("offset").toLongLong();
|
||||||
|
readerItem.size = xml.attributes().value("size").toLongLong();
|
||||||
|
m_items.push_back(readerItem);
|
||||||
|
m_itemsMap[readerItem.name] = readerItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (xml.isEndElement()) {
|
||||||
|
if (xml.name() == "ds3") {
|
||||||
|
ds3TagEntered = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ds3FileReader::loadItem(const QString &name, QByteArray *byteArray)
|
||||||
|
{
|
||||||
|
byteArray->clear();
|
||||||
|
if (!m_headerIsGood)
|
||||||
|
return;
|
||||||
|
if (m_itemsMap.find(name) == m_itemsMap.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Ds3ReaderItem readerItem = m_itemsMap[name];
|
||||||
|
QFile file(m_filename);
|
||||||
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!file.seek(m_binaryOffset + readerItem.offset)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*byteArray = file.read(readerItem.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QList<Ds3ReaderItem> &Ds3FileReader::items()
|
||||||
|
{
|
||||||
|
return m_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Ds3FileWriter::add(const QString &name, const QString &type, const QByteArray *byteArray)
|
||||||
|
{
|
||||||
|
if (m_itemsMap.find(name) != m_itemsMap.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Ds3WriterItem writerItem;
|
||||||
|
writerItem.type = type;
|
||||||
|
writerItem.name = name;
|
||||||
|
writerItem.byteArray = byteArray;
|
||||||
|
m_itemsMap[name] = writerItem;
|
||||||
|
m_items.push_back(writerItem);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Ds3FileWriter::save(const QString &filename)
|
||||||
|
{
|
||||||
|
QFile file(filename);
|
||||||
|
if (!file.open(QIODevice::WriteOnly)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray headerXml;
|
||||||
|
{
|
||||||
|
QXmlStreamWriter stream(&headerXml);
|
||||||
|
stream.setAutoFormatting(true);
|
||||||
|
stream.writeStartDocument();
|
||||||
|
stream.writeStartElement("ds3");
|
||||||
|
|
||||||
|
long long offset = 0;
|
||||||
|
for (int i = 0; i < m_items.size(); i++) {
|
||||||
|
Ds3WriterItem *writerItem = &m_items[i];
|
||||||
|
stream.writeStartElement(writerItem->type);
|
||||||
|
stream.writeAttribute("name", QString("%1").arg(writerItem->name));
|
||||||
|
stream.writeAttribute("offset", QString("%1").arg(offset));
|
||||||
|
stream.writeAttribute("size", QString("%1").arg(writerItem->byteArray->size()));
|
||||||
|
offset += writerItem->byteArray->size();
|
||||||
|
stream.writeEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.writeEndElement();
|
||||||
|
stream.writeEndDocument();
|
||||||
|
}
|
||||||
|
char firstLine[1024];
|
||||||
|
int firstLineSizeExcludeSizeSelf = sprintf(firstLine, "%s %s %s ",
|
||||||
|
Ds3FileReader::m_applicationName.toUtf8().constData(),
|
||||||
|
Ds3FileReader::m_fileFormatVersion.toUtf8().constData(),
|
||||||
|
Ds3FileReader::m_headFormat.toUtf8().constData());
|
||||||
|
unsigned int headerSize = firstLineSizeExcludeSizeSelf + 12 + headerXml.size();
|
||||||
|
char headerSizeString[100] = {0};
|
||||||
|
sprintf(headerSizeString, "%010u\r\n", headerSize);
|
||||||
|
file.write(firstLine, firstLineSizeExcludeSizeSelf);
|
||||||
|
file.write(headerSizeString, strlen(headerSizeString));
|
||||||
|
file.write(headerXml);
|
||||||
|
for (int i = 0; i < m_items.size(); i++) {
|
||||||
|
Ds3WriterItem *writerItem = &m_items[i];
|
||||||
|
file.write(*writerItem->byteArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
#ifndef DS3_FILE_H
|
||||||
|
#define DS3_FILE_H
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
/*
|
||||||
|
DUST3D 1.0 xml 12345
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ds3>
|
||||||
|
<model name="ant.xml" offset="0" size="1024"/>
|
||||||
|
<asset name="ant.jpg" offset="1024" size="279306"/>
|
||||||
|
</ds3>
|
||||||
|
... Binary content ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Ds3ReaderItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QString type;
|
||||||
|
QString name;
|
||||||
|
long long offset;
|
||||||
|
long long size;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Ds3FileReader : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Ds3FileReader(const QString &filename);
|
||||||
|
void loadItem(const QString &name, QByteArray *byteArray);
|
||||||
|
const QList<Ds3ReaderItem> &items();
|
||||||
|
static QString m_applicationName;
|
||||||
|
static QString m_fileFormatVersion;
|
||||||
|
static QString m_headFormat;
|
||||||
|
private:
|
||||||
|
std::map<QString, Ds3ReaderItem> m_itemsMap;
|
||||||
|
QList<Ds3ReaderItem> m_items;
|
||||||
|
QString m_filename;
|
||||||
|
private:
|
||||||
|
QString readFirstLine();
|
||||||
|
bool m_headerIsGood;
|
||||||
|
long long m_binaryOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Ds3WriterItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QString type;
|
||||||
|
QString name;
|
||||||
|
const QByteArray *byteArray;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Ds3FileWriter : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
bool add(const QString &name, const QString &type, const QByteArray *byteArray);
|
||||||
|
bool save(const QString &filename);
|
||||||
|
private:
|
||||||
|
std::map<QString, Ds3WriterItem> m_itemsMap;
|
||||||
|
QList<Ds3WriterItem> m_items;
|
||||||
|
QString m_filename;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -8,17 +8,18 @@
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include <QStackedWidget>
|
#include <QStackedWidget>
|
||||||
|
#include <QXmlStreamReader>
|
||||||
|
#include <QBuffer>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "skeletonwidget.h"
|
#include "skeletonwidget.h"
|
||||||
#include "combineeditwidget.h"
|
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
|
#include "ds3file.h"
|
||||||
|
|
||||||
MainWindow::MainWindow()
|
MainWindow::MainWindow()
|
||||||
{
|
{
|
||||||
m_partsPageButton = new QPushButton("Parts");
|
m_modelPageButton = new QPushButton("Model");
|
||||||
m_combinePageButton = new QPushButton("Combine");
|
m_sharePageButton = new QPushButton("Share");
|
||||||
m_motionPageButton = new QPushButton("Motion");
|
|
||||||
|
|
||||||
QWidget *hrWidget = new QWidget;
|
QWidget *hrWidget = new QWidget;
|
||||||
hrWidget->setFixedHeight(2);
|
hrWidget->setFixedHeight(2);
|
||||||
|
@ -27,25 +28,22 @@ MainWindow::MainWindow()
|
||||||
hrWidget->setContentsMargins(0, 0, 0, 0);
|
hrWidget->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
QButtonGroup *pageButtonGroup = new QButtonGroup;
|
QButtonGroup *pageButtonGroup = new QButtonGroup;
|
||||||
pageButtonGroup->addButton(m_partsPageButton);
|
pageButtonGroup->addButton(m_modelPageButton);
|
||||||
pageButtonGroup->addButton(m_combinePageButton);
|
pageButtonGroup->addButton(m_sharePageButton);
|
||||||
pageButtonGroup->addButton(m_motionPageButton);
|
|
||||||
|
|
||||||
m_partsPageButton->setCheckable(true);
|
m_modelPageButton->setCheckable(true);
|
||||||
m_combinePageButton->setCheckable(true);
|
m_sharePageButton->setCheckable(true);
|
||||||
m_motionPageButton->setCheckable(true);
|
|
||||||
|
|
||||||
pageButtonGroup->setExclusive(true);
|
pageButtonGroup->setExclusive(true);
|
||||||
|
|
||||||
m_combinePageButton->setChecked(true);
|
m_modelPageButton->setChecked(true);
|
||||||
|
|
||||||
QHBoxLayout *topButtonsLayout = new QHBoxLayout;
|
QHBoxLayout *topButtonsLayout = new QHBoxLayout;
|
||||||
topButtonsLayout->setContentsMargins(0, 0, 0, 0);
|
topButtonsLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
topButtonsLayout->setSpacing(0);
|
topButtonsLayout->setSpacing(0);
|
||||||
topButtonsLayout->addStretch();
|
topButtonsLayout->addStretch();
|
||||||
topButtonsLayout->addWidget(m_partsPageButton);
|
topButtonsLayout->addWidget(m_modelPageButton);
|
||||||
topButtonsLayout->addWidget(m_combinePageButton);
|
topButtonsLayout->addWidget(m_sharePageButton);
|
||||||
topButtonsLayout->addWidget(m_motionPageButton);
|
|
||||||
topButtonsLayout->addStretch();
|
topButtonsLayout->addStretch();
|
||||||
|
|
||||||
QVBoxLayout *topLayout = new QVBoxLayout;
|
QVBoxLayout *topLayout = new QVBoxLayout;
|
||||||
|
@ -54,86 +52,46 @@ MainWindow::MainWindow()
|
||||||
topLayout->addLayout(topButtonsLayout);
|
topLayout->addLayout(topButtonsLayout);
|
||||||
topLayout->addWidget(hrWidget);
|
topLayout->addWidget(hrWidget);
|
||||||
|
|
||||||
QVBoxLayout *partsRightLayout = new QVBoxLayout;
|
QVBoxLayout *modelRightLayout = new QVBoxLayout;
|
||||||
|
|
||||||
partsRightLayout->addSpacing(20);
|
modelRightLayout->addSpacing(20);
|
||||||
|
|
||||||
QPushButton *changeTurnaroundButton = new QPushButton(" Change Turnaround ");
|
QPushButton *changeTurnaroundButton = new QPushButton(" Change Turnaround ");
|
||||||
partsRightLayout->addWidget(changeTurnaroundButton);
|
modelRightLayout->addWidget(changeTurnaroundButton);
|
||||||
|
|
||||||
QPushButton *exportPartsModelButton = new QPushButton(" Export Model(.obj) ");
|
QPushButton *exportPartsModelButton = new QPushButton(" Export ");
|
||||||
partsRightLayout->addWidget(exportPartsModelButton);
|
modelRightLayout->addWidget(exportPartsModelButton);
|
||||||
|
|
||||||
QPushButton *newPartsButton = new QPushButton(" New Parts ");
|
QPushButton *newModelButton = new QPushButton(" New ");
|
||||||
partsRightLayout->addWidget(newPartsButton);
|
modelRightLayout->addWidget(newModelButton);
|
||||||
|
|
||||||
QPushButton *loadPartsButton = new QPushButton(" Load Parts ");
|
QPushButton *loadModelButton = new QPushButton(" Load ");
|
||||||
partsRightLayout->addWidget(loadPartsButton);
|
modelRightLayout->addWidget(loadModelButton);
|
||||||
|
|
||||||
QPushButton *savePartsButton = new QPushButton(" Save Parts ");
|
QPushButton *saveModelButton = new QPushButton(" Save ");
|
||||||
partsRightLayout->addWidget(savePartsButton);
|
modelRightLayout->addWidget(saveModelButton);
|
||||||
|
|
||||||
QPushButton *savePartsAsButton = new QPushButton(" Save Parts as ");
|
QPushButton *saveModelAsButton = new QPushButton(" Save as ");
|
||||||
partsRightLayout->addWidget(savePartsAsButton);
|
modelRightLayout->addWidget(saveModelAsButton);
|
||||||
savePartsAsButton->hide();
|
saveModelAsButton->hide();
|
||||||
|
|
||||||
partsRightLayout->addStretch();
|
modelRightLayout->addStretch();
|
||||||
|
|
||||||
SkeletonWidget *skeletonWidget = new SkeletonWidget(this);
|
SkeletonWidget *skeletonWidget = new SkeletonWidget(this);
|
||||||
m_skeletonWidget = skeletonWidget;
|
m_skeletonWidget = skeletonWidget;
|
||||||
|
|
||||||
QHBoxLayout *partsPageLayout = new QHBoxLayout;
|
QHBoxLayout *modelPageLayout = new QHBoxLayout;
|
||||||
partsPageLayout->addWidget(skeletonWidget);
|
modelPageLayout->addWidget(skeletonWidget);
|
||||||
partsPageLayout->addLayout(partsRightLayout);
|
modelPageLayout->addLayout(modelRightLayout);
|
||||||
|
|
||||||
QWidget *partsPageWidget = new QWidget;
|
QWidget *modelPageWidget = new QWidget;
|
||||||
partsPageWidget->setLayout(partsPageLayout);
|
modelPageWidget->setLayout(modelPageLayout);
|
||||||
|
|
||||||
QVBoxLayout *combineRightLayout = new QVBoxLayout;
|
QWidget *sharePageWidget = new QWidget;
|
||||||
|
|
||||||
combineRightLayout->addSpacing(20);
|
|
||||||
|
|
||||||
QPushButton *importPartsToCombineButton = new QPushButton(" Import Parts ");
|
|
||||||
combineRightLayout->addWidget(importPartsToCombineButton);
|
|
||||||
|
|
||||||
QPushButton *exportCombineModelButton = new QPushButton(" Export Model(.obj) ");
|
|
||||||
combineRightLayout->addWidget(exportCombineModelButton);
|
|
||||||
|
|
||||||
QPushButton *newCombineButton = new QPushButton(" New Combine ");
|
|
||||||
combineRightLayout->addWidget(newCombineButton);
|
|
||||||
|
|
||||||
QPushButton *loadCombineButton = new QPushButton(" Load Combine ");
|
|
||||||
combineRightLayout->addWidget(loadCombineButton);
|
|
||||||
|
|
||||||
QPushButton *saveCombineButton = new QPushButton(" Save Combine ");
|
|
||||||
combineRightLayout->addWidget(saveCombineButton);
|
|
||||||
|
|
||||||
QPushButton *saveCombineAsButton = new QPushButton(" Save Combine as ");
|
|
||||||
combineRightLayout->addWidget(saveCombineAsButton);
|
|
||||||
saveCombineAsButton->hide();
|
|
||||||
|
|
||||||
combineRightLayout->addStretch();
|
|
||||||
|
|
||||||
combineRightLayout->setSizeConstraint(QLayout::SetMinimumSize);
|
|
||||||
|
|
||||||
CombineEditWidget *combineEditWidget = new CombineEditWidget();
|
|
||||||
|
|
||||||
QHBoxLayout *combinePageLayout = new QHBoxLayout;
|
|
||||||
combinePageLayout->addSpacing(10);
|
|
||||||
combinePageLayout->addWidget(combineEditWidget);
|
|
||||||
combinePageLayout->addStretch();
|
|
||||||
combinePageLayout->addLayout(combineRightLayout);
|
|
||||||
combinePageLayout->addSpacing(10);
|
|
||||||
|
|
||||||
QWidget *combinePageWidget = new QWidget;
|
|
||||||
combinePageWidget->setLayout(combinePageLayout);
|
|
||||||
|
|
||||||
QWidget *motionPageWidget = new QWidget;
|
|
||||||
|
|
||||||
QStackedWidget *stackedWidget = new QStackedWidget;
|
QStackedWidget *stackedWidget = new QStackedWidget;
|
||||||
stackedWidget->addWidget(partsPageWidget);
|
stackedWidget->addWidget(modelPageWidget);
|
||||||
stackedWidget->addWidget(combinePageWidget);
|
stackedWidget->addWidget(sharePageWidget);
|
||||||
stackedWidget->addWidget(motionPageWidget);
|
|
||||||
|
|
||||||
m_stackedWidget = stackedWidget;
|
m_stackedWidget = stackedWidget;
|
||||||
|
|
||||||
|
@ -152,60 +110,85 @@ MainWindow::MainWindow()
|
||||||
connectResult = connect(changeTurnaroundButton, SIGNAL(clicked()), skeletonWidget, SLOT(changeTurnaround()));
|
connectResult = connect(changeTurnaroundButton, SIGNAL(clicked()), skeletonWidget, SLOT(changeTurnaround()));
|
||||||
assert(connectResult);
|
assert(connectResult);
|
||||||
|
|
||||||
connectResult = connect(m_partsPageButton, SIGNAL(clicked()), this, SLOT(updatePageButtons()));
|
connectResult = connect(m_modelPageButton, SIGNAL(clicked()), this, SLOT(updatePageButtons()));
|
||||||
assert(connectResult);
|
assert(connectResult);
|
||||||
|
|
||||||
connectResult = connect(m_combinePageButton, SIGNAL(clicked()), this, SLOT(updatePageButtons()));
|
connectResult = connect(m_sharePageButton, SIGNAL(clicked()), this, SLOT(updatePageButtons()));
|
||||||
assert(connectResult);
|
assert(connectResult);
|
||||||
|
|
||||||
connectResult = connect(m_motionPageButton, SIGNAL(clicked()), this, SLOT(updatePageButtons()));
|
connectResult = connect(saveModelButton, SIGNAL(clicked()), this, SLOT(saveModel()));
|
||||||
assert(connectResult);
|
assert(connectResult);
|
||||||
|
|
||||||
connectResult = connect(savePartsButton, SIGNAL(clicked()), this, SLOT(saveParts()));
|
connectResult = connect(loadModelButton, SIGNAL(clicked()), this, SLOT(loadModel()));
|
||||||
assert(connectResult);
|
|
||||||
|
|
||||||
connectResult = connect(loadPartsButton, SIGNAL(clicked()), this, SLOT(loadParts()));
|
|
||||||
assert(connectResult);
|
assert(connectResult);
|
||||||
|
|
||||||
updatePageButtons();
|
updatePageButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::loadParts()
|
void MainWindow::loadModel()
|
||||||
{
|
{
|
||||||
QString filename = QFileDialog::getOpenFileName(this,
|
QString filename = QFileDialog::getOpenFileName(this,
|
||||||
tr("Load Parts"), ".",
|
tr("Load Model"), ".",
|
||||||
tr("Xml files (*.xml)"));
|
tr("Dust 3D Project (*.ds3)"));
|
||||||
if (filename.isEmpty())
|
if (filename.isEmpty())
|
||||||
return;
|
return;
|
||||||
m_skeletonWidget->graphicsView()->loadFromXml(filename);
|
Ds3FileReader ds3Reader(filename);
|
||||||
|
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 xmlReader(data);
|
||||||
|
m_skeletonWidget->graphicsView()->loadFromXmlStream(xmlReader);
|
||||||
|
} else if (item.type == "asset") {
|
||||||
|
if (item.name == "canvas.png") {
|
||||||
|
QByteArray data;
|
||||||
|
ds3Reader.loadItem(item.name, &data);
|
||||||
|
QImage image = QImage::fromData(data, "PNG");
|
||||||
|
m_skeletonWidget->graphicsView()->updateBackgroundImage(image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::saveParts()
|
void MainWindow::saveModel()
|
||||||
{
|
{
|
||||||
if (m_savePartsAs.isEmpty()) {
|
if (m_saveModelAs.isEmpty()) {
|
||||||
m_savePartsAs = QFileDialog::getSaveFileName(this,
|
m_saveModelAs = QFileDialog::getSaveFileName(this,
|
||||||
tr("Save Parts"), ".",
|
tr("Save Model"), ".",
|
||||||
tr("Xml files (*.xml)"));
|
tr("Dust 3D Project (*.ds3)"));
|
||||||
if (m_savePartsAs.isEmpty()) {
|
if (m_saveModelAs.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_skeletonWidget->graphicsView()->saveToXml(m_savePartsAs);
|
|
||||||
|
Ds3FileWriter ds3Writer;
|
||||||
|
|
||||||
|
QByteArray modelXml;
|
||||||
|
QXmlStreamWriter stream(&modelXml);
|
||||||
|
m_skeletonWidget->graphicsView()->saveToXmlStream(&stream);
|
||||||
|
if (modelXml.size() > 0)
|
||||||
|
ds3Writer.add("model1.xml", "model", &modelXml);
|
||||||
|
|
||||||
|
QByteArray imageByteArray;
|
||||||
|
QBuffer pngBuffer(&imageByteArray);
|
||||||
|
pngBuffer.open(QIODevice::WriteOnly);
|
||||||
|
m_skeletonWidget->graphicsView()->backgroundImage().save(&pngBuffer, "PNG");
|
||||||
|
if (imageByteArray.size() > 0)
|
||||||
|
ds3Writer.add("canvas.png", "asset", &imageByteArray);
|
||||||
|
|
||||||
|
ds3Writer.save(m_saveModelAs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::updatePageButtons()
|
void MainWindow::updatePageButtons()
|
||||||
{
|
{
|
||||||
if (m_partsPageButton->isChecked()) {
|
if (m_modelPageButton->isChecked()) {
|
||||||
m_stackedWidget->setCurrentIndex(0);
|
m_stackedWidget->setCurrentIndex(0);
|
||||||
}
|
}
|
||||||
if (m_combinePageButton->isChecked()) {
|
if (m_sharePageButton->isChecked()) {
|
||||||
m_stackedWidget->setCurrentIndex(1);
|
m_stackedWidget->setCurrentIndex(1);
|
||||||
}
|
}
|
||||||
if (m_motionPageButton->isChecked()) {
|
m_modelPageButton->setStyleSheet(m_modelPageButton->isChecked() ? Theme::tabButtonSelectedStylesheet : Theme::tabButtonStylesheet);
|
||||||
m_stackedWidget->setCurrentIndex(2);
|
m_sharePageButton->setStyleSheet(m_sharePageButton->isChecked() ? Theme::tabButtonSelectedStylesheet : Theme::tabButtonStylesheet);
|
||||||
}
|
|
||||||
m_partsPageButton->setStyleSheet(m_partsPageButton->isChecked() ? Theme::tabButtonSelectedStylesheet : Theme::tabButtonStylesheet);
|
|
||||||
m_combinePageButton->setStyleSheet(m_combinePageButton->isChecked() ? Theme::tabButtonSelectedStylesheet : Theme::tabButtonStylesheet);
|
|
||||||
m_motionPageButton->setStyleSheet(m_motionPageButton->isChecked() ? Theme::tabButtonSelectedStylesheet : Theme::tabButtonStylesheet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,14 +14,13 @@ public:
|
||||||
MainWindow();
|
MainWindow();
|
||||||
public slots:
|
public slots:
|
||||||
void updatePageButtons();
|
void updatePageButtons();
|
||||||
void saveParts();
|
void saveModel();
|
||||||
void loadParts();
|
void loadModel();
|
||||||
private:
|
private:
|
||||||
QPushButton *m_partsPageButton;
|
QPushButton *m_modelPageButton;
|
||||||
QPushButton *m_combinePageButton;
|
QPushButton *m_sharePageButton;
|
||||||
QPushButton *m_motionPageButton;
|
|
||||||
QStackedWidget *m_stackedWidget;
|
QStackedWidget *m_stackedWidget;
|
||||||
QString m_savePartsAs;
|
QString m_saveModelAs;
|
||||||
SkeletonWidget *m_skeletonWidget;
|
SkeletonWidget *m_skeletonWidget;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ static const char *fragmentShaderSourceCore =
|
||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" highp vec3 L = normalize(lightPos - vert);\n"
|
" highp vec3 L = normalize(lightPos - vert);\n"
|
||||||
" highp float NL = max(dot(normalize(vertNormal), L), 0.0);\n"
|
" highp float NL = max(dot(normalize(vertNormal), L), 0.0);\n"
|
||||||
" highp vec3 color = vec3(0.99, 0.4, 0.13);\n"
|
" highp vec3 color = vec3(1.0, 1.0, 1.0);\n"
|
||||||
" highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);\n"
|
" highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);\n"
|
||||||
" fragColor = vec4(col, 1.0);\n"
|
" fragColor = vec4(col, 1.0);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
@ -134,7 +134,7 @@ static const char *fragmentShaderSource =
|
||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" highp vec3 L = normalize(lightPos - vert);\n"
|
" highp vec3 L = normalize(lightPos - vert);\n"
|
||||||
" highp float NL = max(dot(normalize(vertNormal), L), 0.0);\n"
|
" highp float NL = max(dot(normalize(vertNormal), L), 0.0);\n"
|
||||||
" highp vec3 color = vec3(0.99, 0.4, 0.13);\n"
|
" highp vec3 color = vec3(1.0, 1.0, 1.0);\n"
|
||||||
" highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);\n"
|
" highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);\n"
|
||||||
" gl_FragColor = vec4(col, 1.0);\n"
|
" gl_FragColor = vec4(col, 1.0);\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include <QGraphicsPixmapItem>
|
#include <QGraphicsPixmapItem>
|
||||||
#include <QXmlStreamWriter>
|
#include <QXmlStreamWriter>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QApplication>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -48,7 +49,7 @@ void SkeletonEditGraphicsView::toggleAddNodeMode()
|
||||||
void SkeletonEditGraphicsView::applyAddNodeMode()
|
void SkeletonEditGraphicsView::applyAddNodeMode()
|
||||||
{
|
{
|
||||||
m_pendingNodeItem->setVisible(m_inAddNodeMode);
|
m_pendingNodeItem->setVisible(m_inAddNodeMode);
|
||||||
m_pendingEdgeItem->setVisible(m_inAddNodeMode);
|
m_pendingEdgeItem->setVisible(m_inAddNodeMode && m_nextStartNodeItem);
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +94,10 @@ void SkeletonEditGraphicsView::mousePressEvent(QMouseEvent *event)
|
||||||
if (m_lastHoverNodeItem) {
|
if (m_lastHoverNodeItem) {
|
||||||
setNextStartNodeItem(m_lastHoverNodeItem->master());
|
setNextStartNodeItem(m_lastHoverNodeItem->master());
|
||||||
m_lastHoverNodeItem = NULL;
|
m_lastHoverNodeItem = NULL;
|
||||||
|
} else {
|
||||||
|
if (m_nextStartNodeItem) {
|
||||||
|
setNextStartNodeItem(NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,6 +107,7 @@ void SkeletonEditGraphicsView::mousePressEvent(QMouseEvent *event)
|
||||||
void SkeletonEditGraphicsView::mouseDoubleClickEvent(QMouseEvent *event)
|
void SkeletonEditGraphicsView::mouseDoubleClickEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
QWidget::mouseDoubleClickEvent(event);
|
QWidget::mouseDoubleClickEvent(event);
|
||||||
|
if (QApplication::keyboardModifiers() & Qt::ControlModifier)
|
||||||
emit changeTurnaroundTriggered();
|
emit changeTurnaroundTriggered();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,6 +116,21 @@ float SkeletonEditGraphicsView::findXForSlave(float x)
|
||||||
return x - m_backgroundItem->boundingRect().width() / 4;
|
return x - m_backgroundItem->boundingRect().width() / 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkeletonEditGraphicsView::keyPressEvent(QKeyEvent *event)
|
||||||
|
{
|
||||||
|
QWidget::keyPressEvent(event);
|
||||||
|
if (!m_backgroundLoaded)
|
||||||
|
return;
|
||||||
|
if (event->key() == Qt::Key_A)
|
||||||
|
toggleAddNodeMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkeletonEditGraphicsView::resizeEvent(QResizeEvent *event)
|
||||||
|
{
|
||||||
|
QFrame::resizeEvent(event);
|
||||||
|
emit sizeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void SkeletonEditGraphicsView::mouseReleaseEvent(QMouseEvent *event)
|
void SkeletonEditGraphicsView::mouseReleaseEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
QWidget::mouseReleaseEvent(event);
|
QWidget::mouseReleaseEvent(event);
|
||||||
|
@ -135,8 +156,6 @@ void SkeletonEditGraphicsView::mouseReleaseEvent(QMouseEvent *event)
|
||||||
emit nodesChanged();
|
emit nodesChanged();
|
||||||
}
|
}
|
||||||
m_isMovingNodeItem = false;
|
m_isMovingNodeItem = false;
|
||||||
} else if (event->button() == Qt::RightButton) {
|
|
||||||
toggleAddNodeMode();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,6 +332,16 @@ void SkeletonEditGraphicsView::updateBackgroundImage(const QImage &image)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPixmap SkeletonEditGraphicsView::backgroundImage()
|
||||||
|
{
|
||||||
|
return m_backgroundItem->pixmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkeletonEditGraphicsView::hasBackgroundImage()
|
||||||
|
{
|
||||||
|
return m_backgroundLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
void SkeletonEditGraphicsView::adjustItems(QSizeF oldSceneSize, QSizeF newSceneSize)
|
void SkeletonEditGraphicsView::adjustItems(QSizeF oldSceneSize, QSizeF newSceneSize)
|
||||||
{
|
{
|
||||||
if (oldSceneSize == newSceneSize)
|
if (oldSceneSize == newSceneSize)
|
||||||
|
@ -338,13 +367,8 @@ void SkeletonEditGraphicsView::adjustItems(QSizeF oldSceneSize, QSizeF newSceneS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonEditGraphicsView::loadFromXml(const QString &filename)
|
void SkeletonEditGraphicsView::loadFromXmlStream(QXmlStreamReader &reader)
|
||||||
{
|
{
|
||||||
QFile file(filename);
|
|
||||||
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float radiusMul = 1.0;
|
float radiusMul = 1.0;
|
||||||
float xMul = 1.0;
|
float xMul = 1.0;
|
||||||
float yMul = radiusMul;
|
float yMul = radiusMul;
|
||||||
|
@ -353,33 +377,34 @@ void SkeletonEditGraphicsView::loadFromXml(const QString &filename)
|
||||||
std::vector<std::map<QString, QString>> pendingEdges;
|
std::vector<std::map<QString, QString>> pendingEdges;
|
||||||
std::map<QString, SkeletonEditNodeItem *> addedNodeMapById;
|
std::map<QString, SkeletonEditNodeItem *> addedNodeMapById;
|
||||||
|
|
||||||
QXmlStreamReader xml;
|
while (!reader.atEnd()) {
|
||||||
xml.setDevice(&file);
|
reader.readNext();
|
||||||
while (!xml.atEnd()) {
|
if (reader.isStartElement()) {
|
||||||
xml.readNext();
|
if (reader.name() == "canvas") {
|
||||||
printf("tokenString:%s\n", xml.tokenString().toUtf8().constData());
|
QString canvasWidth = reader.attributes().value("width").toString();
|
||||||
if (xml.isStartElement()) {
|
QString canvasHeight = reader.attributes().value("height").toString();
|
||||||
printf("name:%s\n", xml.name().toUtf8().constData());
|
|
||||||
if (xml.name() == "canvas") {
|
|
||||||
QString canvasWidth = xml.attributes().value("width").toString();
|
|
||||||
QString canvasHeight = xml.attributes().value("height").toString();
|
|
||||||
float canvasHeightWidth = canvasWidth.toFloat();
|
float canvasHeightWidth = canvasWidth.toFloat();
|
||||||
float canvasHeightVal = canvasHeight.toFloat();
|
float canvasHeightVal = canvasHeight.toFloat();
|
||||||
|
if (!hasBackgroundImage()) {
|
||||||
|
QPixmap emptyImage((int)canvasHeightWidth, (int)canvasHeightVal);
|
||||||
|
emptyImage.fill(QWidget::palette().color(QWidget::backgroundRole()));
|
||||||
|
updateBackgroundImage(emptyImage.toImage());
|
||||||
|
}
|
||||||
if (canvasHeightVal > 0)
|
if (canvasHeightVal > 0)
|
||||||
radiusMul = (float)scene()->sceneRect().height() / canvasHeightVal;
|
radiusMul = (float)scene()->sceneRect().height() / canvasHeightVal;
|
||||||
if (canvasHeightWidth > 0)
|
if (canvasHeightWidth > 0)
|
||||||
xMul = (float)scene()->sceneRect().width() / canvasHeightWidth;
|
xMul = (float)scene()->sceneRect().width() / canvasHeightWidth;
|
||||||
yMul = radiusMul;
|
yMul = radiusMul;
|
||||||
} else if (xml.name() == "origin") {
|
} else if (reader.name() == "origin") {
|
||||||
if (pendingNodes.size() > 0) {
|
if (pendingNodes.size() > 0) {
|
||||||
pendingNodes[pendingNodes.size() - 1]["x"] = QString("%1").arg(xml.attributes().value("x").toString().toFloat() * xMul);
|
pendingNodes[pendingNodes.size() - 1]["x"] = QString("%1").arg(reader.attributes().value("x").toString().toFloat() * xMul);
|
||||||
pendingNodes[pendingNodes.size() - 1]["y"] = QString("%1").arg(xml.attributes().value("y").toString().toFloat() * yMul);
|
pendingNodes[pendingNodes.size() - 1]["y"] = QString("%1").arg(reader.attributes().value("y").toString().toFloat() * yMul);
|
||||||
}
|
}
|
||||||
} else if (xml.name() == "node") {
|
} else if (reader.name() == "node") {
|
||||||
QString nodeId = xml.attributes().value("id").toString();
|
QString nodeId = reader.attributes().value("id").toString();
|
||||||
QString nodeType = xml.attributes().value("type").toString();
|
QString nodeType = reader.attributes().value("type").toString();
|
||||||
QString nodePairId = xml.attributes().value("pair").toString();
|
QString nodePairId = reader.attributes().value("pair").toString();
|
||||||
QString nodeRadius = xml.attributes().value("radius").toString();
|
QString nodeRadius = reader.attributes().value("radius").toString();
|
||||||
std::map<QString, QString> pendingNode;
|
std::map<QString, QString> pendingNode;
|
||||||
pendingNode["id"] = nodeId;
|
pendingNode["id"] = nodeId;
|
||||||
pendingNode["type"] = nodeType;
|
pendingNode["type"] = nodeType;
|
||||||
|
@ -388,10 +413,10 @@ void SkeletonEditGraphicsView::loadFromXml(const QString &filename)
|
||||||
pendingNode["x"] = "0";
|
pendingNode["x"] = "0";
|
||||||
pendingNode["y"] = "0";
|
pendingNode["y"] = "0";
|
||||||
pendingNodes.push_back(pendingNode);
|
pendingNodes.push_back(pendingNode);
|
||||||
} else if (xml.name() == "edge") {
|
} else if (reader.name() == "edge") {
|
||||||
QString edgeId = xml.attributes().value("id").toString();
|
QString edgeId = reader.attributes().value("id").toString();
|
||||||
QString edgeFromNodeId = xml.attributes().value("from").toString();
|
QString edgeFromNodeId = reader.attributes().value("from").toString();
|
||||||
QString edgeToNodeId = xml.attributes().value("to").toString();
|
QString edgeToNodeId = reader.attributes().value("to").toString();
|
||||||
if (!edgeFromNodeId.isEmpty() && !edgeToNodeId.isEmpty()) {
|
if (!edgeFromNodeId.isEmpty() && !edgeToNodeId.isEmpty()) {
|
||||||
std::map<QString, QString> pendingEdge;
|
std::map<QString, QString> pendingEdge;
|
||||||
pendingEdge["id"] = edgeId;
|
pendingEdge["id"] = edgeId;
|
||||||
|
@ -431,18 +456,14 @@ void SkeletonEditGraphicsView::loadFromXml(const QString &filename)
|
||||||
emit nodesChanged();
|
emit nodesChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonEditGraphicsView::saveToXml(const QString &filename)
|
void SkeletonEditGraphicsView::saveToXmlStream(QXmlStreamWriter *writer)
|
||||||
{
|
{
|
||||||
QFile file(filename);
|
writer->setAutoFormatting(true);
|
||||||
file.open(QIODevice::WriteOnly);
|
writer->writeStartDocument();
|
||||||
|
|
||||||
QXmlStreamWriter stream(&file);
|
writer->writeStartElement("canvas");
|
||||||
stream.setAutoFormatting(true);
|
writer->writeAttribute("width", QString("%1").arg(scene()->sceneRect().width()));
|
||||||
stream.writeStartDocument();
|
writer->writeAttribute("height", QString("%1").arg(scene()->sceneRect().height()));
|
||||||
|
|
||||||
stream.writeStartElement("canvas");
|
|
||||||
stream.writeAttribute("width", QString("%1").arg(scene()->sceneRect().width()));
|
|
||||||
stream.writeAttribute("height", QString("%1").arg(scene()->sceneRect().height()));
|
|
||||||
|
|
||||||
QList<QGraphicsItem *>::iterator it;
|
QList<QGraphicsItem *>::iterator it;
|
||||||
QList<QGraphicsItem *> list = scene()->items();
|
QList<QGraphicsItem *> list = scene()->items();
|
||||||
|
@ -455,40 +476,40 @@ void SkeletonEditGraphicsView::saveToXml(const QString &filename)
|
||||||
nextNodeId++;
|
nextNodeId++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stream.writeStartElement("nodes");
|
writer->writeStartElement("nodes");
|
||||||
for (it = list.begin(); it != list.end(); ++it) {
|
for (it = list.begin(); it != list.end(); ++it) {
|
||||||
if ((*it)->data(0).toString() == "node") {
|
if ((*it)->data(0).toString() == "node") {
|
||||||
SkeletonEditNodeItem *nodeItem = static_cast<SkeletonEditNodeItem *>(*it);
|
SkeletonEditNodeItem *nodeItem = static_cast<SkeletonEditNodeItem *>(*it);
|
||||||
stream.writeStartElement("node");
|
writer->writeStartElement("node");
|
||||||
stream.writeAttribute("id", QString("node%1").arg(nodeIdMap[nodeItem]));
|
writer->writeAttribute("id", QString("node%1").arg(nodeIdMap[nodeItem]));
|
||||||
stream.writeAttribute("type", nodeItem->isMaster() ? "master" : "slave");
|
writer->writeAttribute("type", nodeItem->isMaster() ? "master" : "slave");
|
||||||
stream.writeAttribute("pair", QString("node%1").arg(nodeIdMap[nodeItem->pair()]));
|
writer->writeAttribute("pair", QString("node%1").arg(nodeIdMap[nodeItem->pair()]));
|
||||||
stream.writeAttribute("radius", QString("%1").arg(nodeItem->radius()));
|
writer->writeAttribute("radius", QString("%1").arg(nodeItem->radius()));
|
||||||
stream.writeStartElement("origin");
|
writer->writeStartElement("origin");
|
||||||
QPointF origin = nodeItem->origin();
|
QPointF origin = nodeItem->origin();
|
||||||
stream.writeAttribute("x", QString("%1").arg(origin.x()));
|
writer->writeAttribute("x", QString("%1").arg(origin.x()));
|
||||||
stream.writeAttribute("y", QString("%1").arg(origin.y()));
|
writer->writeAttribute("y", QString("%1").arg(origin.y()));
|
||||||
stream.writeEndElement();
|
writer->writeEndElement();
|
||||||
stream.writeEndElement();
|
writer->writeEndElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stream.writeEndElement();
|
writer->writeEndElement();
|
||||||
stream.writeStartElement("edges");
|
writer->writeStartElement("edges");
|
||||||
int nextEdgeId = 1;
|
int nextEdgeId = 1;
|
||||||
for (it = list.begin(); it != list.end(); ++it) {
|
for (it = list.begin(); it != list.end(); ++it) {
|
||||||
if ((*it)->data(0).toString() == "edge") {
|
if ((*it)->data(0).toString() == "edge") {
|
||||||
SkeletonEditEdgeItem *edgeItem = static_cast<SkeletonEditEdgeItem *>(*it);
|
SkeletonEditEdgeItem *edgeItem = static_cast<SkeletonEditEdgeItem *>(*it);
|
||||||
stream.writeStartElement("edge");
|
writer->writeStartElement("edge");
|
||||||
stream.writeAttribute("id", QString("edge%1").arg(nextEdgeId));
|
writer->writeAttribute("id", QString("edge%1").arg(nextEdgeId));
|
||||||
stream.writeAttribute("from", QString("node%1").arg(nodeIdMap[edgeItem->firstNode()]));
|
writer->writeAttribute("from", QString("node%1").arg(nodeIdMap[edgeItem->firstNode()]));
|
||||||
stream.writeAttribute("to", QString("node%1").arg(nodeIdMap[edgeItem->secondNode()]));
|
writer->writeAttribute("to", QString("node%1").arg(nodeIdMap[edgeItem->secondNode()]));
|
||||||
stream.writeEndElement();
|
writer->writeEndElement();
|
||||||
nextEdgeId++;
|
nextEdgeId++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stream.writeEndElement();
|
writer->writeEndElement();
|
||||||
|
|
||||||
stream.writeEndElement();
|
writer->writeEndElement();
|
||||||
stream.writeEndDocument();
|
writer->writeEndDocument();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
#define SKELETON_EDIT_GRAPHICS_VIEW_H
|
#define SKELETON_EDIT_GRAPHICS_VIEW_H
|
||||||
#include <QGraphicsView>
|
#include <QGraphicsView>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
|
#include <QKeyEvent>
|
||||||
|
#include <QXmlStreamWriter>
|
||||||
|
#include <QXmlStreamReader>
|
||||||
#include "skeletoneditnodeitem.h"
|
#include "skeletoneditnodeitem.h"
|
||||||
#include "skeletoneditedgeitem.h"
|
#include "skeletoneditedgeitem.h"
|
||||||
|
|
||||||
|
@ -9,6 +12,7 @@ class SkeletonEditGraphicsView : public QGraphicsView
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
signals:
|
signals:
|
||||||
|
void sizeChanged();
|
||||||
void nodesChanged();
|
void nodesChanged();
|
||||||
void changeTurnaroundTriggered();
|
void changeTurnaroundTriggered();
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -17,14 +21,18 @@ public slots:
|
||||||
public:
|
public:
|
||||||
SkeletonEditGraphicsView(QWidget *parent = 0);
|
SkeletonEditGraphicsView(QWidget *parent = 0);
|
||||||
void updateBackgroundImage(const QImage &image);
|
void updateBackgroundImage(const QImage &image);
|
||||||
void saveToXml(const QString &filename);
|
void saveToXmlStream(QXmlStreamWriter *writer);
|
||||||
void loadFromXml(const QString &filename);
|
void loadFromXmlStream(QXmlStreamReader &reader);
|
||||||
|
bool hasBackgroundImage();
|
||||||
|
QPixmap backgroundImage();
|
||||||
protected:
|
protected:
|
||||||
void mouseMoveEvent(QMouseEvent *event);
|
void mouseMoveEvent(QMouseEvent *event);
|
||||||
void wheelEvent(QWheelEvent *event);
|
void wheelEvent(QWheelEvent *event);
|
||||||
void mouseReleaseEvent(QMouseEvent *event);
|
void mouseReleaseEvent(QMouseEvent *event);
|
||||||
void mousePressEvent(QMouseEvent *event);
|
void mousePressEvent(QMouseEvent *event);
|
||||||
void mouseDoubleClickEvent(QMouseEvent *event);
|
void mouseDoubleClickEvent(QMouseEvent *event);
|
||||||
|
void keyPressEvent(QKeyEvent *event);
|
||||||
|
void resizeEvent(QResizeEvent *event);
|
||||||
private:
|
private:
|
||||||
QGraphicsPixmapItem *m_backgroundItem;
|
QGraphicsPixmapItem *m_backgroundItem;
|
||||||
QGraphicsEllipseItem *m_pendingNodeItem;
|
QGraphicsEllipseItem *m_pendingNodeItem;
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
#include "skeletoneditwidget.h"
|
|
||||||
#include <QGraphicsScene>
|
|
||||||
#include <QGraphicsView>
|
|
||||||
#include <QGridLayout>
|
|
||||||
#include <QGraphicsPixmapItem>
|
|
||||||
|
|
||||||
// Modifed from http://doc.qt.io/qt-5/qtwidgets-graphicsview-chip-view-cpp.html
|
|
||||||
|
|
||||||
SkeletonEditWidget::SkeletonEditWidget(QWidget *parent) :
|
|
||||||
QFrame(parent)
|
|
||||||
{
|
|
||||||
m_graphicsView = new SkeletonEditGraphicsView(this);
|
|
||||||
m_graphicsView->setRenderHint(QPainter::Antialiasing, false);
|
|
||||||
m_graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
||||||
m_graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
||||||
|
|
||||||
m_graphicsView->setBackgroundBrush(QBrush(QWidget::palette().color(QWidget::backgroundRole()), Qt::SolidPattern));
|
|
||||||
|
|
||||||
QGridLayout *mainLayout = new QGridLayout;
|
|
||||||
mainLayout->addWidget(m_graphicsView, 0, 0, 1, 1);
|
|
||||||
|
|
||||||
setLayout(mainLayout);
|
|
||||||
}
|
|
||||||
|
|
||||||
SkeletonEditGraphicsView *SkeletonEditWidget::graphicsView()
|
|
||||||
{
|
|
||||||
return m_graphicsView;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkeletonEditWidget::resizeEvent(QResizeEvent *event)
|
|
||||||
{
|
|
||||||
QFrame::resizeEvent(event);
|
|
||||||
emit sizeChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkeletonEditWidget::mouseMoveEvent(QMouseEvent *event)
|
|
||||||
{
|
|
||||||
QFrame::mouseMoveEvent(event);
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
#ifndef SKELETON_EDIT_WIDGET_H
|
|
||||||
#define SKELETON_EDIT_WIDGET_H
|
|
||||||
#include <QFrame>
|
|
||||||
#include <QGraphicsView>
|
|
||||||
#include <QGraphicsScene>
|
|
||||||
#include <QGraphicsPixmapItem>
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include <QGraphicsEllipseItem>
|
|
||||||
#include "skeletoneditgraphicsview.h"
|
|
||||||
|
|
||||||
class SkeletonEditWidget : public QFrame
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
signals:
|
|
||||||
void sizeChanged();
|
|
||||||
public:
|
|
||||||
SkeletonEditWidget(QWidget *parent = 0);
|
|
||||||
SkeletonEditGraphicsView *graphicsView();
|
|
||||||
protected:
|
|
||||||
void resizeEvent(QResizeEvent *event);
|
|
||||||
void mouseMoveEvent(QMouseEvent *event);
|
|
||||||
private:
|
|
||||||
SkeletonEditGraphicsView *m_graphicsView;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -34,6 +34,7 @@ SkeletonToMesh::SkeletonToMesh(SkeletonEditGraphicsView *graphicsView) :
|
||||||
node.originX = origin.x();
|
node.originX = origin.x();
|
||||||
node.originY = origin.y();
|
node.originY = origin.y();
|
||||||
node.originZ = nodeItem->slave()->origin().x();
|
node.originZ = nodeItem->slave()->origin().x();
|
||||||
|
node.processed = false;
|
||||||
node.bmeshNodeId = -1;
|
node.bmeshNodeId = -1;
|
||||||
node.radius = nodeItem->radius();
|
node.radius = nodeItem->radius();
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ struct SkeletonNode
|
||||||
float originY;
|
float originY;
|
||||||
float originZ;
|
float originZ;
|
||||||
float radius;
|
float radius;
|
||||||
|
bool processed;
|
||||||
int bmeshNodeId;
|
int bmeshNodeId;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "skeletonwidget.h"
|
#include "skeletonwidget.h"
|
||||||
#include "skeletoneditwidget.h"
|
|
||||||
#include "meshlite.h"
|
#include "meshlite.h"
|
||||||
#include "skeletontomesh.h"
|
#include "skeletontomesh.h"
|
||||||
#include "turnaroundloader.h"
|
#include "turnaroundloader.h"
|
||||||
|
@ -24,7 +23,12 @@ SkeletonWidget::SkeletonWidget(QWidget *parent) :
|
||||||
QHBoxLayout *topLayout = new QHBoxLayout;
|
QHBoxLayout *topLayout = new QHBoxLayout;
|
||||||
topLayout->addStretch();
|
topLayout->addStretch();
|
||||||
|
|
||||||
m_skeletonEditWidget = new SkeletonEditWidget;
|
m_graphicsView = new SkeletonEditGraphicsView(this);
|
||||||
|
m_graphicsView->setRenderHint(QPainter::Antialiasing, false);
|
||||||
|
m_graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||||
|
m_graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||||
|
|
||||||
|
m_graphicsView->setBackgroundBrush(QBrush(QWidget::palette().color(QWidget::backgroundRole()), Qt::SolidPattern));
|
||||||
|
|
||||||
m_modelingWidget = new ModelingWidget(this);
|
m_modelingWidget = new ModelingWidget(this);
|
||||||
m_modelingWidget->setMinimumSize(128, 128);
|
m_modelingWidget->setMinimumSize(128, 128);
|
||||||
|
@ -59,7 +63,7 @@ SkeletonWidget::SkeletonWidget(QWidget *parent) :
|
||||||
|
|
||||||
QHBoxLayout *middleLayout = new QHBoxLayout;
|
QHBoxLayout *middleLayout = new QHBoxLayout;
|
||||||
middleLayout->addLayout(leftLayout);
|
middleLayout->addLayout(leftLayout);
|
||||||
middleLayout->addWidget(m_skeletonEditWidget);
|
middleLayout->addWidget(m_graphicsView);
|
||||||
middleLayout->addLayout(rightLayout);
|
middleLayout->addLayout(rightLayout);
|
||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
|
@ -73,19 +77,19 @@ SkeletonWidget::SkeletonWidget(QWidget *parent) :
|
||||||
|
|
||||||
bool connectResult;
|
bool connectResult;
|
||||||
|
|
||||||
connectResult = connect(addAction, SIGNAL(triggered(bool)), m_skeletonEditWidget->graphicsView(), SLOT(turnOnAddNodeMode()));
|
connectResult = connect(addAction, SIGNAL(triggered(bool)), m_graphicsView, SLOT(turnOnAddNodeMode()));
|
||||||
assert(connectResult);
|
assert(connectResult);
|
||||||
|
|
||||||
connectResult = connectResult = connect(selectAction, SIGNAL(triggered(bool)), m_skeletonEditWidget->graphicsView(), SLOT(turnOffAddNodeMode()));
|
connectResult = connectResult = connect(selectAction, SIGNAL(triggered(bool)), m_graphicsView, SLOT(turnOffAddNodeMode()));
|
||||||
assert(connectResult);
|
assert(connectResult);
|
||||||
|
|
||||||
connectResult = connect(m_skeletonEditWidget->graphicsView(), SIGNAL(nodesChanged()), this, SLOT(skeletonChanged()));
|
connectResult = connect(m_graphicsView, SIGNAL(nodesChanged()), this, SLOT(skeletonChanged()));
|
||||||
assert(connectResult);
|
assert(connectResult);
|
||||||
|
|
||||||
connectResult = connect(m_skeletonEditWidget, SIGNAL(sizeChanged()), this, SLOT(turnaroundChanged()));
|
connectResult = connect(m_graphicsView, SIGNAL(sizeChanged()), this, SLOT(turnaroundChanged()));
|
||||||
assert(connectResult);
|
assert(connectResult);
|
||||||
|
|
||||||
connectResult = connect(m_skeletonEditWidget->graphicsView(), SIGNAL(changeTurnaroundTriggered()), this, SLOT(changeTurnaround()));
|
connectResult = connect(m_graphicsView, SIGNAL(changeTurnaroundTriggered()), this, SLOT(changeTurnaround()));
|
||||||
assert(connectResult);
|
assert(connectResult);
|
||||||
|
|
||||||
//connectResult = connect(clipButton, SIGNAL(clicked()), this, SLOT(saveClip()));
|
//connectResult = connect(clipButton, SIGNAL(clicked()), this, SLOT(saveClip()));
|
||||||
|
@ -94,7 +98,7 @@ SkeletonWidget::SkeletonWidget(QWidget *parent) :
|
||||||
|
|
||||||
SkeletonEditGraphicsView *SkeletonWidget::graphicsView()
|
SkeletonEditGraphicsView *SkeletonWidget::graphicsView()
|
||||||
{
|
{
|
||||||
return m_skeletonEditWidget->graphicsView();
|
return m_graphicsView;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonWidget::showModelingWidgetAtCorner()
|
void SkeletonWidget::showModelingWidgetAtCorner()
|
||||||
|
@ -130,7 +134,7 @@ void SkeletonWidget::skeletonChanged()
|
||||||
m_skeletonDirty = false;
|
m_skeletonDirty = false;
|
||||||
|
|
||||||
QThread *thread = new QThread;
|
QThread *thread = new QThread;
|
||||||
m_skeletonToMesh = new SkeletonToMesh(m_skeletonEditWidget->graphicsView());
|
m_skeletonToMesh = new SkeletonToMesh(m_graphicsView);
|
||||||
m_skeletonToMesh->moveToThread(thread);
|
m_skeletonToMesh->moveToThread(thread);
|
||||||
connect(thread, SIGNAL(started()), m_skeletonToMesh, SLOT(process()));
|
connect(thread, SIGNAL(started()), m_skeletonToMesh, SLOT(process()));
|
||||||
connect(m_skeletonToMesh, SIGNAL(finished()), this, SLOT(meshReady()));
|
connect(m_skeletonToMesh, SIGNAL(finished()), this, SLOT(meshReady()));
|
||||||
|
@ -153,7 +157,7 @@ void SkeletonWidget::turnaroundChanged()
|
||||||
|
|
||||||
QThread *thread = new QThread;
|
QThread *thread = new QThread;
|
||||||
m_turnaroundLoader = new TurnaroundLoader(m_turnaroundFilename,
|
m_turnaroundLoader = new TurnaroundLoader(m_turnaroundFilename,
|
||||||
m_skeletonEditWidget->rect().size());
|
m_graphicsView->rect().size());
|
||||||
m_turnaroundLoader->moveToThread(thread);
|
m_turnaroundLoader->moveToThread(thread);
|
||||||
connect(thread, SIGNAL(started()), m_turnaroundLoader, SLOT(process()));
|
connect(thread, SIGNAL(started()), m_turnaroundLoader, SLOT(process()));
|
||||||
connect(m_turnaroundLoader, SIGNAL(finished()), this, SLOT(turnaroundImageReady()));
|
connect(m_turnaroundLoader, SIGNAL(finished()), this, SLOT(turnaroundImageReady()));
|
||||||
|
@ -166,7 +170,7 @@ void SkeletonWidget::turnaroundImageReady()
|
||||||
{
|
{
|
||||||
QImage *backgroundImage = m_turnaroundLoader->takeResultImage();
|
QImage *backgroundImage = m_turnaroundLoader->takeResultImage();
|
||||||
if (backgroundImage && backgroundImage->width() > 0 && backgroundImage->height() > 0) {
|
if (backgroundImage && backgroundImage->width() > 0 && backgroundImage->height() > 0) {
|
||||||
m_skeletonEditWidget->graphicsView()->updateBackgroundImage(*backgroundImage);
|
m_graphicsView->updateBackgroundImage(*backgroundImage);
|
||||||
}
|
}
|
||||||
delete backgroundImage;
|
delete backgroundImage;
|
||||||
delete m_turnaroundLoader;
|
delete m_turnaroundLoader;
|
||||||
|
@ -187,13 +191,3 @@ void SkeletonWidget::changeTurnaround()
|
||||||
turnaroundChanged();
|
turnaroundChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonWidget::saveClip()
|
|
||||||
{
|
|
||||||
QImage image = m_modelingWidget->grabFramebuffer();
|
|
||||||
//QTableWidgetItem *item = new QTableWidgetItem;
|
|
||||||
//item->setSizeHint(QSize(32, 32));
|
|
||||||
//item->setIcon(QPixmap::fromImage(image.scaled(32, 32)));
|
|
||||||
//m_clipTableWidget->insertRow(m_clipTableWidget->rowCount());
|
|
||||||
//m_clipTableWidget->setItem(m_clipTableWidget->rowCount() - 1, 0, item);
|
|
||||||
//image.save("/Users/jeremy/Repositories/dust3d/gl.png");
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include "modelingwidget.h"
|
#include "modelingwidget.h"
|
||||||
#include "skeletoneditwidget.h"
|
|
||||||
#include "skeletontomesh.h"
|
#include "skeletontomesh.h"
|
||||||
#include "turnaroundloader.h"
|
#include "turnaroundloader.h"
|
||||||
#include "skeletoneditgraphicsview.h"
|
#include "skeletoneditgraphicsview.h"
|
||||||
|
@ -22,11 +21,10 @@ public slots:
|
||||||
void turnaroundChanged();
|
void turnaroundChanged();
|
||||||
void turnaroundImageReady();
|
void turnaroundImageReady();
|
||||||
void changeTurnaround();
|
void changeTurnaround();
|
||||||
void saveClip();
|
|
||||||
void showModelingWidgetAtCorner();
|
void showModelingWidgetAtCorner();
|
||||||
private:
|
private:
|
||||||
ModelingWidget *m_modelingWidget;
|
ModelingWidget *m_modelingWidget;
|
||||||
SkeletonEditWidget *m_skeletonEditWidget;
|
SkeletonEditGraphicsView *m_graphicsView;
|
||||||
SkeletonToMesh *m_skeletonToMesh;
|
SkeletonToMesh *m_skeletonToMesh;
|
||||||
bool m_skeletonDirty;
|
bool m_skeletonDirty;
|
||||||
TurnaroundLoader *m_turnaroundLoader;
|
TurnaroundLoader *m_turnaroundLoader;
|
||||||
|
|
Loading…
Reference in New Issue