Core/Gui: Render primitives on top of the scene in PickGeometry

+ added some better grouping for items, which are assigned per object
  right now. For example, if we exceed 10 items per object it gets an
  additional group.

Co-authored-by: realthunder <realthunder@users.noreply.github.com>
This commit is contained in:
tetektoza
2025-06-25 11:28:25 +02:00
parent 59b234028f
commit c856c9ea01
17 changed files with 614 additions and 91 deletions

View File

@@ -44,10 +44,18 @@
# include <Inventor/elements/SoLineWidthElement.h>
# include <Inventor/errors/SoDebugError.h>
# include <Inventor/misc/SoState.h>
# include <Inventor/nodes/SoGroup.h>
# include <Inventor/actions/SoSearchAction.h>
#endif
#include <Gui/Selection/SoFCUnifiedSelection.h>
#include <Gui/Selection/Selection.h>
#include <Base/Console.h>
#include "SoBrepEdgeSet.h"
#include "SoBrepFaceSet.h"
#include "ViewProviderExt.h"
#include <Gui/Inventor/So3DAnnotation.h>
using namespace PartGui;
@@ -79,6 +87,20 @@ void SoBrepEdgeSet::GLRender(SoGLRenderAction *action)
SelContextPtr ctx = Gui::SoFCSelectionRoot::getRenderContext<SelContext>(this,selContext,ctx2);
if(ctx2 && ctx2->selectionIndex.empty())
return;
if (Gui::Selection()
.isPickGeometryActive() && !Gui::SoDelayedAnnotationsElement::isProcessingDelayedPaths
&& ((ctx && !ctx->hl.empty()) || viewProvider->isFaceHighlightActive())) {
// if we are using pickgeometry - add this to delayed paths with priority
// as we want to get this rendered on top of everything
viewProvider->setFaceHighlightActive(true);
Gui::SoDelayedAnnotationsElement::addDelayedPath(action->getState(),
action->getCurPath()->copy(),
200);
return;
}
if(selContext2->checkGlobal(ctx)) {
if(selContext2->isSelectAll()) {
selContext2->sl.clear();
@@ -132,9 +154,23 @@ void SoBrepEdgeSet::GLRender(SoGLRenderAction *action)
}
if(ctx2 && !ctx2->selectionIndex.empty())
renderSelection(action,ctx2,false);
else
else if (Gui::Selection().isPickGeometryActive()
&& ((ctx && !ctx->hl.empty()) || viewProvider->isFaceHighlightActive())
&& Gui::SoDelayedAnnotationsElement::isProcessingDelayedPaths) {
state->push();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(false);
glDisable(GL_DEPTH_TEST);
inherited::GLRender(action);
state->pop();
}
else {
inherited::GLRender(action);
}
// Workaround for #0000433
//#if !defined(FC_OS_WIN32)
if(!action->isRenderingDelayedPaths())

View File

@@ -36,6 +36,8 @@ class SoTextureCoordinateBundle;
namespace PartGui {
class ViewProviderPartExt;
class PartGuiExport SoBrepEdgeSet : public SoIndexedLineSet {
using inherited = SoIndexedLineSet;
@@ -44,6 +46,8 @@ class PartGuiExport SoBrepEdgeSet : public SoIndexedLineSet {
public:
static void initClass();
SoBrepEdgeSet();
void setViewProvider(ViewProviderPartExt* vp) { viewProvider = vp; }
protected:
~SoBrepEdgeSet() override = default;
@@ -68,11 +72,15 @@ private:
void renderSelection(SoGLRenderAction *action, SelContextPtr, bool push=true);
bool validIndexes(const SoCoordinateElement*, const std::vector<int32_t>&) const;
private:
SelContextPtr selContext;
SelContextPtr selContext2;
Gui::SoFCSelectionCounter selCounter;
uint32_t packedColor{0};
// backreference to viewprovider that owns this node
ViewProviderPartExt* viewProvider = nullptr;
};
} // namespace PartGui

View File

@@ -73,8 +73,12 @@
#include <Gui/SoFCInteractiveElement.h>
#include <Gui/Selection/SoFCSelectionAction.h>
#include <Gui/Selection/SoFCUnifiedSelection.h>
#include <Gui/Inventor/So3DAnnotation.h>
#include "SoBrepFaceSet.h"
#include "ViewProviderExt.h"
#include "SoBrepEdgeSet.h"
using namespace PartGui;
@@ -188,6 +192,9 @@ void SoBrepFaceSet::doAction(SoAction* action)
ctx->highlightIndex = -1;
touch();
}
if (viewProvider) {
viewProvider->setFaceHighlightActive(false);
}
return;
}
@@ -204,6 +211,9 @@ void SoBrepFaceSet::doAction(SoAction* action)
ctx->highlightIndex = -1;
touch();
}
if (viewProvider) {
viewProvider->setFaceHighlightActive(false);
}
}else {
int index = static_cast<const SoFaceDetail*>(detail)->getPartIndex();
SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext);
@@ -521,6 +531,40 @@ void SoBrepFaceSet::GLRender(SoGLRenderAction *action)
auto state = action->getState();
selCounter.checkRenderCache(state);
// for the tool add this node to delayed paths as we want to render it on top of the scene
if (Gui::Selection().isPickGeometryActive() && ctx && ctx->isHighlighted()
&& !ctx->isHighlightAll() && ctx->highlightIndex >= 0
&& ctx->highlightIndex < partIndex.getNum()) {
if (!Gui::SoDelayedAnnotationsElement::isProcessingDelayedPaths) {
if (viewProvider) {
viewProvider->setFaceHighlightActive(true);
}
const SoPath* currentPath = action->getCurPath();
Gui::SoDelayedAnnotationsElement::addDelayedPath(action->getState(),
currentPath->copy(),
100);
return;
} else {
// during priority delayed paths processing:
// render base faces normally first, then render highlight on top
inherited::GLRender(action);
state->push();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(false);
glDisable(GL_DEPTH_TEST);
renderHighlight(action, ctx);
state->pop();
return;
}
}
// override material binding to PER_PART_INDEX to achieve
// preselection/selection with transparency
@@ -730,7 +774,7 @@ bool SoBrepFaceSet::overrideMaterialBinding(SoGLRenderAction *action, SelContext
singleColor = ctx?-1:1;
}
bool partialRender = ctx2 && !ctx2->isSelectAll();
bool partialRender = (ctx2 && !ctx2->isSelectAll());
if(singleColor>0 && !partialRender) {
//optimization for single color non-partial rendering
@@ -772,7 +816,8 @@ bool SoBrepFaceSet::overrideMaterialBinding(SoGLRenderAction *action, SelContext
packedColors.push_back(ctx->highlightColor.getPackedValue(trans0));
matIndex[ctx->highlightIndex] = packedColors.size()-1;
}
}else{
}
else{
if(partialRender) {
packedColors.push_back(SbColor(1.0,1.0,1.0).getPackedValue(1.0));
matIndex.resize(partIndex.getNum(),0);
@@ -848,7 +893,7 @@ bool SoBrepFaceSet::overrideMaterialBinding(SoGLRenderAction *action, SelContext
SoLazyElement::setPacked(state, this, packedColors.size(), packedColors.data(), hasTransparency);
SoTextureEnabledElement::set(state,this,false);
if(hasTransparency && action->isRenderingDelayedPaths()) {
if (hasTransparency && action->isRenderingDelayedPaths()) {
// rendering delayed paths means we are doing annotation (e.g.
// always on top rendering). To render transparency correctly in
// this case, we shall use openGL transparency blend. Override

View File

@@ -38,6 +38,8 @@ class SoTextureCoordinateBundle;
namespace PartGui {
class ViewProviderPartExt;
/**
* First some words to the history and the reason why we have this class:
* In older FreeCAD versions we had an own Inventor node for each sub-element of a shape with its own highlight node.
@@ -79,6 +81,8 @@ class PartGuiExport SoBrepFaceSet : public SoIndexedFaceSet {
public:
static void initClass();
SoBrepFaceSet();
void setViewProvider(ViewProviderPartExt* vp) { viewProvider = vp; }
SoMFInt32 partIndex;
@@ -154,6 +158,9 @@ private:
// Define some VBO pointer for the current mesh
class VBO;
std::unique_ptr<VBO> pimpl;
// backreference to viewprovider that owns this node
ViewProviderPartExt* viewProvider = nullptr;
};
} // namespace PartGui

View File

@@ -44,7 +44,9 @@
#endif
#include <Gui/Selection/SoFCUnifiedSelection.h>
#include <Gui/Inventor/So3DAnnotation.h>
#include "ViewProviderExt.h"
#include "SoBrepPointSet.h"
@@ -81,6 +83,18 @@ void SoBrepPointSet::GLRender(SoGLRenderAction *action)
return;
if(selContext2->checkGlobal(ctx))
ctx = selContext2;
// for pickgeometry, add this node to delayed path if it is highlighted and render it on
// top of everything else (highest priority)
if (Gui::Selection().isPickGeometryActive() && ctx && ctx->isHighlighted()
&& !ctx->isHighlightAll() && ctx->highlightIndex >= 0
&& !Gui::SoDelayedAnnotationsElement::isProcessingDelayedPaths) {
viewProvider->setFaceHighlightActive(true);
Gui::SoDelayedAnnotationsElement::addDelayedPath(action->getState(),
action->getCurPath()->copy(),
300);
return;
}
if(ctx && ctx->highlightIndex == std::numeric_limits<int>::max()) {
if(ctx->selectionIndex.empty() || ctx->isSelectAll()) {
@@ -121,8 +135,15 @@ void SoBrepPointSet::GLRender(SoGLRenderAction *action)
}
if(ctx2 && !ctx2->selectionIndex.empty())
renderSelection(action,ctx2,false);
else
else if (Gui::SoDelayedAnnotationsElement::isProcessingDelayedPaths) {
glPushAttrib(GL_DEPTH_BUFFER_BIT);
glDepthFunc(GL_ALWAYS);
inherited::GLRender(action);
glPopAttrib();
}
else {
inherited::GLRender(action);
}
// Workaround for #0000433
//#if !defined(FC_OS_WIN32)

View File

@@ -36,6 +36,8 @@ class SoTextureCoordinateBundle;
namespace PartGui {
class ViewProviderPartExt;
class PartGuiExport SoBrepPointSet : public SoPointSet {
using inherited = SoPointSet;
@@ -44,6 +46,8 @@ class PartGuiExport SoBrepPointSet : public SoPointSet {
public:
static void initClass();
SoBrepPointSet();
void setViewProvider(ViewProviderPartExt* vp) { viewProvider = vp; }
protected:
~SoBrepPointSet() override = default;
@@ -64,6 +68,9 @@ private:
SelContextPtr selContext2;
Gui::SoFCSelectionCounter selCounter;
uint32_t packedColor{0};
// backreference to viewprovider that owns this node
ViewProviderPartExt* viewProvider = nullptr;
};
} // namespace PartGui

View File

@@ -191,6 +191,7 @@ ViewProviderPartExt::ViewProviderPartExt()
coords = new SoCoordinate3();
coords->ref();
faceset = new SoBrepFaceSet();
faceset->setViewProvider(this);
faceset->ref();
norm = new SoNormal;
norm->ref();
@@ -198,8 +199,10 @@ ViewProviderPartExt::ViewProviderPartExt()
normb->value = SoNormalBinding::PER_VERTEX_INDEXED;
normb->ref();
lineset = new SoBrepEdgeSet();
lineset->setViewProvider(this);
lineset->ref();
nodeset = new SoBrepPointSet();
nodeset->setViewProvider(this);
nodeset->ref();
pcFaceBind = new SoMaterialBinding();
@@ -447,9 +450,9 @@ void ViewProviderPartExt::attach(App::DocumentObject *pcFeat)
// normal viewing with edges and points
pcNormalRoot->addChild(pcPointsRoot);
pcNormalRoot->addChild(wireframe);
pcNormalRoot->addChild(offset);
pcNormalRoot->addChild(pcFlatRoot);
pcNormalRoot->addChild(wireframe);
// just faces with no edges or points
pcFlatRoot->addChild(pShapeHints);

View File

@@ -156,6 +156,9 @@ public:
bool allowOverride(const App::DocumentObject &) const override;
void setFaceHighlightActive(bool active) { faceHighlightActive = active; }
bool isFaceHighlightActive() const { return faceHighlightActive; }
/** @name Edit methods */
//@{
void setupContextMenu(QMenu*, QObject*, const char*) override;
@@ -213,6 +216,7 @@ protected:
bool VisualTouched;
bool NormalsFromUV;
bool faceHighlightActive = false;
private:
Gui::ViewProviderFaceTexture texture;