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
This commit is contained in:
PaddleStroke
2025-09-23 00:47:12 +02:00
committed by GitHub
parent 4179075b72
commit ec4b18cd30
2 changed files with 62 additions and 18 deletions

View File

@@ -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<std::string, Base::Color> 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;i<linkView->getSize();++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);
}
}

View File

@@ -686,17 +686,19 @@ std::map<std::string,Base::Color> ViewProviderPartExt::getElementColors(const ch
auto color = ShapeAppearance.getDiffuseColor();
color.setTransparency(Base::fromPercent(Transparency.getValue()));
bool singleColor = true;
for(int i=0;i<size;++i) {
if (ShapeAppearance.getDiffuseColor(i) != color) {
ret[std::string(element, 4) + std::to_string(i + 1)] =
ShapeAppearance.getDiffuseColor(i);
for (int i = 0; i < size; ++i) {
Base::Color faceColor = ShapeAppearance.getDiffuseColor(i);
faceColor.setTransparency(ShapeAppearance.getTransparency(i));
if (faceColor != color) {
ret[std::string(element, 4) + std::to_string(i + 1)] = faceColor;
}
singleColor = singleColor
&& ShapeAppearance.getDiffuseColor(0) == ShapeAppearance.getDiffuseColor(i);
Base::Color firstFaceColor = ShapeAppearance.getDiffuseColor(0);
firstFaceColor.setTransparency(ShapeAppearance.getTransparency(0));
singleColor = singleColor && (faceColor == firstFaceColor);
}
if(size && singleColor) {
if (size > 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);
}
}