diff --git a/src/skeletondocument.cpp b/src/skeletondocument.cpp index 8ac78ae4..9b2612c3 100644 --- a/src/skeletondocument.cpp +++ b/src/skeletondocument.cpp @@ -41,7 +41,8 @@ SkeletonDocument::SkeletonDocument() : m_textureImageUpdateVersion(0), m_ambientOcclusionBaker(nullptr), m_ambientOcclusionBakedImageUpdateVersion(0), - m_sharedContextWidget(nullptr) + m_sharedContextWidget(nullptr), + m_allPositionRelatedLocksEnabled(true) { } @@ -62,6 +63,16 @@ void SkeletonDocument::uiReady() emit editModeChanged(); } +void SkeletonDocument::SkeletonDocument::enableAllPositionRelatedLocks() +{ + m_allPositionRelatedLocksEnabled = true; +} + +void SkeletonDocument::SkeletonDocument::disableAllPositionRelatedLocks() +{ + m_allPositionRelatedLocksEnabled = false; +} + void SkeletonDocument::breakEdge(QUuid edgeId) { const SkeletonEdge *edge = findEdge(edgeId); @@ -456,13 +467,13 @@ void SkeletonDocument::moveNodeBy(QUuid nodeId, float x, float y, float z) qDebug() << "Find node failed:" << nodeId; return; } - if (isPartReadonly(it->second.partId)) + if (m_allPositionRelatedLocksEnabled && isPartReadonly(it->second.partId)) return; - if (!xlocked) + if (!(m_allPositionRelatedLocksEnabled && xlocked)) it->second.x += x; - if (!ylocked) + if (!(m_allPositionRelatedLocksEnabled && ylocked)) it->second.y += y; - if (!zlocked) + if (!(m_allPositionRelatedLocksEnabled && zlocked)) it->second.z += z; auto part = partMap.find(it->second.partId); if (part != partMap.end()) @@ -473,11 +484,11 @@ void SkeletonDocument::moveNodeBy(QUuid nodeId, float x, float y, float z) void SkeletonDocument::moveOriginBy(float x, float y, float z) { - if (!xlocked) + if (!(m_allPositionRelatedLocksEnabled && xlocked)) originX += x; - if (!ylocked) + if (!(m_allPositionRelatedLocksEnabled && ylocked)) originY += y; - if (!zlocked) + if (!(m_allPositionRelatedLocksEnabled && zlocked)) originZ += z; markAllDirty(); emit originChanged(); @@ -491,13 +502,13 @@ void SkeletonDocument::setNodeOrigin(QUuid nodeId, float x, float y, float z) qDebug() << "Find node failed:" << nodeId; return; } - if (isPartReadonly(it->second.partId)) + if ((m_allPositionRelatedLocksEnabled && isPartReadonly(it->second.partId))) return; - if (!xlocked) + if (!(m_allPositionRelatedLocksEnabled && xlocked)) it->second.x = x; - if (!ylocked) + if (!(m_allPositionRelatedLocksEnabled && ylocked)) it->second.y = y; - if (!zlocked) + if (!(m_allPositionRelatedLocksEnabled && zlocked)) it->second.z = z; auto part = partMap.find(it->second.partId); if (part != partMap.end()) diff --git a/src/skeletondocument.h b/src/skeletondocument.h index a8970798..b2d21358 100644 --- a/src/skeletondocument.h +++ b/src/skeletondocument.h @@ -465,6 +465,8 @@ public slots: void setXlockState(bool locked); void setYlockState(bool locked); void setZlockState(bool locked); + void enableAllPositionRelatedLocks(); + void disableAllPositionRelatedLocks(); private: void splitPartByNode(std::vector> *groups, QUuid nodeId); void joinNodeAndNeiborsToGroup(std::vector *group, QUuid nodeId, std::set *visitMap, QUuid noUseEdgeId=QUuid()); @@ -497,6 +499,7 @@ private: // need initialize unsigned long long m_ambientOcclusionBakedImageUpdateVersion; QOpenGLWidget *m_sharedContextWidget; QUuid m_currentCanvasComponentId; + bool m_allPositionRelatedLocksEnabled; private: static unsigned long m_maxSnapshot; std::deque m_undoItems; diff --git a/src/skeletondocumentwindow.cpp b/src/skeletondocumentwindow.cpp index dac3de06..a7a422bd 100644 --- a/src/skeletondocumentwindow.cpp +++ b/src/skeletondocumentwindow.cpp @@ -110,9 +110,6 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() : toolButtonLayout->setSpacing(0); toolButtonLayout->setContentsMargins(5, 10, 4, 0); - QPushButton *undoButton = new QPushButton(QChar(fa::undo)); - Theme::initAwesomeButton(undoButton); - QPushButton *addButton = new QPushButton(QChar(fa::plus)); Theme::initAwesomeButton(addButton); @@ -139,9 +136,13 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() : m_zlockButton = new QPushButton(QChar('Z')); initLockButton(m_zlockButton); updateZlockButtonState(); + + QPushButton *rotateCounterclockwiseButton = new QPushButton(QChar(fa::rotateleft)); + Theme::initAwesomeButton(rotateCounterclockwiseButton); + + QPushButton *rotateClockwiseButton = new QPushButton(QChar(fa::rotateright)); + Theme::initAwesomeButton(rotateClockwiseButton); - toolButtonLayout->addWidget(undoButton); - toolButtonLayout->addSpacing(10); toolButtonLayout->addWidget(addButton); toolButtonLayout->addWidget(selectButton); toolButtonLayout->addWidget(dragButton); @@ -151,6 +152,9 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() : toolButtonLayout->addWidget(m_xlockButton); toolButtonLayout->addWidget(m_ylockButton); toolButtonLayout->addWidget(m_zlockButton); + toolButtonLayout->addSpacing(10); + toolButtonLayout->addWidget(rotateCounterclockwiseButton); + toolButtonLayout->addWidget(rotateClockwiseButton); QLabel *verticalLogoLabel = new QLabel; QImage verticalLogoImage; @@ -477,9 +481,8 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() : connect(m_document, &SkeletonDocument::turnaroundChanged, graphicsWidget, &SkeletonGraphicsWidget::turnaroundChanged); - connect(undoButton, &QPushButton::clicked, [=]() { - m_document->undo(); - }); + connect(rotateCounterclockwiseButton, &QPushButton::clicked, graphicsWidget, &SkeletonGraphicsWidget::rotateAllMainProfileCounterclockwise90DegreeAlongOrigin); + connect(rotateClockwiseButton, &QPushButton::clicked, graphicsWidget, &SkeletonGraphicsWidget::rotateAllMainProfileClockwise90DegreeAlongOrigin); connect(addButton, &QPushButton::clicked, [=]() { m_document->setEditMode(SkeletonDocumentEditMode::Add); @@ -554,6 +557,9 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() : connect(graphicsWidget, &SkeletonGraphicsWidget::setXlockState, m_document, &SkeletonDocument::setXlockState); connect(graphicsWidget, &SkeletonGraphicsWidget::setYlockState, m_document, &SkeletonDocument::setYlockState); connect(graphicsWidget, &SkeletonGraphicsWidget::setZlockState, m_document, &SkeletonDocument::setZlockState); + + connect(graphicsWidget, &SkeletonGraphicsWidget::enableAllPositionRelatedLocks, m_document, &SkeletonDocument::enableAllPositionRelatedLocks); + connect(graphicsWidget, &SkeletonGraphicsWidget::disableAllPositionRelatedLocks, m_document, &SkeletonDocument::disableAllPositionRelatedLocks); connect(graphicsWidget, &SkeletonGraphicsWidget::changeTurnaround, this, &SkeletonDocumentWindow::changeTurnaround); connect(graphicsWidget, &SkeletonGraphicsWidget::save, this, &SkeletonDocumentWindow::save); diff --git a/src/skeletongraphicswidget.cpp b/src/skeletongraphicswidget.cpp index f9b6d94a..2facb5e6 100644 --- a/src/skeletongraphicswidget.cpp +++ b/src/skeletongraphicswidget.cpp @@ -765,8 +765,7 @@ void SkeletonGraphicsWidget::rotateSelected(int degree) readMergedSkeletonNodeSetFromRangeSelection(&nodeItems); QVector2D center; - qNormalizeAngle(degree); - + if (1 == nodeItems.size() && m_document->originSettled()) { // Rotate all children nodes around this node // 1. Pick who is the parent from neighbors @@ -826,10 +825,17 @@ void SkeletonGraphicsWidget::rotateSelected(int degree) center = centerOfNodeItemSet(nodeItems); } + rotateItems(nodeItems, degree, center); +} + +void SkeletonGraphicsWidget::rotateItems(const std::set &nodeItems, int degree, QVector2D center) +{ + emit disableAllPositionRelatedLocks(); + QVector3D centerPoint(center.x(), center.y(), 0); + qNormalizeAngle(degree); for (const auto &it: nodeItems) { SkeletonGraphicsNodeItem *nodeItem = it; QMatrix4x4 mat; - QVector3D centerPoint(center.x(), center.y(), 0); QPointF nodeOrigin = nodeItem->origin(); QVector3D nodeOriginPoint(nodeOrigin.x(), nodeOrigin.y(), 0); QVector3D p = nodeOriginPoint - centerPoint; @@ -844,6 +850,17 @@ void SkeletonGraphicsWidget::rotateSelected(int degree) emit moveNodeBy(nodeItem->id(), 0, byY, byX); } } + emit enableAllPositionRelatedLocks(); +} + +void SkeletonGraphicsWidget::rotateAllSideProfile(int degree) +{ + std::set items; + for (const auto &item: nodeItemMap) { + items.insert(item.second.second); + } + QVector2D center(scenePosFromUnified(QPointF(m_document->originZ, m_document->originY))); + rotateItems(items, degree, center); } void SkeletonGraphicsWidget::moveCheckedOrigin(float byX, float byY) @@ -1038,6 +1055,26 @@ void SkeletonGraphicsWidget::rotateCounterclockwise90Degree() emit groupOperationAdded(); } +void SkeletonGraphicsWidget::rotateAllMainProfileClockwise90DegreeAlongOrigin() +{ + if (!m_document->originSettled()) + return; + emit batchChangeBegin(); + emit rotateAllSideProfile(90); + emit batchChangeEnd(); + emit groupOperationAdded(); +} + +void SkeletonGraphicsWidget::rotateAllMainProfileCounterclockwise90DegreeAlongOrigin() +{ + if (!m_document->originSettled()) + return; + emit batchChangeBegin(); + emit rotateAllSideProfile(360 - 90); + emit batchChangeEnd(); + emit groupOperationAdded(); +} + bool SkeletonGraphicsWidget::mouseRelease(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { diff --git a/src/skeletongraphicswidget.h b/src/skeletongraphicswidget.h index 92d43241..78dcba48 100644 --- a/src/skeletongraphicswidget.h +++ b/src/skeletongraphicswidget.h @@ -386,6 +386,8 @@ signals: void setNodeOrigin(QUuid nodeId, float x, float y, float z); void zoomRenderedModelBy(float delta); void switchNodeXZ(QUuid nodeId); + void enableAllPositionRelatedLocks(); + void disableAllPositionRelatedLocks(); public: SkeletonGraphicsWidget(const SkeletonDocument *document); std::map> nodeItemMap; @@ -440,6 +442,8 @@ public slots: void flipVertically(); void rotateClockwise90Degree(); void rotateCounterclockwise90Degree(); + void rotateAllMainProfileClockwise90DegreeAlongOrigin(); + void rotateAllMainProfileCounterclockwise90DegreeAlongOrigin(); void removeAllContent(); void breakSelected(); void connectSelected(); @@ -486,6 +490,8 @@ private: void setItemHoveredOnAllProfiles(QGraphicsItem *item, bool hovered); void alignSelectedToGlobal(bool alignToVerticalCenter, bool alignToHorizontalCenter); void alignSelectedToLocal(bool alignToVerticalCenter, bool alignToHorizontalCenter); + void rotateItems(const std::set &nodeItems, int degree, QVector2D center); + void rotateAllSideProfile(int degree); private: //need initalize const SkeletonDocument *m_document; QGraphicsPixmapItem *m_backgroundItem;