FreeCAD

Форк
0
/
SoBrepPointSet.cpp 
352 строки · 12.8 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2011 Werner Mayer <wmayer[at]users.sourceforge.net>     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
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.      *
10
 *                                                                         *
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.                  *
15
 *                                                                         *
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                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24

25
#ifndef _PreComp_
26
# ifdef FC_OS_WIN32
27
#  include <windows.h>
28
# endif
29
# ifdef FC_OS_MACOSX
30
#  include <OpenGL/gl.h>
31
# else
32
#  include <GL/gl.h>
33
# endif
34
# include <algorithm>
35
# include <cfloat>
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>
44
#endif
45

46
#include <Gui/SoFCUnifiedSelection.h>
47

48
#include "SoBrepPointSet.h"
49

50

51
using namespace PartGui;
52

53
SO_NODE_SOURCE(SoBrepPointSet)
54

55
void SoBrepPointSet::initClass()
56
{
57
    SO_NODE_INIT_CLASS(SoBrepPointSet, SoPointSet, "PointSet");
58
}
59

60
SoBrepPointSet::SoBrepPointSet()
61
    : selContext(std::make_shared<SelContext>())
62
    , selContext2(std::make_shared<SelContext>())
63
{
64
    SO_NODE_CONSTRUCTOR(SoBrepPointSet);
65
}
66

67
void SoBrepPointSet::GLRender(SoGLRenderAction *action)
68
{
69
    auto state = action->getState();
70
    selCounter.checkRenderCache(state);
71

72
    const SoCoordinateElement* coords = SoCoordinateElement::getInstance(state);
73
    int num = coords->getNum() - this->startIndex.getValue();
74
    if (num < 0) {
75
        // Fixes: #0000545: Undo revolve causes crash 'illegal storage'
76
        return;
77
    }
78
    SelContextPtr ctx2;
79
    SelContextPtr ctx = Gui::SoFCSelectionRoot::getRenderContext<SelContext>(this,selContext,ctx2);
80
    if(ctx2 && ctx2->selectionIndex.empty())
81
        return;
82
    if(selContext2->checkGlobal(ctx))
83
        ctx = selContext2;
84

85
    if(ctx && ctx->highlightIndex==INT_MAX) {
86
        if(ctx->selectionIndex.empty() || ctx->isSelectAll()) {
87
            if(ctx2) {
88
                ctx2->selectionColor = ctx->highlightColor;
89
                renderSelection(action,ctx2);
90
            } else
91
                renderHighlight(action,ctx);
92
        }else{
93
            if(!action->isRenderingDelayedPaths())
94
                renderSelection(action,ctx);
95
            if(ctx2) {
96
                ctx2->selectionColor = ctx->highlightColor;
97
                renderSelection(action,ctx2);
98
            } else
99
                renderHighlight(action,ctx);
100
            if(action->isRenderingDelayedPaths())
101
                renderSelection(action,ctx);
102
        }
103
        return;
104
    }
105

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);
113
            }else
114
                renderSelection(action,ctx);
115
            if(action->isRenderingDelayedPaths())
116
                renderHighlight(action,ctx);
117
            return;
118
        }
119
        if(!action->isRenderingDelayedPaths())
120
            renderSelection(action,ctx);
121
    }
122
    if(ctx2 && !ctx2->selectionIndex.empty())
123
        renderSelection(action,ctx2,false);
124
    else
125
        inherited::GLRender(action);
126

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);
135
//#endif
136
}
137

138
void SoBrepPointSet::GLRenderBelowPath(SoGLRenderAction * action)
139
{
140
    inherited::GLRenderBelowPath(action);
141
}
142

143
void SoBrepPointSet::getBoundingBox(SoGetBoundingBoxAction * action) {
144

145
    SelContextPtr ctx2 = Gui::SoFCSelectionRoot::getSecondaryActionContext<SelContext>(action,this);
146
    if(!ctx2 || ctx2->isSelectAll()) {
147
        inherited::getBoundingBox(action);
148
        return;
149
    }
150

151
    if(ctx2->selectionIndex.empty())
152
        return;
153

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();
159

160
    SbBox3f bbox;
161
    for(auto idx : ctx2->selectionIndex) {
162
        if(idx >= startIndex && idx < numverts)
163
            bbox.extendBy(coords3d[idx]);
164
    }
165

166
    if(!bbox.isEmpty())
167
        action->extendBy(bbox);
168
}
169

170
void SoBrepPointSet::renderHighlight(SoGLRenderAction *action, SelContextPtr ctx)
171
{
172
    if(!ctx || ctx->highlightIndex<0)
173
        return;
174

175
    SoState * state = action->getState();
176
    state->push();
177
    float ps = SoPointSizeElement::get(state);
178
    if (ps < 4.0f) SoPointSizeElement::set(state, this, 4.0f);
179

180
    SoLazyElement::setEmissive(state, &ctx->highlightColor);
181
    packedColor = ctx->highlightColor.getPackedValue(0.0);
182
    SoLazyElement::setPacked(state, this,1, &packedColor,false);
183

184
    const SoCoordinateElement * coords;
185
    const SbVec3f * normals;
186

187
    this->getVertexData(state, coords, normals, false);
188

189
    SoMaterialBundle mb(action);
190
    mb.sendFirst(); // make sure we have the correct material
191

192
    int id = ctx->highlightIndex;
193
    const SbVec3f * coords3d = coords->getArrayPtr3();
194
    if(coords3d) {
195
        if(id == INT_MAX) {
196
            glBegin(GL_POINTS);
197
            for(int idx=startIndex.getValue();idx<coords->getNum();++idx)
198
                glVertex3fv((const GLfloat*) (coords3d + idx));
199
            glEnd();
200
        }else if (id < this->startIndex.getValue() || id >= coords->getNum()) {
201
            SoDebugError::postWarning("SoBrepPointSet::renderHighlight", "highlightIndex out of range");
202
        }
203
        else {
204
            glBegin(GL_POINTS);
205
            glVertex3fv((const GLfloat*) (coords3d + id));
206
            glEnd();
207
        }
208
    }
209
    state->pop();
210
}
211

212
void SoBrepPointSet::renderSelection(SoGLRenderAction *action, SelContextPtr ctx, bool push)
213
{
214
    SoState * state = action->getState();
215
    if(push) {
216
        state->push();
217
        float ps = SoPointSizeElement::get(state);
218
        if (ps < 4.0f) SoPointSizeElement::set(state, this, 4.0f);
219

220
        SoLazyElement::setEmissive(state, &ctx->selectionColor);
221
        packedColor = ctx->selectionColor.getPackedValue(0.0);
222
        SoLazyElement::setPacked(state, this,1, &packedColor,false);
223
    }
224

225
    const SoCoordinateElement * coords;
226
    const SbVec3f * normals;
227

228
    this->getVertexData(state, coords, normals, false);
229

230
    SoMaterialBundle mb(action);
231
    mb.sendFirst(); // make sure we have the correct material
232

233
    bool warn = false;
234
    int startIndex = this->startIndex.getValue();
235
    const SbVec3f * coords3d = coords->getArrayPtr3();
236
    if(coords3d) {
237
        glBegin(GL_POINTS);
238
        if(ctx->isSelectAll()) {
239
            for(int idx=startIndex;idx<coords->getNum();++idx)
240
                glVertex3fv((const GLfloat*) (coords3d + idx));
241
        }else{
242
            for(auto idx : ctx->selectionIndex) {
243
                if(idx >= startIndex && idx < coords->getNum())
244
                    glVertex3fv((const GLfloat*) (coords3d + idx));
245
                else
246
                    warn = true;
247
            }
248
        }
249
        glEnd();
250
    }
251
    if(warn)
252
        SoDebugError::postWarning("SoBrepPointSet::renderSelection", "selectionIndex out of range");
253
    if(push) state->pop();
254
}
255

256
void SoBrepPointSet::doAction(SoAction* action)
257
{
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);
263
            if(ctx) {
264
                ctx->highlightIndex = -1;
265
                touch();
266
            }
267
            return;
268
        }
269
        SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext);
270
        const SoDetail* detail = hlaction->getElement();
271
        if (!detail) {
272
            ctx->highlightIndex = INT_MAX;
273
            ctx->highlightColor = hlaction->getColor();
274
            touch();
275
            return;
276
        }else if (!detail->isOfType(SoPointDetail::getClassTypeId())) {
277
            ctx->highlightIndex = -1;
278
            touch();
279
            return;
280
        }
281

282
        int index = static_cast<const SoPointDetail*>(detail)->getCoordinateIndex();
283
        if(index!=ctx->highlightIndex) {
284
            ctx->highlightIndex = index;
285
            ctx->highlightColor = hlaction->getColor();
286
            touch();
287
        }
288
        return;
289
    }
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);
299
            touch();
300
            return;
301
        } case Gui::SoSelectionElementAction::None:
302
            if(selaction->isSecondary()) {
303
                if(Gui::SoFCSelectionRoot::removeActionContext(action,this))
304
                    touch();
305
            } else {
306
                SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext,false);
307
                if(ctx) {
308
                    ctx->selectionIndex.clear();
309
                    touch();
310
                }
311
            }
312
            return;
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
323
                    // here.
324
                    auto ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext);
325
                    selCounter.checkAction(selaction,ctx);
326
                    touch();
327
                }
328
                return;
329
            }
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)
338
                    touch();
339
            } else {
340
                SelContextPtr ctx = Gui::SoFCSelectionRoot::getActionContext(action,this,selContext,false);
341
                if(ctx && ctx->removeIndex(index))
342
                    touch();
343
            }
344
            break;
345
        } default:
346
            break;
347
        }
348
        return;
349
    }
350

351
    inherited::doAction(action);
352
}
353

354

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.