/*************************************************************************** * Copyright (c) 2011 Werner Mayer * * * * 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_ # ifdef FC_OS_WIN32 # include # endif # ifdef FC_OS_MACOSX # include # else # include # endif # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include #endif #include "SoBrepPointSet.h" #include #include using namespace PartGui; SO_NODE_SOURCE(SoBrepPointSet); void SoBrepPointSet::initClass() { SO_NODE_INIT_CLASS(SoBrepPointSet, SoPointSet, "PointSet"); } SoBrepPointSet::SoBrepPointSet() { SO_NODE_CONSTRUCTOR(SoBrepPointSet); SO_NODE_ADD_FIELD(highlightIndex, (-1)); SO_NODE_ADD_FIELD(selectionIndex, (-1)); selectionIndex.setNum(0); } void SoBrepPointSet::GLRender(SoGLRenderAction *action) { const SoCoordinateElement* coords = SoCoordinateElement::getInstance(action->getState()); int num = coords->getNum() - this->startIndex.getValue(); if (num < 0) { // Fixes: #0000545: Undo revolve causes crash 'illegal storage' return; } if (this->selectionIndex.getNum() > 0) renderSelection(action); if (this->highlightIndex.getValue() >= 0) renderHighlight(action); inherited::GLRender(action); // Workaround for #0000433 //#if !defined(FC_OS_WIN32) if (this->highlightIndex.getValue() >= 0) renderHighlight(action); if (this->selectionIndex.getNum() > 0) renderSelection(action); //#endif } void SoBrepPointSet::GLRenderBelowPath(SoGLRenderAction * action) { inherited::GLRenderBelowPath(action); } void SoBrepPointSet::renderShape(const SoGLCoordinateElement * const coords, const int32_t *cindices, int numindices) { const SbVec3f * coords3d = coords->getArrayPtr3(); int previ; const int32_t *end = cindices + numindices; glBegin(GL_POINTS); while (cindices < end) { previ = *cindices++; glVertex3fv((const GLfloat*) (coords3d + previ)); } glEnd(); } void SoBrepPointSet::renderHighlight(SoGLRenderAction *action) { SoState * state = action->getState(); state->push(); float ps = SoPointSizeElement::get(state); if (ps < 4.0f) SoPointSizeElement::set(state, this, 4.0f); SoLazyElement::setEmissive(state, &this->highlightColor); SoOverrideElement::setEmissiveColorOverride(state, this, TRUE); SoLazyElement::setDiffuse(state, this,1, &this->highlightColor,&this->colorpacker); SoOverrideElement::setDiffuseColorOverride(state, this, TRUE); const SoCoordinateElement * coords; const SbVec3f * normals; this->getVertexData(state, coords, normals, FALSE); SoMaterialBundle mb(action); mb.sendFirst(); // make sure we have the correct material int32_t id = this->highlightIndex.getValue(); if (id < this->startIndex.getValue() || id >= coords->getNum()) { SoDebugError::postWarning("SoBrepPointSet::renderHighlight", "highlightIndex out of range"); } else { renderShape(static_cast(coords), &id, 1); } state->pop(); } void SoBrepPointSet::renderSelection(SoGLRenderAction *action) { SoState * state = action->getState(); state->push(); float ps = SoPointSizeElement::get(state); if (ps < 4.0f) SoPointSizeElement::set(state, this, 4.0f); SoLazyElement::setEmissive(state, &this->selectionColor); SoOverrideElement::setEmissiveColorOverride(state, this, TRUE); SoLazyElement::setDiffuse(state, this,1, &this->selectionColor,&this->colorpacker); SoOverrideElement::setDiffuseColorOverride(state, this, TRUE); const SoCoordinateElement * coords; const SbVec3f * normals; const int32_t * cindices; int numcindices; this->getVertexData(state, coords, normals, FALSE); SoMaterialBundle mb(action); mb.sendFirst(); // make sure we have the correct material cindices = this->selectionIndex.getValues(0); numcindices = this->selectionIndex.getNum(); if (!validIndexes(coords, this->startIndex.getValue(), cindices, numcindices)) { SoDebugError::postWarning("SoBrepPointSet::renderSelection", "selectionIndex out of range"); } else { renderShape(static_cast(coords), cindices, numcindices); } state->pop(); } bool SoBrepPointSet::validIndexes(const SoCoordinateElement* coords, int32_t startIndex, const int32_t * cindices, int numcindices) const { for (int i=0; i= coords->getNum()) { return false; } } return true; } void SoBrepPointSet::doAction(SoAction* action) { if (action->getTypeId() == Gui::SoHighlightElementAction::getClassTypeId()) { Gui::SoHighlightElementAction* hlaction = static_cast(action); if (!hlaction->isHighlighted()) { this->highlightIndex = -1; return; } const SoDetail* detail = hlaction->getElement(); if (detail) { if (!detail->isOfType(SoPointDetail::getClassTypeId())) { this->highlightIndex = -1; return; } int index = static_cast(detail)->getCoordinateIndex(); this->highlightIndex.setValue(index); this->highlightColor = hlaction->getColor(); } } else if (action->getTypeId() == Gui::SoSelectionElementAction::getClassTypeId()) { Gui::SoSelectionElementAction* selaction = static_cast(action); this->selectionColor = selaction->getColor(); if (selaction->getType() == Gui::SoSelectionElementAction::All) { const SoCoordinateElement* coords = SoCoordinateElement::getInstance(action->getState()); int num = coords->getNum() - this->startIndex.getValue(); this->selectionIndex.setNum(num); int32_t* v = this->selectionIndex.startEditing(); int32_t s = this->startIndex.getValue(); for (int i=0; iselectionIndex.finishEditing(); return; } else if (selaction->getType() == Gui::SoSelectionElementAction::None) { this->selectionIndex.setNum(0); return; } const SoDetail* detail = selaction->getElement(); if (detail) { if (!detail->isOfType(SoPointDetail::getClassTypeId())) { return; } int index = static_cast(detail)->getCoordinateIndex(); switch (selaction->getType()) { case Gui::SoSelectionElementAction::Append: { if (this->selectionIndex.find(index) < 0) { int start = this->selectionIndex.getNum(); this->selectionIndex.set1Value(start, index); } } break; case Gui::SoSelectionElementAction::Remove: { int start = this->selectionIndex.find(index); if (start >= 0) this->selectionIndex.deleteValues(start,1); } break; default: break; } } } inherited::doAction(action); }