Files
create/src/Gui/SoFCUnifiedSelection.cpp

816 lines
32 KiB
C++

/***************************************************************************
* 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 "PreCompiled.h"
#ifndef _PreComp_
# include <qstatusbar.h>
# include <qstring.h>
# include <Inventor/details/SoFaceDetail.h>
# include <Inventor/details/SoLineDetail.h>
#endif
#include <Inventor/elements/SoOverrideElement.h>
#include <Inventor/elements/SoLazyElement.h>
#include <Inventor/elements/SoCacheElement.h>
#include <Inventor/elements/SoOverrideElement.h>
#include <Inventor/elements/SoWindowElement.h>
#include <Inventor/SoFullPath.h>
#include <Inventor/actions/SoGLRenderAction.h>
#include <Inventor/actions/SoHandleEventAction.h>
#include <Inventor/events/SoKeyboardEvent.h>
#include <Inventor/elements/SoComplexityElement.h>
#include <Inventor/elements/SoComplexityTypeElement.h>
#include <Inventor/elements/SoCoordinateElement.h>
#include <Inventor/elements/SoElements.h>
#include <Inventor/elements/SoFontNameElement.h>
#include <Inventor/elements/SoFontSizeElement.h>
#include <Inventor/elements/SoMaterialBindingElement.h>
#include <Inventor/elements/SoModelMatrixElement.h>
#include <Inventor/elements/SoShapeStyleElement.h>
#include <Inventor/elements/SoProfileCoordinateElement.h>
#include <Inventor/elements/SoProfileElement.h>
#include <Inventor/elements/SoSwitchElement.h>
#include <Inventor/elements/SoUnitsElement.h>
#include <Inventor/elements/SoViewVolumeElement.h>
#include <Inventor/elements/SoViewingMatrixElement.h>
#include <Inventor/elements/SoViewportRegionElement.h>
#include <Inventor/events/SoMouseButtonEvent.h>
#include <Inventor/misc/SoState.h>
#include <Inventor/misc/SoChildList.h>
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoMaterialBinding.h>
#include <Inventor/nodes/SoNormalBinding.h>
#include <Inventor/events/SoLocation2Event.h>
#include <Inventor/SoPickedPoint.h>
#ifdef FC_OS_MACOSX
# include <OpenGL/gl.h>
#else
# ifdef FC_OS_WIN32
# include <windows.h>
# endif
# include <GL/gl.h>
#endif
#include <QtOpenGL.h>
#include <Base/Console.h>
#include <App/Application.h>
#include <App/Document.h>
#include <Gui/Document.h>
#include <App/DocumentObject.h>
#include "SoFCUnifiedSelection.h"
#include "Application.h"
#include "MainWindow.h"
#include "Selection.h"
#include "ViewProvider.h"
#include "SoFCInteractiveElement.h"
#include "SoFCSelectionAction.h"
#include "ViewProviderDocumentObject.h"
#include "ViewProviderGeometryObject.h"
using namespace Gui;
SoFullPath * Gui::SoFCUnifiedSelection::currenthighlight = NULL;
// *************************************************************************
SO_NODE_SOURCE(SoFCUnifiedSelection);
/*!
Constructor.
*/
SoFCUnifiedSelection::SoFCUnifiedSelection() : pcDocument(0)
{
SO_NODE_CONSTRUCTOR(SoFCUnifiedSelection);
SO_NODE_ADD_FIELD(colorHighlight, (SbColor(1.0f, 0.6f, 0.0f)));
SO_NODE_ADD_FIELD(colorSelection, (SbColor(0.1f, 0.8f, 0.1f)));
SO_NODE_ADD_FIELD(highlightMode, (AUTO));
SO_NODE_ADD_FIELD(selectionMode, (ON));
SO_NODE_ADD_FIELD(selectionRole, (true));
SO_NODE_DEFINE_ENUM_VALUE(HighlightModes, AUTO);
SO_NODE_DEFINE_ENUM_VALUE(HighlightModes, ON);
SO_NODE_DEFINE_ENUM_VALUE(HighlightModes, OFF);
SO_NODE_SET_SF_ENUM_TYPE (highlightMode, HighlightModes);
highlighted = false;
setPreSelection = false;
preSelection = -1;
}
/*!
Destructor.
*/
SoFCUnifiedSelection::~SoFCUnifiedSelection()
{
// If we're being deleted and we're the current highlight,
// NULL out that variable
if (currenthighlight != NULL) {
currenthighlight->unref();
currenthighlight = NULL;
}
}
// doc from parent
void
SoFCUnifiedSelection::initClass(void)
{
SO_NODE_INIT_CLASS(SoFCUnifiedSelection,SoSeparator,"Separator");
}
void SoFCUnifiedSelection::finish()
{
atexit_cleanup();
}
void SoFCUnifiedSelection::applySettings()
{
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->highlightMode = SoFCUnifiedSelection::OFF;
}
else {
// Search for a user defined value with the current color as default
SbColor highlightColor = this->colorHighlight.getValue();
unsigned long highlight = (unsigned long)(highlightColor.getPackedValue());
highlight = hGrp->GetUnsigned("HighlightColor", highlight);
highlightColor.setPackedValue((uint32_t)highlight, transparency);
this->colorHighlight.setValue(highlightColor);
}
if (!enableSel) {
this->selectionMode = SoFCUnifiedSelection::OFF;
}
else {
// Do the same with the selection color
SbColor selectionColor = this->colorSelection.getValue();
unsigned long selection = (unsigned long)(selectionColor.getPackedValue());
selection = hGrp->GetUnsigned("SelectionColor", selection);
selectionColor.setPackedValue((uint32_t)selection, transparency);
this->colorSelection.setValue(selectionColor);
}
}
const char* SoFCUnifiedSelection::getFileFormatName(void) const
{
return "Separator";
}
void SoFCUnifiedSelection::write(SoWriteAction * action)
{
SoOutput * out = action->getOutput();
if (out->getStage() == SoOutput::WRITE) {
// Do not write out the fields of this class
if (this->writeHeader(out, true, false)) return;
SoGroup::doAction((SoAction *)action);
this->writeFooter(out);
}
else {
inherited::write(action);
}
}
int SoFCUnifiedSelection::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*
SoFCUnifiedSelection::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 0;
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;
}
void SoFCUnifiedSelection::doAction(SoAction *action)
{
if (action->getTypeId() == SoFCEnableHighlightAction::getClassTypeId()) {
SoFCEnableHighlightAction *preaction = (SoFCEnableHighlightAction*)action;
if (preaction->highlight) {
this->highlightMode = SoFCUnifiedSelection::AUTO;
}
else {
this->highlightMode = SoFCUnifiedSelection::OFF;
}
}
if (action->getTypeId() == SoFCEnableSelectionAction::getClassTypeId()) {
SoFCEnableSelectionAction *selaction = (SoFCEnableSelectionAction*)action;
if (selaction->selection) {
this->selectionMode = SoFCUnifiedSelection::ON;
}
else {
this->selectionMode = SoFCUnifiedSelection::OFF;
}
}
if (action->getTypeId() == SoFCSelectionColorAction::getClassTypeId()) {
SoFCSelectionColorAction *colaction = (SoFCSelectionColorAction*)action;
this->colorSelection = colaction->selectionColor;
}
if (action->getTypeId() == SoFCHighlightColorAction::getClassTypeId()) {
SoFCHighlightColorAction *colaction = (SoFCHighlightColorAction*)action;
this->colorHighlight = colaction->highlightColor;
}
if (highlightMode.getValue() != OFF && action->getTypeId() == SoFCHighlightAction::getClassTypeId()) {
SoFCHighlightAction *hilaction = static_cast<SoFCHighlightAction*>(action);
// Do not clear currently highlighted object when setting new pre-selection
if (!setPreSelection && hilaction->SelChange.Type == SelectionChanges::RmvPreselect) {
if (currenthighlight) {
SoHighlightElementAction action;
action.apply(currenthighlight);
currenthighlight->unref();
currenthighlight = 0;
}
}
}
if (selectionMode.getValue() == ON && action->getTypeId() == SoFCSelectionAction::getClassTypeId()) {
SoFCSelectionAction *selaction = static_cast<SoFCSelectionAction*>(action);
if (selaction->SelChange.Type == SelectionChanges::AddSelection ||
selaction->SelChange.Type == SelectionChanges::RmvSelection) {
// selection changes inside the 3d view are handled in handleEvent()
App::Document* doc = App::GetApplication().getDocument(selaction->SelChange.pDocName);
App::DocumentObject* obj = doc->getObject(selaction->SelChange.pObjectName);
ViewProvider*vp = Application::Instance->getViewProvider(obj);
if (vp && vp->useNewSelectionModel() && vp->isSelectable()) {
SoDetail* detail = vp->getDetail(selaction->SelChange.pSubName);
SoSelectionElementAction::Type type = SoSelectionElementAction::None;
if (selaction->SelChange.Type == SelectionChanges::AddSelection) {
if (detail)
type = SoSelectionElementAction::Append;
else
type = SoSelectionElementAction::All;
}
else {
if (detail)
type = SoSelectionElementAction::Remove;
else
type = SoSelectionElementAction::None;
}
if(checkSelectionStyle(type,vp)) {
SoSelectionElementAction action(type);
action.setColor(this->colorSelection.getValue());
action.setElement(detail);
action.apply(vp->getRoot());
}
delete detail;
}
}
else if (selaction->SelChange.Type == SelectionChanges::ClrSelection ||
selaction->SelChange.Type == SelectionChanges::SetSelection) {
std::vector<ViewProvider*> vps;
if (this->pcDocument)
vps = this->pcDocument->getViewProvidersOfType(ViewProviderDocumentObject::getClassTypeId());
for (std::vector<ViewProvider*>::iterator it = vps.begin(); it != vps.end(); ++it) {
ViewProviderDocumentObject* vpd = static_cast<ViewProviderDocumentObject*>(*it);
if (vpd->useNewSelectionModel()) {
SoSelectionElementAction::Type type;
if(Selection().isSelected(vpd->getObject()) && vpd->isSelectable())
type = SoSelectionElementAction::All;
else
type = SoSelectionElementAction::None;
if(checkSelectionStyle(type,vpd)) {
SoSelectionElementAction action(type);
action.setColor(this->colorSelection.getValue());
action.apply(vpd->getRoot());
}
}
}
}
}
inherited::doAction( action );
}
// doc from parent
void
SoFCUnifiedSelection::handleEvent(SoHandleEventAction * action)
{
// If off then don't handle this event
if (!selectionRole.getValue()) {
inherited::handleEvent(action);
return;
}
static char buf[513];
HighlightModes mymode = (HighlightModes) this->highlightMode.getValue();
const SoEvent * event = action->getEvent();
// If we don't need to pick for locate highlighting,
// then just behave as separator and return.
// NOTE: we still have to pick for ON even though we don't have
// to re-render, because the app needs to be notified as the mouse
// goes over locate highlight nodes.
//if (highlightMode.getValue() == OFF) {
// inherited::handleEvent( action );
// return;
//}
//
// If this is a mouseMotion event, then check for locate highlighting
//
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) {
// check to see if the mouse is over our geometry...
const SoPickedPoint * pp = this->getPickedPoint(action);
SoFullPath *pPath = (pp != NULL) ? (SoFullPath *) pp->getPath() : NULL;
ViewProvider *vp = 0;
ViewProviderDocumentObject* vpd = 0;
if (this->pcDocument && pPath && pPath->containsPath(action->getCurPath()))
vp = this->pcDocument->getViewProviderByPathFromTail(pPath);
if (vp && vp->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
vpd = static_cast<ViewProviderDocumentObject*>(vp);
//SbBool old_state = highlighted;
highlighted = false;
if (vpd && vpd->useNewSelectionModel() && vpd->isSelectable()) {
std::string documentName = vpd->getObject()->getDocument()->getName();
std::string objectLabel = vpd->getObject()->Label.getStrValue();
std::string objectName = vpd->getObject()->getNameInDocument();
std::string subElementName = vpd->getElement(pp ? pp->getDetail() : 0);
this->preSelection = 1;
static char buf[513];
snprintf(buf,512,"Preselected: %s - %s.%s.%s (%g, %g, %g)"
,objectLabel.c_str()
,documentName.c_str()
,objectName.c_str()
,subElementName.c_str()
,pp->getPoint()[0]
,pp->getPoint()[1]
,pp->getPoint()[2]);
getMainWindow()->showMessage(QString::fromUtf8(buf));
setPreSelection = true;
if (Gui::Selection().setPreselect(documentName.c_str()
,objectName.c_str()
,subElementName.c_str()
,pp->getPoint()[0]
,pp->getPoint()[1]
,pp->getPoint()[2])){
SoSearchAction sa;
sa.setNode(vp->getRoot());
sa.apply(vp->getRoot());
if (sa.getPath()) {
highlighted = true;
if (currenthighlight && currenthighlight->getTail() != sa.getPath()->getTail()) {
SoHighlightElementAction action;
action.setHighlighted(false);
action.apply(currenthighlight);
currenthighlight->unref();
currenthighlight = 0;
//old_state = !highlighted;
}
else if (currenthighlight) {
// clean-up the highlight path before assigning a new path
currenthighlight->unref();
currenthighlight = 0;
}
currenthighlight = static_cast<SoFullPath*>(sa.getPath()->copy());
currenthighlight->ref();
}
}
setPreSelection = false;
}
// nothing picked
else if (!pp) {
if (this->preSelection > 0) {
this->preSelection = 0;
// touch() makes sure to call GLRenderBelowPath so that the cursor can be updated
// because only from there the SoGLWidgetElement delivers the OpenGL window
this->touch();
}
}
if (currenthighlight/* && old_state != highlighted*/) {
SoHighlightElementAction action;
action.setHighlighted(highlighted);
action.setColor(this->colorHighlight.getValue());
action.setElement(pp ? pp->getDetail() : 0);
action.apply(currenthighlight);
if (!highlighted) {
currenthighlight->unref();
currenthighlight = 0;
}
this->touch();
}
}
}
// mouse press events for (de)selection
else if (event->isOfType(SoMouseButtonEvent::getClassTypeId()) &&
selectionMode.getValue() == SoFCUnifiedSelection::ON) {
const SoMouseButtonEvent* e = static_cast<const SoMouseButtonEvent *>(event);
if (SoMouseButtonEvent::isButtonReleaseEvent(e,SoMouseButtonEvent::BUTTON1)) {
// check to see if the mouse is over a geometry...
const SoPickedPoint * pp = this->getPickedPoint(action);
SoFullPath *pPath = (pp != NULL) ? (SoFullPath *) pp->getPath() : NULL;
ViewProvider *vp = 0;
ViewProviderDocumentObject* vpd = 0;
if (this->pcDocument && pPath && pPath->containsPath(action->getCurPath()))
vp = this->pcDocument->getViewProviderByPathFromTail(pPath);
if (vp && vp->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
vpd = static_cast<ViewProviderDocumentObject*>(vp);
if (vpd && vpd->useNewSelectionModel() && vpd->isSelectable()) {
SoSelectionElementAction::Type type = SoSelectionElementAction::None;
std::string documentName = vpd->getObject()->getDocument()->getName();
std::string objectName = vpd->getObject()->getNameInDocument();
std::string subElementName = vpd->getElement(pp ? pp->getDetail() : 0);
if (event->wasCtrlDown()) {
if (Gui::Selection().isSelected(documentName.c_str()
,objectName.c_str()
,subElementName.c_str())) {
Gui::Selection().rmvSelection(documentName.c_str()
,objectName.c_str()
,subElementName.c_str());
type = SoSelectionElementAction::Remove;
}
else {
bool ok = Gui::Selection().addSelection(documentName.c_str()
,objectName.c_str()
,subElementName.c_str()
,pp->getPoint()[0]
,pp->getPoint()[1]
,pp->getPoint()[2]);
if (ok)
type = SoSelectionElementAction::Append;
if (mymode == OFF) {
snprintf(buf,512,"Selected: %s.%s.%s (%g, %g, %g)"
,documentName.c_str()
,objectName.c_str()
,subElementName.c_str()
,pp->getPoint()[0]
,pp->getPoint()[1]
,pp->getPoint()[2]);
getMainWindow()->showMessage(QString::fromLatin1(buf));
}
}
}
else { // Ctrl
if (!Gui::Selection().isSelected(documentName.c_str()
,objectName.c_str()
,subElementName.c_str())) {
Gui::Selection().clearSelection(documentName.c_str());
bool ok = Gui::Selection().addSelection(documentName.c_str()
,objectName.c_str()
,subElementName.c_str()
,pp->getPoint()[0]
,pp->getPoint()[1]
,pp->getPoint()[2]);
if (ok)
type = SoSelectionElementAction::Append;
}
else {
Gui::Selection().clearSelection(documentName.c_str());
bool ok = Gui::Selection().addSelection(documentName.c_str()
,objectName.c_str()
,0
,pp->getPoint()[0]
,pp->getPoint()[1]
,pp->getPoint()[2]);
if (ok)
type = SoSelectionElementAction::All;
}
if (mymode == OFF) {
snprintf(buf,512,"Selected: %s.%s.%s (%g, %g, %g)"
,documentName.c_str()
,objectName.c_str()
,subElementName.c_str()
,pp->getPoint()[0]
,pp->getPoint()[1]
,pp->getPoint()[2]);
getMainWindow()->showMessage(QString::fromLatin1(buf));
}
}
action->setHandled();
if (currenthighlight && checkSelectionStyle(type,vpd)) {
SoSelectionElementAction action(type);
action.setColor(this->colorSelection.getValue());
action.setElement(pp ? pp->getDetail() : 0);
action.apply(currenthighlight);
this->touch();
}
} // picked point
else if (!pp) {
// user clicked onto empty space but in case Ctrl key was pressed
// then mark the action as handled to avoid that the navigation style
// processes the action and clears the selection
if (event->wasCtrlDown()) {
action->setHandled();
}
}
} // mouse release
}
inherited::handleEvent(action);
}
bool SoFCUnifiedSelection::checkSelectionStyle(int type, ViewProvider *vp) {
if((type == SoSelectionElementAction::All ||
type == SoSelectionElementAction::None) &&
vp->isDerivedFrom(ViewProviderGeometryObject::getClassTypeId()) &&
static_cast<ViewProviderGeometryObject*>(vp)->SelectionStyle.getValue()==1)
{
bool selected = type==SoSelectionElementAction::All;
static_cast<ViewProviderGeometryObject*>(vp)->showBoundingBox(selected);
if(selected) return false;
}
return true;
}
void SoFCUnifiedSelection::GLRenderBelowPath(SoGLRenderAction * action)
{
inherited::GLRenderBelowPath(action);
// nothing picked, so restore the arrow cursor if needed
if (this->preSelection == 0) {
// this is called when a selection gate forbade to select an object
// and the user moved the mouse to an empty area
this->preSelection = -1;
QtGLWidget* window;
SoState *state = action->getState();
SoGLWidgetElement::get(state, window);
QWidget* parent = window ? window->parentWidget() : 0;
if (parent) {
QCursor c = parent->cursor();
if (c.shape() == Qt::ForbiddenCursor) {
c.setShape(Qt::ArrowCursor);
parent->setCursor(c);
}
}
}
}
// ---------------------------------------------------------------
SO_ACTION_SOURCE(SoHighlightElementAction);
void SoHighlightElementAction::initClass()
{
SO_ACTION_INIT_CLASS(SoHighlightElementAction,SoAction);
SO_ENABLE(SoHighlightElementAction, SoSwitchElement);
SO_ACTION_ADD_METHOD(SoNode,nullAction);
SO_ENABLE(SoHighlightElementAction, SoCoordinateElement);
SO_ACTION_ADD_METHOD(SoGroup,callDoAction);
SO_ACTION_ADD_METHOD(SoIndexedLineSet,callDoAction);
SO_ACTION_ADD_METHOD(SoIndexedFaceSet,callDoAction);
SO_ACTION_ADD_METHOD(SoPointSet,callDoAction);
}
SoHighlightElementAction::SoHighlightElementAction () : _highlight(false), _det(0)
{
SO_ACTION_CONSTRUCTOR(SoHighlightElementAction);
}
SoHighlightElementAction::~SoHighlightElementAction()
{
}
void SoHighlightElementAction::beginTraversal(SoNode *node)
{
traverse(node);
}
void SoHighlightElementAction::callDoAction(SoAction *action,SoNode *node)
{
node->doAction(action);
}
void SoHighlightElementAction::setHighlighted(SbBool ok)
{
this->_highlight = ok;
}
SbBool SoHighlightElementAction::isHighlighted() const
{
return this->_highlight;
}
void SoHighlightElementAction::setColor(const SbColor& c)
{
this->_color = c;
}
const SbColor& SoHighlightElementAction::getColor() const
{
return this->_color;
}
void SoHighlightElementAction::setElement(const SoDetail* det)
{
this->_det = det;
}
const SoDetail* SoHighlightElementAction::getElement() const
{
return this->_det;
}
// ---------------------------------------------------------------
SO_ACTION_SOURCE(SoSelectionElementAction);
void SoSelectionElementAction::initClass()
{
SO_ACTION_INIT_CLASS(SoSelectionElementAction,SoAction);
SO_ENABLE(SoSelectionElementAction, SoSwitchElement);
SO_ACTION_ADD_METHOD(SoNode,nullAction);
SO_ENABLE(SoSelectionElementAction, SoCoordinateElement);
SO_ACTION_ADD_METHOD(SoCoordinate3,callDoAction);
SO_ACTION_ADD_METHOD(SoGroup,callDoAction);
SO_ACTION_ADD_METHOD(SoIndexedLineSet,callDoAction);
SO_ACTION_ADD_METHOD(SoIndexedFaceSet,callDoAction);
SO_ACTION_ADD_METHOD(SoPointSet,callDoAction);
}
SoSelectionElementAction::SoSelectionElementAction (Type t) : _type(t), _det(0)
{
SO_ACTION_CONSTRUCTOR(SoSelectionElementAction);
}
SoSelectionElementAction::~SoSelectionElementAction()
{
}
void SoSelectionElementAction::beginTraversal(SoNode *node)
{
traverse(node);
}
void SoSelectionElementAction::callDoAction(SoAction *action,SoNode *node)
{
node->doAction(action);
}
SoSelectionElementAction::Type
SoSelectionElementAction::getType() const
{
return this->_type;
}
void SoSelectionElementAction::setColor(const SbColor& c)
{
this->_color = c;
}
const SbColor& SoSelectionElementAction::getColor() const
{
return this->_color;
}
void SoSelectionElementAction::setElement(const SoDetail* det)
{
this->_det = det;
}
const SoDetail* SoSelectionElementAction::getElement() const
{
return this->_det;
}
// ---------------------------------------------------------------
SO_ACTION_SOURCE(SoVRMLAction);
void SoVRMLAction::initClass()
{
SO_ACTION_INIT_CLASS(SoVRMLAction,SoAction);
SO_ENABLE(SoVRMLAction, SoSwitchElement);
SO_ACTION_ADD_METHOD(SoNode,nullAction);
SO_ENABLE(SoVRMLAction, SoCoordinateElement);
SO_ENABLE(SoVRMLAction, SoMaterialBindingElement);
SO_ENABLE(SoVRMLAction, SoLazyElement);
SO_ENABLE(SoVRMLAction, SoShapeStyleElement);
SO_ACTION_ADD_METHOD(SoCoordinate3,callDoAction);
SO_ACTION_ADD_METHOD(SoMaterialBinding,callDoAction);
SO_ACTION_ADD_METHOD(SoMaterial,callDoAction);
SO_ACTION_ADD_METHOD(SoNormalBinding,callDoAction);
SO_ACTION_ADD_METHOD(SoGroup,callDoAction);
SO_ACTION_ADD_METHOD(SoIndexedLineSet,callDoAction);
SO_ACTION_ADD_METHOD(SoIndexedFaceSet,callDoAction);
SO_ACTION_ADD_METHOD(SoPointSet,callDoAction);
}
SoVRMLAction::SoVRMLAction() : overrideMode(true)
{
SO_ACTION_CONSTRUCTOR(SoVRMLAction);
}
SoVRMLAction::~SoVRMLAction()
{
}
void SoVRMLAction::setOverrideMode(SbBool on)
{
overrideMode = on;
}
SbBool SoVRMLAction::isOverrideMode() const
{
return overrideMode;
}
void SoVRMLAction::callDoAction(SoAction *action, SoNode *node)
{
if (node->getTypeId().isDerivedFrom(SoNormalBinding::getClassTypeId()) && action->isOfType(SoVRMLAction::getClassTypeId())) {
SoVRMLAction* vrmlAction = static_cast<SoVRMLAction*>(action);
if (vrmlAction->overrideMode) {
SoNormalBinding* bind = static_cast<SoNormalBinding*>(node);
vrmlAction->bindList.push_back(bind->value.getValue());
// this normal binding causes some problems for the part view provider
// See also #0002222: Number of normals in exported VRML is wrong
if (bind->value.getValue() == static_cast<int>(SoNormalBinding::PER_VERTEX_INDEXED))
bind->value = SoNormalBinding::OVERALL;
}
else if (!vrmlAction->bindList.empty()) {
static_cast<SoNormalBinding*>(node)->value = static_cast<SoNormalBinding::Binding>(vrmlAction->bindList.front());
vrmlAction->bindList.pop_front();
}
}
node->doAction(action);
}