24
#include "PreCompiled.h"
29
#include <Inventor/SoEventManager.h>
30
#include <Inventor/SoRenderManager.h>
31
#include <Inventor/SbViewportRegion.h>
32
#include <Inventor/actions/SoGLRenderAction.h>
33
#include <Inventor/actions/SoSearchAction.h>
34
#include <Inventor/events/SoLocation2Event.h>
35
#include <Inventor/events/SoMouseButtonEvent.h>
36
#include <Inventor/nodes/SoSeparator.h>
37
#include <Inventor/nodes/SoOrthographicCamera.h>
38
#include <Inventor/nodes/SoDirectionalLight.h>
39
#include <Inventor/scxml/ScXML.h>
40
#include <Inventor/scxml/SoScXMLStateMachine.h>
42
#include <QApplication>
44
#include <QColorDialog>
48
#include <QResizeEvent>
51
#include <QGraphicsView>
52
#include <QPaintEngine>
53
#include <QGraphicsItem>
54
#include <QGraphicsSceneMouseEvent>
55
#include <QGraphicsProxyWidget>
58
#include "GLGraphicsView.h"
59
#include <App/Application.h>
60
#include <Gui/Document.h>
61
#include <Gui/ViewProvider.h>
63
#include <Quarter/devices/Mouse.h>
64
#include <Quarter/devices/Keyboard.h>
65
#include <Quarter/devices/SpaceNavigatorDevice.h>
70
#define GL_MULTISAMPLE 0x809D
75
GraphicsView::GraphicsView()
79
GraphicsView::~GraphicsView()
83
bool GraphicsView::viewportEvent(QEvent* event)
85
if (event->type() == QEvent::Paint || event->type() == QEvent::Resize) {
86
return QGraphicsView::viewportEvent(event);
88
else if (event->type() == QEvent::MouseMove ||
89
event->type() == QEvent::Wheel ||
90
event->type() == QEvent::MouseButtonDblClick ||
91
event->type() == QEvent::MouseButtonRelease ||
92
event->type() == QEvent::MouseButtonPress) {
93
QMouseEvent* mouse = static_cast<QMouseEvent*>(event);
94
QGraphicsItem *item = itemAt(mouse->pos());
96
QGraphicsView::viewportEvent(event);
100
return QGraphicsView::viewportEvent(event);
103
return QGraphicsView::viewportEvent(event);
106
void GraphicsView::resizeEvent(QResizeEvent *event)
109
scene()->setSceneRect(
110
QRect(QPoint(0, 0), event->size()));
111
QGraphicsView::resizeEvent(event);
117
class SceneEventFilter::Private
120
QList<SIM::Coin3D::Quarter::InputDevice *> devices;
121
GraphicsScene * scene;
122
QPoint globalmousepos;
125
void trackWindowSize(QResizeEvent * event)
127
this->windowsize = SbVec2s(event->size().width(),
128
event->size().height());
130
Q_FOREACH(SIM::Coin3D::Quarter::InputDevice * device, this->devices) {
131
device->setWindowSize(this->windowsize);
135
void trackPointerPosition(QMouseEvent * event)
137
assert(this->windowsize[1] != -1);
138
this->globalmousepos = event->globalPos();
140
SbVec2s mousepos(event->pos().x(), this->windowsize[1] - event->pos().y() - 1);
141
Q_FOREACH(SIM::Coin3D::Quarter::InputDevice * device, this->devices) {
142
device->setMousePosition(mousepos);
147
#define PRIVATE(obj) obj->pimpl
149
SceneEventFilter::SceneEventFilter(QObject * parent)
152
PRIVATE(this) = new Private;
154
PRIVATE(this)->scene = dynamic_cast<GraphicsScene *>(parent);
155
assert(PRIVATE(this)->scene);
157
PRIVATE(this)->windowsize = SbVec2s(PRIVATE(this)->scene->width(),
158
PRIVATE(this)->scene->height());
160
PRIVATE(this)->devices += new SIM::Coin3D::Quarter::Mouse;
161
PRIVATE(this)->devices += new SIM::Coin3D::Quarter::Keyboard;
163
#ifdef HAVE_SPACENAV_LIB
164
PRIVATE(this)->devices += new SpaceNavigatorDevice;
169
SceneEventFilter::~SceneEventFilter()
171
qDeleteAll(PRIVATE(this)->devices);
172
delete PRIVATE(this);
179
SceneEventFilter::registerInputDevice(SIM::Coin3D::Quarter::InputDevice * device)
181
PRIVATE(this)->devices += device;
188
SceneEventFilter::unregisterInputDevice(SIM::Coin3D::Quarter::InputDevice * device)
190
int i = PRIVATE(this)->devices.indexOf(device);
192
PRIVATE(this)->devices.removeAt(i);
202
SceneEventFilter::eventFilter(QObject *, QEvent * qevent)
205
std::unique_ptr<QEvent> sceneev;
206
switch (qevent->type()) {
208
case QEvent::GraphicsSceneMouseMove:
210
QGraphicsSceneMouseEvent* ev = static_cast<QGraphicsSceneMouseEvent*>(qevent);
211
sceneev.reset(new QMouseEvent(QEvent::MouseMove, ev->pos().toPoint(),
212
ev->button(), ev->buttons(), ev->modifiers()));
213
qevent = sceneev.get();
216
case QEvent::GraphicsSceneMousePress:
218
QGraphicsSceneMouseEvent* ev = static_cast<QGraphicsSceneMouseEvent*>(qevent);
219
sceneev.reset(new QMouseEvent(QEvent::MouseButtonPress, ev->pos().toPoint(),
220
ev->button(), ev->buttons(), ev->modifiers()));
221
qevent = sceneev.get();
224
case QEvent::GraphicsSceneMouseRelease:
226
QGraphicsSceneMouseEvent* ev = static_cast<QGraphicsSceneMouseEvent*>(qevent);
227
sceneev.reset(new QMouseEvent(QEvent::MouseButtonRelease, ev->pos().toPoint(),
228
ev->button(), ev->buttons(), ev->modifiers()));
229
qevent = sceneev.get();
232
case QEvent::GraphicsSceneMouseDoubleClick:
234
QGraphicsSceneMouseEvent* ev = static_cast<QGraphicsSceneMouseEvent*>(qevent);
235
sceneev.reset(new QMouseEvent(QEvent::MouseButtonDblClick, ev->pos().toPoint(),
236
ev->button(), ev->buttons(), ev->modifiers()));
237
qevent = sceneev.get();
240
case QEvent::GraphicsSceneWheel:
242
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
243
QGraphicsSceneWheelEvent* ev = static_cast<QGraphicsSceneWheelEvent*>(qevent);
244
sceneev.reset(new QWheelEvent(ev->pos().toPoint(), ev->delta(), ev->buttons(),
245
ev->modifiers(), ev->orientation()));
246
qevent = sceneev.get();
250
case QEvent::GraphicsSceneResize:
252
QGraphicsSceneResizeEvent* ev = static_cast<QGraphicsSceneResizeEvent*>(qevent);
253
sceneev.reset(new QResizeEvent(ev->newSize().toSize(), ev->oldSize().toSize()));
254
qevent = sceneev.get();
263
switch (qevent->type()) {
264
case QEvent::MouseMove:
265
case QEvent::MouseButtonPress:
266
case QEvent::MouseButtonRelease:
267
case QEvent::MouseButtonDblClick:
268
PRIVATE(this)->trackPointerPosition(dynamic_cast<QMouseEvent *>(qevent));
271
PRIVATE(this)->trackWindowSize(dynamic_cast<QResizeEvent *>(qevent));
279
Q_FOREACH(SIM::Coin3D::Quarter::InputDevice * device, PRIVATE(this)->devices) {
280
const SoEvent * soevent = device->translateEvent(qevent);
281
if (soevent && PRIVATE(this)->scene->processSoEvent(soevent)) {
292
SceneEventFilter::globalMousePosition(void) const
294
return PRIVATE(this)->globalmousepos;
301
QDialog *GraphicsScene::createDialog(const QString &windowTitle) const
303
QDialog *dialog = new QDialog(0, Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
305
dialog->setWindowOpacity(0.8);
306
dialog->setWindowTitle(windowTitle);
307
dialog->setLayout(new QVBoxLayout);
312
GraphicsScene::GraphicsScene()
313
: m_backgroundColor(0, 170, 255)
317
headlight = new SoDirectionalLight();
319
sceneNode = new SoSeparator();
322
this->addEllipse(20,20, 120, 60);
323
QWidget *controls = createDialog(tr("Controls"));
325
QCheckBox *wireframe = new QCheckBox(tr("Render as wireframe"));
327
controls->layout()->addWidget(wireframe);
329
QCheckBox *normals = new QCheckBox(tr("Display normals vectors"));
330
controls->layout()->addWidget(normals);
332
QPushButton *colorButton = new QPushButton(tr("Choose model color"));
333
controls->layout()->addWidget(colorButton);
335
QWidget *instructions = createDialog(tr("Instructions"));
336
instructions->layout()->addWidget(new QLabel(tr("Use mouse wheel to zoom model, and click and drag to rotate model")));
337
instructions->layout()->addWidget(new QLabel(tr("Move the sun around to change the light position")));
339
QGraphicsProxyWidget* g1 = addWidget(instructions);
340
g1->setWindowFlags(Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
341
QGraphicsProxyWidget* g2 = addWidget(controls);
342
g2->setWindowFlags(Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
343
controls->setAttribute(Qt::WA_TranslucentBackground);
346
Q_FOREACH (QGraphicsItem *item, items()) {
347
item->setFlag(QGraphicsItem::ItemIsMovable);
348
item->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
350
const QRectF rect = item->boundingRect();
351
item->setPos(pos.x() - rect.x(), pos.y() - rect.y());
352
pos += QPointF(0, 10 + rect.height());
355
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
358
sorendermanager = new SoRenderManager;
360
sorendermanager->setAutoClipping(SoRenderManager::VARIABLE_NEAR_PLANE);
362
sorendermanager->setBackgroundColor(SbColor4f(0.0f, 0.0f, 0.0f, 0.0f));
363
sorendermanager->activate();
365
soeventmanager = new SoEventManager;
366
soeventmanager->setNavigationState(SoEventManager::MIXED_NAVIGATION);
368
eventfilter = new SceneEventFilter(this);
370
connect(this, SIGNAL(sceneRectChanged(const QRectF&)),
371
this, SLOT(onSceneRectChanged(const QRectF&)));
374
GraphicsScene::~GraphicsScene()
378
delete sorendermanager;
379
delete soeventmanager;
383
void GraphicsScene::viewAll()
385
SoCamera* cam = sorendermanager->getCamera();
387
cam->viewAll(sceneNode, sorendermanager->getViewportRegion());
391
GraphicsScene::getEventFilter(void) const
397
GraphicsScene::processSoEvent(const SoEvent * event)
400
return soeventmanager && soeventmanager->processEvent(event);
407
GraphicsScene::addStateMachine(SoScXMLStateMachine * statemachine)
409
SoEventManager * em = this->getSoEventManager();
410
em->addSoScXMLStateMachine(statemachine);
411
statemachine->setSceneGraphRoot(this->getSoRenderManager()->getSceneGraph());
412
statemachine->setActiveCamera(this->getSoRenderManager()->getCamera());
416
GraphicsScene::removeStateMachine(SoScXMLStateMachine * statemachine)
418
SoEventManager * em = this->getSoEventManager();
419
statemachine->setSceneGraphRoot(NULL);
420
statemachine->setActiveCamera(NULL);
421
em->removeSoScXMLStateMachine(statemachine);
425
GraphicsScene::setNavigationModeFile(const QUrl & url)
429
if (url.scheme()== QLatin1String("coin")) {
430
filename = url.path();
435
if (filename[0] == QLatin1Char('/')) {
436
filename.remove(0,1);
438
filename = url.scheme() + QLatin1Char(':') + filename;
440
else if (url.scheme() == QLatin1String("file"))
441
filename = url.toLocalFile();
442
else if (url.isEmpty()) {
450
QByteArray filenametmp = filename.toLocal8Bit();
451
ScXMLStateMachine * stateMachine = NULL;
453
if (filenametmp.startsWith("coin:")){
454
stateMachine = ScXML::readFile(filenametmp.data());
458
QFile file(QString::fromLatin1(filenametmp));
459
if (file.open(QIODevice::ReadOnly)) {
460
QByteArray fileContents = file.readAll();
461
#if COIN_MAJOR_VERSION >= 4
462
stateMachine = ScXML::readBuffer(SbByteBuffer(fileContents.size(), fileContents.constData()));
464
stateMachine = ScXML::readBuffer(fileContents.constData());
470
if (stateMachine && stateMachine->isOfType(SoScXMLStateMachine::getClassTypeId())) {
471
SoScXMLStateMachine * newsm = static_cast<SoScXMLStateMachine *>(stateMachine);
473
this->addStateMachine(newsm);
484
SoNode* GraphicsScene::getSceneGraph() const
490
GraphicsScene::searchForCamera(SoNode * root)
493
sa.setInterest(SoSearchAction::FIRST);
494
sa.setType(SoCamera::getClassTypeId());
498
SoNode * node = sa.getPath()->getTail();
499
if (node && node->isOfType(SoCamera::getClassTypeId())) {
500
return (SoCamera *) node;
506
void GraphicsScene::setSceneGraph(SoNode * node)
508
if (node == sceneNode) {
517
SoCamera * camera = NULL;
518
SoSeparator * superscene = NULL;
519
bool viewall = false;
525
superscene = new SoSeparator;
526
superscene->addChild(headlight);
529
if (!(camera = searchForCamera(node))) {
530
camera = new SoOrthographicCamera;
531
superscene->addChild(camera);
535
superscene->addChild(node);
538
soeventmanager->setCamera(camera);
539
sorendermanager->setCamera(camera);
540
soeventmanager->setSceneGraph(superscene);
541
sorendermanager->setSceneGraph(superscene);
552
GraphicsScene::getSoRenderManager(void) const
554
return sorendermanager;
558
GraphicsScene::getSoEventManager(void) const
560
return soeventmanager;
563
void GraphicsScene::onSceneRectChanged(const QRectF & rect)
565
SbViewportRegion vp(rect.width(), rect.height());
566
sorendermanager->setViewportRegion(vp);
567
soeventmanager->setViewportRegion(vp);
570
void GraphicsScene::drawBackground(QPainter *painter, const QRectF &)
572
if (painter->paintEngine()->type() != QPaintEngine::OpenGL && painter->paintEngine()->type() != QPaintEngine::OpenGL2) {
573
qWarning("GraphicsScene: drawBackground needs a QGLWidget to be set as viewport on the graphics view");
577
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
578
const int delta = m_time.elapsed() - m_lastTime;
582
sorendermanager->render(true,
586
painter->fillRect(40,40,40,60,Qt::lightGray);
587
painter->drawText(50,50, QString::fromLatin1("Done with QPainter"));
590
QTimer::singleShot(20, this, SLOT(update()));
593
void GraphicsScene::setBackgroundColor(const QColor& color)
595
if (color.isValid()) {
596
m_backgroundColor = color;
599
SbColor4f bgcolor(SbClamp(color.red() / 255.0, 0.0, 1.0),
600
SbClamp(color.green() / 255.0, 0.0, 1.0),
601
SbClamp(color.blue() / 255.0, 0.0, 1.0),
602
SbClamp(color.alpha() / 255.0, 0.0, 1.0));
603
sorendermanager->setBackgroundColor(bgcolor);
604
sorendermanager->scheduleRedraw();
608
void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
610
QGraphicsScene::mouseMoveEvent(event);
611
if (event->isAccepted())
613
if (event->buttons() & Qt::LeftButton) {
619
void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
621
QGraphicsScene::mousePressEvent(event);
622
if (event->isAccepted())
625
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
626
m_mouseEventTime = m_time.elapsed();
631
void GraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
633
QGraphicsScene::mouseReleaseEvent(event);
634
if (event->isAccepted())
641
void GraphicsScene::wheelEvent(QGraphicsSceneWheelEvent *event)
643
QGraphicsScene::wheelEvent(event);
644
if (event->isAccepted())
652
GraphicsView3D::GraphicsView3D(Gui::Document* doc, QWidget* parent)
653
: Gui::MDIView(doc, parent), m_scene(new GraphicsScene()), m_view(new GraphicsView)
655
m_view->installEventFilter(m_scene->getEventFilter());
656
m_view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
657
m_view->setScene(m_scene);
658
m_scene->setNavigationModeFile(QUrl(QString::fromLatin1("coin:///scxml/navigation/examiner.xml")));
660
std::vector<ViewProvider*> v = doc->getViewProvidersOfType(ViewProvider::getClassTypeId());
661
SoSeparator* root = new SoSeparator();
662
for (std::vector<ViewProvider*>::iterator it = v.begin(); it != v.end(); ++it)
663
root->addChild((*it)->getRoot());
664
m_scene->setSceneGraph(root);
665
setCentralWidget(m_view);
669
hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
672
OnChange(*hGrp,"BackgroundColor");
675
GraphicsView3D::~GraphicsView3D()
682
void GraphicsView3D::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::MessageType Reason)
684
const ParameterGrp& rGrp = static_cast<ParameterGrp&>(rCaller);
686
if (strcmp(Reason, "BackgroundColor") == 0)
688
unsigned long col1 = rGrp.GetUnsigned("BackgroundColor",3940932863UL);
692
r1 = ((col1 >> 24) & 0xff) / 255.0; g1 = ((col1 >> 16) & 0xff) / 255.0; b1 = ((col1 >> 8) & 0xff) / 255.0;
693
m_scene->setBackgroundColor(QColor::fromRgbF(r1, g1, b1));
696
#include "moc_GLGraphicsView.cpp"