Implement ungroupping components

master
Jeremy HU 2022-10-10 22:05:16 +11:00
parent c729099f0d
commit 5d5a1c04bd
4 changed files with 90 additions and 4 deletions

View File

@ -113,7 +113,8 @@ PartManageWidget::PartManageWidget(Document *document, QWidget *parent):
connect(m_document, &Document::partDisableStateChanged, this, &PartManageWidget::updateToolButtons); connect(m_document, &Document::partDisableStateChanged, this, &PartManageWidget::updateToolButtons);
connect(m_document, &Document::componentChildrenChanged, 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::groupOperationAdded, m_document, &Document::saveSnapshot);
connect(this, &PartManageWidget::customContextMenuRequested, this, &PartManageWidget::showContextMenu); connect(this, &PartManageWidget::customContextMenuRequested, this, &PartManageWidget::showContextMenu);
@ -225,6 +226,16 @@ void PartManageWidget::updateToolButtons()
m_propertyButton->setEnabled(enablePropertyButton); 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) void PartManageWidget::showContextMenu(const QPoint &pos)
{ {
auto selectedComponentIds = m_componentPreviewGridWidget->getSelectedComponentIds(); auto selectedComponentIds = m_componentPreviewGridWidget->getSelectedComponentIds();
@ -239,8 +250,17 @@ void PartManageWidget::showContextMenu(const QPoint &pos)
emit this->groupComponents(selectedComponentIds); emit this->groupComponents(selectedComponentIds);
emit this->groupOperationAdded(); emit this->groupOperationAdded();
}); });
contextMenu.addAction(&makeGroupAction); 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)); contextMenu.exec(mapToGlobal(pos));
} }

View File

@ -16,6 +16,7 @@ signals:
void unselectAllOnCanvas(); void unselectAllOnCanvas();
void selectPartOnCanvas(const dust3d::Uuid &partId); void selectPartOnCanvas(const dust3d::Uuid &partId);
void groupComponents(const std::vector<dust3d::Uuid> &componentIds); void groupComponents(const std::vector<dust3d::Uuid> &componentIds);
void ungroupComponent(const dust3d::Uuid &componentId);
void groupOperationAdded(); void groupOperationAdded();
public slots: public slots:
void selectComponentByPartId(const dust3d::Uuid &partId); void selectComponentByPartId(const dust3d::Uuid &partId);
@ -37,6 +38,7 @@ private:
QPushButton *m_propertyButton = nullptr; QPushButton *m_propertyButton = nullptr;
void updateToolButtons(); void updateToolButtons();
void updateLevelUpButton(); void updateLevelUpButton();
bool hasSelectedGroupedComponent();
}; };
#endif #endif

View File

@ -520,7 +520,38 @@ void SkeletonDocument::setComponentExpandState(dust3d::Uuid componentId, bool ex
emit optionsChanged(); emit optionsChanged();
} }
void SkeletonDocument::createNewComponentAndMoveTheseIn(const std::vector<dust3d::Uuid> &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<dust3d::Uuid> &componentIds)
{ {
if (componentIds.empty()) if (componentIds.empty())
return; return;
@ -533,6 +564,10 @@ void SkeletonDocument::createNewComponentAndMoveTheseIn(const std::vector<dust3d
auto it = componentIds.begin(); auto it = componentIds.begin();
SkeletonComponent *oldParent = (SkeletonComponent *)findComponentParent(*it); SkeletonComponent *oldParent = (SkeletonComponent *)findComponentParent(*it);
if (nullptr == oldParent) {
dust3dDebug << "Expected parent component to be found, component:" << it->toString();
return;
}
auto oldParentId = oldParent->id; auto oldParentId = oldParent->id;
oldParent->replaceChild(*it, newParentId); oldParent->replaceChild(*it, newParentId);
for (++it; it != componentIds.end(); ++it) { for (++it; it != componentIds.end(); ++it) {

View File

@ -445,6 +445,34 @@ public:
m_childrenIdSet.insert(childId); m_childrenIdSet.insert(childId);
childrenIds.push_back(childId); childrenIds.push_back(childId);
} }
void replaceChildWithOthers(const dust3d::Uuid &childId, const std::vector<dust3d::Uuid> &others)
{
if (m_childrenIdSet.find(childId) == m_childrenIdSet.end())
return;
m_childrenIdSet.erase(childId);
std::vector<dust3d::Uuid> 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) void removeChild(dust3d::Uuid childId)
{ {
if (m_childrenIdSet.find(childId) == m_childrenIdSet.end()) if (m_childrenIdSet.find(childId) == m_childrenIdSet.end())
@ -678,7 +706,8 @@ public slots:
void addComponent(dust3d::Uuid parentId); void addComponent(dust3d::Uuid parentId);
void moveComponent(dust3d::Uuid componentId, dust3d::Uuid toParentId); void moveComponent(dust3d::Uuid componentId, dust3d::Uuid toParentId);
void setCurrentCanvasComponentId(dust3d::Uuid componentId); void setCurrentCanvasComponentId(dust3d::Uuid componentId);
void createNewComponentAndMoveTheseIn(const std::vector<dust3d::Uuid> &componentIds); void groupComponents(const std::vector<dust3d::Uuid> &componentIds);
void ungroupComponent(const dust3d::Uuid &componentId);
void createNewChildComponent(dust3d::Uuid parentComponentId); void createNewChildComponent(dust3d::Uuid parentComponentId);
void setComponentExpandState(dust3d::Uuid componentId, bool expanded); void setComponentExpandState(dust3d::Uuid componentId, bool expanded);
void hideOtherComponents(dust3d::Uuid componentId); void hideOtherComponents(dust3d::Uuid componentId);