FreeCAD / src /Gui /Selection /SoFCSelection.cpp
AbdulElahGwaith's picture
Upload folder using huggingface_hub
985c397 verified
// SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************
* Copyright (c) 2005 Jürgen Riegel <juergen.riegel@web.de> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include <QString>
#include <Inventor/SoFullPath.h>
#include <Inventor/SoPickedPoint.h>
#include <Inventor/actions/SoGLRenderAction.h>
#include <Inventor/actions/SoHandleEventAction.h>
#include <Inventor/details/SoFaceDetail.h>
#include <Inventor/details/SoLineDetail.h>
#include <Inventor/elements/SoLazyElement.h>
#include <Inventor/elements/SoMaterialBindingElement.h>
#include <Inventor/elements/SoOverrideElement.h>
#include <Inventor/elements/SoWindowElement.h>
#include <Inventor/events/SoKeyboardEvent.h>
#include <Inventor/events/SoLocation2Event.h>
#include <Inventor/events/SoMouseButtonEvent.h>
#include <Inventor/misc/SoState.h>
#include <Base/UnitsApi.h>
#include "SoFCSelection.h"
#include "MainWindow.h"
#include "SoFCSelectionAction.h"
#include "SoFCUnifiedSelection.h"
#include "ViewParams.h"
using namespace Gui;
namespace Gui
{
void printPreselectionInfo(
const char* documentName,
const char* objectName,
const char* subElementName,
float x,
float y,
float z,
double precision
);
}
SoFullPath* Gui::SoFCSelection::currenthighlight = nullptr;
// *************************************************************************
SO_NODE_SOURCE(SoFCSelection)
/*!
Constructor.
*/
SoFCSelection::SoFCSelection()
{
SO_NODE_CONSTRUCTOR(SoFCSelection);
SO_NODE_ADD_FIELD(colorHighlight, (SbColor(0.8f, 0.1f, 0.1f)));
SO_NODE_ADD_FIELD(colorSelection, (SbColor(0.1f, 0.8f, 0.1f)));
SO_NODE_ADD_FIELD(style, (EMISSIVE));
SO_NODE_ADD_FIELD(preselectionMode, (AUTO));
SO_NODE_ADD_FIELD(selectionMode, (SEL_ON));
SO_NODE_ADD_FIELD(selected, (NOTSELECTED));
SO_NODE_ADD_FIELD(documentName, (""));
SO_NODE_ADD_FIELD(objectName, (""));
SO_NODE_ADD_FIELD(subElementName, (""));
SO_NODE_ADD_FIELD(useNewSelection, (true));
SO_NODE_DEFINE_ENUM_VALUE(Styles, EMISSIVE);
SO_NODE_DEFINE_ENUM_VALUE(Styles, EMISSIVE_DIFFUSE);
SO_NODE_DEFINE_ENUM_VALUE(Styles, BOX);
SO_NODE_SET_SF_ENUM_TYPE(style, Styles);
SO_NODE_DEFINE_ENUM_VALUE(PreselectionModes, AUTO);
SO_NODE_DEFINE_ENUM_VALUE(PreselectionModes, ON);
SO_NODE_DEFINE_ENUM_VALUE(PreselectionModes, OFF);
SO_NODE_SET_SF_ENUM_TYPE(preselectionMode, PreselectionModes);
SO_NODE_DEFINE_ENUM_VALUE(SelectionModes, SEL_ON);
SO_NODE_DEFINE_ENUM_VALUE(SelectionModes, SEL_OFF);
SO_NODE_SET_SF_ENUM_TYPE(selectionMode, SelectionModes);
SO_NODE_DEFINE_ENUM_VALUE(Selected, NOTSELECTED);
SO_NODE_DEFINE_ENUM_VALUE(Selected, SELECTED);
SO_NODE_SET_SF_ENUM_TYPE(selected, Selected);
highlighted = false;
bShift = false;
bCtrl = false;
selected = NOTSELECTED;
useNewSelection = ViewParams::instance()->getUseNewSelection();
selContext = std::make_shared<SelContext>();
selContext2 = std::make_shared<SelContext>();
}
/*!
Destructor.
*/
SoFCSelection::~SoFCSelection()
{
// If we're being deleted and we're the current highlight,
// NULL out that variable
if (currenthighlight
&& (!currenthighlight->getTail()->isOfType(SoFCSelection::getClassTypeId()))) {
currenthighlight->unref();
currenthighlight = nullptr;
}
// delete THIS;
}
// doc from parent
void SoFCSelection::initClass()
{
SO_NODE_INIT_CLASS(SoFCSelection, SoGroup, "Group");
}
void SoFCSelection::finish()
{
atexit_cleanup();
}
/*!
Static method that can be used to turn off the current highlight.
*/
void SoFCSelection::turnOffCurrentHighlight(SoGLRenderAction* action)
{
SoFCSelection::turnoffcurrent(action);
}
void SoFCSelection::doAction(SoAction* action)
{
if (useNewSelection.getValue() && action->getCurPathCode() != SoAction::OFF_PATH) {
if (action->getTypeId() == Gui::SoHighlightElementAction::getClassTypeId()) {
auto hlaction = static_cast<Gui::SoHighlightElementAction*>(action);
if (!hlaction->isHighlighted()) {
auto ctx = Gui::SoFCSelectionRoot::getActionContext(action, this, selContext, false);
if (ctx && ctx->isHighlighted()) {
ctx->highlightIndex = -1;
touch();
}
}
else {
auto ctx = Gui::SoFCSelectionRoot::getActionContext(action, this, selContext);
if (ctx) {
ctx->highlightColor = hlaction->getColor();
if (!ctx->isHighlighted()) {
ctx->highlightIndex = 0;
touch();
}
}
}
return;
}
else if (action->getTypeId() == Gui::SoSelectionElementAction::getClassTypeId()) {
auto selaction = static_cast<Gui::SoSelectionElementAction*>(action);
if (selaction->getType() == Gui::SoSelectionElementAction::All
|| selaction->getType() == Gui::SoSelectionElementAction::Append) {
SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action, this, selContext);
if (ctx) {
ctx->selectionColor = selaction->getColor();
if (!ctx->isSelectAll()) {
ctx->selectAll();
this->touch();
}
}
}
else if (selaction->getType() == Gui::SoSelectionElementAction::None
|| selaction->getType() == Gui::SoSelectionElementAction::Remove) {
SelContextPtr ctx
= Gui::SoFCSelectionRoot::getActionContext(action, this, selContext, false);
if (ctx && ctx->isSelected()) {
ctx->selectionIndex.clear();
this->touch();
}
}
return;
}
}
if (action->getTypeId() == SoFCDocumentAction::getClassTypeId()) {
auto docaction = static_cast<SoFCDocumentAction*>(action);
this->documentName = docaction->documentName;
}
if (action->getTypeId() == SoFCDocumentObjectAction::getClassTypeId()) {
auto objaction = static_cast<SoFCDocumentObjectAction*>(action);
objaction->documentName = this->documentName.getValue();
objaction->objectName = this->objectName.getValue();
objaction->componentName = this->subElementName.getValue();
objaction->setHandled();
}
if (!useNewSelection.getValue()) {
if (action->getTypeId() == SoFCEnablePreselectionAction::getClassTypeId()) {
auto preaction = static_cast<SoFCEnablePreselectionAction*>(action);
if (preaction->enabled) {
this->preselectionMode = SoFCSelection::AUTO;
}
else {
this->preselectionMode = SoFCSelection::OFF;
}
}
if (action->getTypeId() == SoFCEnableSelectionAction::getClassTypeId()) {
auto selaction = static_cast<SoFCEnableSelectionAction*>(action);
if (selaction->enabled) {
this->selectionMode = SoFCSelection::SEL_ON;
}
else {
this->selectionMode = SoFCSelection::SEL_OFF;
if (selected.getValue() == SELECTED) {
this->selected = NOTSELECTED;
}
}
}
if (action->getTypeId() == SoFCSelectionColorAction::getClassTypeId()) {
auto colaction = static_cast<SoFCSelectionColorAction*>(action);
this->colorSelection = colaction->selectionColor;
}
if (action->getTypeId() == SoFCHighlightColorAction::getClassTypeId()) {
auto colaction = static_cast<SoFCHighlightColorAction*>(action);
this->colorHighlight = colaction->highlightColor;
}
if (selectionMode.getValue() == SEL_ON
&& action->getTypeId() == SoFCSelectionAction::getClassTypeId()) {
auto selaction = static_cast<SoFCSelectionAction*>(action);
if (selaction->SelChange.Type == SelectionChanges::AddSelection
|| selaction->SelChange.Type == SelectionChanges::RmvSelection) {
if (documentName.getValue() == selaction->SelChange.pDocName
&& objectName.getValue() == selaction->SelChange.pObjectName
&& (subElementName.getValue() == selaction->SelChange.pSubName
|| *(selaction->SelChange.pSubName) == '\0')) {
if (selaction->SelChange.Type == SelectionChanges::AddSelection) {
if (selected.getValue() == NOTSELECTED) {
selected = SELECTED;
}
}
else {
if (selected.getValue() == SELECTED) {
selected = NOTSELECTED;
}
}
return;
}
}
else if (selaction->SelChange.Type == SelectionChanges::ClrSelection) {
if (documentName.getValue() == selaction->SelChange.pDocName
|| strcmp(selaction->SelChange.pDocName, "") == 0) {
if (selected.getValue() == SELECTED) {
selected = NOTSELECTED;
}
}
}
else if (selaction->SelChange.Type == SelectionChanges::SetSelection) {
bool sel = Selection().isSelected(
documentName.getValue().getString(),
objectName.getValue().getString() /*,
subElementName.getValue().getString()*/
);
if (sel) {
if (selected.getValue() == NOTSELECTED) {
selected = SELECTED;
}
}
else {
if (selected.getValue() == SELECTED) {
selected = NOTSELECTED;
}
}
}
}
}
inherited::doAction(action);
}
int SoFCSelection::getPriority(const SoPickedPoint* p)
{
const SoDetail* detail = p->getDetail();
if (!detail) {
return 0;
}
if (detail->isOfType(SoFaceDetail::getClassTypeId())) {
return 1;
}
if (detail->isOfType(SoLineDetail::getClassTypeId())) {
return 2;
}
if (detail->isOfType(SoPointDetail::getClassTypeId())) {
return 3;
}
return 0;
}
const SoPickedPoint* SoFCSelection::getPickedPoint(SoHandleEventAction* action) const
{
// To identify the picking of lines in a concave area we have to
// get all intersection points. If we have two or more intersection
// points where the first is of a face and the second of a line with
// almost similar coordinates we use the second point, instead.
const SoPickedPointList& points = action->getPickedPointList();
if (points.getLength() == 0) {
return nullptr;
}
else if (points.getLength() == 1) {
return points[0];
}
const SoPickedPoint* picked = points[0];
int picked_prio = getPriority(picked);
const SbVec3f& picked_pt = picked->getPoint();
for (int i = 1; i < points.getLength(); i++) {
const SoPickedPoint* cur = points[i];
int cur_prio = getPriority(cur);
const SbVec3f& cur_pt = cur->getPoint();
if ((cur_prio > picked_prio) && picked_pt.equals(cur_pt, 0.01f)) {
picked = cur;
picked_prio = cur_prio;
}
}
return picked;
}
// doc from parent
void SoFCSelection::handleEvent(SoHandleEventAction* action)
{
if (useNewSelection.getValue()) {
inherited::handleEvent(action);
return;
}
static char buf[513];
auto mymode = static_cast<PreselectionModes>(this->preselectionMode.getValue());
const SoEvent* event = action->getEvent();
// mouse move events for preselection
if (event->isOfType(SoLocation2Event::getClassTypeId())) {
// NOTE: If preselection is off then we do not check for a picked point because otherwise
// this search may slow down extremely the system on really big data sets. In this case we
// just check for a picked point if the data set has been selected.
if (mymode == AUTO || mymode == ON) {
const SoPickedPoint* pp = this->getPickedPoint(action);
if (pp && pp->getPath()->containsPath(action->getCurPath())) {
if (!highlighted) {
if (Gui::Selection().setPreselect(
documentName.getValue().getString(),
objectName.getValue().getString(),
subElementName.getValue().getString(),
pp->getPoint()[0],
pp->getPoint()[1],
pp->getPoint()[2]
)) {
SoFCSelection::turnoffcurrent(action);
SoFCSelection::currenthighlight = static_cast<SoFullPath*>(
action->getCurPath()->copy()
);
SoFCSelection::currenthighlight->ref();
highlighted = true;
this->touch(); // force scene redraw
this->redrawHighlighted(action, true);
}
}
const auto& pt = pp->getPoint();
printPreselectionInfo(
documentName.getValue().getString(),
objectName.getValue().getString(),
subElementName.getValue().getString(),
pt[0],
pt[1],
pt[2],
1e-7
);
}
else { // picked point
if (highlighted) {
if (mymode == AUTO) {
SoFCSelection::turnoffcurrent(action);
}
// FIXME: I think we should set 'highlighted' to false whenever no point is
// picked else
highlighted = false;
Gui::Selection().rmvPreselect();
}
}
}
} // key press events
else if (event->isOfType(SoKeyboardEvent ::getClassTypeId())) {
auto const e = static_cast<const SoKeyboardEvent*>(event);
if (SoKeyboardEvent::isKeyPressEvent(e, SoKeyboardEvent::LEFT_SHIFT)
|| SoKeyboardEvent::isKeyPressEvent(e, SoKeyboardEvent::RIGHT_SHIFT)) {
bShift = true;
}
if (SoKeyboardEvent::isKeyReleaseEvent(e, SoKeyboardEvent::LEFT_SHIFT)
|| SoKeyboardEvent::isKeyReleaseEvent(e, SoKeyboardEvent::RIGHT_SHIFT)) {
bShift = false;
}
if (SoKeyboardEvent::isKeyPressEvent(e, SoKeyboardEvent::LEFT_CONTROL)
|| SoKeyboardEvent::isKeyPressEvent(e, SoKeyboardEvent::RIGHT_CONTROL)) {
bCtrl = true;
}
if (SoKeyboardEvent::isKeyReleaseEvent(e, SoKeyboardEvent::LEFT_CONTROL)
|| SoKeyboardEvent::isKeyReleaseEvent(e, SoKeyboardEvent::RIGHT_CONTROL)) {
bCtrl = false;
}
} // mouse press events for (de)selection
else if (event->isOfType(SoMouseButtonEvent::getClassTypeId())) {
auto const e = static_cast<const SoMouseButtonEvent*>(event);
if (SoMouseButtonEvent::isButtonReleaseEvent(e, SoMouseButtonEvent::BUTTON1)) {
// FIXME: Shouldn't we remove the preselection for newly selected objects?
// Otherwise the tree signals that an object is preselected even though it is
// hidden. (Werner)
const SoPickedPoint* pp = this->getPickedPoint(action);
if (pp && pp->getPath()->containsPath(action->getCurPath())) {
const auto& pt = pp->getPoint();
if (bCtrl) {
if (Gui::Selection().isSelected(
documentName.getValue().getString(),
objectName.getValue().getString(),
subElementName.getValue().getString()
)) {
Gui::Selection().rmvSelection(
documentName.getValue().getString(),
objectName.getValue().getString(),
subElementName.getValue().getString()
);
}
else {
Gui::Selection().addSelection(
documentName.getValue().getString(),
objectName.getValue().getString(),
subElementName.getValue().getString(),
pt[0],
pt[1],
pt[2]
);
if (mymode == OFF) {
snprintf(
buf,
512,
"Selected: %s.%s.%s (%g, %g, %g)",
documentName.getValue().getString(),
objectName.getValue().getString(),
subElementName.getValue().getString(),
fabs(pt[0]) > 1e-7 ? pt[0] : 0.0,
fabs(pt[1]) > 1e-7 ? pt[1] : 0.0,
fabs(pt[2]) > 1e-7 ? pt[2] : 0.0
);
getMainWindow()->showMessage(QString::fromLatin1(buf));
}
}
}
else { // Ctrl
if (!Gui::Selection().isSelected(
documentName.getValue().getString(),
objectName.getValue().getString(),
subElementName.getValue().getString()
)) {
Gui::Selection().clearSelection(documentName.getValue().getString());
Gui::Selection().addSelection(
documentName.getValue().getString(),
objectName.getValue().getString(),
subElementName.getValue().getString(),
pt[0],
pt[1],
pt[2]
);
}
else {
Gui::Selection().clearSelection(documentName.getValue().getString());
Gui::Selection().addSelection(
documentName.getValue().getString(),
objectName.getValue().getString(),
nullptr,
pt[0],
pt[1],
pt[2]
);
}
if (mymode == OFF) {
snprintf(
buf,
512,
"Selected: %s.%s.%s (%g, %g, %g)",
documentName.getValue().getString(),
objectName.getValue().getString(),
subElementName.getValue().getString(),
fabs(pt[0]) > 1e-7 ? pt[0] : 0.0,
fabs(pt[1]) > 1e-7 ? pt[1] : 0.0,
fabs(pt[2]) > 1e-7 ? pt[2] : 0.0
);
getMainWindow()->showMessage(QString::fromLatin1(buf));
}
}
action->setHandled();
} // picked point
} // mouse release
}
inherited::handleEvent(action);
}
// doc from parent
void SoFCSelection::GLRenderBelowPath(SoGLRenderAction* action)
{
SoState* state = action->getState();
SelContextPtr ctx = Gui::SoFCSelectionRoot::getRenderContext<SelContext>(this, selContext);
if (selContext2->checkGlobal(ctx)) {
ctx = selContext2;
}
if (!useNewSelection.getValue() && selContext == ctx) {
ctx->selectionColor = this->colorSelection.getValue();
ctx->highlightColor = this->colorHighlight.getValue();
if (this->selected.getValue() == SELECTED) {
ctx->selectAll();
}
else {
ctx->selectionIndex.clear();
}
ctx->highlightIndex = this->highlighted ? 0 : -1;
}
// check if preselection is active
if (this->setOverride(action, ctx)) {
inherited::GLRenderBelowPath(action);
state->pop();
}
else {
inherited::GLRenderBelowPath(action);
}
}
void SoFCSelection::GLRender(SoGLRenderAction* action)
{
SoState* state = action->getState();
SelContextPtr ctx = Gui::SoFCSelectionRoot::getRenderContext<SelContext>(this, selContext);
if (selContext2->checkGlobal(ctx)) {
ctx = selContext2;
}
if (!useNewSelection.getValue() && selContext == ctx) {
ctx->selectionColor = this->colorSelection.getValue();
ctx->highlightColor = this->colorHighlight.getValue();
if (this->selected.getValue() == SELECTED) {
ctx->selectAll();
}
else {
ctx->selectionIndex.clear();
}
ctx->highlightIndex = this->highlighted ? 0 : -1;
}
// check if preselection is active
if (this->setOverride(action, ctx)) {
inherited::GLRender(action);
state->pop();
}
else {
inherited::GLRender(action);
}
}
// doc from parent
void SoFCSelection::GLRenderInPath(SoGLRenderAction* action)
{
SelContextPtr ctx = Gui::SoFCSelectionRoot::getRenderContext<SelContext>(this, selContext);
if (selContext2->checkGlobal(ctx)) {
ctx = selContext2;
}
if (!useNewSelection.getValue() && selContext == ctx) {
ctx->selectionColor = this->colorSelection.getValue();
ctx->highlightColor = this->colorHighlight.getValue();
if (this->selected.getValue() == SELECTED) {
ctx->selectAll();
}
else {
ctx->selectionIndex.clear();
}
ctx->highlightIndex = this->highlighted ? 0 : -1;
}
// check if preselection is active
SoState* state = action->getState();
if (this->setOverride(action, ctx)) {
inherited::GLRenderInPath(action);
state->pop();
}
else {
inherited::GLRenderInPath(action);
}
}
SbBool SoFCSelection::preRender(SoGLRenderAction* action, GLint& oldDepthFunc)
//
////////////////////////////////////////////////////////////////////////
{
// If not performing locate highlighting, just return.
if (preselectionMode.getValue() == OFF) {
return false;
}
SoState* state = action->getState();
// ??? prevent caching at this level - for some reason the
// ??? SoWindowElement::copyMatchInfo() method get called, which should
// ??? never be called. We are not caching this node correctly yet....
// SoCacheElement::invalidate(state);
SbBool drawHighlighted
= (preselectionMode.getValue() == ON || isHighlighted(action)
|| selected.getValue() == SELECTED);
if (drawHighlighted) {
// prevent diffuse & emissive color from leaking out...
state->push();
SbColor col;
if (selected.getValue() == SELECTED) {
col = colorSelection.getValue();
}
else {
col = colorHighlight.getValue();
}
// Emissive Color
SoLazyElement::setEmissive(state, &col);
SoOverrideElement::setEmissiveColorOverride(state, this, true);
// Diffuse Color
if (style.getValue() == EMISSIVE_DIFFUSE) {
SoLazyElement::setDiffuse(state, this, 1, &col, &colorpacker);
SoOverrideElement::setDiffuseColorOverride(state, this, true);
}
}
// Draw on top of other things at same z-buffer depth if:
// [a] we're highlighted
// [b] this is the highlighting pass. This occurs when changing from
// non-hilit to lit OR VICE VERSA.
// Otherwise, leave it alone...
if (drawHighlighted || highlighted) {
glGetIntegerv(GL_DEPTH_FUNC, &oldDepthFunc);
if (oldDepthFunc != GL_LEQUAL) {
glDepthFunc(GL_LEQUAL);
}
}
return drawHighlighted;
}
/*!
Empty method in Coin. Can be used by subclasses to be told
when status change.
*/
void SoFCSelection::redrawHighlighted(SoAction* action, SbBool doHighlight)
{
Q_UNUSED(action);
Q_UNUSED(doHighlight);
}
SbBool SoFCSelection::readInstance(SoInput* in, unsigned short flags)
{
// Note: The read in document name can be false, so the caller must ensure pointing to the
// correct document
SbBool ret = inherited::readInstance(in, flags);
return ret;
}
//
// update override state before rendering
//
bool SoFCSelection::setOverride(SoGLRenderAction* action, SelContextPtr ctx)
{
auto mymode = static_cast<PreselectionModes>(this->preselectionMode.getValue());
bool preselected = ctx && ctx->isHighlighted() && (useNewSelection.getValue() || mymode == AUTO);
if (!preselected && mymode != ON && (!ctx || !ctx->isSelected())) {
return false;
}
// uniqueId is returned by SoNode::getNodeId(). It is used to notify change
// and for render cache update. In order to update cache on selection state
// change, We manually change the id here by using a combined hash of the
// original id and context pointer.
auto oldId = this->uniqueId;
this->uniqueId ^= std::hash<void*>()(ctx.get()) + 0x9e3779b9 + (oldId << 6) + (oldId >> 2);
auto mystyle = static_cast<Styles>(this->style.getValue());
if (mystyle == SoFCSelection::BOX) {
if (ctx) {
SoFCSelectionRoot::renderBBox(
action,
this,
preselected ? ctx->highlightColor : ctx->selectionColor
);
}
this->uniqueId = oldId;
return false;
}
SoState* state = action->getState();
state->push();
SoMaterialBindingElement::set(state, SoMaterialBindingElement::OVERALL);
SoOverrideElement::setMaterialBindingOverride(state, this, true);
if (!preselected && ctx) {
SoLazyElement::setEmissive(state, &ctx->selectionColor);
}
else if (ctx) {
SoLazyElement::setEmissive(state, &ctx->highlightColor);
}
SoOverrideElement::setEmissiveColorOverride(state, this, true);
if (SoLazyElement::getLightModel(state) == SoLazyElement::BASE_COLOR
|| mystyle == SoFCSelection::EMISSIVE_DIFFUSE) {
if (!preselected && ctx) {
SoLazyElement::setDiffuse(state, this, 1, &ctx->selectionColor, &colorpacker);
}
else if (ctx) {
SoLazyElement::setDiffuse(state, this, 1, &ctx->highlightColor, &colorpacker);
}
SoOverrideElement::setDiffuseColorOverride(state, this, true);
}
this->uniqueId = oldId;
return true;
}
// private convenience method
void SoFCSelection::turnoffcurrent(SoAction* action)
{
if (SoFCSelection::currenthighlight && SoFCSelection::currenthighlight->getLength()) {
SoNode* tail = SoFCSelection::currenthighlight->getTail();
if (tail->isOfType(SoFCSelection::getClassTypeId())) {
static_cast<SoFCSelection*>(tail)->highlighted = false;
static_cast<SoFCSelection*>(tail)->touch(); // force scene redraw
if (action) {
static_cast<SoFCSelection*>(tail)->redrawHighlighted(action, false);
}
}
}
if (SoFCSelection::currenthighlight) {
SoFCSelection::currenthighlight->unref();
SoFCSelection::currenthighlight = nullptr;
}
}
SbBool SoFCSelection::isHighlighted(SoAction* action)
//
////////////////////////////////////////////////////////////////////////
{
auto actionPath = static_cast<const SoFullPath*>(action->getCurPath());
return (
currenthighlight && currenthighlight->getTail() == actionPath->getTail() && // nested SoHL!
*currenthighlight == *actionPath
);
}
void SoFCSelection::applySettings()
{
// TODO Some view providers got copy of this code: make them use this (2015-09-03, Fat-Zer)
// Note: SoFCUnifiedSelection got the same code, keep in sync or think about a way to share it
float transparency;
ParameterGrp::handle hGrp = Gui::WindowParameter::getDefaultParameter()->GetGroup("View");
bool enablePre = hGrp->GetBool("EnablePreselection", true);
bool enableSel = hGrp->GetBool("EnableSelection", true);
if (!enablePre) {
this->preselectionMode = Gui::SoFCSelection::OFF;
}
else {
// Search for a user defined value with the current color as default
SbColor highlightColor = this->colorHighlight.getValue();
auto highlight = (unsigned long)(highlightColor.getPackedValue());
highlight = hGrp->GetUnsigned("HighlightColor", highlight);
highlightColor.setPackedValue((uint32_t)highlight, transparency);
this->colorHighlight.setValue(highlightColor);
}
if (!enableSel) {
this->selectionMode = Gui::SoFCSelection::SEL_OFF;
}
else {
// Do the same with the selection color
SbColor selectionColor = this->colorSelection.getValue();
auto selection = (unsigned long)(selectionColor.getPackedValue());
selection = hGrp->GetUnsigned("SelectionColor", selection);
selectionColor.setPackedValue((uint32_t)selection, transparency);
this->colorSelection.setValue(selectionColor);
}
}