Finish part mini buttons
parent
8d558aa19f
commit
1c4515abd7
|
@ -184,9 +184,14 @@ void MeshGenerator::process()
|
||||||
std::map<QString, int> partMeshMap;
|
std::map<QString, int> partMeshMap;
|
||||||
std::vector<int> meshIds;
|
std::vector<int> meshIds;
|
||||||
for (const auto &partIdIt: m_snapshot->partIdList) {
|
for (const auto &partIdIt: m_snapshot->partIdList) {
|
||||||
|
const auto part = m_snapshot->parts.find(partIdIt);
|
||||||
int bmeshId = partBmeshMap[partIdIt];
|
int bmeshId = partBmeshMap[partIdIt];
|
||||||
int meshId = meshlite_bmesh_generate_mesh(meshliteContext, bmeshId, 0);
|
int meshId = meshlite_bmesh_generate_mesh(meshliteContext, bmeshId, 0);
|
||||||
qDebug() << "m_requirePartPreviewMap.find:" << partIdIt;
|
if (isTrueValueString(part->second["subdived"])) {
|
||||||
|
int subdivedMeshId = meshlite_subdivide(meshliteContext, meshId);
|
||||||
|
if (subdivedMeshId > 0)
|
||||||
|
meshId = subdivedMeshId;
|
||||||
|
}
|
||||||
if (m_requirePartPreviewMap.find(partIdIt) != m_requirePartPreviewMap.end()) {
|
if (m_requirePartPreviewMap.find(partIdIt) != m_requirePartPreviewMap.end()) {
|
||||||
ModelOfflineRender *render = m_partPreviewRenderMap[partIdIt];
|
ModelOfflineRender *render = m_partPreviewRenderMap[partIdIt];
|
||||||
int trimedMeshId = meshlite_trim(meshliteContext, meshId, 1);
|
int trimedMeshId = meshlite_trim(meshliteContext, meshId, 1);
|
||||||
|
|
|
@ -26,14 +26,6 @@ void SkeletonDocument::removePart(QUuid partId)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonDocument::showPart(QUuid partId)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkeletonDocument::hidePart(QUuid partId)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkeletonDocument::removeEdge(QUuid edgeId)
|
void SkeletonDocument::removeEdge(QUuid edgeId)
|
||||||
{
|
{
|
||||||
const SkeletonEdge *edge = findEdge(edgeId);
|
const SkeletonEdge *edge = findEdge(edgeId);
|
||||||
|
@ -41,6 +33,8 @@ void SkeletonDocument::removeEdge(QUuid edgeId)
|
||||||
qDebug() << "Find edge failed:" << edgeId;
|
qDebug() << "Find edge failed:" << edgeId;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isPartLocked(edge->partId))
|
||||||
|
return;
|
||||||
const SkeletonPart *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;
|
||||||
|
@ -100,6 +94,8 @@ void SkeletonDocument::removeNode(QUuid nodeId)
|
||||||
qDebug() << "Find node failed:" << nodeId;
|
qDebug() << "Find node failed:" << nodeId;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isPartLocked(node->partId))
|
||||||
|
return;
|
||||||
const SkeletonPart *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;
|
||||||
|
@ -178,6 +174,8 @@ void SkeletonDocument::addNode(float x, float y, float z, float radius, QUuid fr
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
partId = fromNode->partId;
|
partId = fromNode->partId;
|
||||||
|
if (isPartLocked(partId))
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
SkeletonNode node;
|
SkeletonNode node;
|
||||||
node.partId = partId;
|
node.partId = partId;
|
||||||
|
@ -245,12 +243,18 @@ void SkeletonDocument::addEdge(QUuid fromNodeId, QUuid toNodeId)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isPartLocked(fromNode->partId))
|
||||||
|
return;
|
||||||
|
|
||||||
toNode = findNode(toNodeId);
|
toNode = findNode(toNodeId);
|
||||||
if (nullptr == toNode) {
|
if (nullptr == toNode) {
|
||||||
qDebug() << "Find node failed:" << toNodeId;
|
qDebug() << "Find node failed:" << toNodeId;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isPartLocked(toNode->partId))
|
||||||
|
return;
|
||||||
|
|
||||||
QUuid toPartId = toNode->partId;
|
QUuid toPartId = toNode->partId;
|
||||||
|
|
||||||
auto fromPart = partMap.find(fromNode->partId);
|
auto fromPart = partMap.find(fromNode->partId);
|
||||||
|
@ -335,11 +339,23 @@ void SkeletonDocument::scaleNodeByAddRadius(QUuid nodeId, float amount)
|
||||||
qDebug() << "Find node failed:" << nodeId;
|
qDebug() << "Find node failed:" << nodeId;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isPartLocked(it->second.partId))
|
||||||
|
return;
|
||||||
it->second.radius += amount;
|
it->second.radius += amount;
|
||||||
emit nodeRadiusChanged(nodeId);
|
emit nodeRadiusChanged(nodeId);
|
||||||
emit skeletonChanged();
|
emit skeletonChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SkeletonDocument::isPartLocked(QUuid partId)
|
||||||
|
{
|
||||||
|
const SkeletonPart *part = findPart(partId);
|
||||||
|
if (nullptr == part) {
|
||||||
|
qDebug() << "Find part failed:" << partId;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return part->locked;
|
||||||
|
}
|
||||||
|
|
||||||
void SkeletonDocument::moveNodeBy(QUuid nodeId, float x, float y, float z)
|
void SkeletonDocument::moveNodeBy(QUuid nodeId, float x, float y, float z)
|
||||||
{
|
{
|
||||||
auto it = nodeMap.find(nodeId);
|
auto it = nodeMap.find(nodeId);
|
||||||
|
@ -347,6 +363,8 @@ void SkeletonDocument::moveNodeBy(QUuid nodeId, float x, float y, float z)
|
||||||
qDebug() << "Find node failed:" << nodeId;
|
qDebug() << "Find node failed:" << nodeId;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isPartLocked(it->second.partId))
|
||||||
|
return;
|
||||||
it->second.x += x;
|
it->second.x += x;
|
||||||
it->second.y += y;
|
it->second.y += y;
|
||||||
it->second.z += z;
|
it->second.z += z;
|
||||||
|
@ -361,6 +379,8 @@ void SkeletonDocument::setNodeOrigin(QUuid nodeId, float x, float y, float z)
|
||||||
qDebug() << "Find node failed:" << nodeId;
|
qDebug() << "Find node failed:" << nodeId;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isPartLocked(it->second.partId))
|
||||||
|
return;
|
||||||
it->second.x = x;
|
it->second.x = x;
|
||||||
it->second.y = y;
|
it->second.y = y;
|
||||||
it->second.z = z;
|
it->second.z = z;
|
||||||
|
@ -375,6 +395,8 @@ void SkeletonDocument::setNodeRadius(QUuid nodeId, float radius)
|
||||||
qDebug() << "Find node failed:" << nodeId;
|
qDebug() << "Find node failed:" << nodeId;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isPartLocked(it->second.partId))
|
||||||
|
return;
|
||||||
it->second.radius = radius;
|
it->second.radius = radius;
|
||||||
emit nodeRadiusChanged(nodeId);
|
emit nodeRadiusChanged(nodeId);
|
||||||
emit skeletonChanged();
|
emit skeletonChanged();
|
||||||
|
@ -479,6 +501,8 @@ void SkeletonDocument::toSnapshot(SkeletonSnapshot *snapshot)
|
||||||
std::map<QString, QString> part;
|
std::map<QString, QString> part;
|
||||||
part["id"] = partIt.second.id.toString();
|
part["id"] = partIt.second.id.toString();
|
||||||
part["visible"] = partIt.second.visible ? "true" : "false";
|
part["visible"] = partIt.second.visible ? "true" : "false";
|
||||||
|
part["locked"] = partIt.second.locked ? "true" : "false";
|
||||||
|
part["subdived"] = partIt.second.subdived ? "true" : "false";
|
||||||
if (!partIt.second.name.isEmpty())
|
if (!partIt.second.name.isEmpty())
|
||||||
part["name"] = partIt.second.name;
|
part["name"] = partIt.second.name;
|
||||||
snapshot->parts[part["id"]] = part;
|
snapshot->parts[part["id"]] = part;
|
||||||
|
@ -560,6 +584,8 @@ void SkeletonDocument::fromSnapshot(const SkeletonSnapshot &snapshot)
|
||||||
SkeletonPart part(QUuid(partKv.first));
|
SkeletonPart part(QUuid(partKv.first));
|
||||||
part.name = valueOfKeyInMapOrEmpty(partKv.second, "name");
|
part.name = valueOfKeyInMapOrEmpty(partKv.second, "name");
|
||||||
part.visible = isTrueValueString(valueOfKeyInMapOrEmpty(partKv.second, "visible"));
|
part.visible = isTrueValueString(valueOfKeyInMapOrEmpty(partKv.second, "visible"));
|
||||||
|
part.locked = isTrueValueString(valueOfKeyInMapOrEmpty(partKv.second, "locked"));
|
||||||
|
part.subdived = isTrueValueString(valueOfKeyInMapOrEmpty(partKv.second, "subdived"));
|
||||||
partMap[part.id] = part;
|
partMap[part.id] = part;
|
||||||
}
|
}
|
||||||
for (const auto &partIdIt: snapshot.partIdList) {
|
for (const auto &partIdIt: snapshot.partIdList) {
|
||||||
|
@ -704,3 +730,45 @@ void SkeletonDocument::generateMesh()
|
||||||
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
|
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
|
||||||
thread->start();
|
thread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkeletonDocument::setPartLockState(QUuid partId, bool locked)
|
||||||
|
{
|
||||||
|
auto part = partMap.find(partId);
|
||||||
|
if (part == partMap.end()) {
|
||||||
|
qDebug() << "Part not found:" << partId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (part->second.locked == locked)
|
||||||
|
return;
|
||||||
|
part->second.locked = locked;
|
||||||
|
emit partLockStateChanged(partId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkeletonDocument::setPartVisibleState(QUuid partId, bool visible)
|
||||||
|
{
|
||||||
|
auto part = partMap.find(partId);
|
||||||
|
if (part == partMap.end()) {
|
||||||
|
qDebug() << "Part not found:" << partId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (part->second.visible == visible)
|
||||||
|
return;
|
||||||
|
part->second.visible = visible;
|
||||||
|
emit partVisibleStateChanged(partId);
|
||||||
|
emit skeletonChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkeletonDocument::setPartSubdivState(QUuid partId, bool subdived)
|
||||||
|
{
|
||||||
|
auto part = partMap.find(partId);
|
||||||
|
if (part == partMap.end()) {
|
||||||
|
qDebug() << "Part not found:" << partId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (part->second.subdived == subdived)
|
||||||
|
return;
|
||||||
|
part->second.subdived = subdived;
|
||||||
|
emit partSubdivStateChanged(partId);
|
||||||
|
emit skeletonChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,11 +80,15 @@ public:
|
||||||
QUuid id;
|
QUuid id;
|
||||||
QString name;
|
QString name;
|
||||||
bool visible;
|
bool visible;
|
||||||
|
bool locked;
|
||||||
|
bool subdived;
|
||||||
QImage preview;
|
QImage preview;
|
||||||
std::vector<QUuid> nodeIds;
|
std::vector<QUuid> nodeIds;
|
||||||
bool previewIsObsolete;
|
bool previewIsObsolete;
|
||||||
SkeletonPart(const QUuid &withId=QUuid()) :
|
SkeletonPart(const QUuid &withId=QUuid()) :
|
||||||
visible(true),
|
visible(true),
|
||||||
|
locked(false),
|
||||||
|
subdived(false),
|
||||||
previewIsObsolete(true)
|
previewIsObsolete(true)
|
||||||
{
|
{
|
||||||
id = withId.isNull() ? QUuid::createUuid() : withId;
|
id = withId.isNull() ? QUuid::createUuid() : withId;
|
||||||
|
@ -134,6 +138,9 @@ signals:
|
||||||
void turnaroundChanged();
|
void turnaroundChanged();
|
||||||
void editModeChanged();
|
void editModeChanged();
|
||||||
void skeletonChanged();
|
void skeletonChanged();
|
||||||
|
void partLockStateChanged(QUuid partId);
|
||||||
|
void partVisibleStateChanged(QUuid partId);
|
||||||
|
void partSubdivStateChanged(QUuid partId);
|
||||||
public:
|
public:
|
||||||
SkeletonDocument();
|
SkeletonDocument();
|
||||||
~SkeletonDocument();
|
~SkeletonDocument();
|
||||||
|
@ -157,8 +164,6 @@ public slots:
|
||||||
void removeNode(QUuid nodeId);
|
void removeNode(QUuid nodeId);
|
||||||
void removeEdge(QUuid edgeId);
|
void removeEdge(QUuid edgeId);
|
||||||
void removePart(QUuid partId);
|
void removePart(QUuid partId);
|
||||||
void showPart(QUuid partId);
|
|
||||||
void hidePart(QUuid partId);
|
|
||||||
void addNode(float x, float y, float z, float radius, QUuid fromNodeId);
|
void addNode(float x, float y, float z, float radius, QUuid fromNodeId);
|
||||||
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);
|
||||||
|
@ -171,10 +176,14 @@ public slots:
|
||||||
void uiReady();
|
void uiReady();
|
||||||
void generateMesh();
|
void generateMesh();
|
||||||
void meshReady();
|
void meshReady();
|
||||||
|
void setPartLockState(QUuid partId, bool locked);
|
||||||
|
void setPartVisibleState(QUuid partId, bool visible);
|
||||||
|
void setPartSubdivState(QUuid partId, bool subdived);
|
||||||
private:
|
private:
|
||||||
void splitPartByNode(std::vector<std::vector<QUuid>> *groups, QUuid nodeId);
|
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());
|
void joinNodeAndNeiborsToGroup(std::vector<QUuid> *group, QUuid nodeId, std::set<QUuid> *visitMap, QUuid noUseEdgeId=QUuid());
|
||||||
void splitPartByEdge(std::vector<std::vector<QUuid>> *groups, QUuid edgeId);
|
void splitPartByEdge(std::vector<std::vector<QUuid>> *groups, QUuid edgeId);
|
||||||
|
bool isPartLocked(QUuid partId);
|
||||||
private:
|
private:
|
||||||
bool m_resultMeshIsObsolete;
|
bool m_resultMeshIsObsolete;
|
||||||
MeshGenerator *m_meshGenerator;
|
MeshGenerator *m_meshGenerator;
|
||||||
|
|
|
@ -97,9 +97,9 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
|
||||||
containerWidget->setMinimumSize(400, 400);
|
containerWidget->setMinimumSize(400, 400);
|
||||||
|
|
||||||
m_modelWidget = new ModelWidget(containerWidget);
|
m_modelWidget = new ModelWidget(containerWidget);
|
||||||
m_modelWidget->setMinimumSize(128, 128);
|
m_modelWidget->setMinimumSize(256, 256);
|
||||||
m_modelWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
m_modelWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||||
m_modelWidget->move(10, 10);
|
m_modelWidget->move(16, 16);
|
||||||
m_modelWidget->setGraphicsFunctions(graphicsWidget);
|
m_modelWidget->setGraphicsFunctions(graphicsWidget);
|
||||||
|
|
||||||
SkeletonPartListWidget *partListWidget = new SkeletonPartListWidget(m_document);
|
SkeletonPartListWidget *partListWidget = new SkeletonPartListWidget(m_document);
|
||||||
|
@ -193,33 +193,13 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
|
||||||
connect(m_document, &SkeletonDocument::edgeRemoved, graphicsWidget, &SkeletonGraphicsWidget::edgeRemoved);
|
connect(m_document, &SkeletonDocument::edgeRemoved, graphicsWidget, &SkeletonGraphicsWidget::edgeRemoved);
|
||||||
connect(m_document, &SkeletonDocument::nodeRadiusChanged, graphicsWidget, &SkeletonGraphicsWidget::nodeRadiusChanged);
|
connect(m_document, &SkeletonDocument::nodeRadiusChanged, graphicsWidget, &SkeletonGraphicsWidget::nodeRadiusChanged);
|
||||||
connect(m_document, &SkeletonDocument::nodeOriginChanged, graphicsWidget, &SkeletonGraphicsWidget::nodeOriginChanged);
|
connect(m_document, &SkeletonDocument::nodeOriginChanged, graphicsWidget, &SkeletonGraphicsWidget::nodeOriginChanged);
|
||||||
|
connect(m_document, &SkeletonDocument::partVisibleStateChanged, graphicsWidget, &SkeletonGraphicsWidget::partVisibleStateChanged);
|
||||||
|
|
||||||
connect(m_document, &SkeletonDocument::partListChanged, partListWidget, &SkeletonPartListWidget::partListChanged);
|
connect(m_document, &SkeletonDocument::partListChanged, partListWidget, &SkeletonPartListWidget::partListChanged);
|
||||||
connect(m_document, &SkeletonDocument::partPreviewChanged, partListWidget, &SkeletonPartListWidget::partPreviewChanged);
|
connect(m_document, &SkeletonDocument::partPreviewChanged, partListWidget, &SkeletonPartListWidget::partPreviewChanged);
|
||||||
|
connect(m_document, &SkeletonDocument::partLockStateChanged, partListWidget, &SkeletonPartListWidget::partLockStateChanged);
|
||||||
/*
|
connect(m_document, &SkeletonDocument::partVisibleStateChanged, partListWidget, &SkeletonPartListWidget::partVisibleStateChanged);
|
||||||
connect(graphicsWidget, &SkeletonGraphicsWidget::checkEdge, edgePropertyWidget, &SkeletonEdgePropertyWidget::showProperties);
|
connect(m_document, &SkeletonDocument::partSubdivStateChanged, partListWidget, &SkeletonPartListWidget::partSubdivStateChanged);
|
||||||
connect(graphicsWidget, &SkeletonGraphicsWidget::uncheckEdge, [=](QUuid edgeId) {
|
|
||||||
edgePropertyWidget->hide();
|
|
||||||
});
|
|
||||||
connect(m_document, &SkeletonDocument::edgeRemoved, [=](QUuid edgeId) {
|
|
||||||
if (edgeId == edgePropertyWidget->currentEdgeId()) {
|
|
||||||
edgePropertyWidget->hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
connect(edgePropertyWidget, &SkeletonEdgePropertyWidget::setEdgeBranchMode, m_document, &SkeletonDocument::setEdgeBranchMode);
|
|
||||||
|
|
||||||
connect(graphicsWidget, &SkeletonGraphicsWidget::checkNode, nodePropertyWidget, &SkeletonNodePropertyWidget::showProperties);
|
|
||||||
connect(graphicsWidget, &SkeletonGraphicsWidget::uncheckNode, [=](QUuid nodeId) {
|
|
||||||
nodePropertyWidget->hide();
|
|
||||||
});
|
|
||||||
connect(m_document, &SkeletonDocument::nodeRemoved, [=](QUuid nodeId) {
|
|
||||||
if (nodeId == nodePropertyWidget->currentNodeId()) {
|
|
||||||
nodePropertyWidget->hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
connect(nodePropertyWidget, &SkeletonNodePropertyWidget::setNodeRootMarkMode, m_document, &SkeletonDocument::setNodeRootMarkMode);
|
|
||||||
*/
|
|
||||||
|
|
||||||
connect(m_document, &SkeletonDocument::skeletonChanged, m_document, &SkeletonDocument::generateMesh);
|
connect(m_document, &SkeletonDocument::skeletonChanged, m_document, &SkeletonDocument::generateMesh);
|
||||||
|
|
||||||
|
|
|
@ -366,11 +366,16 @@ bool SkeletonGraphicsWidget::mousePress(QMouseEvent *event)
|
||||||
}
|
}
|
||||||
QPointF mainProfile = m_cursorNodeItem->origin();
|
QPointF mainProfile = m_cursorNodeItem->origin();
|
||||||
QPointF sideProfile = mainProfile;
|
QPointF sideProfile = mainProfile;
|
||||||
|
if (m_checkedNodeItem) {
|
||||||
|
auto itemIt = nodeItemMap.find(m_checkedNodeItem->id());
|
||||||
|
sideProfile.setX(itemIt->second.second->origin().x());
|
||||||
|
} else {
|
||||||
if (mainProfile.x() >= scene()->width() / 2) {
|
if (mainProfile.x() >= scene()->width() / 2) {
|
||||||
sideProfile.setX(mainProfile.x() - scene()->width() / 4);
|
sideProfile.setX(mainProfile.x() - scene()->width() / 4);
|
||||||
} else {
|
} else {
|
||||||
sideProfile.setX(mainProfile.x() +scene()->width() / 4);
|
sideProfile.setX(mainProfile.x() +scene()->width() / 4);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
QPointF unifiedMainPos = scenePosToUnified(mainProfile);
|
QPointF unifiedMainPos = scenePosToUnified(mainProfile);
|
||||||
QPointF unifiedSidePos = scenePosToUnified(sideProfile);
|
QPointF unifiedSidePos = scenePosToUnified(sideProfile);
|
||||||
if (isFloatEqual(m_lastAddedX, unifiedMainPos.x()) && isFloatEqual(m_lastAddedY, unifiedMainPos.y()) && isFloatEqual(m_lastAddedZ, unifiedSidePos.x()))
|
if (isFloatEqual(m_lastAddedX, unifiedMainPos.x()) && isFloatEqual(m_lastAddedY, unifiedMainPos.y()) && isFloatEqual(m_lastAddedZ, unifiedSidePos.x()))
|
||||||
|
@ -642,3 +647,27 @@ void SkeletonGraphicsWidget::edgeChanged(QUuid edgeId)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkeletonGraphicsWidget::partVisibleStateChanged(QUuid partId)
|
||||||
|
{
|
||||||
|
const SkeletonPart *part = m_document->findPart(partId);
|
||||||
|
for (const auto &nodeId: part->nodeIds) {
|
||||||
|
const SkeletonNode *node = m_document->findNode(nodeId);
|
||||||
|
for (auto edgeIt = node->edgeIds.begin(); edgeIt != node->edgeIds.end(); edgeIt++) {
|
||||||
|
auto edgeItemIt = edgeItemMap.find(*edgeIt);
|
||||||
|
if (edgeItemIt == edgeItemMap.end()) {
|
||||||
|
qDebug() << "Edge item not found:" << *edgeIt;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
edgeItemIt->second.first->setVisible(part->visible);
|
||||||
|
edgeItemIt->second.second->setVisible(part->visible);
|
||||||
|
}
|
||||||
|
auto nodeItemIt = nodeItemMap.find(nodeId);
|
||||||
|
if (nodeItemIt == nodeItemMap.end()) {
|
||||||
|
qDebug() << "Node item not found:" << nodeId;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nodeItemIt->second.first->setVisible(part->visible);
|
||||||
|
nodeItemIt->second.second->setVisible(part->visible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -264,6 +264,7 @@ public slots:
|
||||||
void canvasResized();
|
void canvasResized();
|
||||||
void editModeChanged();
|
void editModeChanged();
|
||||||
void updateCursor();
|
void updateCursor();
|
||||||
|
void partVisibleStateChanged(QUuid partId);
|
||||||
private slots:
|
private slots:
|
||||||
void turnaroundImageReady();
|
void turnaroundImageReady();
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -8,20 +8,17 @@ SkeletonPartWidget::SkeletonPartWidget(const SkeletonDocument *document, QUuid p
|
||||||
m_document(document),
|
m_document(document),
|
||||||
m_partId(partId)
|
m_partId(partId)
|
||||||
{
|
{
|
||||||
m_visibleButton = new QPushButton(QChar(fa::eye));
|
m_visibleButton = new QPushButton();
|
||||||
m_visibleButton->setStyleSheet("QPushButton {border: none; background: none; color: #252525;}");
|
updateButton(m_visibleButton, QChar(fa::eye), false);
|
||||||
m_visibleButton->setFont(Theme::awesome()->font(Theme::miniIconFontSize));
|
initButton(m_visibleButton);
|
||||||
m_visibleButton->setFixedSize(Theme::miniIconSize, Theme::miniIconSize);
|
|
||||||
|
|
||||||
m_lockButton = new QPushButton(QChar(fa::unlock));
|
m_lockButton = new QPushButton();
|
||||||
m_lockButton->setStyleSheet("QPushButton {border: none; background: none; color: #252525;}");
|
updateButton(m_lockButton, QChar(fa::unlock), false);
|
||||||
m_lockButton->setFont(Theme::awesome()->font(Theme::miniIconFontSize));
|
initButton(m_lockButton);
|
||||||
m_lockButton->setFixedSize(Theme::miniIconSize, Theme::miniIconSize);
|
|
||||||
|
|
||||||
m_subdivButton = new QPushButton(QChar(fa::cube));
|
m_subdivButton = new QPushButton();
|
||||||
m_subdivButton->setStyleSheet("QPushButton {border: none; background: none; color: #252525;}");
|
updateButton(m_subdivButton, QChar(fa::cube), false);
|
||||||
m_subdivButton->setFont(Theme::awesome()->font(Theme::miniIconFontSize));
|
initButton(m_subdivButton);
|
||||||
m_subdivButton->setFixedSize(Theme::miniIconSize, Theme::miniIconSize);
|
|
||||||
|
|
||||||
m_previewLabel = new QLabel;
|
m_previewLabel = new QLabel;
|
||||||
|
|
||||||
|
@ -34,46 +31,141 @@ SkeletonPartWidget::SkeletonPartWidget(const SkeletonDocument *document, QUuid p
|
||||||
miniToolLayout->addWidget(m_subdivButton);
|
miniToolLayout->addWidget(m_subdivButton);
|
||||||
miniToolLayout->addStretch();
|
miniToolLayout->addStretch();
|
||||||
|
|
||||||
|
QWidget *hrWidget = new QWidget;
|
||||||
|
hrWidget->setFixedHeight(1);
|
||||||
|
hrWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
|
hrWidget->setStyleSheet(QString("background-color: #252525;"));
|
||||||
|
hrWidget->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
mainLayout->setSpacing(0);
|
mainLayout->setSpacing(0);
|
||||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
mainLayout->addLayout(miniToolLayout);
|
mainLayout->addLayout(miniToolLayout);
|
||||||
mainLayout->addWidget(m_previewLabel);
|
mainLayout->addWidget(m_previewLabel);
|
||||||
|
mainLayout->addWidget(hrWidget);
|
||||||
|
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
connect(this, &SkeletonPartWidget::setPartLockState, m_document, &SkeletonDocument::setPartLockState);
|
||||||
|
connect(this, &SkeletonPartWidget::setPartVisibleState, m_document, &SkeletonDocument::setPartVisibleState);
|
||||||
|
connect(this, &SkeletonPartWidget::setPartSubdivState, m_document, &SkeletonDocument::setPartSubdivState);
|
||||||
|
|
||||||
|
connect(m_lockButton, &QPushButton::clicked, [=]() {
|
||||||
|
if (m_lockButton->text() == QChar(fa::lock)) {
|
||||||
|
emit setPartLockState(m_partId, false);
|
||||||
|
} else {
|
||||||
|
emit setPartLockState(m_partId, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_visibleButton, &QPushButton::clicked, [=]() {
|
||||||
|
if (m_visibleButton->text() == QChar(fa::eye)) {
|
||||||
|
emit setPartVisibleState(m_partId, false);
|
||||||
|
} else {
|
||||||
|
emit setPartVisibleState(m_partId, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_subdivButton, &QPushButton::clicked, [=]() {
|
||||||
|
if (m_subdivButton->text() == QChar(fa::cube)) {
|
||||||
|
emit setPartSubdivState(m_partId, true);
|
||||||
|
} else {
|
||||||
|
emit setPartSubdivState(m_partId, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
QLabel *SkeletonPartWidget::previewLabel()
|
void SkeletonPartWidget::initButton(QPushButton *button)
|
||||||
{
|
{
|
||||||
return m_previewLabel;
|
button->setFont(Theme::awesome()->font(Theme::miniIconFontSize));
|
||||||
|
button->setFixedSize(Theme::miniIconSize, Theme::miniIconSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonPartWidget::reload()
|
void SkeletonPartWidget::updateButton(QPushButton *button, QChar icon, bool highlighted)
|
||||||
|
{
|
||||||
|
button->setText(icon);
|
||||||
|
if (highlighted)
|
||||||
|
button->setStyleSheet("QPushButton {border: none; background: none; color: #f7d9c8;}");
|
||||||
|
else
|
||||||
|
button->setStyleSheet("QPushButton {border: none; background: none; color: #252525;}");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkeletonPartWidget::updatePreview()
|
||||||
{
|
{
|
||||||
const SkeletonPart *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;
|
||||||
}
|
}
|
||||||
//m_nameLabel->setText(part->name.isEmpty() ? part->id.toString() : part->name);
|
|
||||||
m_previewLabel->setPixmap(QPixmap::fromImage(part->preview));
|
m_previewLabel->setPixmap(QPixmap::fromImage(part->preview));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkeletonPartWidget::updateLockButton()
|
||||||
|
{
|
||||||
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
||||||
|
if (!part) {
|
||||||
|
qDebug() << "Part not found:" << m_partId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (part->locked)
|
||||||
|
updateButton(m_lockButton, QChar(fa::lock), true);
|
||||||
|
else
|
||||||
|
updateButton(m_lockButton, QChar(fa::unlock), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkeletonPartWidget::updateVisibleButton()
|
||||||
|
{
|
||||||
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
||||||
|
if (!part) {
|
||||||
|
qDebug() << "Part not found:" << m_partId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (part->visible)
|
||||||
|
updateButton(m_visibleButton, QChar(fa::eye), false);
|
||||||
|
else
|
||||||
|
updateButton(m_visibleButton, QChar(fa::eyeslash), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkeletonPartWidget::updateSubdivButton()
|
||||||
|
{
|
||||||
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
||||||
|
if (!part) {
|
||||||
|
qDebug() << "Part not found:" << m_partId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (part->subdived)
|
||||||
|
updateButton(m_subdivButton, QChar(fa::cubes), true);
|
||||||
|
else
|
||||||
|
updateButton(m_subdivButton, QChar(fa::cube), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkeletonPartWidget::reload()
|
||||||
|
{
|
||||||
|
updatePreview();
|
||||||
|
updateLockButton();
|
||||||
|
updateVisibleButton();
|
||||||
|
updateSubdivButton();
|
||||||
|
}
|
||||||
|
|
||||||
SkeletonPartListWidget::SkeletonPartListWidget(const SkeletonDocument *document) :
|
SkeletonPartListWidget::SkeletonPartListWidget(const SkeletonDocument *document) :
|
||||||
m_document(document)
|
m_document(document)
|
||||||
{
|
{
|
||||||
setSelectionMode(QAbstractItemView::NoSelection);
|
setSelectionMode(QAbstractItemView::NoSelection);
|
||||||
|
setFocusPolicy(Qt::NoFocus);
|
||||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||||
setSpacing(1);
|
setSpacing(0);
|
||||||
setContentsMargins(0, 0, 0, 0);
|
setContentsMargins(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonPartListWidget::partChanged(QUuid partId)
|
void SkeletonPartListWidget::partChanged(QUuid partId)
|
||||||
{
|
{
|
||||||
auto itemIt = m_itemMap.find(partId);
|
auto item = m_itemMap.find(partId);
|
||||||
if (itemIt == m_itemMap.end()) {
|
if (item == m_itemMap.end()) {
|
||||||
|
qDebug() << "Part item not found:" << partId;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
SkeletonPartWidget *widget = (SkeletonPartWidget *)itemWidget(item->second);
|
||||||
|
widget->reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonPartListWidget::partListChanged()
|
void SkeletonPartListWidget::partListChanged()
|
||||||
|
@ -93,18 +185,46 @@ void SkeletonPartListWidget::partListChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonPartListWidget::partPreviewChanged(QUuid partid)
|
void SkeletonPartListWidget::partPreviewChanged(QUuid partId)
|
||||||
{
|
{
|
||||||
const SkeletonPart *part = m_document->findPart(partid);
|
auto item = m_itemMap.find(partId);
|
||||||
if (!part) {
|
|
||||||
qDebug() << "Part not found:" << partid;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto item = m_itemMap.find(partid);
|
|
||||||
if (item == m_itemMap.end()) {
|
if (item == m_itemMap.end()) {
|
||||||
qDebug() << "Part item not found:" << partid;
|
qDebug() << "Part item not found:" << partId;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SkeletonPartWidget *widget = (SkeletonPartWidget *)itemWidget(item->second);
|
SkeletonPartWidget *widget = (SkeletonPartWidget *)itemWidget(item->second);
|
||||||
widget->previewLabel()->setPixmap(QPixmap::fromImage(part->preview));
|
widget->updatePreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkeletonPartListWidget::partLockStateChanged(QUuid partId)
|
||||||
|
{
|
||||||
|
auto item = m_itemMap.find(partId);
|
||||||
|
if (item == m_itemMap.end()) {
|
||||||
|
qDebug() << "Part item not found:" << partId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SkeletonPartWidget *widget = (SkeletonPartWidget *)itemWidget(item->second);
|
||||||
|
widget->updateLockButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkeletonPartListWidget::partVisibleStateChanged(QUuid partId)
|
||||||
|
{
|
||||||
|
auto item = m_itemMap.find(partId);
|
||||||
|
if (item == m_itemMap.end()) {
|
||||||
|
qDebug() << "Part item not found:" << partId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SkeletonPartWidget *widget = (SkeletonPartWidget *)itemWidget(item->second);
|
||||||
|
widget->updateVisibleButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkeletonPartListWidget::partSubdivStateChanged(QUuid partId)
|
||||||
|
{
|
||||||
|
auto item = m_itemMap.find(partId);
|
||||||
|
if (item == m_itemMap.end()) {
|
||||||
|
qDebug() << "Part item not found:" << partId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SkeletonPartWidget *widget = (SkeletonPartWidget *)itemWidget(item->second);
|
||||||
|
widget->updateSubdivButton();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,17 @@
|
||||||
class SkeletonPartWidget : public QWidget
|
class SkeletonPartWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
signals:
|
||||||
|
void setPartLockState(QUuid partId, bool locked);
|
||||||
|
void setPartVisibleState(QUuid partId, bool visible);
|
||||||
|
void setPartSubdivState(QUuid partId, bool subdived);
|
||||||
public:
|
public:
|
||||||
SkeletonPartWidget(const SkeletonDocument *document, QUuid partId);
|
SkeletonPartWidget(const SkeletonDocument *document, QUuid partId);
|
||||||
void reload();
|
void reload();
|
||||||
QLabel *previewLabel();
|
void updatePreview();
|
||||||
|
void updateLockButton();
|
||||||
|
void updateVisibleButton();
|
||||||
|
void updateSubdivButton();
|
||||||
private:
|
private:
|
||||||
const SkeletonDocument *m_document;
|
const SkeletonDocument *m_document;
|
||||||
QUuid m_partId;
|
QUuid m_partId;
|
||||||
|
@ -21,6 +28,9 @@ private:
|
||||||
QPushButton *m_lockButton;
|
QPushButton *m_lockButton;
|
||||||
QPushButton *m_subdivButton;
|
QPushButton *m_subdivButton;
|
||||||
QLabel *m_nameLabel;
|
QLabel *m_nameLabel;
|
||||||
|
private:
|
||||||
|
void initButton(QPushButton *button);
|
||||||
|
void updateButton(QPushButton *button, QChar icon, bool highlighted);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SkeletonPartListWidget : public QListWidget
|
class SkeletonPartListWidget : public QListWidget
|
||||||
|
@ -32,6 +42,9 @@ public slots:
|
||||||
void partChanged(QUuid partId);
|
void partChanged(QUuid partId);
|
||||||
void partListChanged();
|
void partListChanged();
|
||||||
void partPreviewChanged(QUuid partid);
|
void partPreviewChanged(QUuid partid);
|
||||||
|
void partLockStateChanged(QUuid partId);
|
||||||
|
void partVisibleStateChanged(QUuid partId);
|
||||||
|
void partSubdivStateChanged(QUuid partId);
|
||||||
private:
|
private:
|
||||||
const SkeletonDocument *m_document;
|
const SkeletonDocument *m_document;
|
||||||
std::map<QUuid, QListWidgetItem *> m_itemMap;
|
std::map<QUuid, QListWidgetItem *> m_itemMap;
|
||||||
|
|
Loading…
Reference in New Issue