From 5d5a1c04bd38a519b83344ace42e9f3da1dfc331 Mon Sep 17 00:00:00 2001 From: Jeremy HU Date: Mon, 10 Oct 2022 22:05:16 +1100 Subject: [PATCH] Implement ungroupping components --- application/sources/part_manage_widget.cc | 24 +++++++++++++-- application/sources/part_manage_widget.h | 2 ++ application/sources/skeleton_document.cc | 37 ++++++++++++++++++++++- application/sources/skeleton_document.h | 31 ++++++++++++++++++- 4 files changed, 90 insertions(+), 4 deletions(-) diff --git a/application/sources/part_manage_widget.cc b/application/sources/part_manage_widget.cc index b827b5be..9837ccf0 100644 --- a/application/sources/part_manage_widget.cc +++ b/application/sources/part_manage_widget.cc @@ -113,7 +113,8 @@ PartManageWidget::PartManageWidget(Document *document, QWidget *parent): connect(m_document, &Document::partDisableStateChanged, this, &PartManageWidget::updateToolButtons); connect(m_document, &Document::componentChildrenChanged, this, &PartManageWidget::updateToolButtons); - connect(this, &PartManageWidget::groupComponents, m_document, &Document::createNewComponentAndMoveTheseIn); + connect(this, &PartManageWidget::groupComponents, m_document, &Document::groupComponents); + connect(this, &PartManageWidget::ungroupComponent, m_document, &Document::ungroupComponent); connect(this, &PartManageWidget::groupOperationAdded, m_document, &Document::saveSnapshot); connect(this, &PartManageWidget::customContextMenuRequested, this, &PartManageWidget::showContextMenu); @@ -225,6 +226,16 @@ void PartManageWidget::updateToolButtons() m_propertyButton->setEnabled(enablePropertyButton); } +bool PartManageWidget::hasSelectedGroupedComponent() +{ + auto selectedComponents = m_componentPreviewGridWidget->getSelectedComponents(); + for (auto &component: selectedComponents) { + if (!component->childrenIds.empty()) + return true; + } + return false; +} + void PartManageWidget::showContextMenu(const QPoint &pos) { auto selectedComponentIds = m_componentPreviewGridWidget->getSelectedComponentIds(); @@ -239,8 +250,17 @@ void PartManageWidget::showContextMenu(const QPoint &pos) emit this->groupComponents(selectedComponentIds); emit this->groupOperationAdded(); }); - contextMenu.addAction(&makeGroupAction); + QAction ungroupAction(tr("Ungroup"), this); + if (hasSelectedGroupedComponent()) { + connect(&ungroupAction, &QAction::triggered, this, [=]() { + for (const auto &it: selectedComponentIds) + emit this->ungroupComponent(it); + emit this->groupOperationAdded(); + }); + contextMenu.addAction(&ungroupAction); + } + contextMenu.exec(mapToGlobal(pos)); } diff --git a/application/sources/part_manage_widget.h b/application/sources/part_manage_widget.h index e5d1f465..0e611a3c 100644 --- a/application/sources/part_manage_widget.h +++ b/application/sources/part_manage_widget.h @@ -16,6 +16,7 @@ signals: void unselectAllOnCanvas(); void selectPartOnCanvas(const dust3d::Uuid &partId); void groupComponents(const std::vector &componentIds); + void ungroupComponent(const dust3d::Uuid &componentId); void groupOperationAdded(); public slots: void selectComponentByPartId(const dust3d::Uuid &partId); @@ -37,6 +38,7 @@ private: QPushButton *m_propertyButton = nullptr; void updateToolButtons(); void updateLevelUpButton(); + bool hasSelectedGroupedComponent(); }; #endif diff --git a/application/sources/skeleton_document.cc b/application/sources/skeleton_document.cc index 94b68f78..b9f6e5a7 100644 --- a/application/sources/skeleton_document.cc +++ b/application/sources/skeleton_document.cc @@ -520,7 +520,38 @@ void SkeletonDocument::setComponentExpandState(dust3d::Uuid componentId, bool ex emit optionsChanged(); } -void SkeletonDocument::createNewComponentAndMoveTheseIn(const std::vector &componentIds) +void SkeletonDocument::ungroupComponent(const dust3d::Uuid &componentId) +{ + if (componentId.isNull()) + return; + SkeletonComponent *component = (SkeletonComponent *)findComponent(componentId); + if (nullptr == component) { + dust3dDebug << "Component not found:" << componentId.toString(); + return; + } + if (component->childrenIds.empty()) + return; + auto childrenIds = component->childrenIds; + SkeletonComponent *newParent = (SkeletonComponent *)findComponentParent(componentId); + if (nullptr == newParent) { + dust3dDebug << "Expected parent component to be found, component:" << componentId.toString(); + return; + } + auto newParentId = newParent->id; + newParent->replaceChildWithOthers(componentId, childrenIds); + for (const auto &childId: childrenIds) { + SkeletonComponent *child = (SkeletonComponent *)findComponent(childId); + if (nullptr == child) + continue; + child->parentId = newParentId; + } + componentMap.erase(componentId); + emit componentRemoved(componentId); + emit componentChildrenChanged(newParentId); + emit skeletonChanged(); +} + +void SkeletonDocument::groupComponents(const std::vector &componentIds) { if (componentIds.empty()) return; @@ -533,6 +564,10 @@ void SkeletonDocument::createNewComponentAndMoveTheseIn(const std::vectortoString(); + return; + } auto oldParentId = oldParent->id; oldParent->replaceChild(*it, newParentId); for (++it; it != componentIds.end(); ++it) { diff --git a/application/sources/skeleton_document.h b/application/sources/skeleton_document.h index 6bfed1fb..c886f77e 100644 --- a/application/sources/skeleton_document.h +++ b/application/sources/skeleton_document.h @@ -445,6 +445,34 @@ public: m_childrenIdSet.insert(childId); childrenIds.push_back(childId); } + void replaceChildWithOthers(const dust3d::Uuid &childId, const std::vector &others) + { + if (m_childrenIdSet.find(childId) == m_childrenIdSet.end()) + return; + m_childrenIdSet.erase(childId); + std::vector candidates; + for (const auto &it: others) { + if (m_childrenIdSet.find(it) == m_childrenIdSet.end()) { + m_childrenIdSet.insert(it); + candidates.emplace_back(it); + } + } + for (size_t i = 0; i < childrenIds.size(); ++i) { + if (childId == childrenIds[i]) { + size_t newAddSize = candidates.size() - 1; + if (newAddSize > 0) { + size_t oldSize = childrenIds.size(); + childrenIds.resize(childrenIds.size() + newAddSize); + for (int j = (int)oldSize - 1; j > (int)i; --j) { + childrenIds[j + newAddSize] = childrenIds[j]; + } + } + for (size_t k = 0; k < candidates.size(); ++k) + childrenIds[i + k] = candidates[k]; + break; + } + } + } void removeChild(dust3d::Uuid childId) { if (m_childrenIdSet.find(childId) == m_childrenIdSet.end()) @@ -678,7 +706,8 @@ public slots: void addComponent(dust3d::Uuid parentId); void moveComponent(dust3d::Uuid componentId, dust3d::Uuid toParentId); void setCurrentCanvasComponentId(dust3d::Uuid componentId); - void createNewComponentAndMoveTheseIn(const std::vector &componentIds); + void groupComponents(const std::vector &componentIds); + void ungroupComponent(const dust3d::Uuid &componentId); void createNewChildComponent(dust3d::Uuid parentComponentId); void setComponentExpandState(dust3d::Uuid componentId, bool expanded); void hideOtherComponents(dust3d::Uuid componentId);