From 6222b935f08c63cb6e3f00530096d50e3309be45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Matos?= Date: Tue, 14 Jan 2025 03:38:41 +0000 Subject: [PATCH] Gui: Scene inspector improvements (#18781) * Improve naming for root scene graph switch/separator nodes. * Improve scene graph inspector. This commit improves the scene graph inspector by improving the UI layout and displaying information in a more human-readable way. Instead of having a main generic string column for all node-specific data, introduce specific columns for node name, memory address and data. Better visualization was also added for `SoDrawStyle`, `SoPickStyle` and `SoCoordinate3` node types. --- src/Gui/SceneInspector.cpp | 180 +++++++++++++++++++---- src/Gui/SceneInspector.ui | 2 +- src/Gui/View3DInventorSelection.cpp | 13 +- src/Gui/View3DInventorViewer.cpp | 12 +- src/Gui/ViewProvider.cpp | 1 + src/Gui/ViewProviderGeometryObject.cpp | 4 + src/Gui/ViewProviderTextureExtension.cpp | 7 + src/Mod/Part/Gui/ViewProviderExt.cpp | 12 ++ 8 files changed, 192 insertions(+), 39 deletions(-) diff --git a/src/Gui/SceneInspector.cpp b/src/Gui/SceneInspector.cpp index 4bd1e51838..bec6a63f55 100644 --- a/src/Gui/SceneInspector.cpp +++ b/src/Gui/SceneInspector.cpp @@ -23,6 +23,9 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include +# include +# include +# include # include # include #endif @@ -45,12 +48,20 @@ SceneModel::SceneModel(QObject* parent) { } +enum class Column: std::int8_t { + INVENTOR_TREE = 0, + NAME = 1, + MEMORY_ADDRESS = 2, + DATA = 3, + COUNT = 4, +}; + SceneModel::~SceneModel() = default; int SceneModel::columnCount (const QModelIndex & parent) const { Q_UNUSED(parent); - return 2; + return static_cast(Column::COUNT); } Qt::ItemFlags SceneModel::flags (const QModelIndex & index) const @@ -63,10 +74,19 @@ QVariant SceneModel::headerData (int section, Qt::Orientation orientation, int r if (orientation == Qt::Horizontal) { if (role != Qt::DisplayRole) return {}; - if (section == 0) + + switch ((Column)section) { + case Column::INVENTOR_TREE: return tr("Inventor Tree"); - else if (section == 1) + case Column::NAME: return tr("Name"); + case Column::MEMORY_ADDRESS: + return tr("Address"); + case Column::DATA: + return tr("Data"); + default: + assert(0 && "Not handled yet"); + } } return {}; @@ -82,42 +102,135 @@ void SceneModel::setNode(SoNode* node) this->clear(); this->setHeaderData(0, Qt::Horizontal, tr("Nodes"), Qt::DisplayRole); - this->insertColumns(0,2); + this->insertColumns(0, static_cast(Column::COUNT)); this->insertRows(0,1); setNode(this->index(0, 0), node); } +static std::string_view formatSoSwitchValue(int32_t value) +{ + switch (value) + { + case SO_SWITCH_NONE: + return {"None"}; + case SO_SWITCH_INHERIT: + return {"Inherit"}; + case SO_SWITCH_ALL: + return {"All"}; + default: + return {"Child"}; + } +} + +static std::string_view formatSoSeparatorCacheEnabled(int32_t value) +{ + switch (value) + { + case SoSeparator::OFF: + return {"Off"}; + case SoSeparator::ON: + return {"On"}; + case SoSeparator::AUTO: + return {"Auto"}; + default: + throw Base::ValueError(); + } +} + +static std::string_view formatSoDrawStyleElement(int32_t value) +{ + switch (value) + { + case SoDrawStyleElement::FILLED: + return {"Filled"}; + case SoDrawStyleElement::LINES: + return {"Lines"}; + case SoDrawStyleElement::POINTS: + return {"Points"}; + case SoDrawStyleElement::INVISIBLE: + return {"Invisible"}; + default: + throw Base::ValueError(); + } +} + +static std::string_view formatSoPickStyleElement(int32_t value) +{ + switch (value) + { + case SoPickStyleElement::SHAPE: + return {"Shape"}; + case SoPickStyleElement::BOUNDING_BOX: + return {"BoundingBox"}; + case SoPickStyleElement::UNPICKABLE: + return {"Unpickable"}; + case SoPickStyleElement::SHAPE_ON_TOP: + return {"ShapeOnTop"}; + case SoPickStyleElement::BOUNDING_BOX_ON_TOP: + return {"BoundingBoxOnTop"}; + case SoPickStyleElement::SHAPE_FRONTFACES: + return {"ShapeFrontFaces"}; + default: + throw Base::ValueError(); + } +} + void SceneModel::setNode(QModelIndex index, SoNode* node) { - this->setData(index, QVariant(QString::fromLatin1(QByteArray(node->getTypeId().getName())))); - if (node->getTypeId().isDerivedFrom(SoGroup::getClassTypeId())) { - auto group = static_cast(node); - // insert SoGroup icon - this->insertColumns(0,2,index); - this->insertRows(0,group->getNumChildren(), index); - for (int i=0; igetNumChildren();i++) { - SoNode* child = group->getChild(i); - setNode(this->index(i, 0, index), child); + this->setData(index.siblingAtColumn(static_cast(Column::INVENTOR_TREE)), + QVariant(QString::fromLatin1(QByteArray(node->getTypeId().getName())))); - QHash::iterator it = nodeNames.find(child); - QString name; - QTextStream stream(&name); - stream << child << ", "; - if(child->isOfType(SoSwitch::getClassTypeId())) { - auto pcSwitch = static_cast(child); - stream << pcSwitch->whichChild.getValue() << ", "; - } else if (child->isOfType(SoSeparator::getClassTypeId())) { - auto pcSeparator = static_cast(child); - stream << pcSeparator->renderCaching.getValue() << ", "; - } - if (it != nodeNames.end()) - stream << it.value(); - else - stream << child->getName(); - this->setData(this->index(i, 1, index), QVariant(name)); + QHash::iterator it = nodeNames.find(node); + const QString name { + (it != nodeNames.end()) ? it.value() + : QString::fromLatin1(QByteArray(node->getName())) + }; + this->setData(index.siblingAtColumn(static_cast(Column::NAME)), QVariant(name)); + + this->setData(index.siblingAtColumn(static_cast(Column::MEMORY_ADDRESS)), + QVariant(QString::fromStdString(fmt::format("{}", (void*)node)))); + + QString data; + QTextStream stream(&data); + if(static_cast(node->isOfType(SoSwitch::getClassTypeId()))) { + auto pcSwitch = static_cast(node); + auto value = pcSwitch->whichChild.getValue(); + stream << fmt::format("Which: {} ({})", formatSoSwitchValue(value), value).c_str(); + } else if (static_cast(node->isOfType(SoSeparator::getClassTypeId()))) { + auto pcSeparator = static_cast(node); + auto value = pcSeparator->renderCaching.getValue(); + stream << fmt::format("RenderCaching: {} ({})", formatSoSeparatorCacheEnabled(value), value).c_str(); + } else if (static_cast(node->isOfType(SoDrawStyle::getClassTypeId()))) { + auto pcDrawStyle = static_cast(node); + auto value = pcDrawStyle->style.getValue(); + stream << fmt::format("Style: {} ({})", formatSoDrawStyleElement(value), value).c_str(); + } else if (static_cast(node->isOfType(SoPickStyle::getClassTypeId()))) { + auto pcPickStyle = static_cast(node); + auto value = pcPickStyle->style.getValue(); + stream << fmt::format("Style: {} ({})", formatSoPickStyleElement(value), value).c_str(); + } else if (static_cast(node->isOfType(SoCoordinate3::getClassTypeId()))) { + auto pcCoords = static_cast(node); + auto values = pcCoords->point.getValues(0); + if (values) { + float x { 0 }; + float y { 0 }; + float z { 0 }; + values->getValue(x, y, z); + stream << fmt::format("XYZ: {}, {}, {}", x, y, z).c_str(); + } + } + + this->setData(index.siblingAtColumn((int)Column::DATA), QVariant(data)); + + if (static_cast(node->getTypeId().isDerivedFrom(SoGroup::getClassTypeId()))) { + auto group = static_cast(node); + this->insertColumns(0, static_cast(Column::COUNT), index); + this->insertRows(0, group->getNumChildren(), index); + for (int i=0; i < group->getNumChildren(); i++) { + SoNode* child = group->getChild(i); + setNode(this->index(i, 0, index), child); } } - // insert icon } void SceneModel::setNodeNames(const QHash& names) @@ -169,7 +282,12 @@ void DlgInspector::setNode(SoNode* node) model->setNode(node); QHeaderView* header = ui->treeView->header(); - header->setSectionResizeMode(0, QHeaderView::Stretch); + header->setSectionResizeMode(static_cast(Column::INVENTOR_TREE), QHeaderView::Interactive); + header->resizeSection(static_cast(Column::INVENTOR_TREE), 300); + header->setSectionResizeMode(static_cast(Column::NAME), QHeaderView::Interactive); + header->resizeSection(static_cast(Column::NAME), 200); + header->setSectionResizeMode(static_cast(Column::MEMORY_ADDRESS), QHeaderView::Interactive); + header->setSectionResizeMode(static_cast(Column::DATA), QHeaderView::Stretch); header->setSectionsMovable(false); } diff --git a/src/Gui/SceneInspector.ui b/src/Gui/SceneInspector.ui index a877a25d89..478137cd5c 100644 --- a/src/Gui/SceneInspector.ui +++ b/src/Gui/SceneInspector.ui @@ -6,7 +6,7 @@ 0 0 - 296 + 805 583 diff --git a/src/Gui/View3DInventorSelection.cpp b/src/Gui/View3DInventorSelection.cpp index ce8d144c11..d3fa5008a0 100644 --- a/src/Gui/View3DInventorSelection.cpp +++ b/src/Gui/View3DInventorSelection.cpp @@ -49,19 +49,22 @@ View3DInventorSelection::View3DInventorSelection(SoFCUnifiedSelection* root) pcGroupOnTop = new SoSeparator; pcGroupOnTop->ref(); + pcGroupOnTop->setName("GroupOnTop"); root->addChild(pcGroupOnTop); auto pcGroupOnTopPickStyle = new SoPickStyle; pcGroupOnTopPickStyle->style = SoPickStyle::UNPICKABLE; pcGroupOnTopPickStyle->setOverride(true); + pcGroupOnTopPickStyle->setName("GroupOnTopPickStyle"); pcGroupOnTop->addChild(pcGroupOnTopPickStyle); coin_setenv("COIN_SEPARATE_DIFFUSE_TRANSPARENCY_OVERRIDE", "1", TRUE); - auto pcOnTopMaterial = new SoMaterial; - pcOnTopMaterial->transparency = 0.5; - pcOnTopMaterial->diffuseColor.setIgnored(true); - pcOnTopMaterial->setOverride(true); - pcGroupOnTop->addChild(pcOnTopMaterial); + auto pcGroupOnTopMaterial = new SoMaterial; + pcGroupOnTopMaterial->transparency = 0.5; + pcGroupOnTopMaterial->diffuseColor.setIgnored(true); + pcGroupOnTopMaterial->setOverride(true); + pcGroupOnTopMaterial->setName("GroupOnTopMaterial"); + pcGroupOnTop->addChild(pcGroupOnTopMaterial); { auto selRoot = new SoFCSelectionRoot; diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 72d2515be5..b7bfaab27e 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -443,6 +443,7 @@ void View3DInventorViewer::init() backgroundroot = new SoSeparator; backgroundroot->ref(); this->backgroundroot->addChild(cam); + this->backgroundroot->setName("backgroundroot"); // Background stuff pcBackGround = new SoFCBackgroundGradient; @@ -451,6 +452,7 @@ void View3DInventorViewer::init() // Set up foreground, overlaid scenegraph. this->foregroundroot = new SoSeparator; this->foregroundroot->ref(); + this->foregroundroot->setName("foregroundroot"); auto lm = new SoLightModel; lm->model = SoLightModel::BASE_COLOR; @@ -493,9 +495,14 @@ void View3DInventorViewer::init() pEventCallback->addEventCallback(SoEvent::getClassTypeId(), handleEventCB, this); dimensionRoot = new SoSwitch(SO_SWITCH_NONE); + dimensionRoot->setName("RootDimensions"); pcViewProviderRoot->addChild(dimensionRoot); - dimensionRoot->addChild(new SoSwitch()); //first one will be for the 3d dimensions. - dimensionRoot->addChild(new SoSwitch()); //second one for the delta dimensions. + auto dimensions3d = new SoSwitch(); + dimensions3d->setName("_3dDimensions"); + dimensionRoot->addChild(dimensions3d); //first one will be for the 3d dimensions. + auto dimensionsDelta = new SoSwitch(); + dimensionsDelta->setName("DeltaDimensions"); + dimensionRoot->addChild(dimensionsDelta); //second one for the delta dimensions. // This is a callback node that logs all action that traverse the Inventor tree. #if defined (FC_DEBUG) && defined(FC_LOGGING_CB) @@ -521,6 +528,7 @@ void View3DInventorViewer::init() // Create group for the physical object objectGroup = new SoGroup(); objectGroup->ref(); + objectGroup->setName("ObjectGroup"); pcViewProviderRoot->addChild(objectGroup); // Set our own render action which show a bounding box if diff --git a/src/Gui/ViewProvider.cpp b/src/Gui/ViewProvider.cpp index 5fbaeb758e..6609d809af 100644 --- a/src/Gui/ViewProvider.cpp +++ b/src/Gui/ViewProvider.cpp @@ -107,6 +107,7 @@ ViewProvider::ViewProvider() pcRoot->ref(); pcModeSwitch = new SoSwitch(); pcModeSwitch->ref(); + pcModeSwitch->setName("ModeSwitch"); pcTransform = new SoFCTransform(); pcTransform->ref(); pcRoot->addChild(pcTransform); diff --git a/src/Gui/ViewProviderGeometryObject.cpp b/src/Gui/ViewProviderGeometryObject.cpp index a27478ed23..826cff4139 100644 --- a/src/Gui/ViewProviderGeometryObject.cpp +++ b/src/Gui/ViewProviderGeometryObject.cpp @@ -101,12 +101,15 @@ ViewProviderGeometryObject::ViewProviderGeometryObject() pcShapeMaterial = new SoMaterial; setCoinAppearance(mat); pcShapeMaterial->ref(); + pcShapeMaterial->setName("ShapeMaterial"); pcBoundingBox = new Gui::SoFCBoundingBox; pcBoundingBox->ref(); + pcBoundingBox->setName("BoundingBox"); pcBoundColor = new SoBaseColor(); pcBoundColor->ref(); + pcBoundColor->setName("BoundColor"); sPixmap = "Feature"; } @@ -302,6 +305,7 @@ void ViewProviderGeometryObject::showBoundingBox(bool show) blue = ((bbcol >> 8) & 0xff) / 255.0F; pcBoundSwitch = new SoSwitch(); + pcBoundSwitch->setName("BoundSwitch"); auto pBoundingSep = new SoSeparator(); auto lineStyle = new SoDrawStyle; lineStyle->lineWidth = 2.0F; diff --git a/src/Gui/ViewProviderTextureExtension.cpp b/src/Gui/ViewProviderTextureExtension.cpp index b720fa2a08..2c86e82150 100644 --- a/src/Gui/ViewProviderTextureExtension.cpp +++ b/src/Gui/ViewProviderTextureExtension.cpp @@ -48,14 +48,18 @@ ViewProviderTextureExtension::ViewProviderTextureExtension() pcSwitchAppearance = new SoSwitch; pcSwitchAppearance->ref(); + pcSwitchAppearance->setName("SwitchAppearance"); pcSwitchTexture = new SoSwitch; pcSwitchTexture->ref(); + pcSwitchTexture->setName("SwitchTexture"); pcShapeTexture2D = new SoTexture2; pcShapeTexture2D->ref(); + pcShapeTexture2D->setName("ShapeTexture2D"); pcTextureGroup3D = new SoGroup; pcTextureGroup3D->ref(); + pcTextureGroup3D->setName("TextureGroup3D"); } void ViewProviderTextureExtension::setup(SoMaterial* pcShapeMaterial) @@ -160,10 +164,13 @@ ViewProviderFaceTexture::ViewProviderFaceTexture() // Support for textured faces pcShapeTexture3D = new SoTexture3; pcShapeTexture3D->ref(); + pcShapeTexture3D->setName("ShapeTexture3D"); pcShapeCoordinates = new SoCoordinate3; pcShapeCoordinates->ref(); + pcShapeCoordinates->setName("ShapeCoordinates"); pcShapeFaceset = new SoIndexedFaceSet; pcShapeFaceset->ref(); + pcShapeFaceset->setName("ShapeFaceset"); } ViewProviderFaceTexture::~ViewProviderFaceTexture() diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index 359ff9733a..96a0250f32 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -214,28 +214,35 @@ ViewProviderPartExt::ViewProviderPartExt() pcFaceBind = new SoMaterialBinding(); pcFaceBind->ref(); + pcFaceBind->setName("FaceBind"); pcLineBind = new SoMaterialBinding(); pcLineBind->ref(); + pcLineBind->setName("LineBind"); pcLineMaterial = new SoMaterial; pcLineMaterial->ref(); + pcLineMaterial->setName("LineMaterial"); LineMaterial.touch(); pcPointBind = new SoMaterialBinding(); pcPointBind->ref(); + pcPointBind->setName("PointBind"); pcPointMaterial = new SoMaterial; pcPointMaterial->ref(); + pcPointMaterial->setName("PointMaterial"); PointMaterial.touch(); pcLineStyle = new SoDrawStyle(); pcLineStyle->ref(); pcLineStyle->style = SoDrawStyle::LINES; pcLineStyle->lineWidth = LineWidth.getValue(); + pcLineStyle->setName("LineStyle"); pcPointStyle = new SoDrawStyle(); pcPointStyle->ref(); pcPointStyle->style = SoDrawStyle::POINTS; pcPointStyle->pointSize = PointSize.getValue(); + pcPointStyle->setName("PointStyle"); pShapeHints = new SoShapeHints; pShapeHints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE; @@ -410,9 +417,13 @@ void ViewProviderPartExt::attach(App::DocumentObject *pcFeat) // Workaround for #0000433, i.e. use SoSeparator instead of SoGroup auto* pcNormalRoot = new SoSeparator(); + pcNormalRoot->setName("NormalRoot"); auto* pcFlatRoot = new SoSeparator(); + pcFlatRoot->setName("FlatRoot"); auto* pcWireframeRoot = new SoSeparator(); + pcWireframeRoot->setName("WireframeRoot"); auto* pcPointsRoot = new SoSeparator(); + pcPointsRoot->setName("PointsRoot"); auto* wireframe = new SoSeparator(); // Must turn off all intermediate render caching, and let pcRoot to handle @@ -452,6 +463,7 @@ void ViewProviderPartExt::attach(App::DocumentObject *pcFeat) pcFlatRoot->addChild(texture.getAppearance()); texture.setup(pcShapeMaterial); SoDrawStyle* pcFaceStyle = new SoDrawStyle(); + pcFaceStyle->setName("FaceStyle"); pcFaceStyle->style = SoDrawStyle::FILLED; pcFlatRoot->addChild(pcFaceStyle); pcFlatRoot->addChild(norm);