Make a abstract class for document: SkeletonDocument

This is mainly for reusing the SkeletonGraphicsEditWidget for other purpose, such as the new pose editor.
master
Jeremy Hu 2018-11-03 16:09:42 +08:00
parent e7249db089
commit a4aefdd308
10 changed files with 412 additions and 373 deletions

View File

@ -291,6 +291,9 @@ HEADERS += src/riggerconstruct.h
SOURCES += src/poserconstruct.cpp SOURCES += src/poserconstruct.cpp
HEADERS += src/poserconstruct.h HEADERS += src/poserconstruct.h
SOURCES += src/skeletondocument.cpp
HEADERS += src/skeletondocument.h
SOURCES += src/main.cpp SOURCES += src/main.cpp
HEADERS += src/version.h HEADERS += src/version.h

View File

@ -17,15 +17,8 @@
unsigned long Document::m_maxSnapshot = 1000; unsigned long Document::m_maxSnapshot = 1000;
Document::Document() : Document::Document() :
SkeletonDocument(),
// public // public
originX(0),
originY(0),
originZ(0),
editMode(DocumentEditMode::Select),
xlocked(false),
ylocked(false),
zlocked(false),
radiusLocked(false),
textureGuideImage(nullptr), textureGuideImage(nullptr),
textureImage(nullptr), textureImage(nullptr),
textureBorderImage(nullptr), textureBorderImage(nullptr),
@ -92,7 +85,7 @@ void Document::Document::disableAllPositionRelatedLocks()
void Document::breakEdge(QUuid edgeId) void Document::breakEdge(QUuid edgeId)
{ {
const Edge *edge = findEdge(edgeId); const SkeletonEdge *edge = findEdge(edgeId);
if (nullptr == edge) { if (nullptr == edge) {
qDebug() << "Find edge failed:" << edgeId; qDebug() << "Find edge failed:" << edgeId;
return; return;
@ -102,12 +95,12 @@ void Document::breakEdge(QUuid edgeId)
} }
QUuid firstNodeId = edge->nodeIds[0]; QUuid firstNodeId = edge->nodeIds[0];
QUuid secondNodeId = edge->nodeIds[1]; QUuid secondNodeId = edge->nodeIds[1];
const Node *firstNode = findNode(firstNodeId); const SkeletonNode *firstNode = findNode(firstNodeId);
if (nullptr == firstNode) { if (nullptr == firstNode) {
qDebug() << "Find node failed:" << firstNodeId; qDebug() << "Find node failed:" << firstNodeId;
return; return;
} }
const Node *secondNode = findNode(secondNodeId); const SkeletonNode *secondNode = findNode(secondNodeId);
if (nullptr == secondNode) { if (nullptr == secondNode) {
qDebug() << "Find node failed:" << secondNodeId; qDebug() << "Find node failed:" << secondNodeId;
return; return;
@ -127,14 +120,14 @@ void Document::breakEdge(QUuid edgeId)
void Document::removeEdge(QUuid edgeId) void Document::removeEdge(QUuid edgeId)
{ {
const Edge *edge = findEdge(edgeId); const SkeletonEdge *edge = findEdge(edgeId);
if (nullptr == edge) { if (nullptr == edge) {
qDebug() << "Find edge failed:" << edgeId; qDebug() << "Find edge failed:" << edgeId;
return; return;
} }
if (isPartReadonly(edge->partId)) if (isPartReadonly(edge->partId))
return; return;
const Part *oldPart = findPart(edge->partId); const SkeletonPart *oldPart = findPart(edge->partId);
if (nullptr == oldPart) { if (nullptr == oldPart) {
qDebug() << "Find part failed:" << edge->partId; qDebug() << "Find part failed:" << edge->partId;
return; return;
@ -145,7 +138,7 @@ void Document::removeEdge(QUuid edgeId)
splitPartByEdge(&groups, edgeId); splitPartByEdge(&groups, edgeId);
for (auto groupIt = groups.begin(); groupIt != groups.end(); groupIt++) { for (auto groupIt = groups.begin(); groupIt != groups.end(); groupIt++) {
const auto newUuid = QUuid::createUuid(); const auto newUuid = QUuid::createUuid();
Part &part = partMap[newUuid]; SkeletonPart &part = partMap[newUuid];
part.id = newUuid; part.id = newUuid;
part.copyAttributes(*oldPart); part.copyAttributes(*oldPart);
part.name = nextPartName; part.name = nextPartName;
@ -187,14 +180,14 @@ void Document::removeEdge(QUuid edgeId)
void Document::removeNode(QUuid nodeId) void Document::removeNode(QUuid nodeId)
{ {
const Node *node = findNode(nodeId); const SkeletonNode *node = findNode(nodeId);
if (nullptr == node) { if (nullptr == node) {
qDebug() << "Find node failed:" << nodeId; qDebug() << "Find node failed:" << nodeId;
return; return;
} }
if (isPartReadonly(node->partId)) if (isPartReadonly(node->partId))
return; return;
const Part *oldPart = findPart(node->partId); const SkeletonPart *oldPart = findPart(node->partId);
if (nullptr == oldPart) { if (nullptr == oldPart) {
qDebug() << "Find part failed:" << node->partId; qDebug() << "Find part failed:" << node->partId;
return; return;
@ -205,7 +198,7 @@ void Document::removeNode(QUuid nodeId)
splitPartByNode(&groups, nodeId); splitPartByNode(&groups, nodeId);
for (auto groupIt = groups.begin(); groupIt != groups.end(); groupIt++) { for (auto groupIt = groups.begin(); groupIt != groups.end(); groupIt++) {
const auto newUuid = QUuid::createUuid(); const auto newUuid = QUuid::createUuid();
Part &part = partMap[newUuid]; SkeletonPart &part = partMap[newUuid];
part.id = newUuid; part.id = newUuid;
part.copyAttributes(*oldPart); part.copyAttributes(*oldPart);
part.name = nextPartName; part.name = nextPartName;
@ -260,11 +253,11 @@ void Document::addNode(float x, float y, float z, float radius, QUuid fromNodeId
QUuid Document::createNode(float x, float y, float z, float radius, QUuid fromNodeId) QUuid Document::createNode(float x, float y, float z, float radius, QUuid fromNodeId)
{ {
QUuid partId; QUuid partId;
const Node *fromNode = nullptr; const SkeletonNode *fromNode = nullptr;
bool newPartAdded = false; bool newPartAdded = false;
if (fromNodeId.isNull()) { if (fromNodeId.isNull()) {
const auto newUuid = QUuid::createUuid(); const auto newUuid = QUuid::createUuid();
Part &part = partMap[newUuid]; SkeletonPart &part = partMap[newUuid];
part.id = newUuid; part.id = newUuid;
partId = part.id; partId = part.id;
emit partAdded(partId); emit partAdded(partId);
@ -282,7 +275,7 @@ QUuid Document::createNode(float x, float y, float z, float radius, QUuid fromNo
if (part != partMap.end()) if (part != partMap.end())
part->second.dirty = true; part->second.dirty = true;
} }
Node node; SkeletonNode node;
node.partId = partId; node.partId = partId;
node.setRadius(radius); node.setRadius(radius);
node.x = x; node.x = x;
@ -294,7 +287,7 @@ QUuid Document::createNode(float x, float y, float z, float radius, QUuid fromNo
emit nodeAdded(node.id); emit nodeAdded(node.id);
if (nullptr != fromNode) { if (nullptr != fromNode) {
Edge edge; SkeletonEdge edge;
edge.partId = partId; edge.partId = partId;
edge.nodeIds.push_back(fromNode->id); edge.nodeIds.push_back(fromNode->id);
edge.nodeIds.push_back(node.id); edge.nodeIds.push_back(node.id);
@ -438,9 +431,9 @@ void Document::renamePose(QUuid poseId, QString name)
emit optionsChanged(); emit optionsChanged();
} }
const Edge *Document::findEdgeByNodes(QUuid firstNodeId, QUuid secondNodeId) const const SkeletonEdge *Document::findEdgeByNodes(QUuid firstNodeId, QUuid secondNodeId) const
{ {
const Node *firstNode = nullptr; const SkeletonNode *firstNode = nullptr;
firstNode = findNode(firstNodeId); firstNode = findNode(firstNodeId);
if (nullptr == firstNode) { if (nullptr == firstNode) {
qDebug() << "Find node failed:" << firstNodeId; qDebug() << "Find node failed:" << firstNodeId;
@ -470,8 +463,8 @@ void Document::addEdge(QUuid fromNodeId, QUuid toNodeId)
return; return;
} }
const Node *fromNode = nullptr; const SkeletonNode *fromNode = nullptr;
const Node *toNode = nullptr; const SkeletonNode *toNode = nullptr;
bool toPartRemoved = false; bool toPartRemoved = false;
fromNode = findNode(fromNodeId); fromNode = findNode(fromNodeId);
@ -526,7 +519,7 @@ void Document::addEdge(QUuid fromNodeId, QUuid toNodeId)
} }
} }
Edge edge; SkeletonEdge edge;
edge.partId = fromNode->partId; edge.partId = fromNode->partId;
edge.nodeIds.push_back(fromNode->id); edge.nodeIds.push_back(fromNode->id);
edge.nodeIds.push_back(toNodeId); edge.nodeIds.push_back(toNodeId);
@ -544,7 +537,7 @@ void Document::addEdge(QUuid fromNodeId, QUuid toNodeId)
emit skeletonChanged(); emit skeletonChanged();
} }
const Node *Document::findNode(QUuid nodeId) const const SkeletonNode *Document::findNode(QUuid nodeId) const
{ {
auto it = nodeMap.find(nodeId); auto it = nodeMap.find(nodeId);
if (it == nodeMap.end()) if (it == nodeMap.end())
@ -552,7 +545,7 @@ const Node *Document::findNode(QUuid nodeId) const
return &it->second; return &it->second;
} }
const Edge *Document::findEdge(QUuid edgeId) const const SkeletonEdge *Document::findEdge(QUuid edgeId) const
{ {
auto it = edgeMap.find(edgeId); auto it = edgeMap.find(edgeId);
if (it == edgeMap.end()) if (it == edgeMap.end())
@ -560,7 +553,7 @@ const Edge *Document::findEdge(QUuid edgeId) const
return &it->second; return &it->second;
} }
const Part *Document::findPart(QUuid partId) const const SkeletonPart *Document::findPart(QUuid partId) const
{ {
auto it = partMap.find(partId); auto it = partMap.find(partId);
if (it == partMap.end()) if (it == partMap.end())
@ -623,7 +616,7 @@ void Document::scaleNodeByAddRadius(QUuid nodeId, float amount)
bool Document::isPartReadonly(QUuid partId) const bool Document::isPartReadonly(QUuid partId) const
{ {
const Part *part = findPart(partId); const SkeletonPart *part = findPart(partId);
if (nullptr == part) { if (nullptr == part) {
qDebug() << "Find part failed:" << partId; qDebug() << "Find part failed:" << partId;
return true; return true;
@ -757,7 +750,7 @@ void Document::updateTurnaround(const QImage &image)
emit turnaroundChanged(); emit turnaroundChanged();
} }
void Document::setEditMode(DocumentEditMode mode) void Document::setEditMode(SkeletonDocumentEditMode mode)
{ {
if (editMode == mode) if (editMode == mode)
return; return;
@ -770,7 +763,7 @@ void Document::joinNodeAndNeiborsToGroup(std::vector<QUuid> *group, QUuid nodeId
{ {
if (nodeId.isNull() || visitMap->find(nodeId) != visitMap->end()) if (nodeId.isNull() || visitMap->find(nodeId) != visitMap->end())
return; return;
const Node *node = findNode(nodeId); const SkeletonNode *node = findNode(nodeId);
if (nullptr == node) { if (nullptr == node) {
qDebug() << "Find node failed:" << nodeId; qDebug() << "Find node failed:" << nodeId;
return; return;
@ -780,7 +773,7 @@ void Document::joinNodeAndNeiborsToGroup(std::vector<QUuid> *group, QUuid nodeId
for (auto edgeIt = node->edgeIds.begin(); edgeIt != node->edgeIds.end(); edgeIt++) { for (auto edgeIt = node->edgeIds.begin(); edgeIt != node->edgeIds.end(); edgeIt++) {
if (noUseEdgeId == *edgeIt) if (noUseEdgeId == *edgeIt)
continue; continue;
const Edge *edge = findEdge(*edgeIt); const SkeletonEdge *edge = findEdge(*edgeIt);
if (nullptr == edge) { if (nullptr == edge) {
qDebug() << "Find edge failed:" << *edgeIt; qDebug() << "Find edge failed:" << *edgeIt;
continue; continue;
@ -793,11 +786,11 @@ void Document::joinNodeAndNeiborsToGroup(std::vector<QUuid> *group, QUuid nodeId
void Document::splitPartByNode(std::vector<std::vector<QUuid>> *groups, QUuid nodeId) void Document::splitPartByNode(std::vector<std::vector<QUuid>> *groups, QUuid nodeId)
{ {
const Node *node = findNode(nodeId); const SkeletonNode *node = findNode(nodeId);
std::set<QUuid> visitMap; std::set<QUuid> visitMap;
for (auto edgeIt = node->edgeIds.begin(); edgeIt != node->edgeIds.end(); edgeIt++) { for (auto edgeIt = node->edgeIds.begin(); edgeIt != node->edgeIds.end(); edgeIt++) {
std::vector<QUuid> group; std::vector<QUuid> group;
const Edge *edge = findEdge(*edgeIt); const SkeletonEdge *edge = findEdge(*edgeIt);
if (nullptr == edge) { if (nullptr == edge) {
qDebug() << "Find edge failed:" << *edgeIt; qDebug() << "Find edge failed:" << *edgeIt;
continue; continue;
@ -810,7 +803,7 @@ void Document::splitPartByNode(std::vector<std::vector<QUuid>> *groups, QUuid no
void Document::splitPartByEdge(std::vector<std::vector<QUuid>> *groups, QUuid edgeId) void Document::splitPartByEdge(std::vector<std::vector<QUuid>> *groups, QUuid edgeId)
{ {
const Edge *edge = findEdge(edgeId); const SkeletonEdge *edge = findEdge(edgeId);
if (nullptr == edge) { if (nullptr == edge) {
qDebug() << "Find edge failed:" << edgeId; qDebug() << "Find edge failed:" << edgeId;
return; return;
@ -852,10 +845,10 @@ void Document::toSnapshot(Snapshot *snapshot, const std::set<QUuid> &limitNodeId
std::set<QUuid> limitPartIds; std::set<QUuid> limitPartIds;
std::set<QUuid> limitComponentIds; std::set<QUuid> limitComponentIds;
for (const auto &nodeId: limitNodeIds) { for (const auto &nodeId: limitNodeIds) {
const Node *node = findNode(nodeId); const SkeletonNode *node = findNode(nodeId);
if (!node) if (!node)
continue; continue;
const Part *part = findPart(node->partId); const SkeletonPart *part = findPart(node->partId);
if (!part) if (!part)
continue; continue;
limitPartIds.insert(node->partId); limitPartIds.insert(node->partId);
@ -1121,7 +1114,7 @@ void Document::addFromSnapshot(const Snapshot &snapshot, bool fromPaste)
} }
for (const auto &partKv: snapshot.parts) { for (const auto &partKv: snapshot.parts) {
const auto newUuid = QUuid::createUuid(); const auto newUuid = QUuid::createUuid();
Part &part = partMap[newUuid]; SkeletonPart &part = partMap[newUuid];
part.id = newUuid; part.id = newUuid;
oldNewIdMap[QUuid(partKv.first)] = part.id; oldNewIdMap[QUuid(partKv.first)] = part.id;
part.name = valueOfKeyInMapOrEmpty(partKv.second, "name"); part.name = valueOfKeyInMapOrEmpty(partKv.second, "name");
@ -1158,7 +1151,7 @@ void Document::addFromSnapshot(const Snapshot &snapshot, bool fromPaste)
nodeKv.second.find("z") == nodeKv.second.end() || nodeKv.second.find("z") == nodeKv.second.end() ||
nodeKv.second.find("partId") == nodeKv.second.end()) nodeKv.second.find("partId") == nodeKv.second.end())
continue; continue;
Node node; SkeletonNode node;
oldNewIdMap[QUuid(nodeKv.first)] = node.id; oldNewIdMap[QUuid(nodeKv.first)] = node.id;
node.name = valueOfKeyInMapOrEmpty(nodeKv.second, "name"); node.name = valueOfKeyInMapOrEmpty(nodeKv.second, "name");
node.radius = valueOfKeyInMapOrEmpty(nodeKv.second, "radius").toFloat(); node.radius = valueOfKeyInMapOrEmpty(nodeKv.second, "radius").toFloat();
@ -1175,7 +1168,7 @@ void Document::addFromSnapshot(const Snapshot &snapshot, bool fromPaste)
edgeKv.second.find("to") == edgeKv.second.end() || edgeKv.second.find("to") == edgeKv.second.end() ||
edgeKv.second.find("partId") == edgeKv.second.end()) edgeKv.second.find("partId") == edgeKv.second.end())
continue; continue;
Edge edge; SkeletonEdge edge;
oldNewIdMap[QUuid(edgeKv.first)] = edge.id; oldNewIdMap[QUuid(edgeKv.first)] = edge.id;
edge.name = valueOfKeyInMapOrEmpty(edgeKv.second, "name"); edge.name = valueOfKeyInMapOrEmpty(edgeKv.second, "name");
edge.partId = oldNewIdMap[QUuid(valueOfKeyInMapOrEmpty(edgeKv.second, "partId"))]; edge.partId = oldNewIdMap[QUuid(valueOfKeyInMapOrEmpty(edgeKv.second, "partId"))];
@ -2330,7 +2323,7 @@ bool Document::redoable() const
bool Document::isNodeEditable(QUuid nodeId) const bool Document::isNodeEditable(QUuid nodeId) const
{ {
const Node *node = findNode(nodeId); const SkeletonNode *node = findNode(nodeId);
if (!node) { if (!node) {
qDebug() << "Node id not found:" << nodeId; qDebug() << "Node id not found:" << nodeId;
return false; return false;
@ -2340,7 +2333,7 @@ bool Document::isNodeEditable(QUuid nodeId) const
bool Document::isEdgeEditable(QUuid edgeId) const bool Document::isEdgeEditable(QUuid edgeId) const
{ {
const Edge *edge = findEdge(edgeId); const SkeletonEdge *edge = findEdge(edgeId);
if (!edge) { if (!edge) {
qDebug() << "Edge id not found:" << edgeId; qDebug() << "Edge id not found:" << edgeId;
return false; return false;
@ -2943,3 +2936,13 @@ bool Document::isMeshGenerating() const
return nullptr != m_meshGenerator; return nullptr != m_meshGenerator;
} }
void Document::copyNodes(std::set<QUuid> nodeIdSet) const
{
Snapshot snapshot;
toSnapshot(&snapshot, nodeIdSet, DocumentToSnapshotFor::Nodes);
QString snapshotXml;
QXmlStreamWriter xmlStreamWriter(&snapshotXml);
saveSkeletonToXmlStream(&snapshot, &xmlStreamWriter);
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(snapshotXml);
}

View File

@ -23,179 +23,11 @@
#include "texturetype.h" #include "texturetype.h"
#include "interpolationtype.h" #include "interpolationtype.h"
#include "jointnodetree.h" #include "jointnodetree.h"
#include "skeletondocument.h"
class MaterialPreviewsGenerator; class MaterialPreviewsGenerator;
class MotionsGenerator; class MotionsGenerator;
class Node
{
public:
Node(const QUuid &withId=QUuid()) :
x(0),
y(0),
z(0),
radius(0),
boneMark(BoneMark::None)
{
id = withId.isNull() ? QUuid::createUuid() : withId;
}
void setRadius(float toRadius)
{
if (toRadius < 0)
toRadius = 0.005;
else if (toRadius > 1)
toRadius = 1;
radius = toRadius;
}
QUuid id;
QUuid partId;
QString name;
float x;
float y;
float z;
float radius;
BoneMark boneMark;
std::vector<QUuid> edgeIds;
};
class Edge
{
public:
Edge(const QUuid &withId=QUuid())
{
id = withId.isNull() ? QUuid::createUuid() : withId;
}
QUuid id;
QUuid partId;
QString name;
std::vector<QUuid> nodeIds;
QUuid neighborOf(QUuid nodeId) const
{
if (nodeIds.size() != 2)
return QUuid();
return nodeIds[0] == nodeId ? nodeIds[1] : nodeIds[0];
}
};
class Part
{
public:
~Part()
{
delete m_previewMesh;
}
QUuid id;
QString name;
bool visible;
bool locked;
bool subdived;
bool disabled;
bool xMirrored;
bool zMirrored;
float deformThickness;
float deformWidth;
bool rounded;
QColor color;
bool hasColor;
QUuid componentId;
std::vector<QUuid> nodeIds;
bool dirty;
bool wrapped;
QUuid materialId;
Part(const QUuid &withId=QUuid()) :
visible(true),
locked(false),
subdived(false),
disabled(false),
xMirrored(false),
zMirrored(false),
deformThickness(1.0),
deformWidth(1.0),
rounded(false),
color(Theme::white),
hasColor(false),
dirty(true),
wrapped(false)
{
id = withId.isNull() ? QUuid::createUuid() : withId;
}
void setDeformThickness(float toThickness)
{
if (toThickness < 0)
toThickness = 0;
else if (toThickness > 2)
toThickness = 2;
deformThickness = toThickness;
}
void setDeformWidth(float toWidth)
{
if (toWidth < 0)
toWidth = 0;
else if (toWidth > 2)
toWidth = 2;
deformWidth = toWidth;
}
bool deformThicknessAdjusted() const
{
return fabs(deformThickness - 1.0) >= 0.01;
}
bool deformWidthAdjusted() const
{
return fabs(deformWidth - 1.0) >= 0.01;
}
bool deformAdjusted() const
{
return deformThicknessAdjusted() || deformWidthAdjusted();
}
bool materialAdjusted() const
{
return !materialId.isNull();
}
bool isEditVisible() const
{
return visible && !disabled;
}
void copyAttributes(const Part &other)
{
visible = other.visible;
locked = other.locked;
subdived = other.subdived;
disabled = other.disabled;
xMirrored = other.xMirrored;
zMirrored = other.zMirrored;
deformThickness = other.deformThickness;
deformWidth = other.deformWidth;
rounded = other.rounded;
color = other.color;
hasColor = other.hasColor;
wrapped = other.wrapped;
componentId = other.componentId;
dirty = other.dirty;
materialId = other.materialId;
}
void updatePreviewMesh(MeshLoader *previewMesh)
{
delete m_previewMesh;
m_previewMesh = previewMesh;
}
MeshLoader *takePreviewMesh() const
{
if (nullptr == m_previewMesh)
return nullptr;
return new MeshLoader(*m_previewMesh);
}
private:
Q_DISABLE_COPY(Part);
MeshLoader *m_previewMesh = nullptr;
};
enum class SkeletonProfile
{
Unknown = 0,
Main,
Side
};
class HistoryItem class HistoryItem
{ {
public: public:
@ -203,15 +35,6 @@ public:
Snapshot snapshot; Snapshot snapshot;
}; };
enum class DocumentEditMode
{
Add = 0,
Select,
Drag,
ZoomIn,
ZoomOut
};
class Component class Component
{ {
public: public:
@ -532,7 +355,7 @@ enum class DocumentToSnapshotFor
Motions Motions
}; };
class Document : public QObject class Document : public SkeletonDocument
{ {
Q_OBJECT Q_OBJECT
signals: signals:
@ -620,14 +443,6 @@ signals:
void textureGenerating(); void textureGenerating();
void textureChanged(); void textureChanged();
public: // need initialize public: // need initialize
float originX;
float originY;
float originZ;
DocumentEditMode editMode;
bool xlocked;
bool ylocked;
bool zlocked;
bool radiusLocked;
QImage *textureGuideImage; QImage *textureGuideImage;
QImage *textureImage; QImage *textureImage;
QImage *textureBorderImage; QImage *textureBorderImage;
@ -638,9 +453,9 @@ public: // need initialize
public: public:
Document(); Document();
~Document(); ~Document();
std::map<QUuid, Part> partMap; std::map<QUuid, SkeletonPart> partMap;
std::map<QUuid, Node> nodeMap; std::map<QUuid, SkeletonNode> nodeMap;
std::map<QUuid, Edge> edgeMap; std::map<QUuid, SkeletonEdge> edgeMap;
std::map<QUuid, Component> componentMap; std::map<QUuid, Component> componentMap;
std::map<QUuid, Material> materialMap; std::map<QUuid, Material> materialMap;
std::vector<QUuid> materialIdList; std::vector<QUuid> materialIdList;
@ -649,8 +464,19 @@ public:
std::map<QUuid, Motion> motionMap; std::map<QUuid, Motion> motionMap;
std::vector<QUuid> motionIdList; std::vector<QUuid> motionIdList;
Component rootComponent; Component rootComponent;
QImage turnaround;
QImage preview; 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<QUuid> &neighbors) const override;
void copyNodes(std::set<QUuid> nodeIdSet) const override;
void toSnapshot(Snapshot *snapshot, const std::set<QUuid> &limitNodeIds=std::set<QUuid>(), void toSnapshot(Snapshot *snapshot, const std::set<QUuid> &limitNodeIds=std::set<QUuid>(),
DocumentToSnapshotFor forWhat=DocumentToSnapshotFor::Document, DocumentToSnapshotFor forWhat=DocumentToSnapshotFor::Document,
const std::set<QUuid> &limitPoseIds=std::set<QUuid>(), const std::set<QUuid> &limitPoseIds=std::set<QUuid>(),
@ -658,10 +484,6 @@ public:
const std::set<QUuid> &limitMaterialIds=std::set<QUuid>()) const; const std::set<QUuid> &limitMaterialIds=std::set<QUuid>()) const;
void fromSnapshot(const Snapshot &snapshot); void fromSnapshot(const Snapshot &snapshot);
void addFromSnapshot(const Snapshot &snapshot, bool fromPaste=true); void addFromSnapshot(const Snapshot &snapshot, bool fromPaste=true);
const Node *findNode(QUuid nodeId) const;
const Edge *findEdge(QUuid edgeId) const;
const Part *findPart(QUuid partId) const;
const Edge *findEdgeByNodes(QUuid firstNodeId, QUuid secondNodeId) const;
const Component *findComponent(QUuid componentId) const; const Component *findComponent(QUuid componentId) const;
const Component *findComponentParent(QUuid componentId) const; const Component *findComponentParent(QUuid componentId) const;
QUuid findComponentParentId(QUuid componentId) const; QUuid findComponentParentId(QUuid componentId) const;
@ -675,19 +497,12 @@ public:
const std::map<int, RiggerVertexWeights> *resultRigWeights() const; const std::map<int, RiggerVertexWeights> *resultRigWeights() const;
void updateTurnaround(const QImage &image); void updateTurnaround(const QImage &image);
void setSharedContextWidget(QOpenGLWidget *sharedContextWidget); void setSharedContextWidget(QOpenGLWidget *sharedContextWidget);
bool hasPastableNodesInClipboard() const;
bool hasPastableMaterialsInClipboard() const; bool hasPastableMaterialsInClipboard() const;
bool hasPastablePosesInClipboard() const; bool hasPastablePosesInClipboard() const;
bool hasPastableMotionsInClipboard() const; bool hasPastableMotionsInClipboard() const;
bool undoable() const;
bool redoable() const;
bool isNodeEditable(QUuid nodeId) const;
bool isEdgeEditable(QUuid edgeId) const;
bool originSettled() const;
const Outcome &currentPostProcessedOutcome() const; const Outcome &currentPostProcessedOutcome() const;
bool isExportReady() const; bool isExportReady() const;
bool isPostProcessResultObsolete() const; bool isPostProcessResultObsolete() const;
void findAllNeighbors(QUuid nodeId, std::set<QUuid> &neighbors) const;
void collectComponentDescendantParts(QUuid componentId, std::vector<QUuid> &partIds) const; void collectComponentDescendantParts(QUuid componentId, std::vector<QUuid> &partIds) const;
void collectComponentDescendantComponents(QUuid componentId, std::vector<QUuid> &componentIds) const; void collectComponentDescendantComponents(QUuid componentId, std::vector<QUuid> &componentIds) const;
const std::vector<QString> &resultRigMissingMarkNames() const; const std::vector<QString> &resultRigMissingMarkNames() const;
@ -696,6 +511,9 @@ public:
bool currentRigSucceed() const; bool currentRigSucceed() const;
bool isMeshGenerating() const; bool isMeshGenerating() const;
public slots: public slots:
void undo() override;
void redo() override;
void paste() override;
void removeNode(QUuid nodeId); void removeNode(QUuid nodeId);
void removeEdge(QUuid edgeId); void removeEdge(QUuid edgeId);
void removePart(QUuid partId); void removePart(QUuid partId);
@ -708,7 +526,7 @@ public slots:
void switchNodeXZ(QUuid nodeId); void switchNodeXZ(QUuid nodeId);
void moveOriginBy(float x, float y, float z); void moveOriginBy(float x, float y, float z);
void addEdge(QUuid fromNodeId, QUuid toNodeId); void addEdge(QUuid fromNodeId, QUuid toNodeId);
void setEditMode(DocumentEditMode mode); void setEditMode(SkeletonDocumentEditMode mode);
void uiReady(); void uiReady();
void generateMesh(); void generateMesh();
void regenerateMesh(); void regenerateMesh();
@ -765,9 +583,6 @@ public slots:
void lockDescendantComponents(QUuid componentId); void lockDescendantComponents(QUuid componentId);
void unlockDescendantComponents(QUuid componentId); void unlockDescendantComponents(QUuid componentId);
void saveSnapshot(); void saveSnapshot();
void undo();
void redo();
void paste();
void batchChangeBegin(); void batchChangeBegin();
void batchChangeEnd(); void batchChangeEnd();
void reset(); void reset();

View File

@ -371,7 +371,7 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
m_addAction = new QAction(tr("Add..."), this); m_addAction = new QAction(tr("Add..."), this);
connect(m_addAction, &QAction::triggered, [=]() { connect(m_addAction, &QAction::triggered, [=]() {
m_document->setEditMode(DocumentEditMode::Add); m_document->setEditMode(SkeletonDocumentEditMode::Add);
}); });
m_editMenu->addAction(m_addAction); m_editMenu->addAction(m_addAction);
@ -657,23 +657,23 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
connect(rotateClockwiseButton, &QPushButton::clicked, graphicsWidget, &SkeletonGraphicsWidget::rotateAllMainProfileClockwise90DegreeAlongOrigin); connect(rotateClockwiseButton, &QPushButton::clicked, graphicsWidget, &SkeletonGraphicsWidget::rotateAllMainProfileClockwise90DegreeAlongOrigin);
connect(addButton, &QPushButton::clicked, [=]() { connect(addButton, &QPushButton::clicked, [=]() {
m_document->setEditMode(DocumentEditMode::Add); m_document->setEditMode(SkeletonDocumentEditMode::Add);
}); });
connect(selectButton, &QPushButton::clicked, [=]() { connect(selectButton, &QPushButton::clicked, [=]() {
m_document->setEditMode(DocumentEditMode::Select); m_document->setEditMode(SkeletonDocumentEditMode::Select);
}); });
connect(dragButton, &QPushButton::clicked, [=]() { connect(dragButton, &QPushButton::clicked, [=]() {
m_document->setEditMode(DocumentEditMode::Drag); m_document->setEditMode(SkeletonDocumentEditMode::Drag);
}); });
connect(zoomInButton, &QPushButton::clicked, [=]() { connect(zoomInButton, &QPushButton::clicked, [=]() {
m_document->setEditMode(DocumentEditMode::ZoomIn); m_document->setEditMode(SkeletonDocumentEditMode::ZoomIn);
}); });
connect(zoomOutButton, &QPushButton::clicked, [=]() { connect(zoomOutButton, &QPushButton::clicked, [=]() {
m_document->setEditMode(DocumentEditMode::ZoomOut); m_document->setEditMode(SkeletonDocumentEditMode::ZoomOut);
}); });
connect(m_xlockButton, &QPushButton::clicked, [=]() { connect(m_xlockButton, &QPushButton::clicked, [=]() {

View File

@ -193,7 +193,7 @@ void PartTreeWidget::mousePressEvent(QMouseEvent *event)
void PartTreeWidget::showContextMenu(const QPoint &pos) void PartTreeWidget::showContextMenu(const QPoint &pos)
{ {
const Component *component = nullptr; const Component *component = nullptr;
const Part *part = nullptr; const SkeletonPart *part = nullptr;
PartWidget *partWidget = nullptr; PartWidget *partWidget = nullptr;
std::set<QUuid> unorderedComponentIds = m_selectedComponentIds; std::set<QUuid> unorderedComponentIds = m_selectedComponentIds;

View File

@ -143,7 +143,7 @@ PartWidget::PartWidget(const Document *document, QUuid partId) :
connect(this, &PartWidget::groupOperationAdded, m_document, &Document::saveSnapshot); connect(this, &PartWidget::groupOperationAdded, m_document, &Document::saveSnapshot);
connect(m_lockButton, &QPushButton::clicked, [=]() { connect(m_lockButton, &QPushButton::clicked, [=]() {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -153,7 +153,7 @@ PartWidget::PartWidget(const Document *document, QUuid partId) :
}); });
connect(m_visibleButton, &QPushButton::clicked, [=]() { connect(m_visibleButton, &QPushButton::clicked, [=]() {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -163,7 +163,7 @@ PartWidget::PartWidget(const Document *document, QUuid partId) :
}); });
connect(m_subdivButton, &QPushButton::clicked, [=]() { connect(m_subdivButton, &QPushButton::clicked, [=]() {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -173,7 +173,7 @@ PartWidget::PartWidget(const Document *document, QUuid partId) :
}); });
connect(m_disableButton, &QPushButton::clicked, [=]() { connect(m_disableButton, &QPushButton::clicked, [=]() {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -183,7 +183,7 @@ PartWidget::PartWidget(const Document *document, QUuid partId) :
}); });
connect(m_xMirrorButton, &QPushButton::clicked, [=]() { connect(m_xMirrorButton, &QPushButton::clicked, [=]() {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -193,7 +193,7 @@ PartWidget::PartWidget(const Document *document, QUuid partId) :
}); });
connect(m_deformButton, &QPushButton::clicked, [=]() { connect(m_deformButton, &QPushButton::clicked, [=]() {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -202,7 +202,7 @@ PartWidget::PartWidget(const Document *document, QUuid partId) :
}); });
connect(m_roundButton, &QPushButton::clicked, [=]() { connect(m_roundButton, &QPushButton::clicked, [=]() {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -212,7 +212,7 @@ PartWidget::PartWidget(const Document *document, QUuid partId) :
}); });
connect(m_colorButton, &QPushButton::clicked, [=]() { connect(m_colorButton, &QPushButton::clicked, [=]() {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -221,7 +221,7 @@ PartWidget::PartWidget(const Document *document, QUuid partId) :
}); });
connect(m_wrapButton, &QPushButton::clicked, [=]() { connect(m_wrapButton, &QPushButton::clicked, [=]() {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -287,7 +287,7 @@ void PartWidget::showColorSettingPopup(const QPoint &pos)
{ {
QMenu popupMenu; QMenu popupMenu;
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Find part failed:" << m_partId; qDebug() << "Find part failed:" << m_partId;
return; return;
@ -358,7 +358,7 @@ void PartWidget::showDeformSettingPopup(const QPoint &pos)
{ {
QMenu popupMenu; QMenu popupMenu;
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Find part failed:" << m_partId; qDebug() << "Find part failed:" << m_partId;
return; return;
@ -434,7 +434,7 @@ void PartWidget::updateButton(QPushButton *button, QChar icon, bool highlighted)
void PartWidget::updatePreview() void PartWidget::updatePreview()
{ {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -446,7 +446,7 @@ void PartWidget::updatePreview()
void PartWidget::updateLockButton() void PartWidget::updateLockButton()
{ {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -459,7 +459,7 @@ void PartWidget::updateLockButton()
void PartWidget::updateVisibleButton() void PartWidget::updateVisibleButton()
{ {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -472,7 +472,7 @@ void PartWidget::updateVisibleButton()
void PartWidget::updateSubdivButton() void PartWidget::updateSubdivButton()
{ {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -485,7 +485,7 @@ void PartWidget::updateSubdivButton()
void PartWidget::updateDisableButton() void PartWidget::updateDisableButton()
{ {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -498,7 +498,7 @@ void PartWidget::updateDisableButton()
void PartWidget::updateXmirrorButton() void PartWidget::updateXmirrorButton()
{ {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -511,7 +511,7 @@ void PartWidget::updateXmirrorButton()
void PartWidget::updateDeformButton() void PartWidget::updateDeformButton()
{ {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -524,7 +524,7 @@ void PartWidget::updateDeformButton()
void PartWidget::updateRoundButton() void PartWidget::updateRoundButton()
{ {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -537,7 +537,7 @@ void PartWidget::updateRoundButton()
void PartWidget::updateColorButton() void PartWidget::updateColorButton()
{ {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;
@ -550,7 +550,7 @@ void PartWidget::updateColorButton()
void PartWidget::updateWrapButton() void PartWidget::updateWrapButton()
{ {
const Part *part = m_document->findPart(m_partId); const SkeletonPart *part = m_document->findPart(m_partId);
if (!part) { if (!part) {
qDebug() << "Part not found:" << m_partId; qDebug() << "Part not found:" << m_partId;
return; return;

2
src/skeletondocument.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "skeletondocument.h"

223
src/skeletondocument.h Normal file
View File

@ -0,0 +1,223 @@
#ifndef DUST3D_SKELETON_DOCUMENT_H
#define DUST3D_SKELETON_DOCUMENT_H
#include <QUuid>
#include <QObject>
#include <QString>
#include <cmath>
#include <QImage>
#include "bonemark.h"
#include "theme.h"
#include "meshloader.h"
class SkeletonNode
{
public:
SkeletonNode(const QUuid &withId=QUuid()) :
x(0),
y(0),
z(0),
radius(0),
boneMark(BoneMark::None)
{
id = withId.isNull() ? QUuid::createUuid() : withId;
}
void setRadius(float toRadius)
{
if (toRadius < 0)
toRadius = 0.005;
else if (toRadius > 1)
toRadius = 1;
radius = toRadius;
}
QUuid id;
QUuid partId;
QString name;
float x;
float y;
float z;
float radius;
BoneMark boneMark;
std::vector<QUuid> edgeIds;
};
class SkeletonEdge
{
public:
SkeletonEdge(const QUuid &withId=QUuid())
{
id = withId.isNull() ? QUuid::createUuid() : withId;
}
QUuid id;
QUuid partId;
QString name;
std::vector<QUuid> nodeIds;
QUuid neighborOf(QUuid nodeId) const
{
if (nodeIds.size() != 2)
return QUuid();
return nodeIds[0] == nodeId ? nodeIds[1] : nodeIds[0];
}
};
class SkeletonPart
{
public:
~SkeletonPart()
{
delete m_previewMesh;
}
QUuid id;
QString name;
bool visible;
bool locked;
bool subdived;
bool disabled;
bool xMirrored;
bool zMirrored;
float deformThickness;
float deformWidth;
bool rounded;
QColor color;
bool hasColor;
QUuid componentId;
std::vector<QUuid> nodeIds;
bool dirty;
bool wrapped;
QUuid materialId;
SkeletonPart(const QUuid &withId=QUuid()) :
visible(true),
locked(false),
subdived(false),
disabled(false),
xMirrored(false),
zMirrored(false),
deformThickness(1.0),
deformWidth(1.0),
rounded(false),
color(Theme::white),
hasColor(false),
dirty(true),
wrapped(false)
{
id = withId.isNull() ? QUuid::createUuid() : withId;
}
void setDeformThickness(float toThickness)
{
if (toThickness < 0)
toThickness = 0;
else if (toThickness > 2)
toThickness = 2;
deformThickness = toThickness;
}
void setDeformWidth(float toWidth)
{
if (toWidth < 0)
toWidth = 0;
else if (toWidth > 2)
toWidth = 2;
deformWidth = toWidth;
}
bool deformThicknessAdjusted() const
{
return fabs(deformThickness - 1.0) >= 0.01;
}
bool deformWidthAdjusted() const
{
return fabs(deformWidth - 1.0) >= 0.01;
}
bool deformAdjusted() const
{
return deformThicknessAdjusted() || deformWidthAdjusted();
}
bool materialAdjusted() const
{
return !materialId.isNull();
}
bool isEditVisible() const
{
return visible && !disabled;
}
void copyAttributes(const SkeletonPart &other)
{
visible = other.visible;
locked = other.locked;
subdived = other.subdived;
disabled = other.disabled;
xMirrored = other.xMirrored;
zMirrored = other.zMirrored;
deformThickness = other.deformThickness;
deformWidth = other.deformWidth;
rounded = other.rounded;
color = other.color;
hasColor = other.hasColor;
wrapped = other.wrapped;
componentId = other.componentId;
dirty = other.dirty;
materialId = other.materialId;
}
void updatePreviewMesh(MeshLoader *previewMesh)
{
delete m_previewMesh;
m_previewMesh = previewMesh;
}
MeshLoader *takePreviewMesh() const
{
if (nullptr == m_previewMesh)
return nullptr;
return new MeshLoader(*m_previewMesh);
}
private:
Q_DISABLE_COPY(SkeletonPart);
MeshLoader *m_previewMesh = nullptr;
};
enum class SkeletonDocumentEditMode
{
Add = 0,
Select,
Drag,
ZoomIn,
ZoomOut
};
enum class SkeletonProfile
{
Unknown = 0,
Main,
Side
};
class SkeletonDocument : public QObject
{
Q_OBJECT
public:
float originX = 0;
float originY = 0;
float originZ = 0;
SkeletonDocumentEditMode editMode = SkeletonDocumentEditMode::Select;
bool xlocked = false;
bool ylocked = false;
bool zlocked = false;
bool radiusLocked = false;
QImage turnaround;
virtual const SkeletonNode *findNode(QUuid nodeId) const = 0;
virtual const SkeletonEdge *findEdge(QUuid edgeId) const = 0;
virtual const SkeletonPart *findPart(QUuid partId) const = 0;
virtual const SkeletonEdge *findEdgeByNodes(QUuid firstNodeId, QUuid secondNodeId) const = 0;
virtual bool undoable() const = 0;
virtual bool redoable() const = 0;
virtual bool hasPastableNodesInClipboard() const = 0;
virtual bool originSettled() const = 0;
virtual bool isNodeEditable(QUuid nodeId) const = 0;
virtual bool isEdgeEditable(QUuid edgeId) const = 0;
virtual void findAllNeighbors(QUuid nodeId, std::set<QUuid> &neighbors) const = 0;
virtual void copyNodes(std::set<QUuid> nodeIdSet) const = 0;
public slots:
virtual void undo() = 0;
virtual void redo() = 0;
virtual void paste() = 0;
};
#endif

View File

@ -7,7 +7,6 @@
#include <QVector2D> #include <QVector2D>
#include <QMenu> #include <QMenu>
#include <QApplication> #include <QApplication>
#include <QClipboard>
#include <QMatrix4x4> #include <QMatrix4x4>
#include "skeletongraphicswidget.h" #include "skeletongraphicswidget.h"
#include "theme.h" #include "theme.h"
@ -15,7 +14,7 @@
#include "snapshotxml.h" #include "snapshotxml.h"
#include "markiconcreator.h" #include "markiconcreator.h"
SkeletonGraphicsWidget::SkeletonGraphicsWidget(const Document *document) : SkeletonGraphicsWidget::SkeletonGraphicsWidget(const SkeletonDocument *document) :
m_document(document), m_document(document),
m_backgroundItem(nullptr), m_backgroundItem(nullptr),
m_turnaroundChanged(false), m_turnaroundChanged(false),
@ -45,7 +44,7 @@ SkeletonGraphicsWidget::SkeletonGraphicsWidget(const Document *document) :
m_eventForwardingToModelWidget(false), m_eventForwardingToModelWidget(false),
m_modelWidget(nullptr), m_modelWidget(nullptr),
m_inTempDragMode(false), m_inTempDragMode(false),
m_modeBeforeEnterTempDragMode(DocumentEditMode::Select) m_modeBeforeEnterTempDragMode(SkeletonDocumentEditMode::Select)
{ {
setRenderHint(QPainter::Antialiasing, false); setRenderHint(QPainter::Antialiasing, false);
setBackgroundBrush(QBrush(QWidget::palette().color(QWidget::backgroundRole()), Qt::SolidPattern)); setBackgroundBrush(QBrush(QWidget::palette().color(QWidget::backgroundRole()), Qt::SolidPattern));
@ -107,12 +106,12 @@ void SkeletonGraphicsWidget::disableBackgroundBlur()
void SkeletonGraphicsWidget::showContextMenu(const QPoint &pos) void SkeletonGraphicsWidget::showContextMenu(const QPoint &pos)
{ {
if (DocumentEditMode::Add == m_document->editMode) { if (SkeletonDocumentEditMode::Add == m_document->editMode) {
emit setEditMode(DocumentEditMode::Select); emit setEditMode(SkeletonDocumentEditMode::Select);
return; return;
} }
if (DocumentEditMode::Select != m_document->editMode) { if (SkeletonDocumentEditMode::Select != m_document->editMode) {
return; return;
} }
@ -120,19 +119,19 @@ void SkeletonGraphicsWidget::showContextMenu(const QPoint &pos)
QAction addAction(tr("Add..."), this); QAction addAction(tr("Add..."), this);
connect(&addAction, &QAction::triggered, [=]() { connect(&addAction, &QAction::triggered, [=]() {
emit setEditMode(DocumentEditMode::Add); emit setEditMode(SkeletonDocumentEditMode::Add);
}); });
contextMenu.addAction(&addAction); contextMenu.addAction(&addAction);
QAction undoAction(tr("Undo"), this); QAction undoAction(tr("Undo"), this);
if (m_document->undoable()) { if (m_document->undoable()) {
connect(&undoAction, &QAction::triggered, m_document, &Document::undo); connect(&undoAction, &QAction::triggered, m_document, &SkeletonDocument::undo);
contextMenu.addAction(&undoAction); contextMenu.addAction(&undoAction);
} }
QAction redoAction(tr("Redo"), this); QAction redoAction(tr("Redo"), this);
if (m_document->redoable()) { if (m_document->redoable()) {
connect(&redoAction, &QAction::triggered, m_document, &Document::redo); connect(&redoAction, &QAction::triggered, m_document, &SkeletonDocument::redo);
contextMenu.addAction(&redoAction); contextMenu.addAction(&redoAction);
} }
@ -168,7 +167,7 @@ void SkeletonGraphicsWidget::showContextMenu(const QPoint &pos)
QAction pasteAction(tr("Paste"), this); QAction pasteAction(tr("Paste"), this);
if (m_document->hasPastableNodesInClipboard()) { if (m_document->hasPastableNodesInClipboard()) {
connect(&pasteAction, &QAction::triggered, m_document, &Document::paste); connect(&pasteAction, &QAction::triggered, m_document, &SkeletonDocument::paste);
contextMenu.addAction(&pasteAction); contextMenu.addAction(&pasteAction);
} }
@ -404,7 +403,7 @@ void SkeletonGraphicsWidget::alignSelectedToGlobal(bool alignToVerticalCenter, b
return; return;
emit batchChangeBegin(); emit batchChangeBegin();
for (const auto &nodeItem: nodeItems) { for (const auto &nodeItem: nodeItems) {
const Node *node = m_document->findNode(nodeItem->id()); const SkeletonNode *node = m_document->findNode(nodeItem->id());
if (!node) { if (!node) {
qDebug() << "Find node id failed:" << nodeItem->id(); qDebug() << "Find node id failed:" << nodeItem->id();
continue; continue;
@ -530,25 +529,25 @@ void SkeletonGraphicsWidget::turnaroundImageReady()
void SkeletonGraphicsWidget::updateCursor() void SkeletonGraphicsWidget::updateCursor()
{ {
if (DocumentEditMode::Add != m_document->editMode) { if (SkeletonDocumentEditMode::Add != m_document->editMode) {
m_cursorEdgeItem->hide(); m_cursorEdgeItem->hide();
m_cursorNodeItem->hide(); m_cursorNodeItem->hide();
} }
switch (m_document->editMode) { switch (m_document->editMode) {
case DocumentEditMode::Add: case SkeletonDocumentEditMode::Add:
setCursor(QCursor(Theme::awesome()->icon(fa::plus).pixmap(Theme::toolIconFontSize, Theme::toolIconFontSize))); setCursor(QCursor(Theme::awesome()->icon(fa::plus).pixmap(Theme::toolIconFontSize, Theme::toolIconFontSize)));
break; break;
case DocumentEditMode::Select: case SkeletonDocumentEditMode::Select:
setCursor(QCursor(Theme::awesome()->icon(fa::mousepointer).pixmap(Theme::toolIconFontSize, Theme::toolIconFontSize), Theme::toolIconFontSize / 5, 0)); setCursor(QCursor(Theme::awesome()->icon(fa::mousepointer).pixmap(Theme::toolIconFontSize, Theme::toolIconFontSize), Theme::toolIconFontSize / 5, 0));
break; break;
case DocumentEditMode::Drag: case SkeletonDocumentEditMode::Drag:
setCursor(QCursor(Theme::awesome()->icon(m_dragStarted ? fa::handrocko : fa::handpapero).pixmap(Theme::toolIconFontSize, Theme::toolIconFontSize))); setCursor(QCursor(Theme::awesome()->icon(m_dragStarted ? fa::handrocko : fa::handpapero).pixmap(Theme::toolIconFontSize, Theme::toolIconFontSize)));
break; break;
case DocumentEditMode::ZoomIn: case SkeletonDocumentEditMode::ZoomIn:
setCursor(QCursor(Theme::awesome()->icon(fa::searchplus).pixmap(Theme::toolIconFontSize, Theme::toolIconFontSize))); setCursor(QCursor(Theme::awesome()->icon(fa::searchplus).pixmap(Theme::toolIconFontSize, Theme::toolIconFontSize)));
break; break;
case DocumentEditMode::ZoomOut: case SkeletonDocumentEditMode::ZoomOut:
setCursor(QCursor(Theme::awesome()->icon(fa::searchminus).pixmap(Theme::toolIconFontSize, Theme::toolIconFontSize))); setCursor(QCursor(Theme::awesome()->icon(fa::searchminus).pixmap(Theme::toolIconFontSize, Theme::toolIconFontSize)));
break; break;
} }
@ -559,7 +558,7 @@ void SkeletonGraphicsWidget::updateCursor()
void SkeletonGraphicsWidget::editModeChanged() void SkeletonGraphicsWidget::editModeChanged()
{ {
updateCursor(); updateCursor();
if (DocumentEditMode::Add == m_document->editMode) { if (SkeletonDocumentEditMode::Add == m_document->editMode) {
SkeletonGraphicsNodeItem *choosenNodeItem = nullptr; SkeletonGraphicsNodeItem *choosenNodeItem = nullptr;
if (!m_rangeSelectionSet.empty()) { if (!m_rangeSelectionSet.empty()) {
std::set<SkeletonGraphicsNodeItem *> nodeItems; std::set<SkeletonGraphicsNodeItem *> nodeItems;
@ -648,7 +647,7 @@ bool SkeletonGraphicsWidget::mouseMove(QMouseEvent *event)
return true; return true;
} }
if (DocumentEditMode::Select == m_document->editMode) { if (SkeletonDocumentEditMode::Select == m_document->editMode) {
if (m_rangeSelectionStarted) { if (m_rangeSelectionStarted) {
QPointF mouseScenePos = mouseEventScenePos(event); QPointF mouseScenePos = mouseEventScenePos(event);
m_selectionItem->updateRange(m_rangeSelectionStartPos, mouseScenePos); m_selectionItem->updateRange(m_rangeSelectionStartPos, mouseScenePos);
@ -659,8 +658,8 @@ bool SkeletonGraphicsWidget::mouseMove(QMouseEvent *event)
} }
} }
if (DocumentEditMode::Select == m_document->editMode || if (SkeletonDocumentEditMode::Select == m_document->editMode ||
DocumentEditMode::Add == m_document->editMode) { SkeletonDocumentEditMode::Add == m_document->editMode) {
// //
// > For overlapping nodes, you can make it a bit better by selecting the node center nearest the mouse, rather than simply checking against the wider circle. // > For overlapping nodes, you can make it a bit better by selecting the node center nearest the mouse, rather than simply checking against the wider circle.
@ -746,7 +745,7 @@ bool SkeletonGraphicsWidget::mouseMove(QMouseEvent *event)
hoverPart(hoveredPartId); hoverPart(hoveredPartId);
} }
if (DocumentEditMode::Add == m_document->editMode) { if (SkeletonDocumentEditMode::Add == m_document->editMode) {
QPointF mouseScenePos = mouseEventScenePos(event); QPointF mouseScenePos = mouseEventScenePos(event);
m_cursorNodeItem->setOrigin(mouseScenePos); m_cursorNodeItem->setOrigin(mouseScenePos);
if (!m_cursorNodeItem->isVisible()) { if (!m_cursorNodeItem->isVisible()) {
@ -761,7 +760,7 @@ bool SkeletonGraphicsWidget::mouseMove(QMouseEvent *event)
return true; return true;
} }
if (DocumentEditMode::Select == m_document->editMode) { if (SkeletonDocumentEditMode::Select == m_document->editMode) {
if (m_moveStarted) { if (m_moveStarted) {
if (m_checkedOriginItem) { if (m_checkedOriginItem) {
QPointF mouseScenePos = mouseEventScenePos(event); QPointF mouseScenePos = mouseEventScenePos(event);
@ -781,7 +780,7 @@ bool SkeletonGraphicsWidget::mouseMove(QMouseEvent *event)
bool ikMoved = false; bool ikMoved = false;
if (nodeItems.size() == 1) { if (nodeItems.size() == 1) {
auto &nodeItem = *nodeItems.begin(); auto &nodeItem = *nodeItems.begin();
const Node *node = m_document->findNode(nodeItem->id()); const SkeletonNode *node = m_document->findNode(nodeItem->id());
if (node->edgeIds.size() == 1) { if (node->edgeIds.size() == 1) {
const auto origin = nodeItem->origin(); const auto origin = nodeItem->origin();
byX = mouseScenePos.x() - origin.x(); byX = mouseScenePos.x() - origin.x();
@ -1024,12 +1023,12 @@ bool SkeletonGraphicsWidget::wheel(QWheelEvent *event)
if (fabs(delta) < 1) if (fabs(delta) < 1)
delta = delta < 0 ? -1.0 : 1.0; delta = delta < 0 ? -1.0 : 1.0;
} }
if (DocumentEditMode::Add == m_document->editMode) { if (SkeletonDocumentEditMode::Add == m_document->editMode) {
if (m_cursorNodeItem->isVisible()) { if (m_cursorNodeItem->isVisible()) {
m_cursorNodeItem->setRadius(m_cursorNodeItem->radius() + delta); m_cursorNodeItem->setRadius(m_cursorNodeItem->radius() + delta);
return true; return true;
} }
} else if (DocumentEditMode::Select == m_document->editMode) { } else if (SkeletonDocumentEditMode::Select == m_document->editMode) {
if (!m_rangeSelectionSet.empty()) { if (!m_rangeSelectionSet.empty()) {
if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier)) { if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier)) {
scaleSelected(delta); scaleSelected(delta);
@ -1165,13 +1164,13 @@ QPointF SkeletonGraphicsWidget::mouseEventScenePos(QMouseEvent *event)
bool SkeletonGraphicsWidget::mousePress(QMouseEvent *event) bool SkeletonGraphicsWidget::mousePress(QMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton) { if (event->button() == Qt::LeftButton) {
if (DocumentEditMode::ZoomIn == m_document->editMode) { if (SkeletonDocumentEditMode::ZoomIn == m_document->editMode) {
ViewportAnchor lastAnchor = transformationAnchor(); ViewportAnchor lastAnchor = transformationAnchor();
setTransformationAnchor(QGraphicsView::AnchorUnderMouse); setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
scale(1.5, 1.5); scale(1.5, 1.5);
setTransformationAnchor(lastAnchor); setTransformationAnchor(lastAnchor);
return true; return true;
} else if (DocumentEditMode::ZoomOut == m_document->editMode) { } else if (SkeletonDocumentEditMode::ZoomOut == m_document->editMode) {
ViewportAnchor lastAnchor = transformationAnchor(); ViewportAnchor lastAnchor = transformationAnchor();
setTransformationAnchor(QGraphicsView::AnchorUnderMouse); setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
scale(0.5, 0.5); scale(0.5, 0.5);
@ -1181,13 +1180,13 @@ bool SkeletonGraphicsWidget::mousePress(QMouseEvent *event)
setTransform(QTransform()); setTransform(QTransform());
} }
return true; return true;
} else if (DocumentEditMode::Drag == m_document->editMode) { } else if (SkeletonDocumentEditMode::Drag == m_document->editMode) {
if (!m_dragStarted) { if (!m_dragStarted) {
m_lastGlobalPos = event->globalPos(); m_lastGlobalPos = event->globalPos();
m_dragStarted = true; m_dragStarted = true;
updateCursor(); updateCursor();
} }
} else if (DocumentEditMode::Add == m_document->editMode) { } else if (SkeletonDocumentEditMode::Add == m_document->editMode) {
if (m_cursorNodeItem->isVisible()) { if (m_cursorNodeItem->isVisible()) {
if (m_addFromNodeItem) { if (m_addFromNodeItem) {
if (m_hoveredNodeItem && m_addFromNodeItem && if (m_hoveredNodeItem && m_addFromNodeItem &&
@ -1226,7 +1225,7 @@ bool SkeletonGraphicsWidget::mousePress(QMouseEvent *event)
emit groupOperationAdded(); emit groupOperationAdded();
return true; return true;
} }
} else if (DocumentEditMode::Select == m_document->editMode) { } else if (SkeletonDocumentEditMode::Select == m_document->editMode) {
bool processed = false; bool processed = false;
if (m_hoveredOriginItem != m_checkedOriginItem) { if (m_hoveredOriginItem != m_checkedOriginItem) {
if (m_checkedOriginItem) { if (m_checkedOriginItem) {
@ -1284,7 +1283,7 @@ bool SkeletonGraphicsWidget::mousePress(QMouseEvent *event)
} }
if (event->button() == Qt::LeftButton) { if (event->button() == Qt::LeftButton) {
if (DocumentEditMode::Select == m_document->editMode) { if (SkeletonDocumentEditMode::Select == m_document->editMode) {
if (!m_rangeSelectionStarted) { if (!m_rangeSelectionStarted) {
m_rangeSelectionStartPos = mouseEventScenePos(event); m_rangeSelectionStartPos = mouseEventScenePos(event);
m_rangeSelectionStarted = true; m_rangeSelectionStarted = true;
@ -1398,10 +1397,10 @@ void SkeletonGraphicsWidget::shortcutDelete()
void SkeletonGraphicsWidget::shortcutAddMode() void SkeletonGraphicsWidget::shortcutAddMode()
{ {
if (DocumentEditMode::Add == m_document->editMode) { if (SkeletonDocumentEditMode::Add == m_document->editMode) {
emit setEditMode(DocumentEditMode::Select); emit setEditMode(SkeletonDocumentEditMode::Select);
} else { } else {
emit setEditMode(DocumentEditMode::Add); emit setEditMode(SkeletonDocumentEditMode::Add);
} }
} }
@ -1452,12 +1451,12 @@ void SkeletonGraphicsWidget::shortcutSave()
void SkeletonGraphicsWidget::shortcutSelectMode() void SkeletonGraphicsWidget::shortcutSelectMode()
{ {
emit setEditMode(DocumentEditMode::Select); emit setEditMode(SkeletonDocumentEditMode::Select);
} }
void SkeletonGraphicsWidget::shortcutDragMode() void SkeletonGraphicsWidget::shortcutDragMode()
{ {
emit setEditMode(DocumentEditMode::Drag); emit setEditMode(SkeletonDocumentEditMode::Drag);
} }
void SkeletonGraphicsWidget::shortcutZoomRenderedModelByMinus10() void SkeletonGraphicsWidget::shortcutZoomRenderedModelByMinus10()
@ -1467,7 +1466,7 @@ void SkeletonGraphicsWidget::shortcutZoomRenderedModelByMinus10()
void SkeletonGraphicsWidget::shortcutZoomSelectedByMinus1() void SkeletonGraphicsWidget::shortcutZoomSelectedByMinus1()
{ {
if (DocumentEditMode::Select == m_document->editMode && hasSelection()) { if (SkeletonDocumentEditMode::Select == m_document->editMode && hasSelection()) {
zoomSelected(-1); zoomSelected(-1);
emit groupOperationAdded(); emit groupOperationAdded();
} }
@ -1480,7 +1479,7 @@ void SkeletonGraphicsWidget::shortcutZoomRenderedModelBy10()
void SkeletonGraphicsWidget::shortcutZoomSelectedBy1() void SkeletonGraphicsWidget::shortcutZoomSelectedBy1()
{ {
if (DocumentEditMode::Select == m_document->editMode && hasSelection()) { if (SkeletonDocumentEditMode::Select == m_document->editMode && hasSelection()) {
zoomSelected(1); zoomSelected(1);
emit groupOperationAdded(); emit groupOperationAdded();
} }
@ -1488,7 +1487,7 @@ void SkeletonGraphicsWidget::shortcutZoomSelectedBy1()
void SkeletonGraphicsWidget::shortcutRotateSelectedByMinus1() void SkeletonGraphicsWidget::shortcutRotateSelectedByMinus1()
{ {
if (DocumentEditMode::Select == m_document->editMode && hasSelection()) { if (SkeletonDocumentEditMode::Select == m_document->editMode && hasSelection()) {
rotateSelected(-1); rotateSelected(-1);
emit groupOperationAdded(); emit groupOperationAdded();
} }
@ -1496,7 +1495,7 @@ void SkeletonGraphicsWidget::shortcutRotateSelectedByMinus1()
void SkeletonGraphicsWidget::shortcutRotateSelectedBy1() void SkeletonGraphicsWidget::shortcutRotateSelectedBy1()
{ {
if (DocumentEditMode::Select == m_document->editMode && hasSelection()) { if (SkeletonDocumentEditMode::Select == m_document->editMode && hasSelection()) {
rotateSelected(1); rotateSelected(1);
emit groupOperationAdded(); emit groupOperationAdded();
} }
@ -1504,7 +1503,7 @@ void SkeletonGraphicsWidget::shortcutRotateSelectedBy1()
void SkeletonGraphicsWidget::shortcutMoveSelectedToLeft() void SkeletonGraphicsWidget::shortcutMoveSelectedToLeft()
{ {
if (DocumentEditMode::Select == m_document->editMode) { if (SkeletonDocumentEditMode::Select == m_document->editMode) {
if (m_checkedOriginItem) { if (m_checkedOriginItem) {
moveCheckedOrigin(-1, 0); moveCheckedOrigin(-1, 0);
emit groupOperationAdded(); emit groupOperationAdded();
@ -1517,7 +1516,7 @@ void SkeletonGraphicsWidget::shortcutMoveSelectedToLeft()
void SkeletonGraphicsWidget::shortcutMoveSelectedToRight() void SkeletonGraphicsWidget::shortcutMoveSelectedToRight()
{ {
if (DocumentEditMode::Select == m_document->editMode) { if (SkeletonDocumentEditMode::Select == m_document->editMode) {
if (m_checkedOriginItem) { if (m_checkedOriginItem) {
moveCheckedOrigin(1, 0); moveCheckedOrigin(1, 0);
emit groupOperationAdded(); emit groupOperationAdded();
@ -1530,7 +1529,7 @@ void SkeletonGraphicsWidget::shortcutMoveSelectedToRight()
void SkeletonGraphicsWidget::shortcutMoveSelectedToUp() void SkeletonGraphicsWidget::shortcutMoveSelectedToUp()
{ {
if (DocumentEditMode::Select == m_document->editMode) { if (SkeletonDocumentEditMode::Select == m_document->editMode) {
if (m_checkedOriginItem) { if (m_checkedOriginItem) {
moveCheckedOrigin(0, -1); moveCheckedOrigin(0, -1);
emit groupOperationAdded(); emit groupOperationAdded();
@ -1543,7 +1542,7 @@ void SkeletonGraphicsWidget::shortcutMoveSelectedToUp()
void SkeletonGraphicsWidget::shortcutMoveSelectedToDown() void SkeletonGraphicsWidget::shortcutMoveSelectedToDown()
{ {
if (DocumentEditMode::Select == m_document->editMode) { if (SkeletonDocumentEditMode::Select == m_document->editMode) {
if (m_checkedOriginItem) { if (m_checkedOriginItem) {
moveCheckedOrigin(0, 1); moveCheckedOrigin(0, 1);
emit groupOperationAdded(); emit groupOperationAdded();
@ -1556,7 +1555,7 @@ void SkeletonGraphicsWidget::shortcutMoveSelectedToDown()
void SkeletonGraphicsWidget::shortcutScaleSelectedByMinus1() void SkeletonGraphicsWidget::shortcutScaleSelectedByMinus1()
{ {
if (DocumentEditMode::Select == m_document->editMode && hasSelection()) { if (SkeletonDocumentEditMode::Select == m_document->editMode && hasSelection()) {
scaleSelected(-1); scaleSelected(-1);
emit groupOperationAdded(); emit groupOperationAdded();
} }
@ -1564,7 +1563,7 @@ void SkeletonGraphicsWidget::shortcutScaleSelectedByMinus1()
void SkeletonGraphicsWidget::shortcutScaleSelectedBy1() void SkeletonGraphicsWidget::shortcutScaleSelectedBy1()
{ {
if (DocumentEditMode::Select == m_document->editMode && hasSelection()) { if (SkeletonDocumentEditMode::Select == m_document->editMode && hasSelection()) {
scaleSelected(1); scaleSelected(1);
emit groupOperationAdded(); emit groupOperationAdded();
} }
@ -1572,15 +1571,15 @@ void SkeletonGraphicsWidget::shortcutScaleSelectedBy1()
void SkeletonGraphicsWidget::shortcutSwitchProfileOnSelected() void SkeletonGraphicsWidget::shortcutSwitchProfileOnSelected()
{ {
if (DocumentEditMode::Select == m_document->editMode && hasSelection()) { if (SkeletonDocumentEditMode::Select == m_document->editMode && hasSelection()) {
switchProfileOnRangeSelection(); switchProfileOnRangeSelection();
} }
} }
void SkeletonGraphicsWidget::shortcutShowOrHideSelectedPart() void SkeletonGraphicsWidget::shortcutShowOrHideSelectedPart()
{ {
if (DocumentEditMode::Select == m_document->editMode && !m_lastCheckedPart.isNull()) { if (SkeletonDocumentEditMode::Select == m_document->editMode && !m_lastCheckedPart.isNull()) {
const Part *part = m_document->findPart(m_lastCheckedPart); const SkeletonPart *part = m_document->findPart(m_lastCheckedPart);
bool partVisible = part && part->visible; bool partVisible = part && part->visible;
emit setPartVisibleState(m_lastCheckedPart, !partVisible); emit setPartVisibleState(m_lastCheckedPart, !partVisible);
emit groupOperationAdded(); emit groupOperationAdded();
@ -1589,8 +1588,8 @@ void SkeletonGraphicsWidget::shortcutShowOrHideSelectedPart()
void SkeletonGraphicsWidget::shortcutEnableOrDisableSelectedPart() void SkeletonGraphicsWidget::shortcutEnableOrDisableSelectedPart()
{ {
if (DocumentEditMode::Select == m_document->editMode && !m_lastCheckedPart.isNull()) { if (SkeletonDocumentEditMode::Select == m_document->editMode && !m_lastCheckedPart.isNull()) {
const Part *part = m_document->findPart(m_lastCheckedPart); const SkeletonPart *part = m_document->findPart(m_lastCheckedPart);
bool partDisabled = part && part->disabled; bool partDisabled = part && part->disabled;
emit setPartDisableState(m_lastCheckedPart, !partDisabled); emit setPartDisableState(m_lastCheckedPart, !partDisabled);
emit groupOperationAdded(); emit groupOperationAdded();
@ -1599,8 +1598,8 @@ void SkeletonGraphicsWidget::shortcutEnableOrDisableSelectedPart()
void SkeletonGraphicsWidget::shortcutLockOrUnlockSelectedPart() void SkeletonGraphicsWidget::shortcutLockOrUnlockSelectedPart()
{ {
if (DocumentEditMode::Select == m_document->editMode && !m_lastCheckedPart.isNull()) { if (SkeletonDocumentEditMode::Select == m_document->editMode && !m_lastCheckedPart.isNull()) {
const Part *part = m_document->findPart(m_lastCheckedPart); const SkeletonPart *part = m_document->findPart(m_lastCheckedPart);
bool partLocked = part && part->locked; bool partLocked = part && part->locked;
emit setPartLockState(m_lastCheckedPart, !partLocked); emit setPartLockState(m_lastCheckedPart, !partLocked);
emit groupOperationAdded(); emit groupOperationAdded();
@ -1609,8 +1608,8 @@ void SkeletonGraphicsWidget::shortcutLockOrUnlockSelectedPart()
void SkeletonGraphicsWidget::shortcutXmirrorOnOrOffSelectedPart() void SkeletonGraphicsWidget::shortcutXmirrorOnOrOffSelectedPart()
{ {
if (DocumentEditMode::Select == m_document->editMode && !m_lastCheckedPart.isNull()) { if (SkeletonDocumentEditMode::Select == m_document->editMode && !m_lastCheckedPart.isNull()) {
const Part *part = m_document->findPart(m_lastCheckedPart); const SkeletonPart *part = m_document->findPart(m_lastCheckedPart);
bool partXmirrored = part && part->xMirrored; bool partXmirrored = part && part->xMirrored;
emit setPartXmirrorState(m_lastCheckedPart, !partXmirrored); emit setPartXmirrorState(m_lastCheckedPart, !partXmirrored);
emit groupOperationAdded(); emit groupOperationAdded();
@ -1619,8 +1618,8 @@ void SkeletonGraphicsWidget::shortcutXmirrorOnOrOffSelectedPart()
void SkeletonGraphicsWidget::shortcutSubdivedOrNotSelectedPart() void SkeletonGraphicsWidget::shortcutSubdivedOrNotSelectedPart()
{ {
if (DocumentEditMode::Select == m_document->editMode && !m_lastCheckedPart.isNull()) { if (SkeletonDocumentEditMode::Select == m_document->editMode && !m_lastCheckedPart.isNull()) {
const Part *part = m_document->findPart(m_lastCheckedPart); const SkeletonPart *part = m_document->findPart(m_lastCheckedPart);
bool partSubdived = part && part->subdived; bool partSubdived = part && part->subdived;
emit setPartSubdivState(m_lastCheckedPart, !partSubdived); emit setPartSubdivState(m_lastCheckedPart, !partSubdived);
emit groupOperationAdded(); emit groupOperationAdded();
@ -1629,8 +1628,8 @@ void SkeletonGraphicsWidget::shortcutSubdivedOrNotSelectedPart()
void SkeletonGraphicsWidget::shortcutRoundEndOrNotSelectedPart() void SkeletonGraphicsWidget::shortcutRoundEndOrNotSelectedPart()
{ {
if (DocumentEditMode::Select == m_document->editMode && !m_lastCheckedPart.isNull()) { if (SkeletonDocumentEditMode::Select == m_document->editMode && !m_lastCheckedPart.isNull()) {
const Part *part = m_document->findPart(m_lastCheckedPart); const SkeletonPart *part = m_document->findPart(m_lastCheckedPart);
bool partRounded = part && part->rounded; bool partRounded = part && part->rounded;
emit setPartRoundState(m_lastCheckedPart, !partRounded); emit setPartRoundState(m_lastCheckedPart, !partRounded);
emit groupOperationAdded(); emit groupOperationAdded();
@ -1639,8 +1638,8 @@ void SkeletonGraphicsWidget::shortcutRoundEndOrNotSelectedPart()
void SkeletonGraphicsWidget::shortcutWrapOrNotSelectedPart() void SkeletonGraphicsWidget::shortcutWrapOrNotSelectedPart()
{ {
if (DocumentEditMode::Select == m_document->editMode && !m_lastCheckedPart.isNull()) { if (SkeletonDocumentEditMode::Select == m_document->editMode && !m_lastCheckedPart.isNull()) {
const Part *part = m_document->findPart(m_lastCheckedPart); const SkeletonPart *part = m_document->findPart(m_lastCheckedPart);
bool partWrapped = part && part->wrapped; bool partWrapped = part && part->wrapped;
emit setPartWrapState(m_lastCheckedPart, !partWrapped); emit setPartWrapState(m_lastCheckedPart, !partWrapped);
emit groupOperationAdded(); emit groupOperationAdded();
@ -1650,13 +1649,13 @@ void SkeletonGraphicsWidget::shortcutWrapOrNotSelectedPart()
bool SkeletonGraphicsWidget::keyPress(QKeyEvent *event) bool SkeletonGraphicsWidget::keyPress(QKeyEvent *event)
{ {
if (event->key() == Qt::Key_Space) { if (event->key() == Qt::Key_Space) {
if (DocumentEditMode::ZoomIn == m_document->editMode || if (SkeletonDocumentEditMode::ZoomIn == m_document->editMode ||
DocumentEditMode::ZoomOut == m_document->editMode || SkeletonDocumentEditMode::ZoomOut == m_document->editMode ||
DocumentEditMode::Select == m_document->editMode || SkeletonDocumentEditMode::Select == m_document->editMode ||
DocumentEditMode::Add == m_document->editMode) { SkeletonDocumentEditMode::Add == m_document->editMode) {
m_inTempDragMode = true; m_inTempDragMode = true;
m_modeBeforeEnterTempDragMode = m_document->editMode; m_modeBeforeEnterTempDragMode = m_document->editMode;
emit setEditMode(DocumentEditMode::Drag); emit setEditMode(SkeletonDocumentEditMode::Drag);
return true; return true;
} }
} }
@ -1692,7 +1691,7 @@ void SkeletonGraphicsWidget::originChanged()
void SkeletonGraphicsWidget::nodeAdded(QUuid nodeId) void SkeletonGraphicsWidget::nodeAdded(QUuid nodeId)
{ {
const Node *node = m_document->findNode(nodeId); const SkeletonNode *node = m_document->findNode(nodeId);
if (nullptr == node) { if (nullptr == node) {
qDebug() << "New node added but node id not exist:" << nodeId; qDebug() << "New node added but node id not exist:" << nodeId;
return; return;
@ -1730,7 +1729,7 @@ void SkeletonGraphicsWidget::nodeAdded(QUuid nodeId)
void SkeletonGraphicsWidget::edgeAdded(QUuid edgeId) void SkeletonGraphicsWidget::edgeAdded(QUuid edgeId)
{ {
const Edge *edge = m_document->findEdge(edgeId); const SkeletonEdge *edge = m_document->findEdge(edgeId);
if (nullptr == edge) { if (nullptr == edge) {
qDebug() << "New edge added but edge id not exist:" << edgeId; qDebug() << "New edge added but edge id not exist:" << edgeId;
return; return;
@ -1810,7 +1809,7 @@ void SkeletonGraphicsWidget::edgeRemoved(QUuid edgeId)
void SkeletonGraphicsWidget::nodeRadiusChanged(QUuid nodeId) void SkeletonGraphicsWidget::nodeRadiusChanged(QUuid nodeId)
{ {
const Node *node = m_document->findNode(nodeId); const SkeletonNode *node = m_document->findNode(nodeId);
if (nullptr == node) { if (nullptr == node) {
qDebug() << "Node changed but node id not exist:" << nodeId; qDebug() << "Node changed but node id not exist:" << nodeId;
return; return;
@ -1827,7 +1826,7 @@ void SkeletonGraphicsWidget::nodeRadiusChanged(QUuid nodeId)
void SkeletonGraphicsWidget::nodeBoneMarkChanged(QUuid nodeId) void SkeletonGraphicsWidget::nodeBoneMarkChanged(QUuid nodeId)
{ {
const Node *node = m_document->findNode(nodeId); const SkeletonNode *node = m_document->findNode(nodeId);
if (nullptr == node) { if (nullptr == node) {
qDebug() << "Node changed but node id not exist:" << nodeId; qDebug() << "Node changed but node id not exist:" << nodeId;
return; return;
@ -1844,7 +1843,7 @@ void SkeletonGraphicsWidget::nodeBoneMarkChanged(QUuid nodeId)
void SkeletonGraphicsWidget::nodeOriginChanged(QUuid nodeId) void SkeletonGraphicsWidget::nodeOriginChanged(QUuid nodeId)
{ {
const Node *node = m_document->findNode(nodeId); const SkeletonNode *node = m_document->findNode(nodeId);
if (nullptr == node) { if (nullptr == node) {
qDebug() << "Node changed but node id not exist:" << nodeId; qDebug() << "Node changed but node id not exist:" << nodeId;
return; return;
@ -1875,9 +1874,9 @@ void SkeletonGraphicsWidget::edgeChanged(QUuid edgeId)
void SkeletonGraphicsWidget::partVisibleStateChanged(QUuid partId) void SkeletonGraphicsWidget::partVisibleStateChanged(QUuid partId)
{ {
const Part *part = m_document->findPart(partId); const SkeletonPart *part = m_document->findPart(partId);
for (const auto &nodeId: part->nodeIds) { for (const auto &nodeId: part->nodeIds) {
const Node *node = m_document->findNode(nodeId); const SkeletonNode *node = m_document->findNode(nodeId);
for (auto edgeIt = node->edgeIds.begin(); edgeIt != node->edgeIds.end(); edgeIt++) { for (auto edgeIt = node->edgeIds.begin(); edgeIt != node->edgeIds.end(); edgeIt++) {
auto edgeItemIt = edgeItemMap.find(*edgeIt); auto edgeItemIt = edgeItemMap.find(*edgeIt);
if (edgeItemIt == edgeItemMap.end()) { if (edgeItemIt == edgeItemMap.end()) {
@ -1931,7 +1930,7 @@ QUuid SkeletonGraphicsWidget::querySkeletonItemPartId(QGraphicsItem *item)
{ {
if (item->data(0) == "node") { if (item->data(0) == "node") {
SkeletonGraphicsNodeItem *nodeItem = (SkeletonGraphicsNodeItem *)item; SkeletonGraphicsNodeItem *nodeItem = (SkeletonGraphicsNodeItem *)item;
const Node *node = m_document->findNode(nodeItem->id()); const SkeletonNode *node = m_document->findNode(nodeItem->id());
if (!node) { if (!node) {
qDebug() << "Find node id failed:" << nodeItem->id(); qDebug() << "Find node id failed:" << nodeItem->id();
return QUuid(); return QUuid();
@ -1939,7 +1938,7 @@ QUuid SkeletonGraphicsWidget::querySkeletonItemPartId(QGraphicsItem *item)
return node->partId; return node->partId;
} else if (item->data(0) == "edge") { } else if (item->data(0) == "edge") {
SkeletonGraphicsEdgeItem *edgeItem = (SkeletonGraphicsEdgeItem *)item; SkeletonGraphicsEdgeItem *edgeItem = (SkeletonGraphicsEdgeItem *)item;
const Edge *edge = m_document->findEdge(edgeItem->id()); const SkeletonEdge *edge = m_document->findEdge(edgeItem->id());
if (!edge) { if (!edge) {
qDebug() << "Find edge id failed:" << edgeItem->id(); qDebug() << "Find edge id failed:" << edgeItem->id();
return QUuid(); return QUuid();
@ -2081,7 +2080,7 @@ void SkeletonGraphicsWidget::selectPartAllById(QUuid partId)
unselectAll(); unselectAll();
for (const auto &it: nodeItemMap) { for (const auto &it: nodeItemMap) {
SkeletonGraphicsNodeItem *item = it.second.first; SkeletonGraphicsNodeItem *item = it.second.first;
const Node *node = m_document->findNode(item->id()); const SkeletonNode *node = m_document->findNode(item->id());
if (!node) if (!node)
continue; continue;
if (node->partId != partId) if (node->partId != partId)
@ -2090,7 +2089,7 @@ void SkeletonGraphicsWidget::selectPartAllById(QUuid partId)
} }
for (const auto &it: edgeItemMap) { for (const auto &it: edgeItemMap) {
SkeletonGraphicsEdgeItem *item = it.second.first; SkeletonGraphicsEdgeItem *item = it.second.first;
const Edge *edge = m_document->findEdge(item->id()); const SkeletonEdge *edge = m_document->findEdge(item->id());
if (!edge) if (!edge)
continue; continue;
if (edge->partId != partId) if (edge->partId != partId)
@ -2133,7 +2132,7 @@ void SkeletonGraphicsWidget::addPartToSelection(QUuid partId)
QUuid choosenPartId = partId; QUuid choosenPartId = partId;
for (const auto &it: nodeItemMap) { for (const auto &it: nodeItemMap) {
SkeletonGraphicsNodeItem *item = SkeletonProfile::Main == choosenProfile ? it.second.first : it.second.second; SkeletonGraphicsNodeItem *item = SkeletonProfile::Main == choosenProfile ? it.second.first : it.second.second;
const Node *node = m_document->findNode(item->id()); const SkeletonNode *node = m_document->findNode(item->id());
if (!node) if (!node)
continue; continue;
if (choosenPartId.isNull()) { if (choosenPartId.isNull()) {
@ -2145,7 +2144,7 @@ void SkeletonGraphicsWidget::addPartToSelection(QUuid partId)
} }
for (const auto &it: edgeItemMap) { for (const auto &it: edgeItemMap) {
SkeletonGraphicsEdgeItem *item = SkeletonProfile::Main == choosenProfile ? it.second.first : it.second.second; SkeletonGraphicsEdgeItem *item = SkeletonProfile::Main == choosenProfile ? it.second.first : it.second.second;
const Edge *edge = m_document->findEdge(item->id()); const SkeletonEdge *edge = m_document->findEdge(item->id());
if (!edge) if (!edge)
continue; continue;
if (choosenPartId.isNull()) { if (choosenPartId.isNull()) {
@ -2164,18 +2163,18 @@ void SkeletonGraphicsWidget::selectPartAll()
QUuid choosenPartId; QUuid choosenPartId;
if (m_hoveredNodeItem) { if (m_hoveredNodeItem) {
choosenProfile = m_hoveredNodeItem->profile(); choosenProfile = m_hoveredNodeItem->profile();
const Node *node = m_document->findNode(m_hoveredNodeItem->id()); const SkeletonNode *node = m_document->findNode(m_hoveredNodeItem->id());
if (node) if (node)
choosenPartId = node->partId; choosenPartId = node->partId;
} else if (m_hoveredEdgeItem) { } else if (m_hoveredEdgeItem) {
choosenProfile = m_hoveredEdgeItem->profile(); choosenProfile = m_hoveredEdgeItem->profile();
const Edge *edge = m_document->findEdge(m_hoveredEdgeItem->id()); const SkeletonEdge *edge = m_document->findEdge(m_hoveredEdgeItem->id());
if (edge) if (edge)
choosenPartId = edge->partId; choosenPartId = edge->partId;
} }
for (const auto &it: nodeItemMap) { for (const auto &it: nodeItemMap) {
SkeletonGraphicsNodeItem *item = SkeletonProfile::Main == choosenProfile ? it.second.first : it.second.second; SkeletonGraphicsNodeItem *item = SkeletonProfile::Main == choosenProfile ? it.second.first : it.second.second;
const Node *node = m_document->findNode(item->id()); const SkeletonNode *node = m_document->findNode(item->id());
if (!node) if (!node)
continue; continue;
if (choosenPartId.isNull()) { if (choosenPartId.isNull()) {
@ -2187,7 +2186,7 @@ void SkeletonGraphicsWidget::selectPartAll()
} }
for (const auto &it: edgeItemMap) { for (const auto &it: edgeItemMap) {
SkeletonGraphicsEdgeItem *item = SkeletonProfile::Main == choosenProfile ? it.second.first : it.second.second; SkeletonGraphicsEdgeItem *item = SkeletonProfile::Main == choosenProfile ? it.second.first : it.second.second;
const Edge *edge = m_document->findEdge(item->id()); const SkeletonEdge *edge = m_document->findEdge(item->id());
if (!edge) if (!edge)
continue; continue;
if (choosenPartId.isNull()) { if (choosenPartId.isNull()) {
@ -2253,13 +2252,7 @@ void SkeletonGraphicsWidget::copy()
readSkeletonNodeAndEdgeIdSetFromRangeSelection(&nodeIdSet, &edgeIdSet); readSkeletonNodeAndEdgeIdSetFromRangeSelection(&nodeIdSet, &edgeIdSet);
if (nodeIdSet.empty()) if (nodeIdSet.empty())
return; return;
Snapshot snapshot; m_document->copyNodes(nodeIdSet);
m_document->toSnapshot(&snapshot, nodeIdSet, DocumentToSnapshotFor::Nodes);
QString snapshotXml;
QXmlStreamWriter xmlStreamWriter(&snapshotXml);
saveSkeletonToXmlStream(&snapshot, &xmlStreamWriter);
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(snapshotXml);
} }
void SkeletonGraphicsWidget::removeAllContent() void SkeletonGraphicsWidget::removeAllContent()

View File

@ -12,7 +12,7 @@
#include <cmath> #include <cmath>
#include <set> #include <set>
#include <QTimer> #include <QTimer>
#include "document.h" #include "skeletondocument.h"
#include "turnaroundloader.h" #include "turnaroundloader.h"
#include "theme.h" #include "theme.h"
#include "util.h" #include "util.h"
@ -350,7 +350,7 @@ signals:
void scaleNodeByAddRadius(QUuid nodeId, float amount); void scaleNodeByAddRadius(QUuid nodeId, float amount);
void moveNodeBy(QUuid nodeId, float x, float y, float z); void moveNodeBy(QUuid nodeId, float x, float y, float z);
void removeNode(QUuid nodeId); void removeNode(QUuid nodeId);
void setEditMode(DocumentEditMode mode); void setEditMode(SkeletonDocumentEditMode mode);
void removeEdge(QUuid edgeId); void removeEdge(QUuid edgeId);
void addEdge(QUuid fromNodeId, QUuid toNodeId); void addEdge(QUuid fromNodeId, QUuid toNodeId);
void cursorChanged(); void cursorChanged();
@ -385,7 +385,7 @@ signals:
void enableAllPositionRelatedLocks(); void enableAllPositionRelatedLocks();
void disableAllPositionRelatedLocks(); void disableAllPositionRelatedLocks();
public: public:
SkeletonGraphicsWidget(const Document *document); SkeletonGraphicsWidget(const SkeletonDocument *document);
std::map<QUuid, std::pair<SkeletonGraphicsNodeItem *, SkeletonGraphicsNodeItem *>> nodeItemMap; std::map<QUuid, std::pair<SkeletonGraphicsNodeItem *, SkeletonGraphicsNodeItem *>> nodeItemMap;
std::map<QUuid, std::pair<SkeletonGraphicsEdgeItem *, SkeletonGraphicsEdgeItem *>> edgeItemMap; std::map<QUuid, std::pair<SkeletonGraphicsEdgeItem *, SkeletonGraphicsEdgeItem *>> edgeItemMap;
bool mouseMove(QMouseEvent *event); bool mouseMove(QMouseEvent *event);
@ -527,7 +527,7 @@ private:
void rotateItems(const std::set<SkeletonGraphicsNodeItem *> &nodeItems, int degree, QVector2D center); void rotateItems(const std::set<SkeletonGraphicsNodeItem *> &nodeItems, int degree, QVector2D center);
void rotateAllSideProfile(int degree); void rotateAllSideProfile(int degree);
private: //need initalize private: //need initalize
const Document *m_document; const SkeletonDocument *m_document;
QGraphicsPixmapItem *m_backgroundItem; QGraphicsPixmapItem *m_backgroundItem;
bool m_turnaroundChanged; bool m_turnaroundChanged;
TurnaroundLoader *m_turnaroundLoader; TurnaroundLoader *m_turnaroundLoader;
@ -556,7 +556,7 @@ private: //need initalize
bool m_eventForwardingToModelWidget; bool m_eventForwardingToModelWidget;
ModelWidget *m_modelWidget; ModelWidget *m_modelWidget;
bool m_inTempDragMode; bool m_inTempDragMode;
DocumentEditMode m_modeBeforeEnterTempDragMode; SkeletonDocumentEditMode m_modeBeforeEnterTempDragMode;
private: private:
QVector3D m_ikMoveTarget; QVector3D m_ikMoveTarget;
QUuid m_ikMoveEndEffectorId; QUuid m_ikMoveEndEffectorId;