Finish part mini buttons

master
Jeremy Hu 2018-04-08 09:30:55 +08:00
parent 8d558aa19f
commit 1c4515abd7
8 changed files with 294 additions and 69 deletions

View File

@ -184,9 +184,14 @@ void MeshGenerator::process()
std::map<QString, int> partMeshMap;
std::vector<int> meshIds;
for (const auto &partIdIt: m_snapshot->partIdList) {
const auto part = m_snapshot->parts.find(partIdIt);
int bmeshId = partBmeshMap[partIdIt];
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()) {
ModelOfflineRender *render = m_partPreviewRenderMap[partIdIt];
int trimedMeshId = meshlite_trim(meshliteContext, meshId, 1);

View File

@ -26,14 +26,6 @@ void SkeletonDocument::removePart(QUuid partId)
{
}
void SkeletonDocument::showPart(QUuid partId)
{
}
void SkeletonDocument::hidePart(QUuid partId)
{
}
void SkeletonDocument::removeEdge(QUuid edgeId)
{
const SkeletonEdge *edge = findEdge(edgeId);
@ -41,6 +33,8 @@ void SkeletonDocument::removeEdge(QUuid edgeId)
qDebug() << "Find edge failed:" << edgeId;
return;
}
if (isPartLocked(edge->partId))
return;
const SkeletonPart *oldPart = findPart(edge->partId);
if (nullptr == oldPart) {
qDebug() << "Find part failed:" << edge->partId;
@ -100,6 +94,8 @@ void SkeletonDocument::removeNode(QUuid nodeId)
qDebug() << "Find node failed:" << nodeId;
return;
}
if (isPartLocked(node->partId))
return;
const SkeletonPart *oldPart = findPart(node->partId);
if (nullptr == oldPart) {
qDebug() << "Find part failed:" << node->partId;
@ -178,6 +174,8 @@ void SkeletonDocument::addNode(float x, float y, float z, float radius, QUuid fr
return;
}
partId = fromNode->partId;
if (isPartLocked(partId))
return;
}
SkeletonNode node;
node.partId = partId;
@ -245,12 +243,18 @@ void SkeletonDocument::addEdge(QUuid fromNodeId, QUuid toNodeId)
return;
}
if (isPartLocked(fromNode->partId))
return;
toNode = findNode(toNodeId);
if (nullptr == toNode) {
qDebug() << "Find node failed:" << toNodeId;
return;
}
if (isPartLocked(toNode->partId))
return;
QUuid toPartId = toNode->partId;
auto fromPart = partMap.find(fromNode->partId);
@ -335,11 +339,23 @@ void SkeletonDocument::scaleNodeByAddRadius(QUuid nodeId, float amount)
qDebug() << "Find node failed:" << nodeId;
return;
}
if (isPartLocked(it->second.partId))
return;
it->second.radius += amount;
emit nodeRadiusChanged(nodeId);
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)
{
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;
return;
}
if (isPartLocked(it->second.partId))
return;
it->second.x += x;
it->second.y += y;
it->second.z += z;
@ -361,6 +379,8 @@ void SkeletonDocument::setNodeOrigin(QUuid nodeId, float x, float y, float z)
qDebug() << "Find node failed:" << nodeId;
return;
}
if (isPartLocked(it->second.partId))
return;
it->second.x = x;
it->second.y = y;
it->second.z = z;
@ -375,6 +395,8 @@ void SkeletonDocument::setNodeRadius(QUuid nodeId, float radius)
qDebug() << "Find node failed:" << nodeId;
return;
}
if (isPartLocked(it->second.partId))
return;
it->second.radius = radius;
emit nodeRadiusChanged(nodeId);
emit skeletonChanged();
@ -479,6 +501,8 @@ void SkeletonDocument::toSnapshot(SkeletonSnapshot *snapshot)
std::map<QString, QString> part;
part["id"] = partIt.second.id.toString();
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())
part["name"] = partIt.second.name;
snapshot->parts[part["id"]] = part;
@ -560,6 +584,8 @@ void SkeletonDocument::fromSnapshot(const SkeletonSnapshot &snapshot)
SkeletonPart part(QUuid(partKv.first));
part.name = valueOfKeyInMapOrEmpty(partKv.second, "name");
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;
}
for (const auto &partIdIt: snapshot.partIdList) {
@ -704,3 +730,45 @@ void SkeletonDocument::generateMesh()
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
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();
}

View File

@ -80,11 +80,15 @@ public:
QUuid id;
QString name;
bool visible;
bool locked;
bool subdived;
QImage preview;
std::vector<QUuid> nodeIds;
bool previewIsObsolete;
SkeletonPart(const QUuid &withId=QUuid()) :
visible(true),
locked(false),
subdived(false),
previewIsObsolete(true)
{
id = withId.isNull() ? QUuid::createUuid() : withId;
@ -134,6 +138,9 @@ signals:
void turnaroundChanged();
void editModeChanged();
void skeletonChanged();
void partLockStateChanged(QUuid partId);
void partVisibleStateChanged(QUuid partId);
void partSubdivStateChanged(QUuid partId);
public:
SkeletonDocument();
~SkeletonDocument();
@ -157,8 +164,6 @@ public slots:
void removeNode(QUuid nodeId);
void removeEdge(QUuid edgeId);
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 scaleNodeByAddRadius(QUuid nodeId, float amount);
void moveNodeBy(QUuid nodeId, float x, float y, float z);
@ -171,10 +176,14 @@ public slots:
void uiReady();
void generateMesh();
void meshReady();
void setPartLockState(QUuid partId, bool locked);
void setPartVisibleState(QUuid partId, bool visible);
void setPartSubdivState(QUuid partId, bool subdived);
private:
void splitPartByNode(std::vector<std::vector<QUuid>> *groups, QUuid nodeId);
void joinNodeAndNeiborsToGroup(std::vector<QUuid> *group, QUuid nodeId, std::set<QUuid> *visitMap, QUuid noUseEdgeId=QUuid());
void splitPartByEdge(std::vector<std::vector<QUuid>> *groups, QUuid edgeId);
bool isPartLocked(QUuid partId);
private:
bool m_resultMeshIsObsolete;
MeshGenerator *m_meshGenerator;

View File

@ -97,9 +97,9 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
containerWidget->setMinimumSize(400, 400);
m_modelWidget = new ModelWidget(containerWidget);
m_modelWidget->setMinimumSize(128, 128);
m_modelWidget->setMinimumSize(256, 256);
m_modelWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
m_modelWidget->move(10, 10);
m_modelWidget->move(16, 16);
m_modelWidget->setGraphicsFunctions(graphicsWidget);
SkeletonPartListWidget *partListWidget = new SkeletonPartListWidget(m_document);
@ -193,33 +193,13 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
connect(m_document, &SkeletonDocument::edgeRemoved, graphicsWidget, &SkeletonGraphicsWidget::edgeRemoved);
connect(m_document, &SkeletonDocument::nodeRadiusChanged, graphicsWidget, &SkeletonGraphicsWidget::nodeRadiusChanged);
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::partPreviewChanged, partListWidget, &SkeletonPartListWidget::partPreviewChanged);
/*
connect(graphicsWidget, &SkeletonGraphicsWidget::checkEdge, edgePropertyWidget, &SkeletonEdgePropertyWidget::showProperties);
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::partLockStateChanged, partListWidget, &SkeletonPartListWidget::partLockStateChanged);
connect(m_document, &SkeletonDocument::partVisibleStateChanged, partListWidget, &SkeletonPartListWidget::partVisibleStateChanged);
connect(m_document, &SkeletonDocument::partSubdivStateChanged, partListWidget, &SkeletonPartListWidget::partSubdivStateChanged);
connect(m_document, &SkeletonDocument::skeletonChanged, m_document, &SkeletonDocument::generateMesh);

View File

@ -366,11 +366,16 @@ bool SkeletonGraphicsWidget::mousePress(QMouseEvent *event)
}
QPointF mainProfile = m_cursorNodeItem->origin();
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) {
sideProfile.setX(mainProfile.x() - scene()->width() / 4);
} else {
sideProfile.setX(mainProfile.x() +scene()->width() / 4);
}
}
QPointF unifiedMainPos = scenePosToUnified(mainProfile);
QPointF unifiedSidePos = scenePosToUnified(sideProfile);
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);
}
}

View File

@ -264,6 +264,7 @@ public slots:
void canvasResized();
void editModeChanged();
void updateCursor();
void partVisibleStateChanged(QUuid partId);
private slots:
void turnaroundImageReady();
private:

View File

@ -8,20 +8,17 @@ SkeletonPartWidget::SkeletonPartWidget(const SkeletonDocument *document, QUuid p
m_document(document),
m_partId(partId)
{
m_visibleButton = new QPushButton(QChar(fa::eye));
m_visibleButton->setStyleSheet("QPushButton {border: none; background: none; color: #252525;}");
m_visibleButton->setFont(Theme::awesome()->font(Theme::miniIconFontSize));
m_visibleButton->setFixedSize(Theme::miniIconSize, Theme::miniIconSize);
m_visibleButton = new QPushButton();
updateButton(m_visibleButton, QChar(fa::eye), false);
initButton(m_visibleButton);
m_lockButton = new QPushButton(QChar(fa::unlock));
m_lockButton->setStyleSheet("QPushButton {border: none; background: none; color: #252525;}");
m_lockButton->setFont(Theme::awesome()->font(Theme::miniIconFontSize));
m_lockButton->setFixedSize(Theme::miniIconSize, Theme::miniIconSize);
m_lockButton = new QPushButton();
updateButton(m_lockButton, QChar(fa::unlock), false);
initButton(m_lockButton);
m_subdivButton = new QPushButton(QChar(fa::cube));
m_subdivButton->setStyleSheet("QPushButton {border: none; background: none; color: #252525;}");
m_subdivButton->setFont(Theme::awesome()->font(Theme::miniIconFontSize));
m_subdivButton->setFixedSize(Theme::miniIconSize, Theme::miniIconSize);
m_subdivButton = new QPushButton();
updateButton(m_subdivButton, QChar(fa::cube), false);
initButton(m_subdivButton);
m_previewLabel = new QLabel;
@ -34,46 +31,141 @@ SkeletonPartWidget::SkeletonPartWidget(const SkeletonDocument *document, QUuid p
miniToolLayout->addWidget(m_subdivButton);
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;
mainLayout->setSpacing(0);
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->addLayout(miniToolLayout);
mainLayout->addWidget(m_previewLabel);
mainLayout->addWidget(hrWidget);
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);
if (!part) {
qDebug() << "Part not found:" << m_partId;
return;
}
//m_nameLabel->setText(part->name.isEmpty() ? part->id.toString() : part->name);
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) :
m_document(document)
{
setSelectionMode(QAbstractItemView::NoSelection);
setFocusPolicy(Qt::NoFocus);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setSpacing(1);
setSpacing(0);
setContentsMargins(0, 0, 0, 0);
}
void SkeletonPartListWidget::partChanged(QUuid partId)
{
auto itemIt = m_itemMap.find(partId);
if (itemIt == m_itemMap.end()) {
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->reload();
}
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);
if (!part) {
qDebug() << "Part not found:" << partid;
return;
}
auto item = m_itemMap.find(partid);
auto item = m_itemMap.find(partId);
if (item == m_itemMap.end()) {
qDebug() << "Part item not found:" << partid;
qDebug() << "Part item not found:" << partId;
return;
}
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();
}

View File

@ -9,10 +9,17 @@
class SkeletonPartWidget : public QWidget
{
Q_OBJECT
signals:
void setPartLockState(QUuid partId, bool locked);
void setPartVisibleState(QUuid partId, bool visible);
void setPartSubdivState(QUuid partId, bool subdived);
public:
SkeletonPartWidget(const SkeletonDocument *document, QUuid partId);
void reload();
QLabel *previewLabel();
void updatePreview();
void updateLockButton();
void updateVisibleButton();
void updateSubdivButton();
private:
const SkeletonDocument *m_document;
QUuid m_partId;
@ -21,6 +28,9 @@ private:
QPushButton *m_lockButton;
QPushButton *m_subdivButton;
QLabel *m_nameLabel;
private:
void initButton(QPushButton *button);
void updateButton(QPushButton *button, QChar icon, bool highlighted);
};
class SkeletonPartListWidget : public QListWidget
@ -32,6 +42,9 @@ public slots:
void partChanged(QUuid partId);
void partListChanged();
void partPreviewChanged(QUuid partid);
void partLockStateChanged(QUuid partId);
void partVisibleStateChanged(QUuid partId);
void partSubdivStateChanged(QUuid partId);
private:
const SkeletonDocument *m_document;
std::map<QUuid, QListWidgetItem *> m_itemMap;