diff --git a/ACKNOWLEDGEMENTS.html b/ACKNOWLEDGEMENTS.html
index 947272f6..0ed40bfb 100644
--- a/ACKNOWLEDGEMENTS.html
+++ b/ACKNOWLEDGEMENTS.html
@@ -1132,4 +1132,9 @@ https://www.reddit.com/r/gamedev/comments/5iuf3h/i_am_writting_a_3d_monster_mode
Birdy
http://bediyap.com/programming/convert-quaternion-to-euler-rotations/
-
\ No newline at end of file
+
+
+Eadweard Muybridge
+
+ https://en.wikipedia.org/wiki/Eadweard_Muybridge
+
diff --git a/dust3d.pro b/dust3d.pro
index 9642b5c2..54577290 100644
--- a/dust3d.pro
+++ b/dust3d.pro
@@ -294,6 +294,9 @@ HEADERS += src/poserconstruct.h
SOURCES += src/skeletondocument.cpp
HEADERS += src/skeletondocument.h
+SOURCES += src/posedocument.cpp
+HEADERS += src/posedocument.h
+
SOURCES += src/main.cpp
HEADERS += src/version.h
diff --git a/src/document.cpp b/src/document.cpp
index 10371f57..ca4f2292 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -416,6 +416,20 @@ void Document::setPoseParameters(QUuid poseId, std::map attributes)
+{
+ auto findPoseResult = poseMap.find(poseId);
+ if (findPoseResult == poseMap.end()) {
+ qDebug() << "Find pose failed:" << poseId;
+ return;
+ }
+ findPoseResult->second.attributes = attributes;
+ findPoseResult->second.dirty = true;
+ emit posesChanged();
+ emit poseAttributesChanged(poseId);
+ emit optionsChanged();
+}
+
void Document::renamePose(QUuid poseId, QString name)
{
auto findPoseResult = poseMap.find(poseId);
@@ -431,26 +445,6 @@ void Document::renamePose(QUuid poseId, QString name)
emit optionsChanged();
}
-const SkeletonEdge *Document::findEdgeByNodes(QUuid firstNodeId, QUuid secondNodeId) const
-{
- const SkeletonNode *firstNode = nullptr;
- firstNode = findNode(firstNodeId);
- if (nullptr == firstNode) {
- qDebug() << "Find node failed:" << firstNodeId;
- return nullptr;
- }
- for (auto edgeIdIt = firstNode->edgeIds.begin(); edgeIdIt != firstNode->edgeIds.end(); edgeIdIt++) {
- auto edgeIt = edgeMap.find(*edgeIdIt);
- if (edgeIt == edgeMap.end()) {
- qDebug() << "Find edge failed:" << *edgeIdIt;
- continue;
- }
- if (std::find(edgeIt->second.nodeIds.begin(), edgeIt->second.nodeIds.end(), secondNodeId) != edgeIt->second.nodeIds.end())
- return &edgeIt->second;
- }
- return nullptr;
-}
-
bool Document::originSettled() const
{
return !qFuzzyIsNull(originX) && !qFuzzyIsNull(originY) && !qFuzzyIsNull(originZ);
@@ -537,30 +531,6 @@ void Document::addEdge(QUuid fromNodeId, QUuid toNodeId)
emit skeletonChanged();
}
-const SkeletonNode *Document::findNode(QUuid nodeId) const
-{
- auto it = nodeMap.find(nodeId);
- if (it == nodeMap.end())
- return nullptr;
- return &it->second;
-}
-
-const SkeletonEdge *Document::findEdge(QUuid edgeId) const
-{
- auto it = edgeMap.find(edgeId);
- if (it == edgeMap.end())
- return nullptr;
- return &it->second;
-}
-
-const SkeletonPart *Document::findPart(QUuid partId) const
-{
- auto it = partMap.find(partId);
- if (it == partMap.end())
- return nullptr;
- return &it->second;
-}
-
const Component *Document::findComponent(QUuid componentId) const
{
if (componentId.isNull())
@@ -1001,7 +971,7 @@ void Document::toSnapshot(Snapshot *snapshot, const std::set &limitNodeId
continue;
}
auto &poseIt = *findPoseResult;
- std::map pose;
+ std::map pose = poseIt.second.attributes;
pose["id"] = poseIt.second.id.toString();
if (!poseIt.second.name.isEmpty())
pose["name"] = poseIt.second.name;
@@ -1251,6 +1221,13 @@ void Document::addFromSnapshot(const Snapshot &snapshot, bool fromPaste)
newPose.id = newPoseId;
const auto &poseAttributes = poseIt.first;
newPose.name = valueOfKeyInMapOrEmpty(poseAttributes, "name");
+ for (const auto &attribute: poseAttributes) {
+ if (attribute.first == "name" ||
+ attribute.first == "id") {
+ continue;
+ }
+ newPose.attributes.insert({attribute.first, attribute.second});
+ }
newPose.parameters = poseIt.second;
oldNewIdMap[QUuid(valueOfKeyInMapOrEmpty(poseAttributes, "id"))] = newPoseId;
poseIdList.push_back(newPoseId);
@@ -2394,32 +2371,6 @@ void Document::checkExportReadyState()
emit exportReady();
}
-void Document::findAllNeighbors(QUuid nodeId, std::set &neighbors) const
-{
- const auto &node = findNode(nodeId);
- if (nullptr == node) {
- qDebug() << "findNode:" << nodeId << "failed";
- return;
- }
- for (const auto &edgeId: node->edgeIds) {
- const auto &edge = findEdge(edgeId);
- if (nullptr == edge) {
- qDebug() << "findEdge:" << edgeId << "failed";
- continue;
- }
- const auto &neighborNodeId = edge->neighborOf(nodeId);
- if (neighborNodeId.isNull()) {
- qDebug() << "neighborOf:" << nodeId << "is null from edge:" << edgeId;
- continue;
- }
- if (neighbors.find(neighborNodeId) != neighbors.end()) {
- continue;
- }
- neighbors.insert(neighborNodeId);
- findAllNeighbors(neighborNodeId, neighbors);
- }
-}
-
void Document::setSharedContextWidget(QOpenGLWidget *sharedContextWidget)
{
m_sharedContextWidget = sharedContextWidget;
@@ -2945,4 +2896,4 @@ void Document::copyNodes(std::set nodeIdSet) const
saveSkeletonToXmlStream(&snapshot, &xmlStreamWriter);
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(snapshotXml);
-}
\ No newline at end of file
+}
diff --git a/src/document.h b/src/document.h
index f0614746..52f3f33f 100644
--- a/src/document.h
+++ b/src/document.h
@@ -195,6 +195,7 @@ public:
QUuid id;
QString name;
bool dirty = true;
+ std::map attributes;
std::map> parameters;
void updatePreviewMesh(MeshLoader *previewMesh)
{
@@ -424,6 +425,7 @@ signals:
void poseListChanged();
void poseNameChanged(QUuid poseId);
void poseParametersChanged(QUuid poseId);
+ void poseAttributesChanged(QUuid poseId);
void posePreviewChanged(QUuid poseId);
void motionAdded(QUuid motionId);
void motionRemoved(QUuid motionId);
@@ -453,9 +455,6 @@ public: // need initialize
public:
Document();
~Document();
- std::map partMap;
- std::map nodeMap;
- std::map edgeMap;
std::map componentMap;
std::map materialMap;
std::vector materialIdList;
@@ -465,17 +464,12 @@ public:
std::vector motionIdList;
Component rootComponent;
QImage preview;
- const SkeletonNode *findNode(QUuid nodeId) const override;
- const SkeletonEdge *findEdge(QUuid edgeId) const override;
- const SkeletonPart *findPart(QUuid partId) const override;
- const SkeletonEdge *findEdgeByNodes(QUuid firstNodeId, QUuid secondNodeId) const override;
bool undoable() const override;
bool redoable() const override;
bool hasPastableNodesInClipboard() const override;
bool originSettled() const override;
bool isNodeEditable(QUuid nodeId) const override;
bool isEdgeEditable(QUuid edgeId) const override;
- void findAllNeighbors(QUuid nodeId, std::set &neighbors) const override;
void copyNodes(std::set nodeIdSet) const override;
void toSnapshot(Snapshot *snapshot, const std::set &limitNodeIds=std::set(),
DocumentToSnapshotFor forWhat=DocumentToSnapshotFor::Document,
@@ -601,6 +595,7 @@ public slots:
void addPose(QString name, std::map> parameters);
void removePose(QUuid poseId);
void setPoseParameters(QUuid poseId, std::map> parameters);
+ void setPoseAttributes(QUuid poseId, std::map attributes);
void renamePose(QUuid poseId, QString name);
void addMotion(QString name, std::vector clips);
void removeMotion(QUuid motionId);
diff --git a/src/documentwindow.cp b/src/documentwindow.cp
deleted file mode 100644
index b408adeb..00000000
--- a/src/documentwindow.cp
+++ /dev/null
@@ -1,1341 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "documentwindow.h"
-#include "skeletongraphicswidget.h"
-#include "theme.h"
-#include "ds3file.h"
-#include "snapshot.h"
-#include "snapshotxml.h"
-#include "logbrowser.h"
-#include "util.h"
-#include "aboutwidget.h"
-#include "version.h"
-#include "gltffile.h"
-#include "graphicscontainerwidget.h"
-#include "parttreewidget.h"
-#include "rigwidget.h"
-#include "markiconcreator.h"
-#include "motionmanagewidget.h"
-#include "materialmanagewidget.h"
-#include "imageforever.h"
-#include "spinnableawesomebutton.h"
-#include "fbxfile.h"
-#include "shortcuts.h"
-
-int SkeletonDocumentWindow::m_modelRenderWidgetInitialX = 16;
-int SkeletonDocumentWindow::m_modelRenderWidgetInitialY = 16;
-int SkeletonDocumentWindow::m_modelRenderWidgetInitialSize = 128;
-int SkeletonDocumentWindow::m_skeletonRenderWidgetInitialX = SkeletonDocumentWindow::m_modelRenderWidgetInitialX + SkeletonDocumentWindow::m_modelRenderWidgetInitialSize + 16;
-int SkeletonDocumentWindow::m_skeletonRenderWidgetInitialY = SkeletonDocumentWindow::m_modelRenderWidgetInitialY;
-int SkeletonDocumentWindow::m_skeletonRenderWidgetInitialSize = SkeletonDocumentWindow::m_modelRenderWidgetInitialSize;
-
-LogBrowser *g_logBrowser = nullptr;
-std::set g_documentWindows;
-QTextBrowser *g_acknowlegementsWidget = nullptr;
-AboutWidget *g_aboutWidget = nullptr;
-QTextBrowser *g_contributorsWidget = nullptr;
-
-void outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg)
-{
- if (g_logBrowser)
- g_logBrowser->outputMessage(type, msg, context.file, context.line);
-}
-
-void SkeletonDocumentWindow::showAcknowlegements()
-{
- if (!g_acknowlegementsWidget) {
- g_acknowlegementsWidget = new QTextBrowser;
- g_acknowlegementsWidget->setWindowTitle(unifiedWindowTitle(tr("Acknowlegements")));
- g_acknowlegementsWidget->setMinimumSize(QSize(400, 300));
- QFile file(":/ACKNOWLEDGEMENTS.html");
- file.open(QFile::ReadOnly | QFile::Text);
- QTextStream stream(&file);
- g_acknowlegementsWidget->setHtml(stream.readAll());
- }
- g_acknowlegementsWidget->show();
- g_acknowlegementsWidget->activateWindow();
- g_acknowlegementsWidget->raise();
-}
-
-void SkeletonDocumentWindow::showContributors()
-{
- if (!g_contributorsWidget) {
- g_contributorsWidget = new QTextBrowser;
- g_contributorsWidget->setWindowTitle(unifiedWindowTitle(tr("Contributors")));
- g_contributorsWidget->setMinimumSize(QSize(400, 300));
- QFile authors(":/AUTHORS");
- authors.open(QFile::ReadOnly | QFile::Text);
- QFile contributors(":/CONTRIBUTORS");
- contributors.open(QFile::ReadOnly | QFile::Text);
- g_contributorsWidget->setHtml("AUTHORS
" + authors.readAll() + "
CONTRIBUTORS
" + contributors.readAll() + "
");
- }
- g_contributorsWidget->show();
- g_contributorsWidget->activateWindow();
- g_contributorsWidget->raise();
-}
-
-void SkeletonDocumentWindow::showAbout()
-{
- if (!g_aboutWidget) {
- g_aboutWidget = new AboutWidget;
- }
- g_aboutWidget->show();
- g_aboutWidget->activateWindow();
- g_aboutWidget->raise();
-}
-
-SkeletonDocumentWindow::SkeletonDocumentWindow() :
- m_document(nullptr),
- m_firstShow(true),
- m_documentSaved(true),
- m_exportPreviewWidget(nullptr),
- m_advanceSettingWidget(nullptr)
-{
- if (!g_logBrowser) {
- g_logBrowser = new LogBrowser;
- qInstallMessageHandler(&outputMessage);
- }
-
- g_documentWindows.insert(this);
-
- m_document = new Document;
-
- QVBoxLayout *toolButtonLayout = new QVBoxLayout;
- toolButtonLayout->setSpacing(0);
- toolButtonLayout->setContentsMargins(5, 10, 4, 0);
-
- QPushButton *addButton = new QPushButton(QChar(fa::plus));
- Theme::initAwesomeButton(addButton);
-
- QPushButton *selectButton = new QPushButton(QChar(fa::mousepointer));
- Theme::initAwesomeButton(selectButton);
-
- QPushButton *dragButton = new QPushButton(QChar(fa::handrocko));
- Theme::initAwesomeButton(dragButton);
-
- QPushButton *zoomInButton = new QPushButton(QChar(fa::searchplus));
- Theme::initAwesomeButton(zoomInButton);
-
- QPushButton *zoomOutButton = new QPushButton(QChar(fa::searchminus));
- Theme::initAwesomeButton(zoomOutButton);
-
- m_xlockButton = new QPushButton(QChar('X'));
- initLockButton(m_xlockButton);
- updateXlockButtonState();
-
- m_ylockButton = new QPushButton(QChar('Y'));
- initLockButton(m_ylockButton);
- updateYlockButtonState();
-
- m_zlockButton = new QPushButton(QChar('Z'));
- initLockButton(m_zlockButton);
- updateZlockButtonState();
-
- m_radiusLockButton = new QPushButton(QChar(fa::bullseye));
- Theme::initAwesomeButton(m_radiusLockButton);
- updateRadiusLockButtonState();
-
- QPushButton *rotateCounterclockwiseButton = new QPushButton(QChar(fa::rotateleft));
- Theme::initAwesomeButton(rotateCounterclockwiseButton);
-
- QPushButton *rotateClockwiseButton = new QPushButton(QChar(fa::rotateright));
- Theme::initAwesomeButton(rotateClockwiseButton);
-
- SpinnableAwesomeButton *regenerateButton = new SpinnableAwesomeButton();
- regenerateButton->setAwesomeIcon(QChar(fa::recycle));
- connect(m_document, &Document::meshGenerating, this, [=]() {
- regenerateButton->showSpinner(true);
- });
- connect(m_document, &Document::postProcessing, this, [=]() {
- regenerateButton->showSpinner(true);
- });
- connect(m_document, &Document::textureGenerating, this, [=]() {
- regenerateButton->showSpinner(true);
- });
- connect(m_document, &Document::resultTextureChanged, this, [=]() {
- regenerateButton->showSpinner(false);
- });
- connect(regenerateButton->button(), &QPushButton::clicked, m_document, &Document::regenerateMesh);
-
- toolButtonLayout->addWidget(addButton);
- toolButtonLayout->addWidget(selectButton);
- toolButtonLayout->addWidget(dragButton);
- toolButtonLayout->addWidget(zoomInButton);
- toolButtonLayout->addWidget(zoomOutButton);
- toolButtonLayout->addSpacing(10);
- toolButtonLayout->addWidget(m_xlockButton);
- toolButtonLayout->addWidget(m_ylockButton);
- toolButtonLayout->addWidget(m_zlockButton);
- toolButtonLayout->addWidget(m_radiusLockButton);
- toolButtonLayout->addSpacing(10);
- toolButtonLayout->addWidget(rotateCounterclockwiseButton);
- toolButtonLayout->addWidget(rotateClockwiseButton);
- toolButtonLayout->addSpacing(10);
- toolButtonLayout->addWidget(regenerateButton);
-
-
- QLabel *verticalLogoLabel = new QLabel;
- QImage verticalLogoImage;
- verticalLogoImage.load(":/resources/dust3d-vertical.png");
- verticalLogoLabel->setPixmap(QPixmap::fromImage(verticalLogoImage));
-
- QHBoxLayout *logoLayout = new QHBoxLayout;
- logoLayout->addWidget(verticalLogoLabel);
- logoLayout->setContentsMargins(0, 0, 0, 0);
-
- QVBoxLayout *mainLeftLayout = new QVBoxLayout;
- mainLeftLayout->setSpacing(0);
- mainLeftLayout->setContentsMargins(0, 0, 0, 0);
- mainLeftLayout->addLayout(toolButtonLayout);
- mainLeftLayout->addStretch();
- mainLeftLayout->addLayout(logoLayout);
- mainLeftLayout->addSpacing(10);
-
- SkeletonGraphicsWidget *graphicsWidget = new SkeletonGraphicsWidget(m_document);
- m_graphicsWidget = graphicsWidget;
-
- GraphicsContainerWidget *containerWidget = new GraphicsContainerWidget;
- containerWidget->setGraphicsWidget(graphicsWidget);
- QGridLayout *containerLayout = new QGridLayout;
- containerLayout->setSpacing(0);
- containerLayout->setContentsMargins(1, 0, 0, 0);
- containerLayout->addWidget(graphicsWidget);
- containerWidget->setLayout(containerLayout);
- containerWidget->setMinimumSize(400, 400);
-
- m_modelRenderWidget = new ModelWidget(containerWidget);
- m_modelRenderWidget->setMinimumSize(SkeletonDocumentWindow::m_modelRenderWidgetInitialSize, SkeletonDocumentWindow::m_modelRenderWidgetInitialSize);
- m_modelRenderWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
- m_modelRenderWidget->move(SkeletonDocumentWindow::m_modelRenderWidgetInitialX, SkeletonDocumentWindow::m_modelRenderWidgetInitialY);
-
- m_graphicsWidget->setModelWidget(m_modelRenderWidget);
-
- m_document->setSharedContextWidget(m_modelRenderWidget);
-
- setTabPosition(Qt::RightDockWidgetArea, QTabWidget::East);
-
- QDockWidget *partTreeDocker = new QDockWidget(tr("Parts"), this);
- partTreeDocker->setAllowedAreas(Qt::RightDockWidgetArea);
- PartTreeWidget *partTreeWidget = new PartTreeWidget(m_document, partTreeDocker);
- partTreeDocker->setWidget(partTreeWidget);
- addDockWidget(Qt::RightDockWidgetArea, partTreeDocker);
- connect(partTreeDocker, &QDockWidget::topLevelChanged, [=](bool topLevel) {
- Q_UNUSED(topLevel);
- for (const auto &part: m_document->partMap)
- partTreeWidget->partPreviewChanged(part.first);
- });
-
- QDockWidget *materialDocker = new QDockWidget(tr("Materials"), this);
- materialDocker->setAllowedAreas(Qt::RightDockWidgetArea);
- MaterialManageWidget *materialManageWidget = new MaterialManageWidget(m_document, materialDocker);
- materialDocker->setWidget(materialManageWidget);
- connect(materialManageWidget, &MaterialManageWidget::registerDialog, this, &SkeletonDocumentWindow::registerDialog);
- connect(materialManageWidget, &MaterialManageWidget::unregisterDialog, this, &SkeletonDocumentWindow::unregisterDialog);
- addDockWidget(Qt::RightDockWidgetArea, materialDocker);
- connect(materialDocker, &QDockWidget::topLevelChanged, [=](bool topLevel) {
- Q_UNUSED(topLevel);
- for (const auto &material: m_document->materialMap)
- emit m_document->materialPreviewChanged(material.first);
- });
-
- QDockWidget *rigDocker = new QDockWidget(tr("Rig"), this);
- rigDocker->setAllowedAreas(Qt::RightDockWidgetArea);
- m_rigWidget = new RigWidget(m_document, rigDocker);
- rigDocker->setWidget(m_rigWidget);
- addDockWidget(Qt::RightDockWidgetArea, rigDocker);
- connect(rigDocker, &QDockWidget::topLevelChanged, [=](bool topLevel) {
- Q_UNUSED(topLevel);
- updateRigWeightRenderWidget();
- });
-
- QDockWidget *poseDocker = new QDockWidget(tr("Poses"), this);
- poseDocker->setAllowedAreas(Qt::RightDockWidgetArea);
- PoseManageWidget *poseManageWidget = new PoseManageWidget(m_document, poseDocker);
- poseDocker->setWidget(poseManageWidget);
- connect(poseManageWidget, &PoseManageWidget::registerDialog, this, &SkeletonDocumentWindow::registerDialog);
- connect(poseManageWidget, &PoseManageWidget::unregisterDialog, this, &SkeletonDocumentWindow::unregisterDialog);
- addDockWidget(Qt::RightDockWidgetArea, poseDocker);
- connect(poseDocker, &QDockWidget::topLevelChanged, [=](bool topLevel) {
- Q_UNUSED(topLevel);
- for (const auto &pose: m_document->poseMap)
- emit m_document->posePreviewChanged(pose.first);
- });
-
- QDockWidget *motionDocker = new QDockWidget(tr("Motions"), this);
- motionDocker->setAllowedAreas(Qt::RightDockWidgetArea);
- MotionManageWidget *motionManageWidget = new MotionManageWidget(m_document, motionDocker);
- motionDocker->setWidget(motionManageWidget);
- connect(motionManageWidget, &MotionManageWidget::registerDialog, this, &SkeletonDocumentWindow::registerDialog);
- connect(motionManageWidget, &MotionManageWidget::unregisterDialog, this, &SkeletonDocumentWindow::unregisterDialog);
- addDockWidget(Qt::RightDockWidgetArea, motionDocker);
-
- tabifyDockWidget(partTreeDocker, materialDocker);
- tabifyDockWidget(materialDocker, rigDocker);
- tabifyDockWidget(rigDocker, poseDocker);
- tabifyDockWidget(poseDocker, motionDocker);
-
- partTreeDocker->raise();
-
- QHBoxLayout *mainLayout = new QHBoxLayout;
- mainLayout->setSpacing(0);
- mainLayout->setContentsMargins(0, 0, 0, 0);
- mainLayout->addLayout(mainLeftLayout);
- mainLayout->addWidget(containerWidget);
- mainLayout->addSpacing(3);
-
- QWidget *centralWidget = new QWidget;
- centralWidget->setLayout(mainLayout);
-
- setCentralWidget(centralWidget);
- setWindowTitle(APP_NAME);
-
- m_fileMenu = menuBar()->addMenu(tr("File"));
-
- m_newWindowAction = new QAction(tr("New Window"), this);
- connect(m_newWindowAction, &QAction::triggered, this, &SkeletonDocumentWindow::newWindow, Qt::QueuedConnection);
- m_fileMenu->addAction(m_newWindowAction);
-
- m_newDocumentAction = new QAction(tr("New"), this);
- connect(m_newDocumentAction, &QAction::triggered, this, &SkeletonDocumentWindow::newDocument);
- m_fileMenu->addAction(m_newDocumentAction);
-
- m_openAction = new QAction(tr("Open..."), this);
- connect(m_openAction, &QAction::triggered, this, &SkeletonDocumentWindow::open, Qt::QueuedConnection);
- m_fileMenu->addAction(m_openAction);
-
- m_saveAction = new QAction(tr("Save"), this);
- connect(m_saveAction, &QAction::triggered, this, &SkeletonDocumentWindow::save, Qt::QueuedConnection);
- m_fileMenu->addAction(m_saveAction);
-
- m_saveAsAction = new QAction(tr("Save As..."), this);
- connect(m_saveAsAction, &QAction::triggered, this, &SkeletonDocumentWindow::saveAs, Qt::QueuedConnection);
- m_fileMenu->addAction(m_saveAsAction);
-
- m_saveAllAction = new QAction(tr("Save All"), this);
- connect(m_saveAllAction, &QAction::triggered, this, &SkeletonDocumentWindow::saveAll, Qt::QueuedConnection);
- m_fileMenu->addAction(m_saveAllAction);
-
- m_fileMenu->addSeparator();
-
- //m_exportMenu = m_fileMenu->addMenu(tr("Export"));
-
- m_exportAction = new QAction(tr("Export..."), this);
- connect(m_exportAction, &QAction::triggered, this, &SkeletonDocumentWindow::showExportPreview, Qt::QueuedConnection);
- m_fileMenu->addAction(m_exportAction);
-
- m_exportAsObjAction = new QAction(tr("Export as OBJ..."), this);
- connect(m_exportAsObjAction, &QAction::triggered, this, &SkeletonDocumentWindow::exportObjResult, Qt::QueuedConnection);
- m_fileMenu->addAction(m_exportAsObjAction);
-
- //m_exportRenderedAsImageAction = new QAction(tr("Export as PNG..."), this);
- //connect(m_exportRenderedAsImageAction, &QAction::triggered, this, &SkeletonDocumentWindow::exportRenderedResult, Qt::QueuedConnection);
- //m_fileMenu->addAction(m_exportRenderedAsImageAction);
-
- //m_exportAsObjPlusMaterialsAction = new QAction(tr("Wavefront (.obj + .mtl)..."), this);
- //connect(m_exportAsObjPlusMaterialsAction, &QAction::triggered, this, &SkeletonDocumentWindow::exportObjPlusMaterialsResult, Qt::QueuedConnection);
- //m_exportMenu->addAction(m_exportAsObjPlusMaterialsAction);
-
- m_fileMenu->addSeparator();
-
- m_changeTurnaroundAction = new QAction(tr("Change Reference Sheet..."), this);
- connect(m_changeTurnaroundAction, &QAction::triggered, this, &SkeletonDocumentWindow::changeTurnaround, Qt::QueuedConnection);
- m_fileMenu->addAction(m_changeTurnaroundAction);
-
- m_fileMenu->addSeparator();
-
- connect(m_fileMenu, &QMenu::aboutToShow, [=]() {
- m_exportAsObjAction->setEnabled(m_graphicsWidget->hasItems());
- //m_exportAsObjPlusMaterialsAction->setEnabled(m_graphicsWidget->hasItems());
- m_exportAction->setEnabled(m_graphicsWidget->hasItems());
- //m_exportRenderedAsImageAction->setEnabled(m_graphicsWidget->hasItems());
- });
-
- m_editMenu = menuBar()->addMenu(tr("Edit"));
-
- m_addAction = new QAction(tr("Add..."), this);
- connect(m_addAction, &QAction::triggered, [=]() {
- m_document->setEditMode(DocumentEditMode::Add);
- });
- m_editMenu->addAction(m_addAction);
-
- m_undoAction = new QAction(tr("Undo"), this);
- connect(m_undoAction, &QAction::triggered, m_document, &Document::undo);
- m_editMenu->addAction(m_undoAction);
-
- m_redoAction = new QAction(tr("Redo"), this);
- connect(m_redoAction, &QAction::triggered, m_document, &Document::redo);
- m_editMenu->addAction(m_redoAction);
-
- m_deleteAction = new QAction(tr("Delete"), this);
- connect(m_deleteAction, &QAction::triggered, m_graphicsWidget, &SkeletonGraphicsWidget::deleteSelected);
- m_editMenu->addAction(m_deleteAction);
-
- m_breakAction = new QAction(tr("Break"), this);
- connect(m_breakAction, &QAction::triggered, m_graphicsWidget, &SkeletonGraphicsWidget::breakSelected);
- m_editMenu->addAction(m_breakAction);
-
- m_connectAction = new QAction(tr("Connect"), this);
- connect(m_connectAction, &QAction::triggered, m_graphicsWidget, &SkeletonGraphicsWidget::connectSelected);
- m_editMenu->addAction(m_connectAction);
-
- m_cutAction = new QAction(tr("Cut"), this);
- connect(m_cutAction, &QAction::triggered, m_graphicsWidget, &SkeletonGraphicsWidget::cut);
- m_editMenu->addAction(m_cutAction);
-
- m_copyAction = new QAction(tr("Copy"), this);
- connect(m_copyAction, &QAction::triggered, m_graphicsWidget, &SkeletonGraphicsWidget::copy);
- m_editMenu->addAction(m_copyAction);
-
- m_pasteAction = new QAction(tr("Paste"), this);
- connect(m_pasteAction, &QAction::triggered, m_document, &Document::paste);
- m_editMenu->addAction(m_pasteAction);
-
- m_flipHorizontallyAction = new QAction(tr("H Flip"), this);
- connect(m_flipHorizontallyAction, &QAction::triggered, m_graphicsWidget, &SkeletonGraphicsWidget::flipHorizontally);
- m_editMenu->addAction(m_flipHorizontallyAction);
-
- m_flipVerticallyAction = new QAction(tr("V Flip"), this);
- connect(m_flipVerticallyAction, &QAction::triggered, m_graphicsWidget, &SkeletonGraphicsWidget::flipVertically);
- m_editMenu->addAction(m_flipVerticallyAction);
-
- m_rotateClockwiseAction = new QAction(tr("Rotate 90D CW"), this);
- connect(m_rotateClockwiseAction, &QAction::triggered, [=] {
- m_graphicsWidget->rotateClockwise90Degree();
- });
- m_editMenu->addAction(m_rotateClockwiseAction);
-
- m_rotateCounterclockwiseAction = new QAction(tr("Rotate 90D CCW"), this);
- connect(m_rotateCounterclockwiseAction, &QAction::triggered, [=] {
- m_graphicsWidget->rotateCounterclockwise90Degree();
- });
- m_editMenu->addAction(m_rotateCounterclockwiseAction);
-
- m_switchXzAction = new QAction(tr("Switch XZ"), this);
- connect(m_switchXzAction, &QAction::triggered, [=] {
- m_graphicsWidget->switchSelectedXZ();
- });
- m_editMenu->addAction(m_switchXzAction);
-
- m_alignToMenu = new QMenu(tr("Align To"));
-
- m_alignToLocalCenterAction = new QAction(tr("Local Center"), this);
- connect(m_alignToLocalCenterAction, &QAction::triggered, m_graphicsWidget, &SkeletonGraphicsWidget::alignSelectedToLocalCenter);
- m_alignToMenu->addAction(m_alignToLocalCenterAction);
-
- m_alignToLocalVerticalCenterAction = new QAction(tr("Local Vertical Center"), this);
- connect(m_alignToLocalVerticalCenterAction, &QAction::triggered, m_graphicsWidget, &SkeletonGraphicsWidget::alignSelectedToLocalVerticalCenter);
- m_alignToMenu->addAction(m_alignToLocalVerticalCenterAction);
-
- m_alignToLocalHorizontalCenterAction = new QAction(tr("Local Horizontal Center"), this);
- connect(m_alignToLocalHorizontalCenterAction, &QAction::triggered, m_graphicsWidget, &SkeletonGraphicsWidget::alignSelectedToLocalHorizontalCenter);
- m_alignToMenu->addAction(m_alignToLocalHorizontalCenterAction);
-
- m_alignToGlobalCenterAction = new QAction(tr("Global Center"), this);
- connect(m_alignToGlobalCenterAction, &QAction::triggered, m_graphicsWidget, &SkeletonGraphicsWidget::alignSelectedToGlobalCenter);
- m_alignToMenu->addAction(m_alignToGlobalCenterAction);
-
- m_alignToGlobalVerticalCenterAction = new QAction(tr("Global Vertical Center"), this);
- connect(m_alignToGlobalVerticalCenterAction, &QAction::triggered, m_graphicsWidget, &SkeletonGraphicsWidget::alignSelectedToGlobalVerticalCenter);
- m_alignToMenu->addAction(m_alignToGlobalVerticalCenterAction);
-
- m_alignToGlobalHorizontalCenterAction = new QAction(tr("Global Horizontal Center"), this);
- connect(m_alignToGlobalHorizontalCenterAction, &QAction::triggered, m_graphicsWidget, &SkeletonGraphicsWidget::alignSelectedToGlobalHorizontalCenter);
- m_alignToMenu->addAction(m_alignToGlobalHorizontalCenterAction);
-
- m_editMenu->addMenu(m_alignToMenu);
-
- m_markAsMenu = new QMenu(tr("Mark As"));
-
- m_markAsNoneAction = new QAction(tr("None"), this);
- connect(m_markAsNoneAction, &QAction::triggered, [=]() {
- m_graphicsWidget->setSelectedNodesBoneMark(BoneMark::None);
- });
- m_markAsMenu->addAction(m_markAsNoneAction);
-
- m_markAsMenu->addSeparator();
-
- for (int i = 0; i < (int)BoneMark::Count - 1; i++) {
- BoneMark boneMark = (BoneMark)(i + 1);
- m_markAsActions[i] = new QAction(MarkIconCreator::createIcon(boneMark), BoneMarkToDispName(boneMark), this);
- connect(m_markAsActions[i], &QAction::triggered, [=]() {
- m_graphicsWidget->setSelectedNodesBoneMark(boneMark);
- });
- m_markAsMenu->addAction(m_markAsActions[i]);
- }
-
- m_editMenu->addMenu(m_markAsMenu);
-
- m_selectAllAction = new QAction(tr("Select All"), this);
- connect(m_selectAllAction, &QAction::triggered, m_graphicsWidget, &SkeletonGraphicsWidget::selectAll);
- m_editMenu->addAction(m_selectAllAction);
-
- m_selectPartAllAction = new QAction(tr("Select Part"), this);
- connect(m_selectPartAllAction, &QAction::triggered, m_graphicsWidget, &SkeletonGraphicsWidget::selectPartAll);
- m_editMenu->addAction(m_selectPartAllAction);
-
- m_unselectAllAction = new QAction(tr("Unselect All"), this);
- connect(m_unselectAllAction, &QAction::triggered, m_graphicsWidget, &SkeletonGraphicsWidget::unselectAll);
- m_editMenu->addAction(m_unselectAllAction);
-
- connect(m_editMenu, &QMenu::aboutToShow, [=]() {
- m_undoAction->setEnabled(m_document->undoable());
- m_redoAction->setEnabled(m_document->redoable());
- m_deleteAction->setEnabled(m_graphicsWidget->hasSelection());
- m_breakAction->setEnabled(m_graphicsWidget->hasEdgeSelection());
- m_connectAction->setEnabled(m_graphicsWidget->hasTwoDisconnectedNodesSelection());
- m_cutAction->setEnabled(m_graphicsWidget->hasSelection());
- m_copyAction->setEnabled(m_graphicsWidget->hasSelection());
- m_pasteAction->setEnabled(m_document->hasPastableNodesInClipboard());
- m_flipHorizontallyAction->setEnabled(m_graphicsWidget->hasMultipleSelection());
- m_flipVerticallyAction->setEnabled(m_graphicsWidget->hasMultipleSelection());
- m_rotateClockwiseAction->setEnabled(m_graphicsWidget->hasMultipleSelection());
- m_rotateCounterclockwiseAction->setEnabled(m_graphicsWidget->hasMultipleSelection());
- m_switchXzAction->setEnabled(m_graphicsWidget->hasSelection());
- m_alignToGlobalCenterAction->setEnabled(m_graphicsWidget->hasSelection() && m_document->originSettled());
- m_alignToGlobalVerticalCenterAction->setEnabled(m_graphicsWidget->hasSelection() && m_document->originSettled());
- m_alignToGlobalHorizontalCenterAction->setEnabled(m_graphicsWidget->hasSelection() && m_document->originSettled());
- m_alignToLocalCenterAction->setEnabled(m_graphicsWidget->hasMultipleSelection());
- m_alignToLocalVerticalCenterAction->setEnabled(m_graphicsWidget->hasMultipleSelection());
- m_alignToLocalHorizontalCenterAction->setEnabled(m_graphicsWidget->hasMultipleSelection());
- m_alignToMenu->setEnabled((m_graphicsWidget->hasSelection() && m_document->originSettled()) || m_graphicsWidget->hasMultipleSelection());
- m_selectAllAction->setEnabled(m_graphicsWidget->hasItems());
- m_selectPartAllAction->setEnabled(m_graphicsWidget->hasItems());
- m_unselectAllAction->setEnabled(m_graphicsWidget->hasSelection());
- });
-
- m_viewMenu = menuBar()->addMenu(tr("View"));
-
- auto isModelSitInVisibleArea = [](ModelWidget *modelWidget) {
- QRect parentRect = QRect(QPoint(0, 0), modelWidget->parentWidget()->size());
- return parentRect.contains(modelWidget->geometry().center());
- };
-
- m_resetModelWidgetPosAction = new QAction(tr("Show Model"), this);
- connect(m_resetModelWidgetPosAction, &QAction::triggered, [=]() {
- if (!isModelSitInVisibleArea(m_modelRenderWidget)) {
- m_modelRenderWidget->move(SkeletonDocumentWindow::m_modelRenderWidgetInitialX, SkeletonDocumentWindow::m_modelRenderWidgetInitialY);
- }
- });
- m_viewMenu->addAction(m_resetModelWidgetPosAction);
-
- //m_toggleWireframeAction = new QAction(tr("Toggle Wireframe"), this);
- //connect(m_toggleWireframeAction, &QAction::triggered, [=]() {
- // m_modelRenderWidget->toggleWireframe();
- //});
- //m_viewMenu->addAction(m_toggleWireframeAction);
-
- //m_toggleSmoothNormalAction = new QAction(tr("Toggle Smooth Normal"), this);
- //connect(m_toggleSmoothNormalAction, &QAction::triggered, [=]() {
- // m_document->toggleSmoothNormal();
- //});
- //m_viewMenu->addAction(m_toggleSmoothNormalAction);
-
- connect(m_viewMenu, &QMenu::aboutToShow, [=]() {
- m_resetModelWidgetPosAction->setEnabled(!isModelSitInVisibleArea(m_modelRenderWidget));
- });
-
- m_windowMenu = menuBar()->addMenu(tr("Window"));
-
- m_showPartsListAction = new QAction(tr("Parts"), this);
- connect(m_showPartsListAction, &QAction::triggered, [=]() {
- partTreeDocker->show();
- partTreeDocker->raise();
- });
- m_windowMenu->addAction(m_showPartsListAction);
-
- m_showMaterialsAction = new QAction(tr("Materials"), this);
- connect(m_showMaterialsAction, &QAction::triggered, [=]() {
- materialDocker->show();
- materialDocker->raise();
- });
- m_windowMenu->addAction(m_showMaterialsAction);
-
- m_showRigAction = new QAction(tr("Rig"), this);
- connect(m_showRigAction, &QAction::triggered, [=]() {
- rigDocker->show();
- rigDocker->raise();
- });
- m_windowMenu->addAction(m_showRigAction);
-
- m_showPosesAction = new QAction(tr("Poses"), this);
- connect(m_showPosesAction, &QAction::triggered, [=]() {
- poseDocker->show();
- poseDocker->raise();
- });
- m_windowMenu->addAction(m_showPosesAction);
-
- m_showMotionsAction = new QAction(tr("Motions"), this);
- connect(m_showMotionsAction, &QAction::triggered, [=]() {
- motionDocker->show();
- motionDocker->raise();
- });
- m_windowMenu->addAction(m_showMotionsAction);
-
- QMenu *dialogsMenu = m_windowMenu->addMenu(tr("Dialogs"));
- connect(dialogsMenu, &QMenu::aboutToShow, [=]() {
- dialogsMenu->clear();
- if (this->m_dialogs.empty()) {
- QAction *action = dialogsMenu->addAction(tr("None"));
- action->setEnabled(false);
- return;
- }
- for (const auto &dialog: this->m_dialogs) {
- QAction *action = dialogsMenu->addAction(dialog->windowTitle());
- connect(action, &QAction::triggered, [=]() {
- dialog->show();
- dialog->raise();
- });
- }
- });
-
- m_showDebugDialogAction = new QAction(tr("Debug"), this);
- connect(m_showDebugDialogAction, &QAction::triggered, g_logBrowser, &LogBrowser::showDialog);
- m_windowMenu->addAction(m_showDebugDialogAction);
-
- m_showAdvanceSettingAction = new QAction(tr("Advance"), this);
- connect(m_showAdvanceSettingAction, &QAction::triggered, this, &SkeletonDocumentWindow::showAdvanceSetting);
-#ifndef NDEBUG
- m_windowMenu->addAction(m_showAdvanceSettingAction);
-#endif
-
- m_helpMenu = menuBar()->addMenu(tr("Help"));
-
- m_viewSourceAction = new QAction(tr("Fork me on GitHub"), this);
- connect(m_viewSourceAction, &QAction::triggered, this, &SkeletonDocumentWindow::viewSource);
- m_helpMenu->addAction(m_viewSourceAction);
-
- m_helpMenu->addSeparator();
-
- m_seeReferenceGuideAction = new QAction(tr("Reference Guide"), this);
- connect(m_seeReferenceGuideAction, &QAction::triggered, this, &SkeletonDocumentWindow::seeReferenceGuide);
- m_helpMenu->addAction(m_seeReferenceGuideAction);
-
- m_helpMenu->addSeparator();
-
- m_aboutAction = new QAction(tr("About"), this);
- connect(m_aboutAction, &QAction::triggered, this, &SkeletonDocumentWindow::about);
- m_helpMenu->addAction(m_aboutAction);
-
- m_reportIssuesAction = new QAction(tr("Report Issues"), this);
- connect(m_reportIssuesAction, &QAction::triggered, this, &SkeletonDocumentWindow::reportIssues);
- m_helpMenu->addAction(m_reportIssuesAction);
-
- m_helpMenu->addSeparator();
-
- m_seeContributorsAction = new QAction(tr("Contributors"), this);
- connect(m_seeContributorsAction, &QAction::triggered, this, &SkeletonDocumentWindow::seeContributors);
- m_helpMenu->addAction(m_seeContributorsAction);
-
- m_seeAcknowlegementsAction = new QAction(tr("Acknowlegements"), this);
- connect(m_seeAcknowlegementsAction, &QAction::triggered, this, &SkeletonDocumentWindow::seeAcknowlegements);
- m_helpMenu->addAction(m_seeAcknowlegementsAction);
-
- connect(containerWidget, &GraphicsContainerWidget::containerSizeChanged,
- graphicsWidget, &SkeletonGraphicsWidget::canvasResized);
-
- connect(m_document, &Document::turnaroundChanged,
- graphicsWidget, &SkeletonGraphicsWidget::turnaroundChanged);
-
- connect(rotateCounterclockwiseButton, &QPushButton::clicked, graphicsWidget, &SkeletonGraphicsWidget::rotateAllMainProfileCounterclockwise90DegreeAlongOrigin);
- connect(rotateClockwiseButton, &QPushButton::clicked, graphicsWidget, &SkeletonGraphicsWidget::rotateAllMainProfileClockwise90DegreeAlongOrigin);
-
- connect(addButton, &QPushButton::clicked, [=]() {
- m_document->setEditMode(DocumentEditMode::Add);
- });
-
- connect(selectButton, &QPushButton::clicked, [=]() {
- m_document->setEditMode(DocumentEditMode::Select);
- });
-
- connect(dragButton, &QPushButton::clicked, [=]() {
- m_document->setEditMode(DocumentEditMode::Drag);
- });
-
- connect(zoomInButton, &QPushButton::clicked, [=]() {
- m_document->setEditMode(DocumentEditMode::ZoomIn);
- });
-
- connect(zoomOutButton, &QPushButton::clicked, [=]() {
- m_document->setEditMode(DocumentEditMode::ZoomOut);
- });
-
- connect(m_xlockButton, &QPushButton::clicked, [=]() {
- m_document->setXlockState(!m_document->xlocked);
- });
- connect(m_ylockButton, &QPushButton::clicked, [=]() {
- m_document->setYlockState(!m_document->ylocked);
- });
- connect(m_zlockButton, &QPushButton::clicked, [=]() {
- m_document->setZlockState(!m_document->zlocked);
- });
- connect(m_radiusLockButton, &QPushButton::clicked, [=]() {
- m_document->setRadiusLockState(!m_document->radiusLocked);
- });
-
- m_partListDockerVisibleSwitchConnection = connect(m_document, &Document::skeletonChanged, [=]() {
- if (m_graphicsWidget->hasItems()) {
- if (partTreeDocker->isHidden())
- partTreeDocker->show();
- disconnect(m_partListDockerVisibleSwitchConnection);
- }
- });
-
- connect(m_document, &Document::editModeChanged, graphicsWidget, &SkeletonGraphicsWidget::editModeChanged);
-
- connect(graphicsWidget, &SkeletonGraphicsWidget::zoomRenderedModelBy, m_modelRenderWidget, &ModelWidget::zoom);
-
- connect(graphicsWidget, &SkeletonGraphicsWidget::addNode, m_document, &Document::addNode);
- connect(graphicsWidget, &SkeletonGraphicsWidget::scaleNodeByAddRadius, m_document, &Document::scaleNodeByAddRadius);
- connect(graphicsWidget, &SkeletonGraphicsWidget::moveNodeBy, m_document, &Document::moveNodeBy);
- connect(graphicsWidget, &SkeletonGraphicsWidget::setNodeOrigin, m_document, &Document::setNodeOrigin);
- connect(graphicsWidget, &SkeletonGraphicsWidget::setNodeBoneMark, m_document, &Document::setNodeBoneMark);
- connect(graphicsWidget, &SkeletonGraphicsWidget::removeNode, m_document, &Document::removeNode);
- connect(graphicsWidget, &SkeletonGraphicsWidget::setEditMode, m_document, &Document::setEditMode);
- connect(graphicsWidget, &SkeletonGraphicsWidget::removeEdge, m_document, &Document::removeEdge);
- connect(graphicsWidget, &SkeletonGraphicsWidget::addEdge, m_document, &Document::addEdge);
- connect(graphicsWidget, &SkeletonGraphicsWidget::groupOperationAdded, m_document, &Document::saveSnapshot);
- connect(graphicsWidget, &SkeletonGraphicsWidget::undo, m_document, &Document::undo);
- connect(graphicsWidget, &SkeletonGraphicsWidget::redo, m_document, &Document::redo);
- connect(graphicsWidget, &SkeletonGraphicsWidget::paste, m_document, &Document::paste);
- connect(graphicsWidget, &SkeletonGraphicsWidget::batchChangeBegin, m_document, &Document::batchChangeBegin);
- connect(graphicsWidget, &SkeletonGraphicsWidget::batchChangeEnd, m_document, &Document::batchChangeEnd);
- connect(graphicsWidget, &SkeletonGraphicsWidget::breakEdge, m_document, &Document::breakEdge);
- connect(graphicsWidget, &SkeletonGraphicsWidget::moveOriginBy, m_document, &Document::moveOriginBy);
- connect(graphicsWidget, &SkeletonGraphicsWidget::partChecked, m_document, &Document::partChecked);
- connect(graphicsWidget, &SkeletonGraphicsWidget::partUnchecked, m_document, &Document::partUnchecked);
- connect(graphicsWidget, &SkeletonGraphicsWidget::switchNodeXZ, m_document, &Document::switchNodeXZ);
-
- connect(graphicsWidget, &SkeletonGraphicsWidget::setPartLockState, m_document, &Document::setPartLockState);
- connect(graphicsWidget, &SkeletonGraphicsWidget::setPartVisibleState, m_document, &Document::setPartVisibleState);
- connect(graphicsWidget, &SkeletonGraphicsWidget::setPartSubdivState, m_document, &Document::setPartSubdivState);
- connect(graphicsWidget, &SkeletonGraphicsWidget::setPartDisableState, m_document, &Document::setPartDisableState);
- connect(graphicsWidget, &SkeletonGraphicsWidget::setPartXmirrorState, m_document, &Document::setPartXmirrorState);
- connect(graphicsWidget, &SkeletonGraphicsWidget::setPartRoundState, m_document, &Document::setPartRoundState);
- connect(graphicsWidget, &SkeletonGraphicsWidget::setPartWrapState, m_document, &Document::setPartWrapState);
-
- connect(graphicsWidget, &SkeletonGraphicsWidget::setXlockState, m_document, &Document::setXlockState);
- connect(graphicsWidget, &SkeletonGraphicsWidget::setYlockState, m_document, &Document::setYlockState);
- connect(graphicsWidget, &SkeletonGraphicsWidget::setZlockState, m_document, &Document::setZlockState);
-
- connect(graphicsWidget, &SkeletonGraphicsWidget::enableAllPositionRelatedLocks, m_document, &Document::enableAllPositionRelatedLocks);
- connect(graphicsWidget, &SkeletonGraphicsWidget::disableAllPositionRelatedLocks, m_document, &Document::disableAllPositionRelatedLocks);
-
- connect(graphicsWidget, &SkeletonGraphicsWidget::changeTurnaround, this, &SkeletonDocumentWindow::changeTurnaround);
- connect(graphicsWidget, &SkeletonGraphicsWidget::save, this, &SkeletonDocumentWindow::save);
- connect(graphicsWidget, &SkeletonGraphicsWidget::open, this, &SkeletonDocumentWindow::open);
-
- connect(m_document, &Document::optionsChanged, m_document, &Document::saveSnapshot);
-
- connect(m_document, &Document::nodeAdded, graphicsWidget, &SkeletonGraphicsWidget::nodeAdded);
- connect(m_document, &Document::nodeRemoved, graphicsWidget, &SkeletonGraphicsWidget::nodeRemoved);
- connect(m_document, &Document::edgeAdded, graphicsWidget, &SkeletonGraphicsWidget::edgeAdded);
- connect(m_document, &Document::edgeRemoved, graphicsWidget, &SkeletonGraphicsWidget::edgeRemoved);
- connect(m_document, &Document::nodeRadiusChanged, graphicsWidget, &SkeletonGraphicsWidget::nodeRadiusChanged);
- connect(m_document, &Document::nodeBoneMarkChanged, graphicsWidget, &SkeletonGraphicsWidget::nodeBoneMarkChanged);
- connect(m_document, &Document::nodeOriginChanged, graphicsWidget, &SkeletonGraphicsWidget::nodeOriginChanged);
- connect(m_document, &Document::partVisibleStateChanged, graphicsWidget, &SkeletonGraphicsWidget::partVisibleStateChanged);
- connect(m_document, &Document::partDisableStateChanged, graphicsWidget, &SkeletonGraphicsWidget::partVisibleStateChanged);
- connect(m_document, &Document::cleanup, graphicsWidget, &SkeletonGraphicsWidget::removeAllContent);
- connect(m_document, &Document::originChanged, graphicsWidget, &SkeletonGraphicsWidget::originChanged);
- connect(m_document, &Document::checkPart, graphicsWidget, &SkeletonGraphicsWidget::selectPartAllById);
- connect(m_document, &Document::enableBackgroundBlur, graphicsWidget, &SkeletonGraphicsWidget::enableBackgroundBlur);
- connect(m_document, &Document::disableBackgroundBlur, graphicsWidget, &SkeletonGraphicsWidget::disableBackgroundBlur);
- connect(m_document, &Document::uncheckAll, graphicsWidget, &SkeletonGraphicsWidget::unselectAll);
- connect(m_document, &Document::checkNode, graphicsWidget, &SkeletonGraphicsWidget::addSelectNode);
- connect(m_document, &Document::checkEdge, graphicsWidget, &SkeletonGraphicsWidget::addSelectEdge);
-
- connect(partTreeWidget, &PartTreeWidget::currentComponentChanged, m_document, &Document::setCurrentCanvasComponentId);
- connect(partTreeWidget, &PartTreeWidget::moveComponentUp, m_document, &Document::moveComponentUp);
- connect(partTreeWidget, &PartTreeWidget::moveComponentDown, m_document, &Document::moveComponentDown);
- connect(partTreeWidget, &PartTreeWidget::moveComponentToTop, m_document, &Document::moveComponentToTop);
- connect(partTreeWidget, &PartTreeWidget::moveComponentToBottom, m_document, &Document::moveComponentToBottom);
- connect(partTreeWidget, &PartTreeWidget::checkPart, m_document, &Document::checkPart);
- connect(partTreeWidget, &PartTreeWidget::createNewComponentAndMoveThisIn, m_document, &Document::createNewComponentAndMoveThisIn);
- connect(partTreeWidget, &PartTreeWidget::createNewChildComponent, m_document, &Document::createNewChildComponent);
- connect(partTreeWidget, &PartTreeWidget::renameComponent, m_document, &Document::renameComponent);
- connect(partTreeWidget, &PartTreeWidget::setComponentExpandState, m_document, &Document::setComponentExpandState);
- connect(partTreeWidget, &PartTreeWidget::setComponentSmoothAll, m_document, &Document::setComponentSmoothAll);
- connect(partTreeWidget, &PartTreeWidget::setComponentSmoothSeam, m_document, &Document::setComponentSmoothSeam);
- connect(partTreeWidget, &PartTreeWidget::moveComponent, m_document, &Document::moveComponent);
- connect(partTreeWidget, &PartTreeWidget::removeComponent, m_document, &Document::removeComponent);
- connect(partTreeWidget, &PartTreeWidget::hideOtherComponents, m_document, &Document::hideOtherComponents);
- connect(partTreeWidget, &PartTreeWidget::lockOtherComponents, m_document, &Document::lockOtherComponents);
- connect(partTreeWidget, &PartTreeWidget::hideAllComponents, m_document, &Document::hideAllComponents);
- connect(partTreeWidget, &PartTreeWidget::showAllComponents, m_document, &Document::showAllComponents);
- connect(partTreeWidget, &PartTreeWidget::collapseAllComponents, m_document, &Document::collapseAllComponents);
- connect(partTreeWidget, &PartTreeWidget::expandAllComponents, m_document, &Document::expandAllComponents);
- connect(partTreeWidget, &PartTreeWidget::lockAllComponents, m_document, &Document::lockAllComponents);
- connect(partTreeWidget, &PartTreeWidget::unlockAllComponents, m_document, &Document::unlockAllComponents);
- connect(partTreeWidget, &PartTreeWidget::setPartLockState, m_document, &Document::setPartLockState);
- connect(partTreeWidget, &PartTreeWidget::setPartVisibleState, m_document, &Document::setPartVisibleState);
- connect(partTreeWidget, &PartTreeWidget::setComponentInverseState, m_document, &Document::setComponentInverseState);
- connect(partTreeWidget, &PartTreeWidget::hideDescendantComponents, m_document, &Document::hideDescendantComponents);
- connect(partTreeWidget, &PartTreeWidget::showDescendantComponents, m_document, &Document::showDescendantComponents);
- connect(partTreeWidget, &PartTreeWidget::lockDescendantComponents, m_document, &Document::lockDescendantComponents);
- connect(partTreeWidget, &PartTreeWidget::unlockDescendantComponents, m_document, &Document::unlockDescendantComponents);
-
- connect(partTreeWidget, &PartTreeWidget::addPartToSelection, graphicsWidget, &SkeletonGraphicsWidget::addPartToSelection);
-
- connect(m_document, &Document::componentNameChanged, partTreeWidget, &PartTreeWidget::componentNameChanged);
- connect(m_document, &Document::componentChildrenChanged, partTreeWidget, &PartTreeWidget::componentChildrenChanged);
- connect(m_document, &Document::componentRemoved, partTreeWidget, &PartTreeWidget::componentRemoved);
- connect(m_document, &Document::componentAdded, partTreeWidget, &PartTreeWidget::componentAdded);
- connect(m_document, &Document::componentExpandStateChanged, partTreeWidget, &PartTreeWidget::componentExpandStateChanged);
- connect(m_document, &Document::partPreviewChanged, partTreeWidget, &PartTreeWidget::partPreviewChanged);
- connect(m_document, &Document::partLockStateChanged, partTreeWidget, &PartTreeWidget::partLockStateChanged);
- connect(m_document, &Document::partVisibleStateChanged, partTreeWidget, &PartTreeWidget::partVisibleStateChanged);
- connect(m_document, &Document::partSubdivStateChanged, partTreeWidget, &PartTreeWidget::partSubdivStateChanged);
- connect(m_document, &Document::partDisableStateChanged, partTreeWidget, &PartTreeWidget::partDisableStateChanged);
- connect(m_document, &Document::partXmirrorStateChanged, partTreeWidget, &PartTreeWidget::partXmirrorStateChanged);
- connect(m_document, &Document::partDeformThicknessChanged, partTreeWidget, &PartTreeWidget::partDeformChanged);
- connect(m_document, &Document::partDeformWidthChanged, partTreeWidget, &PartTreeWidget::partDeformChanged);
- connect(m_document, &Document::partRoundStateChanged, partTreeWidget, &PartTreeWidget::partRoundStateChanged);
- connect(m_document, &Document::partWrapStateChanged, partTreeWidget, &PartTreeWidget::partWrapStateChanged);
- connect(m_document, &Document::partColorStateChanged, partTreeWidget, &PartTreeWidget::partColorStateChanged);
- connect(m_document, &Document::partMaterialIdChanged, partTreeWidget, &PartTreeWidget::partMaterialIdChanged);
- connect(m_document, &Document::partRemoved, partTreeWidget, &PartTreeWidget::partRemoved);
- connect(m_document, &Document::cleanup, partTreeWidget, &PartTreeWidget::removeAllContent);
- connect(m_document, &Document::partChecked, partTreeWidget, &PartTreeWidget::partChecked);
- connect(m_document, &Document::partUnchecked, partTreeWidget, &PartTreeWidget::partUnchecked);
-
- connect(m_document, &Document::skeletonChanged, m_document, &Document::generateMesh);
- //connect(m_document, &SkeletonDocument::resultMeshChanged, [=]() {
- // if ((m_exportPreviewWidget && m_exportPreviewWidget->isVisible())) {
- // m_document->postProcess();
- // }
- //});
- //connect(m_document, &SkeletonDocument::textureChanged, [=]() {
- // if ((m_exportPreviewWidget && m_exportPreviewWidget->isVisible())) {
- // m_document->generateTexture();
- // }
- //});
- connect(m_document, &Document::textureChanged, m_document, &Document::generateTexture);
- connect(m_document, &Document::resultMeshChanged, m_document, &Document::postProcess);
- connect(m_document, &Document::resultMeshChanged, m_document, &Document::generateRig);
- connect(m_document, &Document::rigChanged, m_document, &Document::generateRig);
- connect(m_document, &Document::postProcessedResultChanged, m_document, &Document::generateTexture);
- //connect(m_document, &SkeletonDocument::resultTextureChanged, m_document, &SkeletonDocument::bakeAmbientOcclusionTexture);
- connect(m_document, &Document::resultTextureChanged, [=]() {
- if (m_document->isMeshGenerating())
- return;
- m_modelRenderWidget->updateMesh(m_document->takeResultTextureMesh());
- });
-
- connect(m_document, &Document::resultMeshChanged, [=]() {
- m_modelRenderWidget->updateMesh(m_document->takeResultMesh());
- });
-
- connect(m_document, &Document::posesChanged, m_document, &Document::generateMotions);
- connect(m_document, &Document::motionsChanged, m_document, &Document::generateMotions);
-
- connect(graphicsWidget, &SkeletonGraphicsWidget::cursorChanged, [=]() {
- m_modelRenderWidget->setCursor(graphicsWidget->cursor());
- //m_skeletonRenderWidget->setCursor(graphicsWidget->cursor());
- });
-
- connect(m_document, &Document::skeletonChanged, this, &SkeletonDocumentWindow::documentChanged);
- connect(m_document, &Document::turnaroundChanged, this, &SkeletonDocumentWindow::documentChanged);
- connect(m_document, &Document::optionsChanged, this, &SkeletonDocumentWindow::documentChanged);
- connect(m_document, &Document::rigChanged, this, &SkeletonDocumentWindow::documentChanged);
-
- connect(m_modelRenderWidget, &ModelWidget::customContextMenuRequested, [=](const QPoint &pos) {
- graphicsWidget->showContextMenu(graphicsWidget->mapFromGlobal(m_modelRenderWidget->mapToGlobal(pos)));
- });
-
- connect(m_document, &Document::xlockStateChanged, this, &SkeletonDocumentWindow::updateXlockButtonState);
- connect(m_document, &Document::ylockStateChanged, this, &SkeletonDocumentWindow::updateYlockButtonState);
- connect(m_document, &Document::zlockStateChanged, this, &SkeletonDocumentWindow::updateZlockButtonState);
- connect(m_document, &Document::radiusLockStateChanged, this, &SkeletonDocumentWindow::updateRadiusLockButtonState);
-
- connect(m_rigWidget, &RigWidget::setRigType, m_document, &Document::setRigType);
-
- connect(m_document, &Document::rigTypeChanged, m_rigWidget, &RigWidget::rigTypeChanged);
- connect(m_document, &Document::resultRigChanged, m_rigWidget, &RigWidget::updateResultInfo);
- connect(m_document, &Document::resultRigChanged, this, &SkeletonDocumentWindow::updateRigWeightRenderWidget);
-
- //connect(m_document, &SkeletonDocument::resultRigChanged, tetrapodPoseEditWidget, &TetrapodPoseEditWidget::updatePreview);
-
- connect(m_document, &Document::poseAdded, this, [=](QUuid poseId) {
- Q_UNUSED(poseId);
- m_document->generatePosePreviews();
- });
- connect(m_document, &Document::poseParametersChanged, this, [=](QUuid poseId) {
- Q_UNUSED(poseId);
- m_document->generatePosePreviews();
- });
- connect(m_document, &Document::resultRigChanged, m_document, &Document::generatePosePreviews);
-
- connect(m_document, &Document::resultRigChanged, m_document, &Document::generateMotions);
-
- connect(m_document, &Document::materialAdded, this, [=](QUuid materialId) {
- Q_UNUSED(materialId);
- m_document->generateMaterialPreviews();
- });
- connect(m_document, &Document::materialLayersChanged, this, [=](QUuid materialId) {
- Q_UNUSED(materialId);
- m_document->generateMaterialPreviews();
- });
-
- initShortCuts(this, m_graphicsWidget);
-
- connect(this, &SkeletonDocumentWindow::initialized, m_document, &Document::uiReady);
-
- QTimer *timer = new QTimer(this);
- timer->setInterval(250);
- connect(timer, &QTimer::timeout, [=] {
- QWidget *focusedWidget = QApplication::focusWidget();
- //qDebug() << (focusedWidget ? ("Focused on:" + QString(focusedWidget->metaObject()->className()) + " title:" + focusedWidget->windowTitle()) : "No Focus") << " isActive:" << isActiveWindow();
- if (nullptr == focusedWidget && isActiveWindow())
- graphicsWidget->setFocus();
- });
- timer->start();
-}
-
-SkeletonDocumentWindow *SkeletonDocumentWindow::createDocumentWindow()
-{
- SkeletonDocumentWindow *documentWindow = new SkeletonDocumentWindow();
- documentWindow->setAttribute(Qt::WA_DeleteOnClose);
- documentWindow->showMaximized();
- return documentWindow;
-}
-
-void SkeletonDocumentWindow::closeEvent(QCloseEvent *event)
-{
- if (m_documentSaved) {
- event->accept();
- return;
- }
-
- QMessageBox::StandardButton answer = QMessageBox::question(this,
- APP_NAME,
- tr("Do you really want to close while there are unsaved changes?"),
- QMessageBox::Yes | QMessageBox::No);
- if (answer == QMessageBox::Yes)
- event->accept();
- else
- event->ignore();
-}
-
-void SkeletonDocumentWindow::setCurrentFilename(const QString &filename)
-{
- m_currentFilename = filename;
- m_documentSaved = true;
- updateTitle();
-}
-
-void SkeletonDocumentWindow::updateTitle()
-{
- QString appName = APP_NAME;
- QString appVer = APP_HUMAN_VER;
- setWindowTitle(QString("%1 %2 %3%4").arg(appName).arg(appVer).arg(m_currentFilename).arg(m_documentSaved ? "" : "*"));
-}
-
-void SkeletonDocumentWindow::documentChanged()
-{
- if (m_documentSaved) {
- m_documentSaved = false;
- updateTitle();
- }
-}
-
-void SkeletonDocumentWindow::newWindow()
-{
- SkeletonDocumentWindow::createDocumentWindow();
-}
-
-void SkeletonDocumentWindow::newDocument()
-{
- if (!m_documentSaved) {
- QMessageBox::StandardButton answer = QMessageBox::question(this,
- APP_NAME,
- tr("Do you really want to create new document and lose the unsaved changes?"),
- QMessageBox::Yes | QMessageBox::No);
- if (answer != QMessageBox::Yes)
- return;
- }
- m_document->reset();
-}
-
-void SkeletonDocumentWindow::saveAs()
-{
- QString filename = QFileDialog::getSaveFileName(this, QString(), QString(),
- tr("Dust3D Document (*.ds3)"));
- if (filename.isEmpty()) {
- return;
- }
- saveTo(filename);
-}
-
-void SkeletonDocumentWindow::saveAll()
-{
- for (auto &window: g_documentWindows) {
- window->save();
- }
-}
-
-void SkeletonDocumentWindow::viewSource()
-{
- QString url = APP_REPOSITORY_URL;
- qDebug() << "viewSource:" << url;
- QDesktopServices::openUrl(QUrl(url));
-}
-
-void SkeletonDocumentWindow::about()
-{
- SkeletonDocumentWindow::showAbout();
-}
-
-void SkeletonDocumentWindow::reportIssues()
-{
- QString url = APP_ISSUES_URL;
- qDebug() << "reportIssues:" << url;
- QDesktopServices::openUrl(QUrl(url));
-}
-
-void SkeletonDocumentWindow::seeReferenceGuide()
-{
- QString url = APP_REFERENCE_GUIDE_URL;
- qDebug() << "referenceGuide:" << url;
- QDesktopServices::openUrl(QUrl(url));
-}
-
-void SkeletonDocumentWindow::seeAcknowlegements()
-{
- SkeletonDocumentWindow::showAcknowlegements();
-}
-
-void SkeletonDocumentWindow::seeContributors()
-{
- SkeletonDocumentWindow::showContributors();
-}
-
-void SkeletonDocumentWindow::initLockButton(QPushButton *button)
-{
- QFont font;
- font.setWeight(QFont::Light);
- font.setPixelSize(Theme::toolIconFontSize);
- font.setBold(false);
-
- button->setFont(font);
- button->setFixedSize(Theme::toolIconSize, Theme::toolIconSize);
- button->setStyleSheet("QPushButton {color: #f7d9c8}");
- button->setFocusPolicy(Qt::NoFocus);
-}
-
-SkeletonDocumentWindow::~SkeletonDocumentWindow()
-{
- g_documentWindows.erase(this);
-}
-
-void SkeletonDocumentWindow::showEvent(QShowEvent *event)
-{
- QMainWindow::showEvent(event);
- if (m_firstShow) {
- m_firstShow = false;
- updateTitle();
- m_document->silentReset();
- m_graphicsWidget->setFocus();
- emit initialized();
- }
-}
-
-void SkeletonDocumentWindow::mousePressEvent(QMouseEvent *event)
-{
- QMainWindow::mousePressEvent(event);
-}
-
-void SkeletonDocumentWindow::changeTurnaround()
-{
- QString fileName = QFileDialog::getOpenFileName(this, QString(), QString(),
- tr("Image Files (*.png *.jpg *.bmp)")).trimmed();
- if (fileName.isEmpty())
- return;
- QImage image;
- if (!image.load(fileName))
- return;
- m_document->updateTurnaround(image);
-}
-
-void SkeletonDocumentWindow::save()
-{
- saveTo(m_currentFilename);
-}
-
-void SkeletonDocumentWindow::saveTo(const QString &saveAsFilename)
-{
- QString filename = saveAsFilename;
-
- if (filename.isEmpty()) {
- filename = QFileDialog::getSaveFileName(this, QString(), QString(),
- tr("Dust3D Document (*.ds3)"));
- if (filename.isEmpty()) {
- return;
- }
- }
-
- QApplication::setOverrideCursor(Qt::WaitCursor);
-
- Ds3FileWriter ds3Writer;
-
- QByteArray modelXml;
- QXmlStreamWriter stream(&modelXml);
- Snapshot snapshot;
- m_document->toSnapshot(&snapshot);
- saveSkeletonToXmlStream(&snapshot, &stream);
- if (modelXml.size() > 0)
- ds3Writer.add("model.xml", "model", &modelXml);
-
- QByteArray imageByteArray;
- QBuffer pngBuffer(&imageByteArray);
- if (!m_document->turnaround.isNull()) {
- pngBuffer.open(QIODevice::WriteOnly);
- m_document->turnaround.save(&pngBuffer, "PNG");
- if (imageByteArray.size() > 0)
- ds3Writer.add("canvas.png", "asset", &imageByteArray);
- }
-
- for (auto &material: snapshot.materials) {
- for (auto &layer: material.second) {
- for (auto &mapItem: layer.second) {
- auto findImageIdString = mapItem.find("linkData");
- if (findImageIdString == mapItem.end())
- continue;
- QUuid imageId = QUuid(findImageIdString->second);
- const QImage *image = ImageForever::get(imageId);
- if (nullptr == image)
- continue;
- QByteArray imageByteArray;
- QBuffer pngBuffer(&imageByteArray);
- pngBuffer.open(QIODevice::WriteOnly);
- image->save(&pngBuffer, "PNG");
- if (imageByteArray.size() > 0)
- ds3Writer.add("images/" + imageId.toString() + ".png", "asset", &imageByteArray);
- }
- }
- }
-
- if (ds3Writer.save(filename)) {
- setCurrentFilename(filename);
- }
-
- QApplication::restoreOverrideCursor();
-}
-
-void SkeletonDocumentWindow::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);
-
- 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(filename);
-}
-
-void SkeletonDocumentWindow::showAdvanceSetting()
-{
- if (nullptr == m_advanceSettingWidget) {
- m_advanceSettingWidget = new AdvanceSettingWidget(m_document, this);
- }
- m_advanceSettingWidget->show();
- m_advanceSettingWidget->raise();
-}
-
-void SkeletonDocumentWindow::exportObjResult()
-{
- QString filename = QFileDialog::getSaveFileName(this, QString(), QString(),
- tr("Wavefront (*.obj)"));
- if (filename.isEmpty()) {
- return;
- }
- QApplication::setOverrideCursor(Qt::WaitCursor);
- MeshLoader *resultMesh = m_document->takeResultMesh();
- if (nullptr != resultMesh) {
- resultMesh->exportAsObj(filename);
- delete resultMesh;
- }
- QApplication::restoreOverrideCursor();
-}
-
-void SkeletonDocumentWindow::showExportPreview()
-{
- if (nullptr == m_exportPreviewWidget) {
- m_exportPreviewWidget = new ExportPreviewWidget(m_document, this);
- connect(m_exportPreviewWidget, &ExportPreviewWidget::regenerate, m_document, &Document::regenerateMesh);
- connect(m_exportPreviewWidget, &ExportPreviewWidget::saveAsGltf, this, &SkeletonDocumentWindow::exportGltfResult);
- connect(m_exportPreviewWidget, &ExportPreviewWidget::saveAsFbx, this, &SkeletonDocumentWindow::exportFbxResult);
- connect(m_document, &Document::resultMeshChanged, m_exportPreviewWidget, &ExportPreviewWidget::checkSpinner);
- connect(m_document, &Document::exportReady, m_exportPreviewWidget, &ExportPreviewWidget::checkSpinner);
- connect(m_document, &Document::resultTextureChanged, m_exportPreviewWidget, &ExportPreviewWidget::updateTexturePreview);
- connect(m_document, &Document::resultBakedTextureChanged, m_exportPreviewWidget, &ExportPreviewWidget::updateTexturePreview);
- registerDialog(m_exportPreviewWidget);
- }
- m_exportPreviewWidget->show();
- m_exportPreviewWidget->raise();
-}
-
-void SkeletonDocumentWindow::exportFbxResult()
-{
- QString filename = QFileDialog::getSaveFileName(this, QString(), QString(),
- tr("Autodesk FBX (.fbx)"));
- if (filename.isEmpty()) {
- return;
- }
- if (!m_document->isExportReady()) {
- qDebug() << "Export but document is not export ready";
- return;
- }
- QApplication::setOverrideCursor(Qt::WaitCursor);
- Outcome skeletonResult = m_document->currentPostProcessedResultContext();
- FbxFileWriter fbxFileWriter(skeletonResult, m_document->resultRigBones(), m_document->resultRigWeights(), filename);
- fbxFileWriter.save();
- QApplication::restoreOverrideCursor();
-}
-
-void SkeletonDocumentWindow::exportGltfResult()
-{
- QString filename = QFileDialog::getSaveFileName(this, QString(), QString(),
- tr("GL Transmission Format (.gltf)"));
- if (filename.isEmpty()) {
- return;
- }
- if (!m_document->isExportReady()) {
- qDebug() << "Export but document is not export ready";
- return;
- }
- QApplication::setOverrideCursor(Qt::WaitCursor);
- Outcome skeletonResult = m_document->currentPostProcessedResultContext();
- GltfFileWriter gltfFileWriter(skeletonResult, m_document->resultRigBones(), m_document->resultRigWeights(), filename);
- gltfFileWriter.save();
- if (m_document->textureImage)
- m_document->textureImage->save(gltfFileWriter.textureFilenameInGltf());
- QFileInfo nameInfo(filename);
- QString borderFilename = nameInfo.path() + QDir::separator() + nameInfo.completeBaseName() + "-BORDER.png";
- if (m_document->textureBorderImage)
- m_document->textureBorderImage->save(borderFilename);
- QString ambientOcclusionFilename = nameInfo.path() + QDir::separator() + nameInfo.completeBaseName() + "-AMBIENT-OCCLUSION.png";
- if (m_document->textureAmbientOcclusionImage)
- m_document->textureAmbientOcclusionImage->save(ambientOcclusionFilename);
- QString colorFilename = nameInfo.path() + QDir::separator() + nameInfo.completeBaseName() + "-COLOR.png";
- if (m_document->textureColorImage)
- m_document->textureColorImage->save(colorFilename);
- QApplication::restoreOverrideCursor();
-}
-
-void SkeletonDocumentWindow::updateXlockButtonState()
-{
- if (m_document->xlocked)
- m_xlockButton->setStyleSheet("QPushButton {color: #252525}");
- else
- m_xlockButton->setStyleSheet("QPushButton {color: #fc6621}");
-}
-
-void SkeletonDocumentWindow::updateYlockButtonState()
-{
- if (m_document->ylocked)
- m_ylockButton->setStyleSheet("QPushButton {color: #252525}");
- else
- m_ylockButton->setStyleSheet("QPushButton {color: #2a5aac}");
-}
-
-void SkeletonDocumentWindow::updateZlockButtonState()
-{
- if (m_document->zlocked)
- m_zlockButton->setStyleSheet("QPushButton {color: #252525}");
- else
- m_zlockButton->setStyleSheet("QPushButton {color: #aaebc4}");
-}
-
-void SkeletonDocumentWindow::updateRadiusLockButtonState()
-{
- if (m_document->radiusLocked)
- m_radiusLockButton->setStyleSheet("QPushButton {color: #252525}");
- else
- m_radiusLockButton->setStyleSheet("QPushButton {color: " + Theme::white.name() + "}");
-}
-
-void SkeletonDocumentWindow::updateRigWeightRenderWidget()
-{
- MeshLoader *resultRigWeightMesh = m_document->takeResultRigWeightMesh();
- if (nullptr == resultRigWeightMesh) {
- m_rigWidget->rigWeightRenderWidget()->hide();
- } else {
- m_rigWidget->rigWeightRenderWidget()->updateMesh(resultRigWeightMesh);
- m_rigWidget->rigWeightRenderWidget()->show();
- m_rigWidget->rigWeightRenderWidget()->update();
- }
-}
-
-void SkeletonDocumentWindow::registerDialog(QWidget *widget)
-{
- m_dialogs.push_back(widget);
-}
-
-void SkeletonDocumentWindow::unregisterDialog(QWidget *widget)
-{
- m_dialogs.erase(std::remove(m_dialogs.begin(), m_dialogs.end(), widget), m_dialogs.end());
-}
diff --git a/src/documentwindow.cpp b/src/documentwindow.cpp
index f246e703..22e62ced 100644
--- a/src/documentwindow.cpp
+++ b/src/documentwindow.cpp
@@ -37,15 +37,15 @@
#include "fbxfile.h"
#include "shortcuts.h"
-int SkeletonDocumentWindow::m_modelRenderWidgetInitialX = 16;
-int SkeletonDocumentWindow::m_modelRenderWidgetInitialY = 16;
-int SkeletonDocumentWindow::m_modelRenderWidgetInitialSize = 128;
-int SkeletonDocumentWindow::m_skeletonRenderWidgetInitialX = SkeletonDocumentWindow::m_modelRenderWidgetInitialX + SkeletonDocumentWindow::m_modelRenderWidgetInitialSize + 16;
-int SkeletonDocumentWindow::m_skeletonRenderWidgetInitialY = SkeletonDocumentWindow::m_modelRenderWidgetInitialY;
-int SkeletonDocumentWindow::m_skeletonRenderWidgetInitialSize = SkeletonDocumentWindow::m_modelRenderWidgetInitialSize;
+int DocumentWindow::m_modelRenderWidgetInitialX = 16;
+int DocumentWindow::m_modelRenderWidgetInitialY = 16;
+int DocumentWindow::m_modelRenderWidgetInitialSize = 128;
+int DocumentWindow::m_skeletonRenderWidgetInitialX = DocumentWindow::m_modelRenderWidgetInitialX + DocumentWindow::m_modelRenderWidgetInitialSize + 16;
+int DocumentWindow::m_skeletonRenderWidgetInitialY = DocumentWindow::m_modelRenderWidgetInitialY;
+int DocumentWindow::m_skeletonRenderWidgetInitialSize = DocumentWindow::m_modelRenderWidgetInitialSize;
LogBrowser *g_logBrowser = nullptr;
-std::set g_documentWindows;
+std::set g_documentWindows;
QTextBrowser *g_acknowlegementsWidget = nullptr;
AboutWidget *g_aboutWidget = nullptr;
QTextBrowser *g_contributorsWidget = nullptr;
@@ -56,7 +56,7 @@ void outputMessage(QtMsgType type, const QMessageLogContext &context, const QStr
g_logBrowser->outputMessage(type, msg, context.file, context.line);
}
-void SkeletonDocumentWindow::showAcknowlegements()
+void DocumentWindow::showAcknowlegements()
{
if (!g_acknowlegementsWidget) {
g_acknowlegementsWidget = new QTextBrowser;
@@ -72,7 +72,7 @@ void SkeletonDocumentWindow::showAcknowlegements()
g_acknowlegementsWidget->raise();
}
-void SkeletonDocumentWindow::showContributors()
+void DocumentWindow::showContributors()
{
if (!g_contributorsWidget) {
g_contributorsWidget = new QTextBrowser;
@@ -89,7 +89,7 @@ void SkeletonDocumentWindow::showContributors()
g_contributorsWidget->raise();
}
-void SkeletonDocumentWindow::showAbout()
+void DocumentWindow::showAbout()
{
if (!g_aboutWidget) {
g_aboutWidget = new AboutWidget;
@@ -99,7 +99,7 @@ void SkeletonDocumentWindow::showAbout()
g_aboutWidget->raise();
}
-SkeletonDocumentWindow::SkeletonDocumentWindow() :
+DocumentWindow::DocumentWindow() :
m_document(nullptr),
m_firstShow(true),
m_documentSaved(true),
@@ -220,9 +220,9 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
m_modelRenderWidget = new ModelWidget(containerWidget);
m_modelRenderWidget->setAttribute(Qt::WA_TransparentForMouseEvents);
- m_modelRenderWidget->setMinimumSize(SkeletonDocumentWindow::m_modelRenderWidgetInitialSize, SkeletonDocumentWindow::m_modelRenderWidgetInitialSize);
+ m_modelRenderWidget->setMinimumSize(DocumentWindow::m_modelRenderWidgetInitialSize, DocumentWindow::m_modelRenderWidgetInitialSize);
m_modelRenderWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
- m_modelRenderWidget->move(SkeletonDocumentWindow::m_modelRenderWidgetInitialX, SkeletonDocumentWindow::m_modelRenderWidgetInitialY);
+ m_modelRenderWidget->move(DocumentWindow::m_modelRenderWidgetInitialX, DocumentWindow::m_modelRenderWidgetInitialY);
m_graphicsWidget->setModelWidget(m_modelRenderWidget);
containerWidget->setModelWidget(m_modelRenderWidget);
@@ -246,8 +246,8 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
materialDocker->setAllowedAreas(Qt::RightDockWidgetArea);
MaterialManageWidget *materialManageWidget = new MaterialManageWidget(m_document, materialDocker);
materialDocker->setWidget(materialManageWidget);
- connect(materialManageWidget, &MaterialManageWidget::registerDialog, this, &SkeletonDocumentWindow::registerDialog);
- connect(materialManageWidget, &MaterialManageWidget::unregisterDialog, this, &SkeletonDocumentWindow::unregisterDialog);
+ connect(materialManageWidget, &MaterialManageWidget::registerDialog, this, &DocumentWindow::registerDialog);
+ connect(materialManageWidget, &MaterialManageWidget::unregisterDialog, this, &DocumentWindow::unregisterDialog);
addDockWidget(Qt::RightDockWidgetArea, materialDocker);
connect(materialDocker, &QDockWidget::topLevelChanged, [=](bool topLevel) {
Q_UNUSED(topLevel);
@@ -269,8 +269,8 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
poseDocker->setAllowedAreas(Qt::RightDockWidgetArea);
PoseManageWidget *poseManageWidget = new PoseManageWidget(m_document, poseDocker);
poseDocker->setWidget(poseManageWidget);
- connect(poseManageWidget, &PoseManageWidget::registerDialog, this, &SkeletonDocumentWindow::registerDialog);
- connect(poseManageWidget, &PoseManageWidget::unregisterDialog, this, &SkeletonDocumentWindow::unregisterDialog);
+ connect(poseManageWidget, &PoseManageWidget::registerDialog, this, &DocumentWindow::registerDialog);
+ connect(poseManageWidget, &PoseManageWidget::unregisterDialog, this, &DocumentWindow::unregisterDialog);
addDockWidget(Qt::RightDockWidgetArea, poseDocker);
connect(poseDocker, &QDockWidget::topLevelChanged, [=](bool topLevel) {
Q_UNUSED(topLevel);
@@ -282,8 +282,8 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
motionDocker->setAllowedAreas(Qt::RightDockWidgetArea);
MotionManageWidget *motionManageWidget = new MotionManageWidget(m_document, motionDocker);
motionDocker->setWidget(motionManageWidget);
- connect(motionManageWidget, &MotionManageWidget::registerDialog, this, &SkeletonDocumentWindow::registerDialog);
- connect(motionManageWidget, &MotionManageWidget::unregisterDialog, this, &SkeletonDocumentWindow::unregisterDialog);
+ connect(motionManageWidget, &MotionManageWidget::registerDialog, this, &DocumentWindow::registerDialog);
+ connect(motionManageWidget, &MotionManageWidget::unregisterDialog, this, &DocumentWindow::unregisterDialog);
addDockWidget(Qt::RightDockWidgetArea, motionDocker);
tabifyDockWidget(partTreeDocker, materialDocker);
@@ -309,27 +309,27 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
m_fileMenu = menuBar()->addMenu(tr("File"));
m_newWindowAction = new QAction(tr("New Window"), this);
- connect(m_newWindowAction, &QAction::triggered, this, &SkeletonDocumentWindow::newWindow, Qt::QueuedConnection);
+ connect(m_newWindowAction, &QAction::triggered, this, &DocumentWindow::newWindow, Qt::QueuedConnection);
m_fileMenu->addAction(m_newWindowAction);
m_newDocumentAction = new QAction(tr("New"), this);
- connect(m_newDocumentAction, &QAction::triggered, this, &SkeletonDocumentWindow::newDocument);
+ connect(m_newDocumentAction, &QAction::triggered, this, &DocumentWindow::newDocument);
m_fileMenu->addAction(m_newDocumentAction);
m_openAction = new QAction(tr("Open..."), this);
- connect(m_openAction, &QAction::triggered, this, &SkeletonDocumentWindow::open, Qt::QueuedConnection);
+ connect(m_openAction, &QAction::triggered, this, &DocumentWindow::open, Qt::QueuedConnection);
m_fileMenu->addAction(m_openAction);
m_saveAction = new QAction(tr("Save"), this);
- connect(m_saveAction, &QAction::triggered, this, &SkeletonDocumentWindow::save, Qt::QueuedConnection);
+ connect(m_saveAction, &QAction::triggered, this, &DocumentWindow::save, Qt::QueuedConnection);
m_fileMenu->addAction(m_saveAction);
m_saveAsAction = new QAction(tr("Save As..."), this);
- connect(m_saveAsAction, &QAction::triggered, this, &SkeletonDocumentWindow::saveAs, Qt::QueuedConnection);
+ connect(m_saveAsAction, &QAction::triggered, this, &DocumentWindow::saveAs, Qt::QueuedConnection);
m_fileMenu->addAction(m_saveAsAction);
m_saveAllAction = new QAction(tr("Save All"), this);
- connect(m_saveAllAction, &QAction::triggered, this, &SkeletonDocumentWindow::saveAll, Qt::QueuedConnection);
+ connect(m_saveAllAction, &QAction::triggered, this, &DocumentWindow::saveAll, Qt::QueuedConnection);
m_fileMenu->addAction(m_saveAllAction);
m_fileMenu->addSeparator();
@@ -337,11 +337,11 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
//m_exportMenu = m_fileMenu->addMenu(tr("Export"));
m_exportAction = new QAction(tr("Export..."), this);
- connect(m_exportAction, &QAction::triggered, this, &SkeletonDocumentWindow::showExportPreview, Qt::QueuedConnection);
+ connect(m_exportAction, &QAction::triggered, this, &DocumentWindow::showExportPreview, Qt::QueuedConnection);
m_fileMenu->addAction(m_exportAction);
m_exportAsObjAction = new QAction(tr("Export as OBJ..."), this);
- connect(m_exportAsObjAction, &QAction::triggered, this, &SkeletonDocumentWindow::exportObjResult, Qt::QueuedConnection);
+ connect(m_exportAsObjAction, &QAction::triggered, this, &DocumentWindow::exportObjResult, Qt::QueuedConnection);
m_fileMenu->addAction(m_exportAsObjAction);
//m_exportRenderedAsImageAction = new QAction(tr("Export as PNG..."), this);
@@ -355,7 +355,7 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
m_fileMenu->addSeparator();
m_changeTurnaroundAction = new QAction(tr("Change Reference Sheet..."), this);
- connect(m_changeTurnaroundAction, &QAction::triggered, this, &SkeletonDocumentWindow::changeTurnaround, Qt::QueuedConnection);
+ connect(m_changeTurnaroundAction, &QAction::triggered, this, &DocumentWindow::changeTurnaround, Qt::QueuedConnection);
m_fileMenu->addAction(m_changeTurnaroundAction);
m_fileMenu->addSeparator();
@@ -530,7 +530,7 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
m_resetModelWidgetPosAction = new QAction(tr("Show Model"), this);
connect(m_resetModelWidgetPosAction, &QAction::triggered, [=]() {
if (!isModelSitInVisibleArea(m_modelRenderWidget)) {
- m_modelRenderWidget->move(SkeletonDocumentWindow::m_modelRenderWidgetInitialX, SkeletonDocumentWindow::m_modelRenderWidgetInitialY);
+ m_modelRenderWidget->move(DocumentWindow::m_modelRenderWidgetInitialX, DocumentWindow::m_modelRenderWidgetInitialY);
}
});
m_viewMenu->addAction(m_resetModelWidgetPosAction);
@@ -610,7 +610,7 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
m_windowMenu->addAction(m_showDebugDialogAction);
m_showAdvanceSettingAction = new QAction(tr("Advance"), this);
- connect(m_showAdvanceSettingAction, &QAction::triggered, this, &SkeletonDocumentWindow::showAdvanceSetting);
+ connect(m_showAdvanceSettingAction, &QAction::triggered, this, &DocumentWindow::showAdvanceSetting);
#ifndef NDEBUG
m_windowMenu->addAction(m_showAdvanceSettingAction);
#endif
@@ -618,33 +618,33 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
m_helpMenu = menuBar()->addMenu(tr("Help"));
m_viewSourceAction = new QAction(tr("Fork me on GitHub"), this);
- connect(m_viewSourceAction, &QAction::triggered, this, &SkeletonDocumentWindow::viewSource);
+ connect(m_viewSourceAction, &QAction::triggered, this, &DocumentWindow::viewSource);
m_helpMenu->addAction(m_viewSourceAction);
m_helpMenu->addSeparator();
m_seeReferenceGuideAction = new QAction(tr("Reference Guide"), this);
- connect(m_seeReferenceGuideAction, &QAction::triggered, this, &SkeletonDocumentWindow::seeReferenceGuide);
+ connect(m_seeReferenceGuideAction, &QAction::triggered, this, &DocumentWindow::seeReferenceGuide);
m_helpMenu->addAction(m_seeReferenceGuideAction);
m_helpMenu->addSeparator();
m_aboutAction = new QAction(tr("About"), this);
- connect(m_aboutAction, &QAction::triggered, this, &SkeletonDocumentWindow::about);
+ connect(m_aboutAction, &QAction::triggered, this, &DocumentWindow::about);
m_helpMenu->addAction(m_aboutAction);
m_reportIssuesAction = new QAction(tr("Report Issues"), this);
- connect(m_reportIssuesAction, &QAction::triggered, this, &SkeletonDocumentWindow::reportIssues);
+ connect(m_reportIssuesAction, &QAction::triggered, this, &DocumentWindow::reportIssues);
m_helpMenu->addAction(m_reportIssuesAction);
m_helpMenu->addSeparator();
m_seeContributorsAction = new QAction(tr("Contributors"), this);
- connect(m_seeContributorsAction, &QAction::triggered, this, &SkeletonDocumentWindow::seeContributors);
+ connect(m_seeContributorsAction, &QAction::triggered, this, &DocumentWindow::seeContributors);
m_helpMenu->addAction(m_seeContributorsAction);
m_seeAcknowlegementsAction = new QAction(tr("Acknowlegements"), this);
- connect(m_seeAcknowlegementsAction, &QAction::triggered, this, &SkeletonDocumentWindow::seeAcknowlegements);
+ connect(m_seeAcknowlegementsAction, &QAction::triggered, this, &DocumentWindow::seeAcknowlegements);
m_helpMenu->addAction(m_seeAcknowlegementsAction);
connect(containerWidget, &GraphicsContainerWidget::containerSizeChanged,
@@ -737,9 +737,9 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
connect(graphicsWidget, &SkeletonGraphicsWidget::enableAllPositionRelatedLocks, m_document, &Document::enableAllPositionRelatedLocks);
connect(graphicsWidget, &SkeletonGraphicsWidget::disableAllPositionRelatedLocks, m_document, &Document::disableAllPositionRelatedLocks);
- connect(graphicsWidget, &SkeletonGraphicsWidget::changeTurnaround, this, &SkeletonDocumentWindow::changeTurnaround);
- connect(graphicsWidget, &SkeletonGraphicsWidget::save, this, &SkeletonDocumentWindow::save);
- connect(graphicsWidget, &SkeletonGraphicsWidget::open, this, &SkeletonDocumentWindow::open);
+ connect(graphicsWidget, &SkeletonGraphicsWidget::changeTurnaround, this, &DocumentWindow::changeTurnaround);
+ connect(graphicsWidget, &SkeletonGraphicsWidget::save, this, &DocumentWindow::save);
+ connect(graphicsWidget, &SkeletonGraphicsWidget::open, this, &DocumentWindow::open);
connect(m_document, &Document::nodeAdded, graphicsWidget, &SkeletonGraphicsWidget::nodeAdded);
connect(m_document, &Document::nodeRemoved, graphicsWidget, &SkeletonGraphicsWidget::nodeRemoved);
@@ -848,25 +848,25 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
//m_skeletonRenderWidget->setCursor(graphicsWidget->cursor());
});
- connect(m_document, &Document::skeletonChanged, this, &SkeletonDocumentWindow::documentChanged);
- connect(m_document, &Document::turnaroundChanged, this, &SkeletonDocumentWindow::documentChanged);
- connect(m_document, &Document::optionsChanged, this, &SkeletonDocumentWindow::documentChanged);
- connect(m_document, &Document::rigChanged, this, &SkeletonDocumentWindow::documentChanged);
+ connect(m_document, &Document::skeletonChanged, this, &DocumentWindow::documentChanged);
+ connect(m_document, &Document::turnaroundChanged, this, &DocumentWindow::documentChanged);
+ connect(m_document, &Document::optionsChanged, this, &DocumentWindow::documentChanged);
+ connect(m_document, &Document::rigChanged, this, &DocumentWindow::documentChanged);
connect(m_modelRenderWidget, &ModelWidget::customContextMenuRequested, [=](const QPoint &pos) {
graphicsWidget->showContextMenu(graphicsWidget->mapFromGlobal(m_modelRenderWidget->mapToGlobal(pos)));
});
- connect(m_document, &Document::xlockStateChanged, this, &SkeletonDocumentWindow::updateXlockButtonState);
- connect(m_document, &Document::ylockStateChanged, this, &SkeletonDocumentWindow::updateYlockButtonState);
- connect(m_document, &Document::zlockStateChanged, this, &SkeletonDocumentWindow::updateZlockButtonState);
- connect(m_document, &Document::radiusLockStateChanged, this, &SkeletonDocumentWindow::updateRadiusLockButtonState);
+ connect(m_document, &Document::xlockStateChanged, this, &DocumentWindow::updateXlockButtonState);
+ connect(m_document, &Document::ylockStateChanged, this, &DocumentWindow::updateYlockButtonState);
+ connect(m_document, &Document::zlockStateChanged, this, &DocumentWindow::updateZlockButtonState);
+ connect(m_document, &Document::radiusLockStateChanged, this, &DocumentWindow::updateRadiusLockButtonState);
connect(m_rigWidget, &RigWidget::setRigType, m_document, &Document::setRigType);
connect(m_document, &Document::rigTypeChanged, m_rigWidget, &RigWidget::rigTypeChanged);
connect(m_document, &Document::resultRigChanged, m_rigWidget, &RigWidget::updateResultInfo);
- connect(m_document, &Document::resultRigChanged, this, &SkeletonDocumentWindow::updateRigWeightRenderWidget);
+ connect(m_document, &Document::resultRigChanged, this, &DocumentWindow::updateRigWeightRenderWidget);
//connect(m_document, &SkeletonDocument::resultRigChanged, tetrapodPoseEditWidget, &TetrapodPoseEditWidget::updatePreview);
@@ -893,7 +893,7 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
initShortCuts(this, m_graphicsWidget);
- connect(this, &SkeletonDocumentWindow::initialized, m_document, &Document::uiReady);
+ connect(this, &DocumentWindow::initialized, m_document, &Document::uiReady);
QTimer *timer = new QTimer(this);
timer->setInterval(250);
@@ -906,15 +906,15 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
timer->start();
}
-SkeletonDocumentWindow *SkeletonDocumentWindow::createDocumentWindow()
+DocumentWindow *DocumentWindow::createDocumentWindow()
{
- SkeletonDocumentWindow *documentWindow = new SkeletonDocumentWindow();
+ DocumentWindow *documentWindow = new DocumentWindow();
documentWindow->setAttribute(Qt::WA_DeleteOnClose);
documentWindow->showMaximized();
return documentWindow;
}
-void SkeletonDocumentWindow::closeEvent(QCloseEvent *event)
+void DocumentWindow::closeEvent(QCloseEvent *event)
{
if (m_documentSaved) {
event->accept();
@@ -931,21 +931,21 @@ void SkeletonDocumentWindow::closeEvent(QCloseEvent *event)
event->ignore();
}
-void SkeletonDocumentWindow::setCurrentFilename(const QString &filename)
+void DocumentWindow::setCurrentFilename(const QString &filename)
{
m_currentFilename = filename;
m_documentSaved = true;
updateTitle();
}
-void SkeletonDocumentWindow::updateTitle()
+void DocumentWindow::updateTitle()
{
QString appName = APP_NAME;
QString appVer = APP_HUMAN_VER;
setWindowTitle(QString("%1 %2 %3%4").arg(appName).arg(appVer).arg(m_currentFilename).arg(m_documentSaved ? "" : "*"));
}
-void SkeletonDocumentWindow::documentChanged()
+void DocumentWindow::documentChanged()
{
if (m_documentSaved) {
m_documentSaved = false;
@@ -953,12 +953,12 @@ void SkeletonDocumentWindow::documentChanged()
}
}
-void SkeletonDocumentWindow::newWindow()
+void DocumentWindow::newWindow()
{
- SkeletonDocumentWindow::createDocumentWindow();
+ DocumentWindow::createDocumentWindow();
}
-void SkeletonDocumentWindow::newDocument()
+void DocumentWindow::newDocument()
{
if (!m_documentSaved) {
QMessageBox::StandardButton answer = QMessageBox::question(this,
@@ -973,7 +973,7 @@ void SkeletonDocumentWindow::newDocument()
m_document->saveSnapshot();
}
-void SkeletonDocumentWindow::saveAs()
+void DocumentWindow::saveAs()
{
QString filename = QFileDialog::getSaveFileName(this, QString(), QString(),
tr("Dust3D Document (*.ds3)"));
@@ -983,50 +983,50 @@ void SkeletonDocumentWindow::saveAs()
saveTo(filename);
}
-void SkeletonDocumentWindow::saveAll()
+void DocumentWindow::saveAll()
{
for (auto &window: g_documentWindows) {
window->save();
}
}
-void SkeletonDocumentWindow::viewSource()
+void DocumentWindow::viewSource()
{
QString url = APP_REPOSITORY_URL;
qDebug() << "viewSource:" << url;
QDesktopServices::openUrl(QUrl(url));
}
-void SkeletonDocumentWindow::about()
+void DocumentWindow::about()
{
- SkeletonDocumentWindow::showAbout();
+ DocumentWindow::showAbout();
}
-void SkeletonDocumentWindow::reportIssues()
+void DocumentWindow::reportIssues()
{
QString url = APP_ISSUES_URL;
qDebug() << "reportIssues:" << url;
QDesktopServices::openUrl(QUrl(url));
}
-void SkeletonDocumentWindow::seeReferenceGuide()
+void DocumentWindow::seeReferenceGuide()
{
QString url = APP_REFERENCE_GUIDE_URL;
qDebug() << "referenceGuide:" << url;
QDesktopServices::openUrl(QUrl(url));
}
-void SkeletonDocumentWindow::seeAcknowlegements()
+void DocumentWindow::seeAcknowlegements()
{
- SkeletonDocumentWindow::showAcknowlegements();
+ DocumentWindow::showAcknowlegements();
}
-void SkeletonDocumentWindow::seeContributors()
+void DocumentWindow::seeContributors()
{
- SkeletonDocumentWindow::showContributors();
+ DocumentWindow::showContributors();
}
-void SkeletonDocumentWindow::initLockButton(QPushButton *button)
+void DocumentWindow::initLockButton(QPushButton *button)
{
QFont font;
font.setWeight(QFont::Light);
@@ -1039,12 +1039,12 @@ void SkeletonDocumentWindow::initLockButton(QPushButton *button)
button->setFocusPolicy(Qt::NoFocus);
}
-SkeletonDocumentWindow::~SkeletonDocumentWindow()
+DocumentWindow::~DocumentWindow()
{
g_documentWindows.erase(this);
}
-void SkeletonDocumentWindow::showEvent(QShowEvent *event)
+void DocumentWindow::showEvent(QShowEvent *event)
{
QMainWindow::showEvent(event);
if (m_firstShow) {
@@ -1056,12 +1056,12 @@ void SkeletonDocumentWindow::showEvent(QShowEvent *event)
}
}
-void SkeletonDocumentWindow::mousePressEvent(QMouseEvent *event)
+void DocumentWindow::mousePressEvent(QMouseEvent *event)
{
QMainWindow::mousePressEvent(event);
}
-void SkeletonDocumentWindow::changeTurnaround()
+void DocumentWindow::changeTurnaround()
{
QString fileName = QFileDialog::getOpenFileName(this, QString(), QString(),
tr("Image Files (*.png *.jpg *.bmp)")).trimmed();
@@ -1073,12 +1073,12 @@ void SkeletonDocumentWindow::changeTurnaround()
m_document->updateTurnaround(image);
}
-void SkeletonDocumentWindow::save()
+void DocumentWindow::save()
{
saveTo(m_currentFilename);
}
-void SkeletonDocumentWindow::saveTo(const QString &saveAsFilename)
+void DocumentWindow::saveTo(const QString &saveAsFilename)
{
QString filename = saveAsFilename;
@@ -1111,6 +1111,7 @@ void SkeletonDocumentWindow::saveTo(const QString &saveAsFilename)
ds3Writer.add("canvas.png", "asset", &imageByteArray);
}
+ std::set imageIds;
for (auto &material: snapshot.materials) {
for (auto &layer: material.second) {
for (auto &mapItem: layer.second) {
@@ -1118,18 +1119,30 @@ void SkeletonDocumentWindow::saveTo(const QString &saveAsFilename)
if (findImageIdString == mapItem.end())
continue;
QUuid imageId = QUuid(findImageIdString->second);
- const QImage *image = ImageForever::get(imageId);
- if (nullptr == image)
- continue;
- QByteArray imageByteArray;
- QBuffer pngBuffer(&imageByteArray);
- pngBuffer.open(QIODevice::WriteOnly);
- image->save(&pngBuffer, "PNG");
- if (imageByteArray.size() > 0)
- ds3Writer.add("images/" + imageId.toString() + ".png", "asset", &imageByteArray);
+ imageIds.insert(imageId);
}
}
}
+
+ for (auto &pose: snapshot.poses) {
+ auto findCanvasImageId = pose.first.find("canvasImageId");
+ if (findCanvasImageId != pose.first.end()) {
+ QUuid imageId = QUuid(findCanvasImageId->second);
+ imageIds.insert(imageId);
+ }
+ }
+
+ for (const auto &imageId: imageIds) {
+ const QImage *image = ImageForever::get(imageId);
+ if (nullptr == image)
+ continue;
+ QByteArray imageByteArray;
+ QBuffer pngBuffer(&imageByteArray);
+ pngBuffer.open(QIODevice::WriteOnly);
+ image->save(&pngBuffer, "PNG");
+ if (imageByteArray.size() > 0)
+ ds3Writer.add("images/" + imageId.toString() + ".png", "asset", &imageByteArray);
+ }
if (ds3Writer.save(filename)) {
setCurrentFilename(filename);
@@ -1138,7 +1151,7 @@ void SkeletonDocumentWindow::saveTo(const QString &saveAsFilename)
QApplication::restoreOverrideCursor();
}
-void SkeletonDocumentWindow::open()
+void DocumentWindow::open()
{
if (!m_documentSaved) {
QMessageBox::StandardButton answer = QMessageBox::question(this,
@@ -1202,7 +1215,7 @@ void SkeletonDocumentWindow::open()
setCurrentFilename(filename);
}
-void SkeletonDocumentWindow::showAdvanceSetting()
+void DocumentWindow::showAdvanceSetting()
{
if (nullptr == m_advanceSettingWidget) {
m_advanceSettingWidget = new AdvanceSettingWidget(m_document, this);
@@ -1211,7 +1224,7 @@ void SkeletonDocumentWindow::showAdvanceSetting()
m_advanceSettingWidget->raise();
}
-void SkeletonDocumentWindow::exportObjResult()
+void DocumentWindow::exportObjResult()
{
QString filename = QFileDialog::getSaveFileName(this, QString(), QString(),
tr("Wavefront (*.obj)"));
@@ -1227,13 +1240,13 @@ void SkeletonDocumentWindow::exportObjResult()
QApplication::restoreOverrideCursor();
}
-void SkeletonDocumentWindow::showExportPreview()
+void DocumentWindow::showExportPreview()
{
if (nullptr == m_exportPreviewWidget) {
m_exportPreviewWidget = new ExportPreviewWidget(m_document, this);
connect(m_exportPreviewWidget, &ExportPreviewWidget::regenerate, m_document, &Document::regenerateMesh);
- connect(m_exportPreviewWidget, &ExportPreviewWidget::saveAsGlb, this, &SkeletonDocumentWindow::exportGlbResult);
- connect(m_exportPreviewWidget, &ExportPreviewWidget::saveAsFbx, this, &SkeletonDocumentWindow::exportFbxResult);
+ connect(m_exportPreviewWidget, &ExportPreviewWidget::saveAsGlb, this, &DocumentWindow::exportGlbResult);
+ connect(m_exportPreviewWidget, &ExportPreviewWidget::saveAsFbx, this, &DocumentWindow::exportFbxResult);
connect(m_document, &Document::resultMeshChanged, m_exportPreviewWidget, &ExportPreviewWidget::checkSpinner);
connect(m_document, &Document::exportReady, m_exportPreviewWidget, &ExportPreviewWidget::checkSpinner);
connect(m_document, &Document::resultTextureChanged, m_exportPreviewWidget, &ExportPreviewWidget::updateTexturePreview);
@@ -1244,7 +1257,7 @@ void SkeletonDocumentWindow::showExportPreview()
m_exportPreviewWidget->raise();
}
-void SkeletonDocumentWindow::exportFbxResult()
+void DocumentWindow::exportFbxResult()
{
QString filename = QFileDialog::getSaveFileName(this, QString(), QString(),
tr("Autodesk FBX (.fbx)"));
@@ -1270,7 +1283,7 @@ void SkeletonDocumentWindow::exportFbxResult()
QApplication::restoreOverrideCursor();
}
-void SkeletonDocumentWindow::exportGlbResult()
+void DocumentWindow::exportGlbResult()
{
QString filename = QFileDialog::getSaveFileName(this, QString(), QString(),
tr("glTF Binary Format (.glb)"));
@@ -1296,7 +1309,7 @@ void SkeletonDocumentWindow::exportGlbResult()
QApplication::restoreOverrideCursor();
}
-void SkeletonDocumentWindow::updateXlockButtonState()
+void DocumentWindow::updateXlockButtonState()
{
if (m_document->xlocked)
m_xlockButton->setStyleSheet("QPushButton {color: #252525}");
@@ -1304,7 +1317,7 @@ void SkeletonDocumentWindow::updateXlockButtonState()
m_xlockButton->setStyleSheet("QPushButton {color: #fc6621}");
}
-void SkeletonDocumentWindow::updateYlockButtonState()
+void DocumentWindow::updateYlockButtonState()
{
if (m_document->ylocked)
m_ylockButton->setStyleSheet("QPushButton {color: #252525}");
@@ -1312,7 +1325,7 @@ void SkeletonDocumentWindow::updateYlockButtonState()
m_ylockButton->setStyleSheet("QPushButton {color: #2a5aac}");
}
-void SkeletonDocumentWindow::updateZlockButtonState()
+void DocumentWindow::updateZlockButtonState()
{
if (m_document->zlocked)
m_zlockButton->setStyleSheet("QPushButton {color: #252525}");
@@ -1320,7 +1333,7 @@ void SkeletonDocumentWindow::updateZlockButtonState()
m_zlockButton->setStyleSheet("QPushButton {color: #aaebc4}");
}
-void SkeletonDocumentWindow::updateRadiusLockButtonState()
+void DocumentWindow::updateRadiusLockButtonState()
{
if (m_document->radiusLocked)
m_radiusLockButton->setStyleSheet("QPushButton {color: #252525}");
@@ -1328,7 +1341,7 @@ void SkeletonDocumentWindow::updateRadiusLockButtonState()
m_radiusLockButton->setStyleSheet("QPushButton {color: " + Theme::white.name() + "}");
}
-void SkeletonDocumentWindow::updateRigWeightRenderWidget()
+void DocumentWindow::updateRigWeightRenderWidget()
{
MeshLoader *resultRigWeightMesh = m_document->takeResultRigWeightMesh();
if (nullptr == resultRigWeightMesh) {
@@ -1340,12 +1353,12 @@ void SkeletonDocumentWindow::updateRigWeightRenderWidget()
}
}
-void SkeletonDocumentWindow::registerDialog(QWidget *widget)
+void DocumentWindow::registerDialog(QWidget *widget)
{
m_dialogs.push_back(widget);
}
-void SkeletonDocumentWindow::unregisterDialog(QWidget *widget)
+void DocumentWindow::unregisterDialog(QWidget *widget)
{
m_dialogs.erase(std::remove(m_dialogs.begin(), m_dialogs.end(), widget), m_dialogs.end());
}
diff --git a/src/documentwindow.h b/src/documentwindow.h
index b9310aae..8b0ddc42 100644
--- a/src/documentwindow.h
+++ b/src/documentwindow.h
@@ -17,15 +17,15 @@
class SkeletonGraphicsWidget;
-class SkeletonDocumentWindow : public QMainWindow
+class DocumentWindow : public QMainWindow
{
Q_OBJECT
signals:
void initialized();
public:
- SkeletonDocumentWindow();
- ~SkeletonDocumentWindow();
- static SkeletonDocumentWindow *createDocumentWindow();
+ DocumentWindow();
+ ~DocumentWindow();
+ static DocumentWindow *createDocumentWindow();
static void showAcknowlegements();
static void showContributors();
static void showAbout();
diff --git a/src/genericposer.cpp b/src/genericposer.cpp
index 2942136f..7ed178c0 100644
--- a/src/genericposer.cpp
+++ b/src/genericposer.cpp
@@ -8,50 +8,7 @@ GenericPoser::GenericPoser(const std::vector &bones) :
void GenericPoser::commit()
{
- for (const auto &item: parameters()) {
- int boneIndex = findBoneIndex(item.first);
- if (-1 == boneIndex) {
- continue;
- }
- auto findPitchResult = item.second.find("pitch");
- auto findYawResult = item.second.find("yaw");
- auto findRollResult = item.second.find("roll");
- if (findPitchResult != item.second.end() ||
- findYawResult != item.second.end() ||
- findRollResult != item.second.end()) {
- float yawAngle = valueOfKeyInMapOrEmpty(item.second, "yaw").toFloat();
- if (item.first.startsWith("Left")) {
- yawAngle = -yawAngle;
- }
- QQuaternion rotation = eulerAnglesToQuaternion(valueOfKeyInMapOrEmpty(item.second, "pitch").toFloat(),
- yawAngle,
- valueOfKeyInMapOrEmpty(item.second, "roll").toFloat());
- m_jointNodeTree.updateRotation(boneIndex, rotation);
- continue;
- }
- auto findIntersectionResult = item.second.find("intersection");
- if (findIntersectionResult != item.second.end()) {
- float intersectionAngle = valueOfKeyInMapOrEmpty(item.second, "intersection").toFloat();
- const RiggerBone &bone = bones()[boneIndex];
- QVector3D axis = bone.baseNormal;
- QQuaternion rotation = QQuaternion::fromAxisAndAngle(axis, intersectionAngle);
- m_jointNodeTree.updateRotation(boneIndex, rotation);
- continue;
- }
- auto findXResult = item.second.find("x");
- auto findYResult = item.second.find("y");
- auto findZResult = item.second.find("z");
- if (findXResult != item.second.end() ||
- findYResult != item.second.end() ||
- findZResult != item.second.end()) {
- float x = valueOfKeyInMapOrEmpty(item.second, "x").toFloat();
- float y = valueOfKeyInMapOrEmpty(item.second, "y").toFloat();
- float z = valueOfKeyInMapOrEmpty(item.second, "z").toFloat();
- QVector3D translation = {x, y, z};
- m_jointNodeTree.addTranslation(boneIndex, translation);
- continue;
- }
- }
+ // TODO:
Poser::commit();
}
diff --git a/src/genericrigger.cpp b/src/genericrigger.cpp
index 4bff8e80..e1a54d27 100644
--- a/src/genericrigger.cpp
+++ b/src/genericrigger.cpp
@@ -302,7 +302,7 @@ bool GenericRigger::rig()
m_resultBones.push_back(RiggerBone());
RiggerBone &bodyBone = m_resultBones.back();
bodyBone.index = m_resultBones.size() - 1;
- bodyBone.name = "Body";
+ bodyBone.name = Rigger::rootBoneName;
bodyBone.headPosition = QVector3D(0, 0, 0);
bodyBone.hasButton = true;
bodyBone.button = {spineNodes.size(), 0};
@@ -378,8 +378,8 @@ bool GenericRigger::rig()
//qDebug() << spineBone.name << "head:" << spineBone.headPosition << "tail:" << spineBone.tailPosition;
if (1 == spineGenerateOrder) {
- m_resultBones[boneIndexMap["Body"]].tailPosition = spineBone.headPosition;
- m_resultBones[boneIndexMap["Body"]].children.push_back(spineBone.index);
+ m_resultBones[boneIndexMap[Rigger::rootBoneName]].tailPosition = spineBone.headPosition;
+ m_resultBones[boneIndexMap[Rigger::rootBoneName]].children.push_back(spineBone.index);
} else {
m_resultBones[boneIndexMap["Spine" + QString::number(spineGenerateOrder - 1)]].tailPosition = spineBone.headPosition;
m_resultBones[boneIndexMap["Spine" + QString::number(spineGenerateOrder - 1)]].children.push_back(spineBone.index);
@@ -396,7 +396,7 @@ bool GenericRigger::rig()
ribBone.headPosition = spineBoneHeadPosition;
boneIndexMap[ribBone.name] = ribBone.index;
if (1 == spineGenerateOrder) {
- m_resultBones[boneIndexMap["Body"]].children.push_back(ribBone.index);
+ m_resultBones[boneIndexMap[Rigger::rootBoneName]].children.push_back(ribBone.index);
} else {
m_resultBones[boneIndexMap["Spine" + QString::number(spineGenerateOrder)]].children.push_back(ribBone.index);
}
diff --git a/src/main.cpp b/src/main.cpp
index a3172576..4dc275c7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -46,7 +46,7 @@ int main(int argc, char ** argv)
font.setBold(false);
QApplication::setFont(font);
- SkeletonDocumentWindow::createDocumentWindow();
+ DocumentWindow::createDocumentWindow();
return app.exec();
}
diff --git a/src/motionmanagewidget.cpp b/src/motionmanagewidget.cpp
index cff342ec..3627f411 100644
--- a/src/motionmanagewidget.cpp
+++ b/src/motionmanagewidget.cpp
@@ -22,14 +22,21 @@ MotionManageWidget::MotionManageWidget(const Document *document, QWidget *parent
connect(m_motionListWidget, &MotionListWidget::modifyMotion, this, &MotionManageWidget::showMotionDialog);
InfoLabel *infoLabel = new InfoLabel;
- infoLabel->setText(tr("Missing Rig"));
infoLabel->show();
auto refreshInfoLabel = [=]() {
if (m_document->currentRigSucceed()) {
- infoLabel->hide();
- addMotionButton->show();
+ if (m_document->rigType == RigType::Tetrapod) {
+ infoLabel->setText("");
+ infoLabel->hide();
+ addMotionButton->show();
+ } else {
+ infoLabel->setText(tr("Motion editor doesn't support this rig type yet: ") + RigTypeToDispName(m_document->rigType));
+ infoLabel->show();
+ addMotionButton->hide();
+ }
} else {
+ infoLabel->setText(tr("Missing Rig"));
infoLabel->show();
addMotionButton->hide();
}
diff --git a/src/posedocument.cpp b/src/posedocument.cpp
new file mode 100644
index 00000000..f3bc2ee5
--- /dev/null
+++ b/src/posedocument.cpp
@@ -0,0 +1,401 @@
+#include
+#include "posedocument.h"
+#include "rigger.h"
+#include "util.h"
+
+constexpr float PoseDocument::m_nodeRadius = 0.01;
+constexpr float PoseDocument::m_groundPlaneHalfThickness = m_nodeRadius / 4;
+
+bool PoseDocument::hasPastableNodesInClipboard() const
+{
+ return false;
+}
+
+bool PoseDocument::originSettled() const
+{
+ return false;
+}
+
+bool PoseDocument::isNodeEditable(QUuid nodeId) const
+{
+ return true;
+}
+
+bool PoseDocument::isEdgeEditable(QUuid edgeId) const
+{
+ return true;
+}
+
+void PoseDocument::copyNodes(std::set nodeIdSet) const
+{
+ // TODO:
+}
+
+void PoseDocument::saveHistoryItem()
+{
+ PoseHistoryItem item;
+ toParameters(item.parameters);
+ m_undoItems.push_back(item);
+}
+
+bool PoseDocument::undoable() const
+{
+ return m_undoItems.size() >= 2;
+}
+
+bool PoseDocument::redoable() const
+{
+ return !m_redoItems.empty();
+}
+
+void PoseDocument::undo()
+{
+ if (!undoable())
+ return;
+ m_redoItems.push_back(m_undoItems.back());
+ m_undoItems.pop_back();
+ const auto &item = m_undoItems.back();
+ fromParameters(&m_riggerBones, item.parameters);
+}
+
+void PoseDocument::redo()
+{
+ if (m_redoItems.empty())
+ return;
+ m_undoItems.push_back(m_redoItems.back());
+ const auto &item = m_redoItems.back();
+ fromParameters(&m_riggerBones, item.parameters);
+ m_redoItems.pop_back();
+}
+
+void PoseDocument::paste()
+{
+}
+
+void PoseDocument::updateTurnaround(const QImage &image)
+{
+ turnaround = image;
+ emit turnaroundChanged();
+}
+
+void PoseDocument::reset()
+{
+ nodeMap.clear();
+ edgeMap.clear();
+ partMap.clear();
+ m_boneNameToIdsMap.clear();
+ m_bonesPartId = QUuid();
+ m_groundPartId = QUuid();
+ m_groundEdgeId = QUuid();
+ emit cleanup();
+ emit parametersChanged();
+}
+
+void PoseDocument::fromParameters(const std::vector *rigBones,
+ const std::map> ¶meters)
+{
+ if (nullptr == rigBones || rigBones->empty()) {
+ m_riggerBones.clear();
+ return;
+ }
+
+ if (&m_riggerBones != rigBones)
+ m_riggerBones = *rigBones;
+
+ QVector3D rootTranslation;
+ std::vector bones = *rigBones;
+ for (auto &bone: bones) {
+ const auto findParameterResult = parameters.find(bone.name);
+ if (findParameterResult == parameters.end())
+ continue;
+ const auto &map = findParameterResult->second;
+ {
+ auto findXResult = map.find("fromX");
+ auto findYResult = map.find("fromY");
+ auto findZResult = map.find("fromZ");
+ if (findXResult != map.end() ||
+ findYResult != map.end() ||
+ findZResult != map.end()) {
+ bone.headPosition = {
+ valueOfKeyInMapOrEmpty(map, "fromX").toFloat(),
+ valueOfKeyInMapOrEmpty(map, "fromY").toFloat(),
+ valueOfKeyInMapOrEmpty(map, "fromZ").toFloat()
+ };
+ }
+ }
+ {
+ auto findXResult = map.find("toX");
+ auto findYResult = map.find("toY");
+ auto findZResult = map.find("toZ");
+ if (findXResult != map.end() ||
+ findYResult != map.end() ||
+ findZResult != map.end()) {
+ bone.tailPosition = {
+ valueOfKeyInMapOrEmpty(map, "toX").toFloat(),
+ valueOfKeyInMapOrEmpty(map, "toY").toFloat(),
+ valueOfKeyInMapOrEmpty(map, "toZ").toFloat()
+ };
+ }
+ }
+ }
+
+ const auto findRoot = parameters.find(Rigger::rootBoneName);
+ if (findRoot != parameters.end()) {
+ const auto &map = findRoot->second;
+ {
+ auto findXResult = map.find("translateX");
+ auto findYResult = map.find("translateY");
+ auto findZResult = map.find("translateZ");
+ if (findXResult != map.end() ||
+ findYResult != map.end() ||
+ findZResult != map.end()) {
+ rootTranslation = {
+ valueOfKeyInMapOrEmpty(map, "translateX").toFloat(),
+ valueOfKeyInMapOrEmpty(map, "translateY").toFloat(),
+ valueOfKeyInMapOrEmpty(map, "translateZ").toFloat()
+ };
+ }
+ }
+ }
+
+ updateRigBones(&bones, rootTranslation);
+}
+
+void PoseDocument::updateRigBones(const std::vector *rigBones, const QVector3D &rootTranslation)
+{
+ reset();
+
+ if (nullptr == rigBones || rigBones->empty()) {
+ return;
+ }
+
+ std::set newAddedNodeIds;
+ std::set newAddedEdgeIds;
+
+ m_bonesPartId = QUuid::createUuid();
+ auto &bonesPart = partMap[m_bonesPartId];
+ bonesPart.id = m_bonesPartId;
+
+ std::vector> edgePairs;
+ for (size_t i = 1; i < rigBones->size(); ++i) {
+ const auto &bone = (*rigBones)[i];
+ for (const auto &child: bone.children) {
+ edgePairs.push_back({i, child});
+ }
+ }
+ std::map boneIndexToHeadNodeIdMap;
+ for (const auto &edgePair: edgePairs) {
+ QUuid firstNodeId, secondNodeId;
+ auto findFirst = boneIndexToHeadNodeIdMap.find(edgePair.first);
+ if (findFirst == boneIndexToHeadNodeIdMap.end()) {
+ const auto &bone = (*rigBones)[edgePair.first];
+ SkeletonNode node;
+ node.partId = m_bonesPartId;
+ node.id = QUuid::createUuid();
+ node.setRadius(m_nodeRadius);
+ node.x = bone.headPosition.x() + 0.5;
+ node.y = -bone.headPosition.y() + 0.5;
+ node.z = -bone.headPosition.z() + 1;
+ nodeMap[node.id] = node;
+ newAddedNodeIds.insert(node.id);
+ boneIndexToHeadNodeIdMap[edgePair.first] = node.id;
+ firstNodeId = node.id;
+ } else {
+ firstNodeId = findFirst->second;
+ }
+ auto findSecond = boneIndexToHeadNodeIdMap.find(edgePair.second);
+ if (findSecond == boneIndexToHeadNodeIdMap.end()) {
+ const auto &bone = (*rigBones)[edgePair.second];
+ SkeletonNode node;
+ node.partId = m_bonesPartId;
+ node.id = QUuid::createUuid();
+ node.setRadius(m_nodeRadius);
+ node.x = bone.headPosition.x() + 0.5;
+ node.y = -bone.headPosition.y() + 0.5;
+ node.z = -bone.headPosition.z() + 1;
+ nodeMap[node.id] = node;
+ newAddedNodeIds.insert(node.id);
+ boneIndexToHeadNodeIdMap[edgePair.second] = node.id;
+ secondNodeId = node.id;
+ } else {
+ secondNodeId = findSecond->second;
+ }
+
+ SkeletonEdge edge;
+ edge.partId = m_bonesPartId;
+ edge.id = QUuid::createUuid();
+ edge.nodeIds.push_back(firstNodeId);
+ edge.nodeIds.push_back(secondNodeId);
+ edgeMap[edge.id] = edge;
+ newAddedEdgeIds.insert(edge.id);
+ nodeMap[firstNodeId].edgeIds.push_back(edge.id);
+ nodeMap[secondNodeId].edgeIds.push_back(edge.id);
+ }
+ for (size_t i = 0; i < rigBones->size(); ++i) {
+ const auto &bone = (*rigBones)[i];
+ if (bone.children.empty()) {
+ const QUuid &firstNodeId = boneIndexToHeadNodeIdMap[i];
+
+ SkeletonNode node;
+ node.partId = m_bonesPartId;
+ node.id = QUuid::createUuid();
+ node.setRadius(m_nodeRadius / 2);
+ node.x = bone.tailPosition.x() + 0.5;
+ node.y = -bone.tailPosition.y() + 0.5;
+ node.z = -bone.tailPosition.z() + 1;
+ nodeMap[node.id] = node;
+ newAddedNodeIds.insert(node.id);
+ m_boneNameToIdsMap[bone.name] = {firstNodeId, node.id};
+
+ SkeletonEdge edge;
+ edge.partId = m_bonesPartId;
+ edge.id = QUuid::createUuid();
+ edge.nodeIds.push_back(firstNodeId);
+ edge.nodeIds.push_back(node.id);
+ edgeMap[edge.id] = edge;
+ newAddedEdgeIds.insert(edge.id);
+ nodeMap[firstNodeId].edgeIds.push_back(edge.id);
+ nodeMap[node.id].edgeIds.push_back(edge.id);
+ continue;
+ }
+ for (const auto &child: bone.children) {
+ m_boneNameToIdsMap[bone.name] = {boneIndexToHeadNodeIdMap[i], boneIndexToHeadNodeIdMap[child]};
+ }
+ }
+
+ m_groundPartId = QUuid::createUuid();
+ auto &groundPart = partMap[m_groundPartId];
+ groundPart.id = m_groundPartId;
+
+ float groundY = findGroundY() + rootTranslation.y();
+
+ std::pair groundNodesPair;
+ {
+ SkeletonNode node;
+ node.partId = m_groundPartId;
+ node.id = QUuid::createUuid();
+ node.setRadius(m_groundPlaneHalfThickness);
+ node.x = -100;
+ node.y = groundY + m_groundPlaneHalfThickness;
+ node.z = -100;
+ nodeMap[node.id] = node;
+ newAddedNodeIds.insert(node.id);
+ groundNodesPair.first = node.id;
+ }
+
+ {
+ SkeletonNode node;
+ node.partId = m_groundPartId;
+ node.id = QUuid::createUuid();
+ node.setRadius(m_groundPlaneHalfThickness);
+ node.x = 100;
+ node.y = groundY + m_groundPlaneHalfThickness;
+ node.z = 100;
+ nodeMap[node.id] = node;
+ newAddedNodeIds.insert(node.id);
+ groundNodesPair.second = node.id;
+ }
+
+ {
+ SkeletonEdge edge;
+ edge.partId = m_groundPartId;
+ edge.id = QUuid::createUuid();
+ edge.nodeIds.push_back(groundNodesPair.first);
+ edge.nodeIds.push_back(groundNodesPair.second);
+ edgeMap[edge.id] = edge;
+ m_groundEdgeId = edge.id;
+ newAddedEdgeIds.insert(edge.id);
+ nodeMap[groundNodesPair.first].edgeIds.push_back(edge.id);
+ nodeMap[groundNodesPair.second].edgeIds.push_back(edge.id);
+ }
+
+ for (const auto &nodeIt: newAddedNodeIds) {
+ emit nodeAdded(nodeIt);
+ }
+ for (const auto &edgeIt: newAddedEdgeIds) {
+ emit edgeAdded(edgeIt);
+ }
+
+ emit parametersChanged();
+}
+
+void PoseDocument::moveNodeBy(QUuid nodeId, float x, float y, float z)
+{
+ auto it = nodeMap.find(nodeId);
+ if (it == nodeMap.end()) {
+ qDebug() << "Find node failed:" << nodeId;
+ return;
+ }
+ it->second.x += x;
+ it->second.y += y;
+ it->second.z += z;
+ emit nodeOriginChanged(it->first);
+ emit parametersChanged();
+}
+
+void PoseDocument::setNodeOrigin(QUuid nodeId, float x, float y, float z)
+{
+ auto it = nodeMap.find(nodeId);
+ if (it == nodeMap.end()) {
+ qDebug() << "Find node failed:" << nodeId;
+ return;
+ }
+ it->second.x = x;
+ it->second.y = y;
+ it->second.z = z;
+ auto part = partMap.find(it->second.partId);
+ if (part != partMap.end())
+ part->second.dirty = true;
+ emit nodeOriginChanged(nodeId);
+ emit parametersChanged();
+}
+
+float PoseDocument::findGroundY() const
+{
+ auto maxY = std::numeric_limits::lowest();
+ for (const auto &nodeIt: nodeMap) {
+ if (nodeIt.second.partId != m_bonesPartId)
+ continue;
+ auto y = nodeIt.second.y + nodeIt.second.radius;
+ if (y > maxY)
+ maxY = y;
+ }
+ return maxY;
+}
+
+void PoseDocument::toParameters(std::map> ¶meters) const
+{
+ float translateY = 0;
+ auto findGroundEdge = edgeMap.find(m_groundEdgeId);
+ if (findGroundEdge != edgeMap.end()) {
+ const auto &nodeIds = findGroundEdge->second.nodeIds;
+ if (nodeIds.size() == 2) {
+ auto findFirstNode = nodeMap.find(nodeIds[0]);
+ auto findSecondNode = nodeMap.find(nodeIds[1]);
+ if (findFirstNode != nodeMap.end() && findSecondNode != nodeMap.end()) {
+ translateY = (findFirstNode->second.y + findSecondNode->second.y) / 2 -
+ (findGroundY() + m_groundPlaneHalfThickness);
+ }
+ }
+ }
+ if (!qFuzzyIsNull(translateY)) {
+ auto &boneParameter = parameters[Rigger::rootBoneName];
+ boneParameter["translateY"] = QString::number(translateY);
+ }
+ for (const auto &item: m_boneNameToIdsMap) {
+ auto &boneParameter = parameters[item.first];
+ const auto &boneNodeIdPair = item.second;
+ auto findFirstNode = nodeMap.find(boneNodeIdPair.first);
+ if (findFirstNode == nodeMap.end())
+ continue;
+ auto findSecondNode = nodeMap.find(boneNodeIdPair.second);
+ if (findSecondNode == nodeMap.end())
+ continue;
+ boneParameter["fromX"] = QString::number(findFirstNode->second.x - 0.5);
+ boneParameter["fromY"] = QString::number(0.5 - findFirstNode->second.y);
+ boneParameter["fromZ"] = QString::number(1.0 - findFirstNode->second.z);
+ boneParameter["toX"] = QString::number(findSecondNode->second.x - 0.5);
+ boneParameter["toY"] = QString::number(0.5 - findSecondNode->second.y);
+ boneParameter["toZ"] = QString::number(1.0 - findSecondNode->second.z);
+ }
+}
diff --git a/src/posedocument.h b/src/posedocument.h
new file mode 100644
index 00000000..0910a96c
--- /dev/null
+++ b/src/posedocument.h
@@ -0,0 +1,66 @@
+#ifndef DUST3D_POSE_DOCUMENT_H
+#define DUST3D_POSE_DOCUMENT_H
+#include