FreeCAD

Форк
0
/
SplitView3DInventor.cpp 
647 строк · 20.0 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2006 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
# include <QSplitter>
27
# include <Inventor/nodes/SoDirectionalLight.h>
28
# include <Inventor/nodes/SoOrthographicCamera.h>
29
# include <Inventor/nodes/SoPerspectiveCamera.h>
30
#endif
31

32
#include <Base/Builder3D.h>
33
#include <Base/Interpreter.h>
34

35
#include "SplitView3DInventor.h"
36
#include "Application.h"
37
#include "Camera.h"
38
#include "Document.h"
39
#include "NavigationStyle.h"
40
#include "SoFCSelectionAction.h"
41
#include "View3DInventorViewer.h"
42
#include "View3DPy.h"
43
#include "View3DSettings.h"
44

45

46
using namespace Gui;
47

48
TYPESYSTEM_SOURCE_ABSTRACT(Gui::AbstractSplitView,Gui::MDIView)
49

50
AbstractSplitView::AbstractSplitView(Gui::Document* pcDocument, QWidget* parent, Qt::WindowFlags wflags)
51
  : MDIView(pcDocument,parent, wflags)
52
{
53
    _viewerPy = nullptr;
54
    // important for highlighting
55
    setMouseTracking(true);
56
}
57

58
AbstractSplitView::~AbstractSplitView()
59
{
60
    for (std::vector<View3DInventorViewer*>::iterator it = _viewer.begin(); it != _viewer.end(); ++it) {
61
        delete *it;
62
    }
63
    if (_viewerPy) {
64
        Base::PyGILStateLocker lock;
65
        Py_DECREF(_viewerPy);
66
    }
67
}
68

69
void AbstractSplitView::deleteSelf()
70
{
71
    for (std::vector<View3DInventorViewer*>::iterator it = _viewer.begin(); it != _viewer.end(); ++it) {
72
        (*it)->setSceneGraph(nullptr);
73
    }
74
    MDIView::deleteSelf();
75
}
76

77
void AbstractSplitView::setDocumentOfViewers(Gui::Document* document)
78
{
79
    for (auto view : _viewer) {
80
        view->setDocument(document);
81
    }
82
}
83

84
void AbstractSplitView::viewAll()
85
{
86
    for (std::vector<View3DInventorViewer*>::iterator it = _viewer.begin(); it != _viewer.end(); ++it)
87
        (*it)->viewAll();
88
}
89

90
bool AbstractSplitView::containsViewProvider(const ViewProvider* vp) const
91
{
92
    for (auto it = _viewer.begin(); it != _viewer.end(); ++it) {
93
        if ((*it)->containsViewProvider(vp))
94
            return true;
95
    }
96

97
    return false;
98
}
99

100
void AbstractSplitView::setupSettings()
101
{
102
    viewSettings = std::make_unique<View3DSettings>(App::GetApplication().GetParameterGroupByPath
103
                                   ("User parameter:BaseApp/Preferences/View"), _viewer);
104
    // tmp. disabled will be activated after redesign of 3d viewer
105
    // check whether the simple or the Full Mouse model is used
106
    viewSettings->ignoreNavigationStyle = true;
107
    // Disable VBO for split screen as this leads to random crashes
108
    viewSettings->ignoreVBO = true;
109
    viewSettings->ignoreTransparent = true;
110
    viewSettings->ignoreRenderCache = true;
111
    viewSettings->ignoreDimensions = true;
112
    viewSettings->applySettings();
113

114
    for (auto view : _viewer) {
115
        NaviCubeSettings naviSettings(App::GetApplication().GetParameterGroupByPath
116
                                     ("User parameter:BaseApp/Preferences/NaviCube"), view);
117
        naviSettings.applySettings();
118
    }
119
}
120

121
View3DInventorViewer* AbstractSplitView::getViewer(unsigned int n) const
122
{
123
    return (_viewer.size() > n ? _viewer[n] : nullptr);
124
}
125

126
void AbstractSplitView::onUpdate()
127
{
128
    update();
129
}
130

131
const char *AbstractSplitView::getName() const
132
{
133
    return "SplitView3DInventor";
134
}
135

136
bool AbstractSplitView::onMsg(const char* pMsg, const char**)
137
{
138
    if (strcmp("ViewFit",pMsg) == 0 ) {
139
        viewAll();
140
        return true;
141
    }
142
    else if (strcmp("ViewBottom",pMsg) == 0) {
143
        SbRotation rot(Camera::rotation(Camera::Bottom));
144
        for (std::vector<View3DInventorViewer*>::iterator it = _viewer.begin(); it != _viewer.end(); ++it) {
145
            SoCamera* cam = (*it)->getSoRenderManager()->getCamera();
146
            cam->orientation.setValue(rot);
147
            (*it)->viewAll();
148
        }
149
        return true;
150
    }
151
    else if (strcmp("ViewFront",pMsg) == 0) {
152
        SbRotation rot(Camera::rotation(Camera::Front));
153
        for (std::vector<View3DInventorViewer*>::iterator it = _viewer.begin(); it != _viewer.end(); ++it) {
154
            SoCamera* cam = (*it)->getSoRenderManager()->getCamera();
155
            cam->orientation.setValue(rot);
156
            (*it)->viewAll();
157
        }
158
        return true;
159
    }
160
    else if (strcmp("ViewLeft",pMsg) == 0) {
161
        SbRotation rot(Camera::rotation(Camera::Left));
162
        for (std::vector<View3DInventorViewer*>::iterator it = _viewer.begin(); it != _viewer.end(); ++it) {
163
            SoCamera* cam = (*it)->getSoRenderManager()->getCamera();
164
            cam->orientation.setValue(rot);
165
            (*it)->viewAll();
166
        }
167
        return true;
168
    }
169
    else if (strcmp("ViewRear",pMsg) == 0) {
170
        SbRotation rot(Camera::rotation(Camera::Rear));
171
        for (std::vector<View3DInventorViewer*>::iterator it = _viewer.begin(); it != _viewer.end(); ++it) {
172
            SoCamera* cam = (*it)->getSoRenderManager()->getCamera();
173
            cam->orientation.setValue(rot);
174
            (*it)->viewAll();
175
        }
176
        return true;
177
    }
178
    else if (strcmp("ViewRight",pMsg) == 0) {
179
        SbRotation rot(Camera::rotation(Camera::Right));
180
        for (std::vector<View3DInventorViewer*>::iterator it = _viewer.begin(); it != _viewer.end(); ++it) {
181
            SoCamera* cam = (*it)->getSoRenderManager()->getCamera();
182
            cam->orientation.setValue(rot);
183
            (*it)->viewAll();
184
        }
185
        return true;
186
    }
187
    else if (strcmp("ViewTop",pMsg) == 0) {
188
        SbRotation rot(Camera::rotation(Camera::Top));
189
        for (std::vector<View3DInventorViewer*>::iterator it = _viewer.begin(); it != _viewer.end(); ++it) {
190
            SoCamera* cam = (*it)->getSoRenderManager()->getCamera();
191
            cam->orientation.setValue(rot);
192
            (*it)->viewAll();
193
        }
194
        return true;
195
    }
196
    else if (strcmp("ViewAxo",pMsg) == 0) {
197
        SbRotation rot(Camera::rotation(Camera::Isometric));
198
        for (std::vector<View3DInventorViewer*>::iterator it = _viewer.begin(); it != _viewer.end(); ++it) {
199
            SoCamera* cam = (*it)->getSoRenderManager()->getCamera();
200
            cam->orientation.setValue(rot);
201
            (*it)->viewAll();
202
        }
203
        return true;
204
    }
205

206
    return false;
207
}
208

209
bool AbstractSplitView::onHasMsg(const char* pMsg) const
210
{
211
    if (strcmp("CanPan",pMsg) == 0) {
212
        return true;
213
    }
214
    else if (strcmp("ViewFit",pMsg) == 0) {
215
        return true;
216
    }
217
    else if (strcmp("ViewBottom",pMsg) == 0) {
218
        return true;
219
    }
220
    else if (strcmp("ViewFront",pMsg) == 0) {
221
        return true;
222
    }
223
    else if (strcmp("ViewLeft",pMsg) == 0) {
224
        return true;
225
    }
226
    else if (strcmp("ViewRear",pMsg) == 0) {
227
        return true;
228
    }
229
    else if (strcmp("ViewRight",pMsg) == 0) {
230
        return true;
231
    }
232
    else if (strcmp("ViewTop",pMsg) == 0) {
233
        return true;
234
    }
235
    else if (strcmp("ViewAxo",pMsg) == 0) {
236
        return true;
237
    }
238
    return false;
239
}
240

241
void AbstractSplitView::setOverrideCursor(const QCursor& aCursor)
242
{
243
    Q_UNUSED(aCursor);
244
    //_viewer->getWidget()->setCursor(aCursor);
245
}
246

247
PyObject *AbstractSplitView::getPyObject()
248
{
249
    if (!_viewerPy)
250
        _viewerPy = new AbstractSplitViewPy(this);
251
    Py_INCREF(_viewerPy);
252
    return _viewerPy;
253
}
254

255
void AbstractSplitView::setPyObject(PyObject *)
256
{
257
    throw Base::AttributeError("Attribute is read-only");
258
}
259

260
int AbstractSplitView::getSize()
261
{
262
    return static_cast<int>(_viewer.size());
263
}
264

265
// ------------------------------------------------------
266

267
void AbstractSplitViewPy::init_type()
268
{
269
    behaviors().name("AbstractSplitViewPy");
270
    behaviors().doc("Python binding class for the Inventor viewer class");
271
    // you must have overwritten the virtual functions
272
    behaviors().supportRepr();
273
    behaviors().supportGetattr();
274
    behaviors().supportSetattr();
275
    behaviors().supportSequenceType();
276

277
    add_varargs_method("fitAll",&AbstractSplitViewPy::fitAll,"fitAll()");
278
    add_varargs_method("viewBottom",&AbstractSplitViewPy::viewBottom,"viewBottom()");
279
    add_varargs_method("viewFront",&AbstractSplitViewPy::viewFront,"viewFront()");
280
    add_varargs_method("viewLeft",&AbstractSplitViewPy::viewLeft,"viewLeft()");
281
    add_varargs_method("viewRear",&AbstractSplitViewPy::viewRear,"viewRear()");
282
    add_varargs_method("viewRight",&AbstractSplitViewPy::viewRight,"viewRight()");
283
    add_varargs_method("viewTop",&AbstractSplitViewPy::viewTop,"viewTop()");
284
    add_varargs_method("viewAxometric",&AbstractSplitViewPy::viewIsometric,"viewAxometric()");
285
    add_varargs_method("viewIsometric",&AbstractSplitViewPy::viewIsometric,"viewIsometric()");
286
    add_varargs_method("getViewer",&AbstractSplitViewPy::getViewer,"getViewer(index)");
287
    add_varargs_method("close",&AbstractSplitViewPy::close,"close()");
288
    add_varargs_method("cast_to_base", &AbstractSplitViewPy::cast_to_base, "cast_to_base() cast to MDIView class");
289
    behaviors().readyType();
290
}
291

292
AbstractSplitViewPy::AbstractSplitViewPy(AbstractSplitView *vi)
293
  : base(vi)
294
{
295
}
296

297
AbstractSplitViewPy::~AbstractSplitViewPy() = default;
298

299
Py::Object AbstractSplitViewPy::cast_to_base(const Py::Tuple&)
300
{
301
    return Gui::MDIViewPy::create(base.getMDIViewPtr());
302
}
303

304
Py::Object AbstractSplitViewPy::repr()
305
{
306
    std::ostringstream s_out;
307
    if (!getSplitViewPtr())
308
        throw Py::RuntimeError("Cannot print representation of deleted object");
309
    s_out << "AbstractSplitView";
310
    return Py::String(s_out.str());
311
}
312

313
// Since with PyCXX it's not possible to make a sub-class of MDIViewPy
314
// a trick is to use MDIViewPy as class member and override getattr() to
315
// join the attributes of both classes. This way all methods of MDIViewPy
316
// appear for SheetViewPy, too.
317
Py::Object AbstractSplitViewPy::getattr(const char * attr)
318
{
319
    getSplitViewPtr();
320
    std::string name( attr );
321
    if (name == "__dict__" || name == "__class__") {
322
        Py::Dict dict_self(BaseType::getattr("__dict__"));
323
        Py::Dict dict_base(base.getattr("__dict__"));
324
        for (const auto& it : dict_base) {
325
            dict_self.setItem(it.first, it.second);
326
        }
327
        return dict_self;
328
    }
329

330
    try {
331
        return BaseType::getattr(attr);
332
    }
333
    catch (Py::AttributeError& e) {
334
        e.clear();
335
        return base.getattr(attr);
336
    }
337
}
338

339
AbstractSplitView* AbstractSplitViewPy::getSplitViewPtr()
340
{
341
    auto view = qobject_cast<AbstractSplitView*>(base.getMDIViewPtr());
342
    if (!(view && view->getViewer(0)))
343
        throw Py::RuntimeError("Object already deleted");
344
    return view;
345
}
346

347
Py::Object AbstractSplitViewPy::fitAll(const Py::Tuple& args)
348
{
349
    if (!PyArg_ParseTuple(args.ptr(), ""))
350
        throw Py::Exception();
351

352
    try {
353
        getSplitViewPtr()->onMsg("ViewFit", nullptr);
354
    }
355
    catch (const Base::Exception& e) {
356
        throw Py::RuntimeError(e.what());
357
    }
358
    catch (const std::exception& e) {
359
        throw Py::RuntimeError(e.what());
360
    }
361
    catch(...) {
362
        throw Py::RuntimeError("Unknown C++ exception");
363
    }
364
    return Py::None();
365
}
366

367
Py::Object AbstractSplitViewPy::viewBottom(const Py::Tuple& args)
368
{
369
    if (!PyArg_ParseTuple(args.ptr(), ""))
370
        throw Py::Exception();
371

372
    try {
373
        getSplitViewPtr()->onMsg("ViewBottom", nullptr);
374
    }
375
    catch (const Base::Exception& e) {
376
        throw Py::RuntimeError(e.what());
377
    }
378
    catch (const std::exception& e) {
379
        throw Py::RuntimeError(e.what());
380
    }
381
    catch(...) {
382
        throw Py::RuntimeError("Unknown C++ exception");
383
    }
384

385
    return Py::None();
386
}
387

388
Py::Object AbstractSplitViewPy::viewFront(const Py::Tuple& args)
389
{
390
    if (!PyArg_ParseTuple(args.ptr(), ""))
391
        throw Py::Exception();
392

393
    try {
394
        getSplitViewPtr()->onMsg("ViewFront", nullptr);
395
    }
396
    catch (const Base::Exception& e) {
397
        throw Py::RuntimeError(e.what());
398
    }
399
    catch (const std::exception& e) {
400
        throw Py::RuntimeError(e.what());
401
    }
402
    catch(...) {
403
        throw Py::RuntimeError("Unknown C++ exception");
404
    }
405

406
    return Py::None();
407
}
408

409
Py::Object AbstractSplitViewPy::viewLeft(const Py::Tuple& args)
410
{
411
    if (!PyArg_ParseTuple(args.ptr(), ""))
412
        throw Py::Exception();
413

414
    try {
415
        getSplitViewPtr()->onMsg("ViewLeft", nullptr);
416
    }
417
    catch (const Base::Exception& e) {
418
        throw Py::RuntimeError(e.what());
419
    }
420
    catch (const std::exception& e) {
421
        throw Py::RuntimeError(e.what());
422
    }
423
    catch(...) {
424
        throw Py::RuntimeError("Unknown C++ exception");
425
    }
426

427
    return Py::None();
428
}
429

430
Py::Object AbstractSplitViewPy::viewRear(const Py::Tuple& args)
431
{
432
    if (!PyArg_ParseTuple(args.ptr(), ""))
433
        throw Py::Exception();
434

435
    try {
436
        getSplitViewPtr()->onMsg("ViewRear", nullptr);
437
    }
438
    catch (const Base::Exception& e) {
439
        throw Py::RuntimeError(e.what());
440
    }
441
    catch (const std::exception& e) {
442
        throw Py::RuntimeError(e.what());
443
    }
444
    catch(...) {
445
        throw Py::RuntimeError("Unknown C++ exception");
446
    }
447

448
    return Py::None();
449
}
450

451
Py::Object AbstractSplitViewPy::viewRight(const Py::Tuple& args)
452
{
453
    if (!PyArg_ParseTuple(args.ptr(), ""))
454
        throw Py::Exception();
455

456
    try {
457
        getSplitViewPtr()->onMsg("ViewRight", nullptr);
458
    }
459
    catch (const Base::Exception& e) {
460
        throw Py::RuntimeError(e.what());
461
    }
462
    catch (const std::exception& e) {
463
        throw Py::RuntimeError(e.what());
464
    }
465
    catch(...) {
466
        throw Py::RuntimeError("Unknown C++ exception");
467
    }
468

469
    return Py::None();
470
}
471

472
Py::Object AbstractSplitViewPy::viewTop(const Py::Tuple& args)
473
{
474
    if (!PyArg_ParseTuple(args.ptr(), ""))
475
        throw Py::Exception();
476

477
    try {
478
        getSplitViewPtr()->onMsg("ViewTop", nullptr);
479
    }
480
    catch (const Base::Exception& e) {
481
        throw Py::RuntimeError(e.what());
482
    }
483
    catch (const std::exception& e) {
484
        throw Py::RuntimeError(e.what());
485
    }
486
    catch(...) {
487
        throw Py::RuntimeError("Unknown C++ exception");
488
    }
489

490
    return Py::None();
491
}
492

493
Py::Object AbstractSplitViewPy::viewIsometric(const Py::Tuple& args)
494
{
495
    if (!PyArg_ParseTuple(args.ptr(), ""))
496
        throw Py::Exception();
497

498
    try {
499
        getSplitViewPtr()->onMsg("ViewAxo", nullptr);
500
    }
501
    catch (const Base::Exception& e) {
502
        throw Py::RuntimeError(e.what());
503
    }
504
    catch (const std::exception& e) {
505
        throw Py::RuntimeError(e.what());
506
    }
507
    catch(...) {
508
        throw Py::RuntimeError("Unknown C++ exception");
509
    }
510

511
    return Py::None();
512
}
513

514
Py::Object AbstractSplitViewPy::getViewer(const Py::Tuple& args)
515
{
516
    int viewIndex;
517
    if (!PyArg_ParseTuple(args.ptr(), "i", &viewIndex))
518
        throw Py::Exception();
519

520
    try {
521
        Gui::View3DInventorViewer* view = getSplitViewPtr()->getViewer(viewIndex);
522
        if (!view)
523
            throw Py::IndexError("Index out of range");
524
        return Py::asObject(view->getPyObject());
525
    }
526
    catch (const Base::Exception& e) {
527
        throw Py::RuntimeError(e.what());
528
    }
529
    catch (const std::exception& e) {
530
        throw Py::RuntimeError(e.what());
531
    }
532
    catch (const Py::Exception&) {
533
        // re-throw
534
        throw;
535
    }
536
    catch(...) {
537
        throw Py::RuntimeError("Unknown C++ exception");
538
    }
539
}
540

541
Py::Object AbstractSplitViewPy::sequence_item(Py_ssize_t viewIndex)
542
{
543
    AbstractSplitView* view = getSplitViewPtr();
544
    if (viewIndex >= view->getSize() || viewIndex < 0)
545
        throw Py::IndexError("Index out of range");
546
    PyObject* viewer = view->getViewer(viewIndex)->getPyObject();
547
    return Py::asObject(viewer);
548
}
549

550
PyCxx_ssize_t AbstractSplitViewPy::sequence_length()
551
{
552
    AbstractSplitView* view = getSplitViewPtr();
553
    return view->getSize();
554
}
555

556
Py::Object AbstractSplitViewPy::close(const Py::Tuple& args)
557
{
558
    if (!PyArg_ParseTuple(args.ptr(), ""))
559
        throw Py::Exception();
560

561
    AbstractSplitView* view = getSplitViewPtr();
562
    view->close();
563
    if (view->parentWidget())
564
        view->parentWidget()->deleteLater();
565

566
    return Py::None();
567
}
568

569
// ------------------------------------------------------
570

571
TYPESYSTEM_SOURCE_ABSTRACT(Gui::SplitView3DInventor, Gui::AbstractSplitView)
572

573
SplitView3DInventor::SplitView3DInventor(int views, Gui::Document* pcDocument, QWidget* parent, Qt::WindowFlags wflags)
574
  : AbstractSplitView(pcDocument,parent, wflags)
575
{
576
    //anti-aliasing settings
577
    bool smoothing = false;
578
    bool glformat = false;
579
    int samples = View3DInventorViewer::getNumSamples();
580
    QtGLFormat f;
581

582
    if (samples > 1) {
583
        glformat = true;
584
        f.setSamples(samples);
585
    }
586
    else if (samples > 0) {
587
        smoothing = true;
588
    }
589

590
    // minimal 2 views
591
    while (views < 2)
592
        views ++;
593

594
    QSplitter* mainSplitter = nullptr;
595

596
    // if views < 3 show them as a row
597
    if (views <= 3) {
598
        mainSplitter = new QSplitter(Qt::Horizontal, this);
599
        for (int i=0; i < views; i++) {
600
            if (glformat)
601
                _viewer.push_back(new View3DInventorViewer(f, mainSplitter));
602
            else
603
                _viewer.push_back(new View3DInventorViewer(mainSplitter));
604
        }
605
    }
606
    else {
607
        mainSplitter = new QSplitter(Qt::Vertical, this);
608
        auto topSplitter = new QSplitter(Qt::Horizontal, mainSplitter);
609
        auto botSplitter = new QSplitter(Qt::Horizontal, mainSplitter);
610

611
        if (glformat) {
612
            _viewer.push_back(new View3DInventorViewer(f, topSplitter));
613
            _viewer.push_back(new View3DInventorViewer(f, topSplitter));
614
        }
615
        else {
616
            _viewer.push_back(new View3DInventorViewer(topSplitter));
617
            _viewer.push_back(new View3DInventorViewer(topSplitter));
618
        }
619

620
        for (int i=2;i<views;i++) {
621
            if (glformat)
622
                _viewer.push_back(new View3DInventorViewer(f, botSplitter));
623
            else
624
                _viewer.push_back(new View3DInventorViewer(botSplitter));
625
        }
626

627
        topSplitter->setOpaqueResize(true);
628
        botSplitter->setOpaqueResize(true);
629
    }
630

631
    if (smoothing) {
632
        for (std::vector<int>::size_type i = 0; i != _viewer.size(); i++)
633
            _viewer[i]->getSoRenderManager()->getGLRenderAction()->setSmoothing(true);
634
    }
635

636
    mainSplitter->show();
637
    setCentralWidget(mainSplitter);
638

639
    setDocumentOfViewers(pcDocument);
640

641
    // apply the user settings
642
    setupSettings();
643
}
644

645
SplitView3DInventor::~SplitView3DInventor() = default;
646

647
#include "moc_SplitView3DInventor.cpp"
648

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

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

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

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