master
Jeremy Hu 2018-04-09 22:24:30 +08:00
parent 5e97e3d268
commit 62fdcbdced
7 changed files with 114 additions and 28 deletions

View File

@ -32,6 +32,7 @@ int main(int argc, char ** argv)
darkPalette.setColor(QPalette::ToolTipBase, Theme::white);
darkPalette.setColor(QPalette::ToolTipText, Theme::white);
darkPalette.setColor(QPalette::Text, Theme::white);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, Theme::black);
darkPalette.setColor(QPalette::Button, QColor(53,53,53));
darkPalette.setColor(QPalette::ButtonText, Theme::white);
darkPalette.setColor(QPalette::BrightText, Theme::red);

View File

@ -14,7 +14,8 @@ unsigned long SkeletonDocument::m_maxSnapshot = 1000;
SkeletonDocument::SkeletonDocument() :
m_resultMeshIsObsolete(false),
m_resultMesh(nullptr),
m_meshGenerator(nullptr)
m_meshGenerator(nullptr),
m_batchChangeRefCount(0)
{
}
@ -754,9 +755,24 @@ void SkeletonDocument::meshReady()
}
}
void SkeletonDocument::batchChangeBegin()
{
m_batchChangeRefCount++;
}
void SkeletonDocument::batchChangeEnd()
{
m_batchChangeRefCount--;
if (0 == m_batchChangeRefCount) {
if (m_resultMeshIsObsolete) {
generateMesh();
}
}
}
void SkeletonDocument::generateMesh()
{
if (nullptr != m_meshGenerator) {
if (nullptr != m_meshGenerator || m_batchChangeRefCount > 0) {
m_resultMeshIsObsolete = true;
return;
}
@ -867,3 +883,15 @@ void SkeletonDocument::paste()
addFromSnapshot(snapshot);
}
}
bool SkeletonDocument::hasPastableContentInClipboard() const
{
const QClipboard *clipboard = QApplication::clipboard();
const QMimeData *mimeData = clipboard->mimeData();
if (mimeData->hasText()) {
if (-1 != mimeData->text().left(1000).indexOf("partIdList"))
return true;
}
return false;
}

View File

@ -106,6 +106,13 @@ public:
}
};
enum class SkeletonProfile
{
Unknown = 0,
Main,
Side
};
class SkeletonHistoryItem
{
public:
@ -121,13 +128,6 @@ enum class SkeletonDocumentEditMode
ZoomOut
};
enum class SkeletonProfile
{
Unknown = 0,
Main,
Side
};
class SkeletonDocument : public QObject
{
Q_OBJECT
@ -170,6 +170,7 @@ public:
Mesh *takeResultMesh();
QImage preview;
void updateTurnaround(const QImage &image);
bool hasPastableContentInClipboard() const;
public slots:
void removeNode(QUuid nodeId);
void removeEdge(QUuid edgeId);
@ -193,6 +194,8 @@ public slots:
void undo();
void redo();
void paste();
void batchChangeBegin();
void batchChangeEnd();
private:
void splitPartByNode(std::vector<std::vector<QUuid>> *groups, QUuid nodeId);
void joinNodeAndNeiborsToGroup(std::vector<QUuid> *group, QUuid nodeId, std::set<QUuid> *visitMap, QUuid noUseEdgeId=QUuid());
@ -205,6 +208,7 @@ private:
static unsigned long m_maxSnapshot;
std::deque<SkeletonHistoryItem> m_undoItems;
std::deque<SkeletonHistoryItem> m_redoItems;
int m_batchChangeRefCount;
};
#endif

View File

@ -195,6 +195,8 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
connect(graphicsWidget, &SkeletonGraphicsWidget::redo, m_document, &SkeletonDocument::redo);
connect(graphicsWidget, &SkeletonGraphicsWidget::paste, m_document, &SkeletonDocument::paste);
connect(graphicsWidget, &SkeletonGraphicsWidget::changeTurnaround, this, &SkeletonDocumentWindow::changeTurnaround);
connect(graphicsWidget, &SkeletonGraphicsWidget::batchChangeBegin, m_document, &SkeletonDocument::batchChangeBegin);
connect(graphicsWidget, &SkeletonGraphicsWidget::batchChangeEnd, m_document, &SkeletonDocument::batchChangeEnd);
connect(m_document, &SkeletonDocument::nodeAdded, graphicsWidget, &SkeletonGraphicsWidget::nodeAdded);
connect(m_document, &SkeletonDocument::nodeRemoved, graphicsWidget, &SkeletonGraphicsWidget::nodeRemoved);

View File

@ -102,10 +102,23 @@ void SkeletonGraphicsWidget::showContextMenu(const QPoint &pos)
QAction pasteAction("Paste", this);
connect(&pasteAction, &QAction::triggered, m_document, &SkeletonDocument::paste);
pasteAction.setEnabled(m_document->hasPastableContentInClipboard());
contextMenu.addAction(&pasteAction);
contextMenu.addSeparator();
QAction flipHorizontallyAction("H Flip", this);
connect(&flipHorizontallyAction, &QAction::triggered, this, &SkeletonGraphicsWidget::flipHorizontally);
flipHorizontallyAction.setEnabled(!m_rangeSelectionSet.empty());
contextMenu.addAction(&flipHorizontallyAction);
QAction flipVerticallyAction("V Flip", this);
connect(&flipVerticallyAction, &QAction::triggered, this, &SkeletonGraphicsWidget::flipVertically);
flipVerticallyAction.setEnabled(!m_rangeSelectionSet.empty());
contextMenu.addAction(&flipVerticallyAction);
contextMenu.addSeparator();
QAction selectAllAction("Select All", this);
connect(&selectAllAction, &QAction::triggered, this, &SkeletonGraphicsWidget::selectAll);
selectAllAction.setEnabled(!nodeItemMap.empty());
@ -123,18 +136,6 @@ void SkeletonGraphicsWidget::showContextMenu(const QPoint &pos)
contextMenu.addSeparator();
QAction addMirrorAction("Mirror", this);
connect(&addMirrorAction, &QAction::triggered, this, &SkeletonGraphicsWidget::addMirror);
addMirrorAction.setEnabled(readSkeletonNodeAndAnyEdgeOfNodeFromRangeSelection(nullptr, nullptr));
contextMenu.addAction(&addMirrorAction);
QAction deleteMirrorAction("Delete Mirror", this);
connect(&deleteMirrorAction, &QAction::triggered, this, &SkeletonGraphicsWidget::deleteMirror);
deleteMirrorAction.setEnabled(readSkeletonNodeAndAnyEdgeOfNodeFromRangeSelection(nullptr, nullptr));
contextMenu.addAction(&deleteMirrorAction);
contextMenu.addSeparator();
QAction changeTurnaroundAction("Change Turnaround..", this);
connect(&changeTurnaroundAction, &QAction::triggered, [=]() {
emit changeTurnaround();
@ -425,11 +426,7 @@ bool SkeletonGraphicsWidget::wheel(QWheelEvent *event)
readMergedSkeletonNodeSetFromRangeSelection(&nodeItems);
float unifiedDelta = sceneRadiusToUnified(delta);
if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier)) {
QVector2D center;
for (const auto &nodeItem: nodeItems) {
center += QVector2D(nodeItem->origin());
}
center /= nodeItems.size();
QVector2D center = centerOfNodeItemSet(nodeItems);
for (const auto &nodeItem: nodeItems) {
QVector2D origin = QVector2D(nodeItem->origin());
QVector2D ray = (center - origin) * 0.01 * delta;
@ -459,6 +456,50 @@ bool SkeletonGraphicsWidget::wheel(QWheelEvent *event)
return false;
}
QVector2D SkeletonGraphicsWidget::centerOfNodeItemSet(const std::set<SkeletonGraphicsNodeItem *> &set)
{
QVector2D center;
for (const auto &nodeItem: set) {
center += QVector2D(nodeItem->origin());
}
center /= set.size();
return center;
}
void SkeletonGraphicsWidget::flipHorizontally()
{
std::set<SkeletonGraphicsNodeItem *> nodeItems;
readMergedSkeletonNodeSetFromRangeSelection(&nodeItems);
if (nodeItems.empty())
return;
QVector2D center = centerOfNodeItemSet(nodeItems);
for (const auto &nodeItem: nodeItems) {
QPointF origin = nodeItem->origin();
float offset = origin.x() - center.x();
float unifiedOffset = -sceneRadiusToUnified(offset * 2);
if (SkeletonProfile::Main == nodeItem->profile()) {
emit moveNodeBy(nodeItem->id(), unifiedOffset, 0, 0);
} else {
emit moveNodeBy(nodeItem->id(), 0, 0, unifiedOffset);
}
}
}
void SkeletonGraphicsWidget::flipVertically()
{
std::set<SkeletonGraphicsNodeItem *> nodeItems;
readMergedSkeletonNodeSetFromRangeSelection(&nodeItems);
if (nodeItems.empty())
return;
QVector2D center = centerOfNodeItemSet(nodeItems);
for (const auto &nodeItem: nodeItems) {
QPointF origin = nodeItem->origin();
float offset = origin.y() - center.y();
float unifiedOffset = -sceneRadiusToUnified(offset * 2);
emit moveNodeBy(nodeItem->id(), 0, unifiedOffset, 0);
}
}
bool SkeletonGraphicsWidget::mouseRelease(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
@ -619,6 +660,7 @@ bool SkeletonGraphicsWidget::mouseDoubleClick(QMouseEvent *event)
void SkeletonGraphicsWidget::deleteSelected()
{
if (!m_rangeSelectionSet.empty()) {
emit batchChangeBegin();
std::set<QUuid> nodeIdSet;
std::set<QUuid> edgeIdSet;
readSkeletonNodeAndEdgeIdSetFromRangeSelection(&nodeIdSet, &edgeIdSet);
@ -628,6 +670,7 @@ void SkeletonGraphicsWidget::deleteSelected()
for (const auto &id: nodeIdSet) {
emit removeNode(id);
}
emit batchChangeEnd();
}
}
@ -1094,3 +1137,6 @@ void SkeletonGraphicsWidget::copy()
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(snapshotXml);
}

View File

@ -264,8 +264,8 @@ signals:
void redo();
void paste();
void changeTurnaround();
void addMirror();
void deleteMirror();
void batchChangeBegin();
void batchChangeEnd();
public:
SkeletonGraphicsWidget(const SkeletonDocument *document);
std::map<QUuid, std::pair<SkeletonGraphicsNodeItem *, SkeletonGraphicsNodeItem *>> nodeItemMap;
@ -308,6 +308,8 @@ public slots:
void selectPartAll();
void cut();
void copy();
void flipHorizontally();
void flipVertically();
private slots:
void turnaroundImageReady();
private:
@ -321,6 +323,7 @@ private:
void checkRangeSelection();
void clearRangeSelection();
void removeItem(QGraphicsItem *item);
QVector2D centerOfNodeItemSet(const std::set<SkeletonGraphicsNodeItem *> &set);
private:
QGraphicsPixmapItem *m_backgroundItem;
const SkeletonDocument *m_document;

View File

@ -13,6 +13,8 @@ public:
std::map<QString, std::map<QString, QString>> nodes;
std::map<QString, std::map<QString, QString>> edges;
std::map<QString, std::map<QString, QString>> parts;
std::map<QString, std::map<QString, QString>> mirrors;
std::map<QString, std::map<QString, QString>> trivialMarkers;
std::vector<QString> partIdList;
public:
SkeletonSnapshot();