From ec4b18cd30935a01669b7179d3d16ff22406a59e Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Tue, 23 Sep 2025 00:47:12 +0200 Subject: [PATCH] Link: make OverrideMaterial use the per-face override. (#23544) * Link: make OverrideMaterial use the per-face override. * Fix small issue on per face transparency * update names * Update ViewProviderExt.cpp --- src/Gui/ViewProviderLink.cpp | 59 +++++++++++++++++++++++----- src/Mod/Part/Gui/ViewProviderExt.cpp | 21 ++++++---- 2 files changed, 62 insertions(+), 18 deletions(-) diff --git a/src/Gui/ViewProviderLink.cpp b/src/Gui/ViewProviderLink.cpp index 2adc25e259..e6d7384b1a 100644 --- a/src/Gui/ViewProviderLink.cpp +++ b/src/Gui/ViewProviderLink.cpp @@ -2079,18 +2079,57 @@ void ViewProviderLink::checkIcon(const App::LinkBaseExtension *ext) { } } -void ViewProviderLink::applyMaterial() { - if(OverrideMaterial.getValue()) - linkView->setMaterial(-1,&ShapeMaterial.getValue()); +void ViewProviderLink::applyMaterial() +{ + if (OverrideMaterial.getValue()) { + // Dispatch a generic Coin3D action to the linked object's scene graph. + // If the linked object is a Part shape, its SoBrepFaceSet node will + // handle this action and apply the color to all its faces. + // This is decoupled and respects the core/module architecture. + + // 1. Get the material from our property. + const auto& material = ShapeMaterial.getValue(); + + // 2. Prepare the color for the rendering action. The action's ultimate + // consumer (SoBrepFaceSet) expects a Base::Color where .a is transparency, + // so we must perform the conversion here at the boundary. + Base::Color renderColor = material.diffuseColor; + renderColor.a = 1.0f - material.transparency; + + // 3. Create a map with the "Face" wildcard to signify "all faces". + std::map colorMap; + colorMap["Face"] = renderColor; + + // 4. Create and dispatch the action. We use a secondary context action, + // which is the established mechanism for this kind of override. + SoSelectionElementAction action(SoSelectionElementAction::Color, + true); // true for secondary + action.swapColors(colorMap); + linkView->getLinkRoot()->doAction(&action); + + // 5. Ensure the old global override mechanism is not used. + linkView->setMaterial(-1, nullptr); + } else { - for(int i=0;igetSize();++i) { - if(MaterialList.getSize()>i && - OverrideMaterialList.getSize()>i && OverrideMaterialList[i]) - linkView->setMaterial(i,&MaterialList[i]); - else - linkView->setMaterial(i,nullptr); + // OVERRIDE IS DISABLED: + // We must clear the per-face override we just applied. + + // 1. Dispatch an empty Color action to clear the secondary context. + SoSelectionElementAction action(SoSelectionElementAction::Color, true); + linkView->getLinkRoot()->doAction(&action); + + // 2. Re-apply any other material settings (e.g., for array elements, + // or clear the old global override if it was set). + linkView->setMaterial(-1, nullptr); + for (int i = 0; i < linkView->getSize(); ++i) { + if (MaterialList.getSize() > i && OverrideMaterialList.getSize() > i + && OverrideMaterialList[i]) { + linkView->setMaterial(i, &MaterialList[i]); + } + else { + linkView->setMaterial(i, nullptr); + } } - linkView->setMaterial(-1,nullptr); } } diff --git a/src/Mod/Part/Gui/ViewProviderExt.cpp b/src/Mod/Part/Gui/ViewProviderExt.cpp index c2c326b808..23a79fb659 100644 --- a/src/Mod/Part/Gui/ViewProviderExt.cpp +++ b/src/Mod/Part/Gui/ViewProviderExt.cpp @@ -686,17 +686,19 @@ std::map ViewProviderPartExt::getElementColors(const ch auto color = ShapeAppearance.getDiffuseColor(); color.setTransparency(Base::fromPercent(Transparency.getValue())); bool singleColor = true; - for(int i=0;i 0 && singleColor) { color = ShapeAppearance.getDiffuseColor(0); - color.setTransparency(Base::fromPercent(0.0F)); + color.setTransparency(ShapeAppearance.getTransparency(0)); ret.clear(); } ret["Face"] = color; @@ -1403,3 +1405,6 @@ void ViewProviderPartExt::handleChangedPropertyName(Base::XMLReader& reader, Gui::ViewProviderGeometryObject::handleChangedPropertyName(reader, TypeName, PropName); } } + + +