2018-03-14 06:43:16 +00:00
|
|
|
#include <QVBoxLayout>
|
|
|
|
#include <QPushButton>
|
|
|
|
#include <QButtonGroup>
|
|
|
|
#include <QGridLayout>
|
|
|
|
#include <QToolBar>
|
|
|
|
#include <QThread>
|
|
|
|
#include <QFileDialog>
|
|
|
|
#include <QApplication>
|
|
|
|
#include <QDesktopWidget>
|
|
|
|
#include <assert.h>
|
|
|
|
#include "skeletonwidget.h"
|
|
|
|
#include "meshlite.h"
|
|
|
|
#include "skeletontomesh.h"
|
|
|
|
#include "turnaroundloader.h"
|
|
|
|
|
|
|
|
SkeletonWidget::SkeletonWidget(QWidget *parent) :
|
|
|
|
QWidget(parent),
|
|
|
|
m_skeletonToMesh(NULL),
|
|
|
|
m_skeletonDirty(false),
|
|
|
|
m_turnaroundLoader(NULL),
|
|
|
|
m_turnaroundDirty(false)
|
|
|
|
{
|
|
|
|
QHBoxLayout *topLayout = new QHBoxLayout;
|
|
|
|
topLayout->addStretch();
|
|
|
|
|
2018-03-15 15:40:30 +00:00
|
|
|
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));
|
2018-03-14 06:43:16 +00:00
|
|
|
|
|
|
|
m_modelingWidget = new ModelingWidget(this);
|
|
|
|
m_modelingWidget->setMinimumSize(128, 128);
|
|
|
|
m_modelingWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
|
|
|
m_modelingWidget->setWindowFlags(Qt::Tool | Qt::Window);
|
|
|
|
m_modelingWidget->setWindowTitle("3D Model");
|
|
|
|
|
|
|
|
QVBoxLayout *rightLayout = new QVBoxLayout;
|
|
|
|
rightLayout->addSpacing(10);
|
|
|
|
rightLayout->addStretch();
|
|
|
|
|
|
|
|
QToolBar *toolbar = new QToolBar;
|
|
|
|
toolbar->setIconSize(QSize(16, 16));
|
|
|
|
toolbar->setOrientation(Qt::Vertical);
|
|
|
|
|
|
|
|
QAction *addAction = new QAction(tr("Add"), this);
|
|
|
|
addAction->setIcon(QIcon(":/resources/add.png"));
|
|
|
|
toolbar->addAction(addAction);
|
|
|
|
|
|
|
|
QAction *selectAction = new QAction(tr("Select"), this);
|
|
|
|
selectAction->setIcon(QIcon(":/resources/select.png"));
|
|
|
|
toolbar->addAction(selectAction);
|
|
|
|
|
|
|
|
QAction *rangeSelectAction = new QAction(tr("Range Select"), this);
|
|
|
|
rangeSelectAction->setIcon(QIcon(":/resources/rangeselect.png"));
|
|
|
|
toolbar->addAction(rangeSelectAction);
|
|
|
|
|
|
|
|
QVBoxLayout *leftLayout = new QVBoxLayout;
|
|
|
|
leftLayout->addWidget(toolbar);
|
|
|
|
leftLayout->addStretch();
|
|
|
|
leftLayout->addSpacing(10);
|
|
|
|
|
|
|
|
QHBoxLayout *middleLayout = new QHBoxLayout;
|
|
|
|
middleLayout->addLayout(leftLayout);
|
2018-03-15 15:40:30 +00:00
|
|
|
middleLayout->addWidget(m_graphicsView);
|
2018-03-14 06:43:16 +00:00
|
|
|
middleLayout->addLayout(rightLayout);
|
|
|
|
|
|
|
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
|
|
|
mainLayout->addLayout(topLayout);
|
|
|
|
//mainLayout->addSpacing(10);
|
|
|
|
mainLayout->addLayout(middleLayout);
|
|
|
|
|
|
|
|
setLayout(mainLayout);
|
|
|
|
|
|
|
|
setWindowTitle(tr("Dust 3D"));
|
|
|
|
|
|
|
|
bool connectResult;
|
|
|
|
|
2018-03-15 15:40:30 +00:00
|
|
|
connectResult = connect(addAction, SIGNAL(triggered(bool)), m_graphicsView, SLOT(turnOnAddNodeMode()));
|
2018-03-14 06:43:16 +00:00
|
|
|
assert(connectResult);
|
|
|
|
|
2018-03-15 15:40:30 +00:00
|
|
|
connectResult = connectResult = connect(selectAction, SIGNAL(triggered(bool)), m_graphicsView, SLOT(turnOffAddNodeMode()));
|
2018-03-14 06:43:16 +00:00
|
|
|
assert(connectResult);
|
|
|
|
|
2018-03-15 15:40:30 +00:00
|
|
|
connectResult = connect(m_graphicsView, SIGNAL(nodesChanged()), this, SLOT(skeletonChanged()));
|
2018-03-14 06:43:16 +00:00
|
|
|
assert(connectResult);
|
|
|
|
|
2018-03-15 15:40:30 +00:00
|
|
|
connectResult = connect(m_graphicsView, SIGNAL(sizeChanged()), this, SLOT(turnaroundChanged()));
|
2018-03-14 06:43:16 +00:00
|
|
|
assert(connectResult);
|
|
|
|
|
2018-03-15 15:40:30 +00:00
|
|
|
connectResult = connect(m_graphicsView, SIGNAL(changeTurnaroundTriggered()), this, SLOT(changeTurnaround()));
|
2018-03-14 06:43:16 +00:00
|
|
|
assert(connectResult);
|
|
|
|
|
|
|
|
//connectResult = connect(clipButton, SIGNAL(clicked()), this, SLOT(saveClip()));
|
|
|
|
//assert(connectResult);
|
|
|
|
}
|
|
|
|
|
2018-03-14 15:22:00 +00:00
|
|
|
SkeletonEditGraphicsView *SkeletonWidget::graphicsView()
|
|
|
|
{
|
2018-03-15 15:40:30 +00:00
|
|
|
return m_graphicsView;
|
2018-03-14 15:22:00 +00:00
|
|
|
}
|
|
|
|
|
2018-03-14 06:43:16 +00:00
|
|
|
void SkeletonWidget::showModelingWidgetAtCorner()
|
|
|
|
{
|
|
|
|
if (!m_modelingWidget->isVisible()) {
|
|
|
|
QPoint pos = QPoint(QApplication::desktop()->width(),
|
|
|
|
QApplication::desktop()->height());
|
|
|
|
m_modelingWidget->move(pos.x() - m_modelingWidget->width(),
|
|
|
|
pos.y() - m_modelingWidget->height());
|
|
|
|
m_modelingWidget->show();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SkeletonWidget::meshReady()
|
|
|
|
{
|
|
|
|
Mesh *resultMesh = m_skeletonToMesh->takeResultMesh();
|
|
|
|
showModelingWidgetAtCorner();
|
|
|
|
m_modelingWidget->updateMesh(resultMesh);
|
|
|
|
delete m_skeletonToMesh;
|
|
|
|
m_skeletonToMesh = NULL;
|
|
|
|
if (m_skeletonDirty) {
|
|
|
|
skeletonChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SkeletonWidget::skeletonChanged()
|
|
|
|
{
|
|
|
|
if (m_skeletonToMesh) {
|
|
|
|
m_skeletonDirty = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_skeletonDirty = false;
|
|
|
|
|
|
|
|
QThread *thread = new QThread;
|
2018-03-15 15:40:30 +00:00
|
|
|
m_skeletonToMesh = new SkeletonToMesh(m_graphicsView);
|
2018-03-14 06:43:16 +00:00
|
|
|
m_skeletonToMesh->moveToThread(thread);
|
|
|
|
connect(thread, SIGNAL(started()), m_skeletonToMesh, SLOT(process()));
|
|
|
|
connect(m_skeletonToMesh, SIGNAL(finished()), this, SLOT(meshReady()));
|
|
|
|
connect(m_skeletonToMesh, SIGNAL(finished()), thread, SLOT(quit()));
|
|
|
|
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
|
|
|
|
thread->start();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SkeletonWidget::turnaroundChanged()
|
|
|
|
{
|
|
|
|
if (m_turnaroundFilename.isEmpty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (m_turnaroundLoader) {
|
|
|
|
m_turnaroundDirty = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_turnaroundDirty = false;
|
|
|
|
|
|
|
|
QThread *thread = new QThread;
|
|
|
|
m_turnaroundLoader = new TurnaroundLoader(m_turnaroundFilename,
|
2018-03-15 15:40:30 +00:00
|
|
|
m_graphicsView->rect().size());
|
2018-03-14 06:43:16 +00:00
|
|
|
m_turnaroundLoader->moveToThread(thread);
|
|
|
|
connect(thread, SIGNAL(started()), m_turnaroundLoader, SLOT(process()));
|
|
|
|
connect(m_turnaroundLoader, SIGNAL(finished()), this, SLOT(turnaroundImageReady()));
|
|
|
|
connect(m_turnaroundLoader, SIGNAL(finished()), thread, SLOT(quit()));
|
|
|
|
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
|
|
|
|
thread->start();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SkeletonWidget::turnaroundImageReady()
|
|
|
|
{
|
|
|
|
QImage *backgroundImage = m_turnaroundLoader->takeResultImage();
|
|
|
|
if (backgroundImage && backgroundImage->width() > 0 && backgroundImage->height() > 0) {
|
2018-03-15 15:40:30 +00:00
|
|
|
m_graphicsView->updateBackgroundImage(*backgroundImage);
|
2018-03-14 06:43:16 +00:00
|
|
|
}
|
|
|
|
delete backgroundImage;
|
|
|
|
delete m_turnaroundLoader;
|
|
|
|
m_turnaroundLoader = NULL;
|
|
|
|
if (m_turnaroundDirty) {
|
|
|
|
turnaroundChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SkeletonWidget::changeTurnaround()
|
|
|
|
{
|
|
|
|
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Turnaround Reference Image"),
|
|
|
|
QString(),
|
|
|
|
tr("Image Files (*.png *.jpg *.bmp)")).trimmed();
|
|
|
|
if (fileName.isEmpty())
|
|
|
|
return;
|
|
|
|
m_turnaroundFilename = fileName;
|
|
|
|
turnaroundChanged();
|
|
|
|
}
|
|
|
|
|