Merge pull request #22029 from tetektoza/realthunder_multiselect_without_pie
Gui: Add a context menu to select obstructed items (from RT's fork Pick Geometry)
This commit is contained in:
@@ -77,7 +77,7 @@ class ExportImportTest(unittest.TestCase):
|
||||
sa.apply(feature.ViewObject.RootNode)
|
||||
paths = sa.getPaths()
|
||||
|
||||
bind = paths.get(2).getTail()
|
||||
bind = paths.get(1).getTail()
|
||||
self.assertEqual(bind.value.getValue(), bind.PER_PART)
|
||||
|
||||
sa = coin.SoSearchAction()
|
||||
@@ -87,5 +87,5 @@ class ExportImportTest(unittest.TestCase):
|
||||
sa.apply(feature.ViewObject.RootNode)
|
||||
paths = sa.getPaths()
|
||||
|
||||
mat = paths.get(2).getTail()
|
||||
mat = paths.get(1).getTail()
|
||||
self.assertEqual(mat.diffuseColor.getNum(), 6)
|
||||
|
||||
@@ -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,26 @@ void SoBrepEdgeSet::GLRender(SoGLRenderAction *action)
|
||||
SelContextPtr ctx = Gui::SoFCSelectionRoot::getRenderContext<SelContext>(this,selContext,ctx2);
|
||||
if(ctx2 && ctx2->selectionIndex.empty())
|
||||
return;
|
||||
|
||||
|
||||
bool hasContextHighlight = ctx && !ctx->hl.empty();
|
||||
bool hasFaceHighlight = viewProvider && viewProvider->isFaceHighlightActive();
|
||||
bool hasAnyHighlight = hasContextHighlight || hasFaceHighlight;
|
||||
|
||||
if (Gui::Selection().isClarifySelectionActive()
|
||||
&& !Gui::SoDelayedAnnotationsElement::isProcessingDelayedPaths
|
||||
&& hasAnyHighlight) {
|
||||
// if we are using clarifyselection - add this to delayed paths with priority
|
||||
// as we want to get this rendered on top of everything
|
||||
if (viewProvider) {
|
||||
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 +160,22 @@ void SoBrepEdgeSet::GLRender(SoGLRenderAction *action)
|
||||
}
|
||||
if(ctx2 && !ctx2->selectionIndex.empty())
|
||||
renderSelection(action,ctx2,false);
|
||||
else
|
||||
else if (Gui::Selection().isClarifySelectionActive()
|
||||
&& !Gui::SoDelayedAnnotationsElement::isProcessingDelayedPaths && hasAnyHighlight) {
|
||||
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())
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,41 @@ void SoBrepFaceSet::GLRender(SoGLRenderAction *action)
|
||||
|
||||
auto state = action->getState();
|
||||
selCounter.checkRenderCache(state);
|
||||
|
||||
bool hasContextHighlight = ctx && ctx->isHighlighted() && !ctx->isHighlightAll()
|
||||
&& ctx->highlightIndex >= 0 && ctx->highlightIndex < partIndex.getNum();
|
||||
|
||||
// for the tool add this node to delayed paths as we want to render it on top of the scene
|
||||
if (Gui::Selection().isClarifySelectionActive() && hasContextHighlight) {
|
||||
|
||||
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 +775,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 +817,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 +894,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -44,7 +44,9 @@
|
||||
#endif
|
||||
|
||||
#include <Gui/Selection/SoFCUnifiedSelection.h>
|
||||
#include <Gui/Inventor/So3DAnnotation.h>
|
||||
|
||||
#include "ViewProviderExt.h"
|
||||
#include "SoBrepPointSet.h"
|
||||
|
||||
|
||||
@@ -81,6 +83,22 @@ void SoBrepPointSet::GLRender(SoGLRenderAction *action)
|
||||
return;
|
||||
if(selContext2->checkGlobal(ctx))
|
||||
ctx = selContext2;
|
||||
|
||||
|
||||
bool hasContextHighlight =
|
||||
ctx && ctx->isHighlighted() && !ctx->isHighlightAll() && ctx->highlightIndex >= 0;
|
||||
// for clarifyselection, add this node to delayed path if it is highlighted and render it on
|
||||
// top of everything else (highest priority)
|
||||
if (Gui::Selection().isClarifySelectionActive() && hasContextHighlight
|
||||
&& !Gui::SoDelayedAnnotationsElement::isProcessingDelayedPaths) {
|
||||
if (viewProvider) {
|
||||
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 +139,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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -49,7 +49,7 @@ class ColorPerFaceTest(unittest.TestCase):
|
||||
sa.apply(box.ViewObject.RootNode)
|
||||
paths = sa.getPaths()
|
||||
|
||||
mat = paths.get(2).getTail()
|
||||
mat = paths.get(1).getTail()
|
||||
self.assertEqual(mat.diffuseColor.getNum(), 6)
|
||||
|
||||
def testBoxAndLink(self):
|
||||
@@ -83,7 +83,7 @@ class ColorPerFaceTest(unittest.TestCase):
|
||||
sa.apply(box.ViewObject.RootNode)
|
||||
paths = sa.getPaths()
|
||||
|
||||
mat = paths.get(2).getTail()
|
||||
mat = paths.get(1).getTail()
|
||||
self.assertEqual(mat.diffuseColor.getNum(), 6)
|
||||
|
||||
def testTransparency(self):
|
||||
@@ -110,7 +110,7 @@ class ColorPerFaceTest(unittest.TestCase):
|
||||
sa.apply(box.ViewObject.RootNode)
|
||||
paths = sa.getPaths()
|
||||
|
||||
bind = paths.get(2).getTail()
|
||||
bind = paths.get(1).getTail()
|
||||
self.assertEqual(bind.value.getValue(), bind.PER_PART)
|
||||
|
||||
sa = coin.SoSearchAction()
|
||||
@@ -120,7 +120,7 @@ class ColorPerFaceTest(unittest.TestCase):
|
||||
sa.apply(box.ViewObject.RootNode)
|
||||
paths = sa.getPaths()
|
||||
|
||||
mat = paths.get(2).getTail()
|
||||
mat = paths.get(1).getTail()
|
||||
self.assertEqual(mat.diffuseColor.getNum(), 6)
|
||||
|
||||
def testMultiFuse(self):
|
||||
@@ -146,7 +146,7 @@ class ColorPerFaceTest(unittest.TestCase):
|
||||
sa.apply(fuse.ViewObject.RootNode)
|
||||
paths = sa.getPaths()
|
||||
|
||||
bind = paths.get(2).getTail()
|
||||
bind = paths.get(1).getTail()
|
||||
self.assertEqual(bind.value.getValue(), bind.PER_PART)
|
||||
|
||||
sa = coin.SoSearchAction()
|
||||
@@ -156,7 +156,7 @@ class ColorPerFaceTest(unittest.TestCase):
|
||||
sa.apply(fuse.ViewObject.RootNode)
|
||||
paths = sa.getPaths()
|
||||
|
||||
mat = paths.get(2).getTail()
|
||||
mat = paths.get(1).getTail()
|
||||
self.assertEqual(mat.diffuseColor.getNum(), 11)
|
||||
|
||||
self.assertEqual(len(fuse.Shape.Faces), 11)
|
||||
@@ -195,7 +195,7 @@ class ColorPerFaceTest(unittest.TestCase):
|
||||
sa.apply(fuse.ViewObject.RootNode)
|
||||
paths = sa.getPaths()
|
||||
|
||||
bind = paths.get(2).getTail()
|
||||
bind = paths.get(1).getTail()
|
||||
self.assertEqual(bind.value.getValue(), bind.PER_PART)
|
||||
|
||||
sa = coin.SoSearchAction()
|
||||
@@ -205,5 +205,5 @@ class ColorPerFaceTest(unittest.TestCase):
|
||||
sa.apply(fuse.ViewObject.RootNode)
|
||||
paths = sa.getPaths()
|
||||
|
||||
mat = paths.get(2).getTail()
|
||||
mat = paths.get(1).getTail()
|
||||
self.assertEqual(mat.diffuseColor.getNum(), 11)
|
||||
|
||||
Reference in New Issue
Block a user