1
/***************************************************************************
2
* Copyright (c) 2011 Werner Mayer <wmayer[at]users.sourceforge.net> *
4
* This file is part of the FreeCAD CAx development system. *
6
* This library is free software; you can redistribute it and/or *
7
* modify it under the terms of the GNU Library General Public *
8
* License as published by the Free Software Foundation; either *
9
* version 2 of the License, or (at your option) any later version. *
11
* This library is distributed in the hope that it will be useful, *
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
* GNU Library General Public License for more details. *
16
* You should have received a copy of the GNU Library General Public *
17
* License along with this library; see the file COPYING.LIB. If not, *
18
* write to the Free Software Foundation, Inc., 59 Temple Place, *
19
* Suite 330, Boston, MA 02111-1307, USA *
21
***************************************************************************/
23
#include "PreCompiled.h"
30
# include <OpenGL/gl.h>
36
# include <Inventor/actions/SoGetBoundingBoxAction.h>
37
# include <Inventor/actions/SoGLRenderAction.h>
38
# include <Inventor/bundles/SoMaterialBundle.h>
39
# include <Inventor/details/SoPointDetail.h>
40
# include <Inventor/elements/SoCoordinateElement.h>
41
# include <Inventor/elements/SoPointSizeElement.h>
42
# include <Inventor/errors/SoDebugError.h>
43
# include <Inventor/misc/SoState.h>
46
#include <Gui/SoFCUnifiedSelection.h>
48
#include "SoBrepPointSet.h"
51
using namespace PartGui;
53
SO_NODE_SOURCE(SoBrepPointSet)
55
void SoBrepPointSet::initClass()
57
SO_NODE_INIT_CLASS(SoBrepPointSet, SoPointSet, "PointSet");
60
SoBrepPointSet::SoBrepPointSet()
61
: selContext(std::make_shared<SelContext>())
62
, selContext2(std::make_shared<SelContext>())
64
SO_NODE_CONSTRUCTOR(SoBrepPointSet);
67
void SoBrepPointSet::GLRender(SoGLRenderAction *action)
69
auto state = action->getState();
70
selCounter.checkRenderCache(state);
72
const SoCoordinateElement* coords = SoCoordinateElement::getInstance(state);
73
int num = coords->getNum() - this->startIndex.getValue();
75
// Fixes: #0000545: Undo revolve causes crash 'illegal storage'
79
SelContextPtr ctx = Gui::SoFCSelectionRoot::getRenderContext<SelContext>(this,selContext,ctx2);
80
if(ctx2 && ctx2->selectionIndex.empty())
82
if(selContext2->checkGlobal(ctx))
85
if(ctx && ctx->highlightIndex==INT_MAX) {
86
if(ctx->selectionIndex.empty() || ctx->isSelectAll()) {
88
ctx2->selectionColor = ctx->highlightColor;
89
renderSelection(action,ctx2);
91
renderHighlight(action,ctx);
93
if(!action->isRenderingDelayedPaths())
94
renderSelection(action,ctx);
96
ctx2->selectionColor = ctx->highlightColor;
97
renderSelection(action,ctx2);
99
renderHighlight(action,ctx);
100
if(action->isRenderingDelayedPaths())
101
renderSelection(action,ctx);
106
if(!action->isRenderingDelayedPaths())
107
renderHighlight(action,ctx);
108
if(ctx && !ctx->selectionIndex.empty()) {
109
if(ctx->isSelectAll()) {
110
if(ctx2 && !ctx2->selectionIndex.empty()) {
111
ctx2->selectionColor = ctx->selectionColor;
112
renderSelection(action,ctx2);
114
renderSelection(action,ctx);
115
if(action->isRenderingDelayedPaths())
116
renderHighlight(action,ctx);
119
if(!action->isRenderingDelayedPaths())
120
renderSelection(action,ctx);
122
if(ctx2 && !ctx2->selectionIndex.empty())
123
renderSelection(action,ctx2,false);
125
inherited::GLRender(action);
127
// Workaround for #0000433
128
//#if !defined(FC_OS_WIN32)
129
if(!action->isRenderingDelayedPaths())
130
renderHighlight(action,ctx);
131
if(ctx && !ctx->selectionIndex.empty())
132
renderSelection(action,ctx);
133
if(action->isRenderingDelayedPaths())
134
renderHighlight(action,ctx);
138
void SoBrepPointSet::GLRenderBelowPath(SoGLRenderAction * action)
140
inherited::GLRenderBelowPath(action);
143
void SoBrepPointSet::getBoundingBox(SoGetBoundingBoxAction * action) {
145
SelContextPtr ctx2 = Gui::SoFCSelectionRoot::getSecondaryActionContext<SelContext>(action,this);
146
if(!ctx2 || ctx2->isSelectAll()) {
147
inherited::getBoundingBox(action);
151
if(ctx2->selectionIndex.empty())
154
auto state = action->getState();
155
auto coords = SoCoordinateElement::getInstance(state);
156
const SbVec3f *coords3d = coords->getArrayPtr3();
157
int numverts = coords->getNum();
158
int startIndex = this->startIndex.getValue();
161
for(auto idx : ctx2->selectionIndex) {
162
if(idx >= startIndex && idx < numverts)
163
bbox.extendBy(coords3d[idx]);
167
action->extendBy(bbox);
170
void SoBrepPointSet::renderHighlight(SoGLRenderAction *action, SelContextPtr ctx)
172
if(!ctx || ctx->highlightIndex<0)
175
SoState * state = action->getState();
177
float ps = SoPointSizeElement::get(state);
178
if (ps < 4.0f) SoPointSizeElement::set(state, this, 4.0f);
180
SoLazyElement::setEmissive(state, &ctx->highlightColor);
181
packedColor = ctx->highlightColor.getPackedValue(0.0);
182
SoLazyElement::setPacked(state, this,1, &packedColor,false);
184
const SoCoordinateElement * coords;
185
const SbVec3f * normals;
187
this->getVertexData(state, coords, normals, false);
189
SoMaterialBundle mb(action);
190
mb.sendFirst(); // make sure we have the correct material
192
int id = ctx->highlightIndex;
193
const SbVec3f * coords3d = coords->getArrayPtr3();
197
for(int idx=startIndex.getValue();idx<coords->getNum();++idx)
198
glVertex3fv((const GLfloat*) (coords3d + idx));
200
}else if (id < this->startIndex.getValue() || id >= coords->getNum()) {
201
SoDebugError::postWarning("SoBrepPointSet::renderHighlight", "highlightIndex out of range");
205
glVertex3fv((const GLfloat*) (coords3d + id));
212
void SoBrepPointSet::renderSelection(SoGLRenderAction *action, SelContextPtr ctx, bool push)
214
SoState * state = action->getState();
217
float ps = SoPointSizeElement::get(state);
218
if (ps < 4.0f) SoPointSizeElement::set(state, this, 4.0f);
220
SoLazyElement::setEmissive(state, &ctx->selectionColor);
221
packedColor = ctx->selectionColor.getPackedValue(0.0);
222
SoLazyElement::setPacked(state, this,1, &packedColor,false);
225
const SoCoordinateElement * coords;
226
const SbVec3f * normals;
228
this->getVertexData(state, coords, normals, false);
230
SoMaterialBundle mb(action);
231
mb.sendFirst(); // make sure we have the correct material
234
int startIndex = this->startIndex.getValue();
235
const SbVec3f * coords3d = coords->getArrayPtr3();
238
if(ctx->isSelectAll()) {
239
for(int idx=startIndex;idx<coords->getNum();++idx)
240
glVertex3fv((const GLfloat*) (coords3d + idx));
242
for(auto idx : ctx->selectionIndex) {
243
if(idx >= startIndex && idx < coords->getNum())
244
glVertex3fv((const GLfloat*) (coords3d + idx));
252
SoDebugError::postWarning("SoBrepPointSet::renderSelection", "selectionIndex out of range");
253
if(push) state->pop();
256
void SoBrepPointSet::doAction(SoAction* action)
258
if (action->getTypeId() == Gui::SoHighlightElementAction::getClassTypeId()) {
259
Gui::SoHighlightElementAction* hlaction = static_cast<Gui::SoHighlightElementAction*>(action);
260
selCounter.checkAction(hlaction);
261
if (!hlaction->isHighlighted()) {
262
SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext,false);
264
ctx->highlightIndex = -1;
269
SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext);
270
const SoDetail* detail = hlaction->getElement();
272
ctx->highlightIndex = INT_MAX;
273
ctx->highlightColor = hlaction->getColor();
276
}else if (!detail->isOfType(SoPointDetail::getClassTypeId())) {
277
ctx->highlightIndex = -1;
282
int index = static_cast<const SoPointDetail*>(detail)->getCoordinateIndex();
283
if(index!=ctx->highlightIndex) {
284
ctx->highlightIndex = index;
285
ctx->highlightColor = hlaction->getColor();
290
else if (action->getTypeId() == Gui::SoSelectionElementAction::getClassTypeId()) {
291
Gui::SoSelectionElementAction* selaction = static_cast<Gui::SoSelectionElementAction*>(action);
292
switch(selaction->getType()) {
293
case Gui::SoSelectionElementAction::All: {
294
SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext);
295
selCounter.checkAction(selaction,ctx);
296
ctx->selectionColor = selaction->getColor();
297
ctx->selectionIndex.clear();
298
ctx->selectionIndex.insert(-1);
301
} case Gui::SoSelectionElementAction::None:
302
if(selaction->isSecondary()) {
303
if(Gui::SoFCSelectionRoot::removeActionContext(action,this))
306
SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext,false);
308
ctx->selectionIndex.clear();
313
case Gui::SoSelectionElementAction::Remove:
314
case Gui::SoSelectionElementAction::Append: {
315
const SoDetail* detail = selaction->getElement();
316
if (!detail || !detail->isOfType(SoPointDetail::getClassTypeId())) {
317
if(selaction->isSecondary()) {
318
// For secondary context, a detail of different type means
319
// the user may want to partial render only other type of
320
// geometry. So we call below to obtain a action context.
321
// If no secondary context exist, it will create an empty
322
// one, and an empty secondary context inhibites drawing
324
auto ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext);
325
selCounter.checkAction(selaction,ctx);
330
int index = static_cast<const SoPointDetail*>(detail)->getCoordinateIndex();
331
if(selaction->getType() == Gui::SoSelectionElementAction::Append) {
332
SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext);
333
selCounter.checkAction(selaction,ctx);
334
ctx->selectionColor = selaction->getColor();
335
if(ctx->isSelectAll())
336
ctx->selectionIndex.clear();
337
if(ctx->selectionIndex.insert(index).second)
340
SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext,false);
341
if(ctx && ctx->removeIndex(index))
351
inherited::doAction(action);