Download src/Gui/Selection/SoFCSelection.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 32.3 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Gui/Selection/SoFCSelection.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Gui/Selection/SoFCSelection.cpp
-
curl -L -o SoFCSelection.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Gui/Selection/SoFCSelection.cpp
32.3 kB
| // 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 * | |
| * * | |
| ***************************************************************************/ | |
| 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); | |
| } | |
| } | |