PartDesign: Add transparent previews
This commit is contained in:
197
src/Mod/Part/Gui/ViewProviderPreviewExtension.cpp
Normal file
197
src/Mod/Part/Gui/ViewProviderPreviewExtension.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/****************************************************************************
|
||||
* *
|
||||
* Copyright (c) 2025 Kacper Donat <kacper@kadet.net> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <Inventor/nodes/SoDrawStyle.h>
|
||||
# include <Inventor/nodes/SoLightModel.h>
|
||||
# include <Inventor/nodes/SoMaterial.h>
|
||||
# include <Inventor/nodes/SoPickStyle.h>
|
||||
# include <Inventor/nodes/SoPolygonOffset.h>
|
||||
#endif
|
||||
|
||||
#include "ViewProviderPreviewExtension.h"
|
||||
#include "ViewProviderExt.h"
|
||||
|
||||
#include <Gui/Utilities.h>
|
||||
#include <Gui/Inventor/So3DAnnotation.h>
|
||||
#include <Mod/Part/App/Tools.h>
|
||||
|
||||
using namespace PartGui;
|
||||
|
||||
SO_NODE_SOURCE(SoPreviewShape);
|
||||
|
||||
const SbColor SoPreviewShape::defaultColor = SbColor(1.F, 0.F, 1.F);
|
||||
|
||||
SoPreviewShape::SoPreviewShape()
|
||||
: coords(new SoCoordinate3)
|
||||
, norm(new SoNormal)
|
||||
, faceset(new PartGui::SoBrepFaceSet)
|
||||
, lineset(new PartGui::SoBrepEdgeSet)
|
||||
, nodeset(new PartGui::SoBrepPointSet)
|
||||
{
|
||||
SO_NODE_CONSTRUCTOR(SoPreviewShape);
|
||||
|
||||
SO_NODE_ADD_FIELD(color, (defaultColor));
|
||||
SO_NODE_ADD_FIELD(transparency, (defaultTransparency));
|
||||
SO_NODE_ADD_FIELD(lineWidth, (defaultLineWidth));
|
||||
|
||||
auto pickStyle = new SoPickStyle;
|
||||
pickStyle->style = SoPickStyle::UNPICKABLE;
|
||||
|
||||
auto* solidLineStyle = new SoDrawStyle();
|
||||
solidLineStyle->lineWidth.connectFrom(&lineWidth);
|
||||
|
||||
auto* hiddenLineStyle = new SoDrawStyle();
|
||||
hiddenLineStyle->lineWidth.connectFrom(&lineWidth);
|
||||
hiddenLineStyle->linePattern = 0xF0F0;
|
||||
|
||||
auto* solidColorLightModel = new SoLightModel();
|
||||
solidColorLightModel->model = SoLightModel::BASE_COLOR;
|
||||
|
||||
auto* normalBinding = new SoNormalBinding();
|
||||
normalBinding->value = SoNormalBinding::PER_VERTEX_INDEXED;
|
||||
|
||||
// This should be OVERALL but then line pattern does not work correctly
|
||||
// Probably a bug in coin to be investigated.
|
||||
auto* materialBinding = new SoMaterialBinding();
|
||||
materialBinding->value = SoMaterialBinding::PER_FACE_INDEXED;
|
||||
|
||||
auto* material = new SoMaterial;
|
||||
material->diffuseColor.connectFrom(&color);
|
||||
material->transparency.connectFrom(&transparency);
|
||||
|
||||
auto* polygonOffset = new SoPolygonOffset;
|
||||
polygonOffset->factor = -0.00001F;
|
||||
polygonOffset->units = -1.0F;
|
||||
polygonOffset->on = true;
|
||||
polygonOffset->styles = SoPolygonOffset::FILLED;
|
||||
|
||||
auto* lineMaterial = new SoMaterial;
|
||||
lineMaterial->diffuseColor.connectFrom(&color);
|
||||
lineMaterial->transparency = 0.0f;
|
||||
|
||||
auto* lineSep = new SoSeparator;
|
||||
lineSep->addChild(normalBinding);
|
||||
lineSep->addChild(materialBinding);
|
||||
lineSep->addChild(solidColorLightModel);
|
||||
lineSep->addChild(lineMaterial);
|
||||
lineSep->addChild(lineset);
|
||||
|
||||
auto* annotation = new Gui::So3DAnnotation;
|
||||
annotation->addChild(hiddenLineStyle);
|
||||
annotation->addChild(material);
|
||||
annotation->addChild(lineSep);
|
||||
annotation->addChild(polygonOffset);
|
||||
annotation->addChild(faceset);
|
||||
|
||||
SoSeparator::addChild(pickStyle);
|
||||
SoSeparator::addChild(solidLineStyle);
|
||||
SoSeparator::addChild(material);
|
||||
SoSeparator::addChild(coords);
|
||||
SoSeparator::addChild(norm);
|
||||
SoSeparator::addChild(lineSep);
|
||||
SoSeparator::addChild(polygonOffset);
|
||||
SoSeparator::addChild(faceset);
|
||||
SoSeparator::addChild(annotation);
|
||||
}
|
||||
|
||||
EXTENSION_PROPERTY_SOURCE(PartGui::ViewProviderPreviewExtension, Gui::ViewProviderExtension)
|
||||
|
||||
ViewProviderPreviewExtension::ViewProviderPreviewExtension()
|
||||
{
|
||||
const Base::Color magenta(1.0F, 0.0F, 1.0F);
|
||||
|
||||
EXTENSION_ADD_PROPERTY_TYPE(
|
||||
PreviewColor,
|
||||
(magenta),
|
||||
"Preview",
|
||||
static_cast<App::PropertyType>(App::Prop_Transient | App::Prop_Hidden),
|
||||
"Color used for 3D Preview");
|
||||
|
||||
initExtensionType(ViewProviderPreviewExtension::getExtensionClassTypeId());
|
||||
}
|
||||
|
||||
void ViewProviderPreviewExtension::extensionAttach(App::DocumentObject* documentObject)
|
||||
{
|
||||
ViewProviderExtension::extensionAttach(documentObject);
|
||||
|
||||
pcPreviewShape = new SoPreviewShape;
|
||||
|
||||
pcPreviewRoot = new SoSeparator;
|
||||
pcPreviewRoot->addChild(pcPreviewShape);
|
||||
|
||||
updatePreviewShape();
|
||||
}
|
||||
void ViewProviderPreviewExtension::extensionOnChanged(const App::Property* prop)
|
||||
{
|
||||
if (prop == &PreviewColor) {
|
||||
pcPreviewShape->color.setValue(Base::convertTo<SbColor>(PreviewColor.getValue()));
|
||||
}
|
||||
|
||||
ViewProviderExtension::extensionOnChanged(prop);
|
||||
}
|
||||
|
||||
void ViewProviderPreviewExtension::updatePreviewShape()
|
||||
{
|
||||
auto vp = freecad_cast<ViewProviderPartExt*>(getExtendedViewProvider());
|
||||
|
||||
if (!vp) {
|
||||
return;
|
||||
}
|
||||
|
||||
ViewProviderPartExt::setupCoinGeometry(getPreviewShape().getShape(),
|
||||
pcPreviewShape->coords,
|
||||
pcPreviewShape->faceset,
|
||||
pcPreviewShape->norm,
|
||||
pcPreviewShape->lineset,
|
||||
pcPreviewShape->nodeset,
|
||||
vp->Deviation.getValue(),
|
||||
vp->AngularDeflection.getValue(),
|
||||
false);
|
||||
|
||||
// For some reason line patterns are not rendered correctly if material binding is set to
|
||||
// anything other than PER_FACE. PER_FACE material binding seems to require materialIndex per
|
||||
// each distinct edge. Until that is fixed, this code forces each edge to use the first material.
|
||||
unsigned lineCoordsCount = pcPreviewShape->lineset->coordIndex.getNum();
|
||||
unsigned lineCount = 1;
|
||||
|
||||
for (unsigned i = 0; i < lineCoordsCount; ++i) {
|
||||
if (pcPreviewShape->lineset->coordIndex[i] < 0) {
|
||||
lineCount++;
|
||||
}
|
||||
}
|
||||
|
||||
pcPreviewShape->lineset->materialIndex.setNum(lineCount);
|
||||
for (unsigned i = 0; i < lineCount; ++i) {
|
||||
pcPreviewShape->lineset->materialIndex.set1Value(i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Gui {
|
||||
EXTENSION_PROPERTY_SOURCE_TEMPLATE(PartGui::ViewProviderPreviewExtensionPython, PartGui::ViewProviderPreviewExtension)
|
||||
|
||||
// explicit template instantiation
|
||||
template class PartGuiExport ViewProviderExtensionPythonT<PartGui::ViewProviderPreviewExtension>;
|
||||
}
|
||||
Reference in New Issue
Block a user