mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-27 12:35:46 +00:00
Migrate from GraphicsWindowQt to QOpenGLWidget
This commit is contained in:
parent
b0a129d6e4
commit
8df7ce545e
@ -54,6 +54,7 @@
|
|||||||
Feature #3537: Shader-based water ripples
|
Feature #3537: Shader-based water ripples
|
||||||
Feature #5492: Let rain and snow collide with statics
|
Feature #5492: Let rain and snow collide with statics
|
||||||
Feature #6447: Add LOD support to Object Paging
|
Feature #6447: Add LOD support to Object Paging
|
||||||
|
Feature #6491: Add support for Qt6
|
||||||
Feature #6726: Lua API for creating new objects
|
Feature #6726: Lua API for creating new objects
|
||||||
Feature #6922: Improve launcher appearance
|
Feature #6922: Improve launcher appearance
|
||||||
Feature #6933: Support high-resolution cursor textures
|
Feature #6933: Support high-resolution cursor textures
|
||||||
|
@ -934,7 +934,11 @@ printf "Qt ${QT_VER}... "
|
|||||||
else
|
else
|
||||||
DLLSUFFIX=""
|
DLLSUFFIX=""
|
||||||
fi
|
fi
|
||||||
add_runtime_dlls $CONFIGURATION "$(pwd)/bin/Qt${QT_VER:0:1}"{Core,Gui,Network,OpenGL,Widgets}${DLLSUFFIX}.dll
|
if [ "${QT_VER:0:1}" -eq "6" ]; then
|
||||||
|
add_runtime_dlls $CONFIGURATION "$(pwd)/bin/Qt${QT_VER:0:1}"{Core,Gui,Network,OpenGL,OpenGLWidgets,Widgets}${DLLSUFFIX}.dll
|
||||||
|
else
|
||||||
|
add_runtime_dlls $CONFIGURATION "$(pwd)/bin/Qt${QT_VER:0:1}"{Core,Gui,Network,OpenGL,Widgets}${DLLSUFFIX}.dll
|
||||||
|
fi
|
||||||
add_qt_platform_dlls $CONFIGURATION "$(pwd)/plugins/platforms/qwindows${DLLSUFFIX}.dll"
|
add_qt_platform_dlls $CONFIGURATION "$(pwd)/plugins/platforms/qwindows${DLLSUFFIX}.dll"
|
||||||
add_qt_style_dlls $CONFIGURATION "$(pwd)/plugins/styles/qwindowsvistastyle${DLLSUFFIX}.dll"
|
add_qt_style_dlls $CONFIGURATION "$(pwd)/plugins/styles/qwindowsvistastyle${DLLSUFFIX}.dll"
|
||||||
done
|
done
|
||||||
|
@ -241,7 +241,7 @@ if (USE_QT)
|
|||||||
if (QT_VERSION_MAJOR VERSION_EQUAL 5)
|
if (QT_VERSION_MAJOR VERSION_EQUAL 5)
|
||||||
find_package(Qt5 5.15 COMPONENTS Core Widgets Network OpenGL REQUIRED)
|
find_package(Qt5 5.15 COMPONENTS Core Widgets Network OpenGL REQUIRED)
|
||||||
else()
|
else()
|
||||||
find_package(Qt6 COMPONENTS Core Widgets Network OpenGL REQUIRED)
|
find_package(Qt6 COMPONENTS Core Widgets Network OpenGL OpenGLWidgets REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
message(STATUS "Using Qt${QT_VERSION}")
|
message(STATUS "Using Qt${QT_VERSION}")
|
||||||
endif()
|
endif()
|
||||||
@ -627,7 +627,7 @@ endif (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clan
|
|||||||
add_subdirectory (extern/osg-ffmpeg-videoplayer)
|
add_subdirectory (extern/osg-ffmpeg-videoplayer)
|
||||||
add_subdirectory (extern/oics)
|
add_subdirectory (extern/oics)
|
||||||
add_subdirectory (extern/Base64)
|
add_subdirectory (extern/Base64)
|
||||||
if ((BUILD_OPENCS OR BUILD_OPENCS_TESTS) AND Qt5_FOUND)
|
if (BUILD_OPENCS OR BUILD_OPENCS_TESTS)
|
||||||
add_subdirectory (extern/osgQt)
|
add_subdirectory (extern/osgQt)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -789,12 +789,8 @@ void Launcher::DataFilesPage::reloadCells(QStringList selectedFiles)
|
|||||||
|
|
||||||
// The following code will run only if there is not another thread currently running it
|
// The following code will run only if there is not another thread currently running it
|
||||||
CellNameLoader cellNameLoader;
|
CellNameLoader cellNameLoader;
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
|
||||||
QSet<QString> set = cellNameLoader.getCellNames(selectedFiles);
|
QSet<QString> set = cellNameLoader.getCellNames(selectedFiles);
|
||||||
QStringList cellNamesList(set.begin(), set.end());
|
QStringList cellNamesList(set.begin(), set.end());
|
||||||
#else
|
|
||||||
QStringList cellNamesList = QStringList::fromSet(cellNameLoader.getCellNames(selectedFiles));
|
|
||||||
#endif
|
|
||||||
std::sort(cellNamesList.begin(), cellNamesList.end());
|
std::sort(cellNamesList.begin(), cellNamesList.end());
|
||||||
emit signalLoadedCellsChanged(cellNamesList);
|
emit signalLoadedCellsChanged(cellNamesList);
|
||||||
}
|
}
|
||||||
|
@ -243,7 +243,11 @@ target_link_libraries(openmw-cs-lib
|
|||||||
components_qt
|
components_qt
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(openmw-cs-lib Qt::Widgets Qt::Core Qt::Network Qt::OpenGL)
|
if (QT_VERSION_MAJOR VERSION_EQUAL 6)
|
||||||
|
target_link_libraries(openmw-cs-lib Qt::Widgets Qt::Core Qt::Network Qt::OpenGL Qt::OpenGLWidgets)
|
||||||
|
else()
|
||||||
|
target_link_libraries(openmw-cs-lib Qt::Widgets Qt::Core Qt::Network Qt::OpenGL)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_link_libraries(openmw-cs-lib ${Boost_LOCALE_LIBRARY})
|
target_link_libraries(openmw-cs-lib ${Boost_LOCALE_LIBRARY})
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
#include <QSurfaceFormat>
|
||||||
|
|
||||||
|
#include <osg/DisplaySettings>
|
||||||
|
|
||||||
#include <components/debug/debugging.hpp>
|
#include <components/debug/debugging.hpp>
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
@ -46,6 +49,19 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void setQSurfaceFormat()
|
||||||
|
{
|
||||||
|
osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
|
||||||
|
QSurfaceFormat format = QSurfaceFormat::defaultFormat();
|
||||||
|
format.setVersion(2, 1);
|
||||||
|
format.setRenderableType(QSurfaceFormat::OpenGL);
|
||||||
|
format.setDepthBufferSize(24);
|
||||||
|
format.setSamples(ds->getMultiSamples());
|
||||||
|
format.setStencilBufferSize(ds->getMinimumNumStencilBits());
|
||||||
|
format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
|
||||||
|
QSurfaceFormat::setDefaultFormat(format);
|
||||||
|
}
|
||||||
|
|
||||||
int runApplication(int argc, char* argv[])
|
int runApplication(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
Platform::init();
|
Platform::init();
|
||||||
@ -60,6 +76,9 @@ int runApplication(int argc, char* argv[])
|
|||||||
qRegisterMetaType<CSMWorld::UniversalId>("CSMWorld::UniversalId");
|
qRegisterMetaType<CSMWorld::UniversalId>("CSMWorld::UniversalId");
|
||||||
qRegisterMetaType<CSMDoc::Message>("CSMDoc::Message");
|
qRegisterMetaType<CSMDoc::Message>("CSMDoc::Message");
|
||||||
|
|
||||||
|
setQSurfaceFormat();
|
||||||
|
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
|
||||||
|
|
||||||
Application application(argc, argv);
|
Application application(argc, argv);
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <QLayout>
|
#include <QLayout>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
|
#include <QSurfaceFormat>
|
||||||
|
|
||||||
#include <apps/opencs/model/prefs/category.hpp>
|
#include <apps/opencs/model/prefs/category.hpp>
|
||||||
#include <apps/opencs/model/prefs/setting.hpp>
|
#include <apps/opencs/model/prefs/setting.hpp>
|
||||||
@ -13,9 +14,8 @@
|
|||||||
#include <apps/opencs/view/render/lightingday.hpp>
|
#include <apps/opencs/view/render/lightingday.hpp>
|
||||||
#include <apps/opencs/view/render/lightingnight.hpp>
|
#include <apps/opencs/view/render/lightingnight.hpp>
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
#include <extern/osgQt/CompositeOsgRenderer.hpp>
|
||||||
#include <extern/osgQt/GraphicsWindowQt>
|
#include <extern/osgQt/osgQOpenGLWidget.hpp>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <osg/Array>
|
#include <osg/Array>
|
||||||
#include <osg/Camera>
|
#include <osg/Camera>
|
||||||
@ -40,7 +40,6 @@
|
|||||||
#include <osgGA/EventQueue>
|
#include <osgGA/EventQueue>
|
||||||
#include <osgGA/GUIEventAdapter>
|
#include <osgGA/GUIEventAdapter>
|
||||||
|
|
||||||
#include <osgViewer/CompositeViewer>
|
|
||||||
#include <osgViewer/GraphicsWindow>
|
#include <osgViewer/GraphicsWindow>
|
||||||
#include <osgViewer/View>
|
#include <osgViewer/View>
|
||||||
#include <osgViewer/ViewerBase>
|
#include <osgViewer/ViewerBase>
|
||||||
@ -67,47 +66,34 @@ namespace CSVRender
|
|||||||
: QWidget(parent, f)
|
: QWidget(parent, f)
|
||||||
, mRootNode(nullptr)
|
, mRootNode(nullptr)
|
||||||
{
|
{
|
||||||
|
|
||||||
osgViewer::CompositeViewer& viewer = CompositeViewer::get();
|
|
||||||
|
|
||||||
osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
|
|
||||||
// ds->setNumMultiSamples(8);
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
|
|
||||||
traits->windowName.clear();
|
|
||||||
traits->windowDecoration = true;
|
|
||||||
traits->x = 0;
|
|
||||||
traits->y = 0;
|
|
||||||
traits->width = width();
|
|
||||||
traits->height = height();
|
|
||||||
traits->doubleBuffer = true;
|
|
||||||
traits->alpha = ds->getMinimumNumAlphaBits();
|
|
||||||
traits->stencil = ds->getMinimumNumStencilBits();
|
|
||||||
traits->sampleBuffers = ds->getMultiSamples();
|
|
||||||
traits->samples = ds->getNumMultiSamples();
|
|
||||||
// Doesn't make much sense as we're running on demand updates, and there seems to be a bug with the refresh rate
|
|
||||||
// when running multiple QGLWidgets
|
|
||||||
traits->vsync = false;
|
|
||||||
|
|
||||||
mView = new osgViewer::View;
|
mView = new osgViewer::View;
|
||||||
updateCameraParameters(traits->width / static_cast<double>(traits->height));
|
updateCameraParameters(width() / static_cast<double>(height()));
|
||||||
|
|
||||||
|
mWidget = new osgQOpenGLWidget(this);
|
||||||
|
|
||||||
|
mRenderer = mWidget->getCompositeViewer();
|
||||||
|
osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> window
|
||||||
|
= new osgViewer::GraphicsWindowEmbedded(0, 0, width(), height());
|
||||||
|
mWidget->setGraphicsWindowEmbedded(window);
|
||||||
|
|
||||||
|
int frameRateLimit = CSMPrefs::get()["Rendering"]["framerate-limit"].toInt();
|
||||||
|
mRenderer->setRunMaxFrameRate(frameRateLimit);
|
||||||
|
mRenderer->setUseConfigureAffinity(false);
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
osg::ref_ptr<osgQt::GraphicsWindowQt> window = new osgQt::GraphicsWindowQt(traits.get());
|
|
||||||
QLayout* layout = new QHBoxLayout(this);
|
QLayout* layout = new QHBoxLayout(this);
|
||||||
layout->setContentsMargins(0, 0, 0, 0);
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
layout->addWidget(window->getGLWidget());
|
layout->addWidget(mWidget);
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
|
|
||||||
mView->getCamera()->setGraphicsContext(window);
|
mView->getCamera()->setGraphicsContext(window);
|
||||||
#endif
|
|
||||||
mView->getCamera()->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
|
|
||||||
|
|
||||||
SceneUtil::LightManager* lightMgr = new SceneUtil::LightManager;
|
SceneUtil::LightManager* lightMgr = new SceneUtil::LightManager;
|
||||||
lightMgr->setStartLight(1);
|
lightMgr->setStartLight(1);
|
||||||
lightMgr->setLightingMask(Mask_Lighting);
|
lightMgr->setLightingMask(Mask_Lighting);
|
||||||
mRootNode = lightMgr;
|
mRootNode = lightMgr;
|
||||||
|
|
||||||
|
mView->getCamera()->setViewport(new osg::Viewport(0, 0, width(), height()));
|
||||||
|
|
||||||
mView->getCamera()->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
|
mView->getCamera()->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
|
||||||
mView->getCamera()->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
|
mView->getCamera()->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
|
||||||
osg::ref_ptr<osg::Material> defaultMat(new osg::Material);
|
osg::ref_ptr<osg::Material> defaultMat(new osg::Material);
|
||||||
@ -122,21 +108,21 @@ namespace CSVRender
|
|||||||
// Add ability to signal osg to show its statistics for debugging purposes
|
// Add ability to signal osg to show its statistics for debugging purposes
|
||||||
mView->addEventHandler(new osgViewer::StatsHandler);
|
mView->addEventHandler(new osgViewer::StatsHandler);
|
||||||
|
|
||||||
viewer.addView(mView);
|
mRenderer->addView(mView);
|
||||||
viewer.setDone(false);
|
mRenderer->setDone(false);
|
||||||
viewer.realize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderWidget::~RenderWidget()
|
RenderWidget::~RenderWidget()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
CompositeViewer::get().removeView(mView);
|
mRenderer->removeView(mView);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
Log(Debug::Error) << "Error in the destructor: " << e.what();
|
Log(Debug::Error) << "Error in the destructor: " << e.what();
|
||||||
}
|
}
|
||||||
|
delete mWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderWidget::flagAsModified()
|
void RenderWidget::flagAsModified()
|
||||||
@ -163,54 +149,6 @@ namespace CSVRender
|
|||||||
window->getEventQueue()->keyRelease(osgGA::GUIEventAdapter::KEY_S);
|
window->getEventQueue()->keyRelease(osgGA::GUIEventAdapter::KEY_S);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
CompositeViewer::CompositeViewer()
|
|
||||||
: mSimulationTime(0.0)
|
|
||||||
{
|
|
||||||
// TODO: Upgrade osgQt to support osgViewer::ViewerBase::DrawThreadPerContext
|
|
||||||
// https://gitlab.com/OpenMW/openmw/-/issues/5481
|
|
||||||
setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
|
|
||||||
|
|
||||||
setUseConfigureAffinity(false);
|
|
||||||
|
|
||||||
// disable the default setting of viewer.done() by pressing Escape.
|
|
||||||
setKeyEventSetsDone(0);
|
|
||||||
|
|
||||||
// Only render when the camera position changed, or content flagged dirty
|
|
||||||
// setRunFrameScheme(osgViewer::ViewerBase::ON_DEMAND);
|
|
||||||
setRunFrameScheme(osgViewer::ViewerBase::CONTINUOUS);
|
|
||||||
|
|
||||||
connect(&mTimer, &QTimer::timeout, this, &CompositeViewer::update);
|
|
||||||
mTimer.start(10);
|
|
||||||
|
|
||||||
int frameRateLimit = CSMPrefs::get()["Rendering"]["framerate-limit"].toInt();
|
|
||||||
setRunMaxFrameRate(frameRateLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
CompositeViewer& CompositeViewer::get()
|
|
||||||
{
|
|
||||||
static CompositeViewer sThis;
|
|
||||||
return sThis;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CompositeViewer::update()
|
|
||||||
{
|
|
||||||
double dt = mFrameTimer.time_s();
|
|
||||||
mFrameTimer.setStartTick();
|
|
||||||
|
|
||||||
emit simulationUpdated(dt);
|
|
||||||
|
|
||||||
mSimulationTime += dt;
|
|
||||||
frame(mSimulationTime);
|
|
||||||
|
|
||||||
double minFrameTime = _runMaxFrameRate > 0.0 ? 1.0 / _runMaxFrameRate : 0.0;
|
|
||||||
if (dt < minFrameTime)
|
|
||||||
{
|
|
||||||
std::this_thread::sleep_for(std::chrono::duration<double>(minFrameTime - dt));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------
|
// ---------------------------------------------------
|
||||||
|
|
||||||
SceneWidget::SceneWidget(std::shared_ptr<Resource::ResourceSystem> resourceSystem, QWidget* parent,
|
SceneWidget::SceneWidget(std::shared_ptr<Resource::ResourceSystem> resourceSystem, QWidget* parent,
|
||||||
@ -268,7 +206,7 @@ namespace CSVRender
|
|||||||
CSMPrefs::get()["Tooltips"].update();
|
CSMPrefs::get()["Tooltips"].update();
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(&CompositeViewer::get(), &CompositeViewer::simulationUpdated, this, &SceneWidget::update);
|
connect(mRenderer, SIGNAL(simulationUpdated(double)), this, SLOT(update(double)));
|
||||||
|
|
||||||
// Shortcuts
|
// Shortcuts
|
||||||
CSMPrefs::Shortcut* focusToolbarShortcut = new CSMPrefs::Shortcut("scene-focus-toolbar", this);
|
CSMPrefs::Shortcut* focusToolbarShortcut = new CSMPrefs::Shortcut("scene-focus-toolbar", this);
|
||||||
@ -560,7 +498,7 @@ namespace CSVRender
|
|||||||
}
|
}
|
||||||
else if (*setting == "Rendering/framerate-limit")
|
else if (*setting == "Rendering/framerate-limit")
|
||||||
{
|
{
|
||||||
CompositeViewer::get().setRunMaxFrameRate(setting->toInt());
|
mRenderer->setRunMaxFrameRate(setting->toInt());
|
||||||
}
|
}
|
||||||
else if (*setting == "Rendering/camera-fov" || *setting == "Rendering/camera-ortho"
|
else if (*setting == "Rendering/camera-fov" || *setting == "Rendering/camera-ortho"
|
||||||
|| *setting == "Rendering/camera-ortho-size")
|
|| *setting == "Rendering/camera-ortho-size")
|
||||||
|
@ -22,6 +22,9 @@
|
|||||||
class QMouseEvent;
|
class QMouseEvent;
|
||||||
class QWheelEvent;
|
class QWheelEvent;
|
||||||
|
|
||||||
|
class osgQOpenGLWidget;
|
||||||
|
class CompositeOsgRenderer;
|
||||||
|
|
||||||
namespace Resource
|
namespace Resource
|
||||||
{
|
{
|
||||||
class ResourceSystem;
|
class ResourceSystem;
|
||||||
@ -73,13 +76,13 @@ namespace CSVRender
|
|||||||
osg::Camera* getCamera();
|
osg::Camera* getCamera();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
osgQOpenGLWidget* mWidget;
|
||||||
|
CompositeOsgRenderer* mRenderer;
|
||||||
osg::ref_ptr<osgViewer::View> mView;
|
osg::ref_ptr<osgViewer::View> mView;
|
||||||
osg::ref_ptr<osg::Group> mRootNode;
|
osg::ref_ptr<osg::Group> mRootNode;
|
||||||
|
|
||||||
void updateCameraParameters(double overrideAspect = -1.0);
|
void updateCameraParameters(double overrideAspect = -1.0);
|
||||||
|
|
||||||
QTimer mTimer;
|
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
|
|
||||||
void toggleRenderStats();
|
void toggleRenderStats();
|
||||||
@ -154,30 +157,6 @@ namespace CSVRender
|
|||||||
|
|
||||||
void focusToolbarRequest();
|
void focusToolbarRequest();
|
||||||
};
|
};
|
||||||
|
|
||||||
// There are rendering glitches when using multiple Viewer instances, work around using CompositeViewer with
|
|
||||||
// multiple views
|
|
||||||
class CompositeViewer : public QObject, public osgViewer::CompositeViewer
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
CompositeViewer();
|
|
||||||
|
|
||||||
static CompositeViewer& get();
|
|
||||||
|
|
||||||
QTimer mTimer;
|
|
||||||
|
|
||||||
private:
|
|
||||||
osg::Timer mFrameTimer;
|
|
||||||
double mSimulationTime;
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void update();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void simulationUpdated(double dt);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,8 +6,11 @@
|
|||||||
#include <QDragEnterEvent>
|
#include <QDragEnterEvent>
|
||||||
#include <QDragMoveEvent>
|
#include <QDragMoveEvent>
|
||||||
#include <QDropEvent>
|
#include <QDropEvent>
|
||||||
|
#include <QGuiApplication>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
|
#include <QScreen>
|
||||||
#include <QToolTip>
|
#include <QToolTip>
|
||||||
|
#include <QWindow>
|
||||||
|
|
||||||
#include <apps/opencs/model/doc/document.hpp>
|
#include <apps/opencs/model/doc/document.hpp>
|
||||||
#include <apps/opencs/model/prefs/category.hpp>
|
#include <apps/opencs/model/prefs/category.hpp>
|
||||||
@ -381,9 +384,14 @@ CSMDoc::Document& CSVRender::WorldspaceWidget::getDocument()
|
|||||||
CSVRender::WorldspaceHitResult CSVRender::WorldspaceWidget::mousePick(
|
CSVRender::WorldspaceHitResult CSVRender::WorldspaceWidget::mousePick(
|
||||||
const QPoint& localPos, unsigned int interactionMask) const
|
const QPoint& localPos, unsigned int interactionMask) const
|
||||||
{
|
{
|
||||||
|
// may be okay to just use devicePixelRatio() directly
|
||||||
|
QScreen* screen = SceneWidget::windowHandle() && SceneWidget::windowHandle()->screen()
|
||||||
|
? SceneWidget::windowHandle()->screen()
|
||||||
|
: QGuiApplication::primaryScreen();
|
||||||
|
|
||||||
// (0,0) is considered the lower left corner of an OpenGL window
|
// (0,0) is considered the lower left corner of an OpenGL window
|
||||||
int x = localPos.x();
|
int x = localPos.x() * screen->devicePixelRatio();
|
||||||
int y = height() - localPos.y();
|
int y = height() * screen->devicePixelRatio() - localPos.y() * screen->devicePixelRatio();
|
||||||
|
|
||||||
// Convert from screen space to world space
|
// Convert from screen space to world space
|
||||||
osg::Matrixd wpvMat;
|
osg::Matrixd wpvMat;
|
||||||
|
@ -141,7 +141,6 @@ void CSVWorld::Table::contextMenuEvent(QContextMenuEvent* event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
if (selectedRows.size() == 1)
|
if (selectedRows.size() == 1)
|
||||||
{
|
{
|
||||||
int row = selectedRows.begin()->row();
|
int row = selectedRows.begin()->row();
|
||||||
@ -173,7 +172,6 @@ void CSVWorld::Table::contextMenuEvent(QContextMenuEvent* event)
|
|||||||
menu.addAction(mPreviewAction);
|
menu.addAction(mPreviewAction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (mHelpAction)
|
if (mHelpAction)
|
||||||
menu.addAction(mHelpAction);
|
menu.addAction(mHelpAction);
|
||||||
@ -390,18 +388,14 @@ CSVWorld::Table::Table(const CSMWorld::UniversalId& id, bool createAndDelete, bo
|
|||||||
mViewAction->setIcon(QIcon(":/cell.png"));
|
mViewAction->setIcon(QIcon(":/cell.png"));
|
||||||
addAction(mViewAction);
|
addAction(mViewAction);
|
||||||
CSMPrefs::Shortcut* viewShortcut = new CSMPrefs::Shortcut("table-view", this);
|
CSMPrefs::Shortcut* viewShortcut = new CSMPrefs::Shortcut("table-view", this);
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
viewShortcut->associateAction(mViewAction);
|
viewShortcut->associateAction(mViewAction);
|
||||||
#endif
|
|
||||||
|
|
||||||
mPreviewAction = new QAction(tr("Preview"), this);
|
mPreviewAction = new QAction(tr("Preview"), this);
|
||||||
connect(mPreviewAction, &QAction::triggered, this, &Table::previewRecord);
|
connect(mPreviewAction, &QAction::triggered, this, &Table::previewRecord);
|
||||||
mPreviewAction->setIcon(QIcon(":edit-preview"));
|
mPreviewAction->setIcon(QIcon(":edit-preview"));
|
||||||
addAction(mPreviewAction);
|
addAction(mPreviewAction);
|
||||||
CSMPrefs::Shortcut* previewShortcut = new CSMPrefs::Shortcut("table-preview", this);
|
CSMPrefs::Shortcut* previewShortcut = new CSMPrefs::Shortcut("table-preview", this);
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
previewShortcut->associateAction(mPreviewAction);
|
previewShortcut->associateAction(mPreviewAction);
|
||||||
#endif
|
|
||||||
|
|
||||||
mExtendedDeleteAction = new QAction(tr("Extended Delete Record"), this);
|
mExtendedDeleteAction = new QAction(tr("Extended Delete Record"), this);
|
||||||
connect(mExtendedDeleteAction, &QAction::triggered, this, &Table::executeExtendedDelete);
|
connect(mExtendedDeleteAction, &QAction::triggered, this, &Table::executeExtendedDelete);
|
||||||
|
17
extern/osgQt/CMakeLists.txt
vendored
17
extern/osgQt/CMakeLists.txt
vendored
@ -2,13 +2,26 @@ set(OSGQT_LIBRARY "osgQt")
|
|||||||
|
|
||||||
# Sources
|
# Sources
|
||||||
|
|
||||||
|
set(SOURCE_H
|
||||||
|
osgQOpenGLWidget.hpp
|
||||||
|
CompositeOsgRenderer.hpp
|
||||||
|
)
|
||||||
|
|
||||||
|
qt_wrap_cpp(SOURCES_H_MOC ${SOURCE_H} )
|
||||||
|
|
||||||
set(OSGQT_SOURCE_FILES
|
set(OSGQT_SOURCE_FILES
|
||||||
GraphicsWindowQt.cpp
|
osgQOpenGLWidget.cpp
|
||||||
|
CompositeOsgRenderer.cpp
|
||||||
|
${SOURCES_H_MOC}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(${OSGQT_LIBRARY} STATIC ${OSGQT_SOURCE_FILES})
|
add_library(${OSGQT_LIBRARY} STATIC ${OSGQT_SOURCE_FILES})
|
||||||
|
|
||||||
target_link_libraries(${OSGQT_LIBRARY} Qt::Core Qt::OpenGL)
|
if (QT_VERSION_MAJOR VERSION_EQUAL 6)
|
||||||
|
target_link_libraries(${OSGQT_LIBRARY} Qt::Core Qt::OpenGL Qt::OpenGLWidgets)
|
||||||
|
else()
|
||||||
|
target_link_libraries(${OSGQT_LIBRARY} Qt::Core Qt::OpenGL)
|
||||||
|
endif()
|
||||||
|
|
||||||
link_directories(${CMAKE_CURRENT_BINARY_DIR})
|
link_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
119
extern/osgQt/CompositeOsgRenderer.cpp
vendored
Normal file
119
extern/osgQt/CompositeOsgRenderer.cpp
vendored
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#include "CompositeOsgRenderer.hpp"
|
||||||
|
#include "osgQOpenGLWidget.hpp"
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <osgViewer/View>
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
CompositeOsgRenderer::CompositeOsgRenderer(QObject* parent)
|
||||||
|
: QObject(parent), osgViewer::CompositeViewer(), mSimulationTime(0.0)
|
||||||
|
{
|
||||||
|
_firstFrame = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompositeOsgRenderer::CompositeOsgRenderer(osg::ArgumentParser* arguments, QObject* parent)
|
||||||
|
: QObject(parent), osgViewer::CompositeViewer(*arguments), mSimulationTime(0.0)
|
||||||
|
{
|
||||||
|
_firstFrame = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompositeOsgRenderer::~CompositeOsgRenderer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompositeOsgRenderer::update()
|
||||||
|
{
|
||||||
|
double dt = mFrameTimer.time_s();
|
||||||
|
mFrameTimer.setStartTick();
|
||||||
|
|
||||||
|
emit simulationUpdated(dt);
|
||||||
|
|
||||||
|
mSimulationTime += dt;
|
||||||
|
osgQOpenGLWidget* osgWidget = dynamic_cast<osgQOpenGLWidget*>(parent());
|
||||||
|
if (osgWidget)
|
||||||
|
{
|
||||||
|
osgWidget->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
double minFrameTime = _runMaxFrameRate > 0.0 ? 1.0 / _runMaxFrameRate : 0.0;
|
||||||
|
if (dt < minFrameTime)
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(std::chrono::duration<double>(minFrameTime - dt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompositeOsgRenderer::resize(int windowWidth, int windowHeight)
|
||||||
|
{
|
||||||
|
if(!m_osgInitialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(RefViews::iterator itr = _views.begin();
|
||||||
|
itr != _views.end();
|
||||||
|
++itr)
|
||||||
|
{
|
||||||
|
osgViewer::View* view = itr->get();
|
||||||
|
if(view)
|
||||||
|
{
|
||||||
|
m_osgWinEmb->resized(0, 0, windowWidth, windowHeight);
|
||||||
|
m_osgWinEmb->getEventQueue()->windowResize(0, 0, windowWidth, windowHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompositeOsgRenderer::setGraphicsWindowEmbedded(osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> osgWinEmb)
|
||||||
|
{
|
||||||
|
m_osgWinEmb = osgWinEmb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompositeOsgRenderer::setupOSG()
|
||||||
|
{
|
||||||
|
m_osgInitialized = true;
|
||||||
|
|
||||||
|
m_osgWinEmb->getEventQueue()->syncWindowRectangleWithGraphicsContext();
|
||||||
|
// disable key event (default is Escape key) that the viewer checks on each
|
||||||
|
// frame to see
|
||||||
|
// if the viewer's done flag should be set to signal end of viewers main
|
||||||
|
// loop.
|
||||||
|
setKeyEventSetsDone(0);
|
||||||
|
setReleaseContextAtEndOfFrameHint(false);
|
||||||
|
setThreadingModel(osgViewer::CompositeViewer::SingleThreaded);
|
||||||
|
|
||||||
|
setRunFrameScheme(osgViewer::ViewerBase::ON_DEMAND);
|
||||||
|
|
||||||
|
connect( &mTimer, SIGNAL(timeout()), this, SLOT(update()) );
|
||||||
|
mTimer.start( 10 );
|
||||||
|
|
||||||
|
osgViewer::CompositeViewer::Windows windows;
|
||||||
|
getWindows(windows);
|
||||||
|
}
|
||||||
|
|
||||||
|
// called from ViewerWidget paintGL() method
|
||||||
|
void CompositeOsgRenderer::frame(double simulationTime)
|
||||||
|
{
|
||||||
|
if(_done) return;
|
||||||
|
|
||||||
|
if(_firstFrame)
|
||||||
|
{
|
||||||
|
viewerInit();
|
||||||
|
realize();
|
||||||
|
_firstFrame = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
advance(simulationTime);
|
||||||
|
|
||||||
|
eventTraversal();
|
||||||
|
updateTraversal();
|
||||||
|
renderingTraversals();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompositeOsgRenderer::timerEvent(QTimerEvent* /*event*/)
|
||||||
|
{
|
||||||
|
// ask ViewerWidget to update 3D view
|
||||||
|
if(getRunFrameScheme() != osgViewer::ViewerBase::ON_DEMAND || checkNeedToDoFrame())
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
46
extern/osgQt/CompositeOsgRenderer.hpp
vendored
Normal file
46
extern/osgQt/CompositeOsgRenderer.hpp
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#ifndef COMPOSITEOSGRENDERER_H
|
||||||
|
#define COMPOSITEOSGRENDERER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <osgViewer/CompositeViewer>
|
||||||
|
|
||||||
|
class CompositeOsgRenderer : public QObject, public osgViewer::CompositeViewer
|
||||||
|
{
|
||||||
|
bool m_osgInitialized {false};
|
||||||
|
osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> m_osgWinEmb;
|
||||||
|
|
||||||
|
osg::Timer mFrameTimer;
|
||||||
|
double mSimulationTime;
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit CompositeOsgRenderer(QObject* parent = nullptr);
|
||||||
|
explicit CompositeOsgRenderer(osg::ArgumentParser* arguments, QObject* parent = nullptr);
|
||||||
|
|
||||||
|
~CompositeOsgRenderer() override;
|
||||||
|
|
||||||
|
virtual void resize(int windowWidth, int windowHeight);
|
||||||
|
|
||||||
|
void setGraphicsWindowEmbedded(osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> osgWinEmb);
|
||||||
|
|
||||||
|
void setupOSG();
|
||||||
|
|
||||||
|
// overrided from osgViewer::ViewerBase
|
||||||
|
void frame(double simulationTime = USE_REFERENCE_TIME) override;
|
||||||
|
|
||||||
|
QTimer mTimer;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void timerEvent(QTimerEvent* event) override;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void update();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void simulationUpdated(double dt);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COMPOSITEOSGRENDERER_H
|
155
extern/osgQt/GraphicsWindowQt
vendored
155
extern/osgQt/GraphicsWindowQt
vendored
@ -1,155 +0,0 @@
|
|||||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009 Wang Rui
|
|
||||||
*
|
|
||||||
* This library is open source and may be redistributed and/or modified under
|
|
||||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
|
||||||
* (at your option) any later version. The full license is in LICENSE file
|
|
||||||
* included with this distribution, and on the openscenegraph.org website.
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* OpenSceneGraph Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef OSGVIEWER_GRAPHICSWINDOWQT
|
|
||||||
#define OSGVIEWER_GRAPHICSWINDOWQT
|
|
||||||
|
|
||||||
#include <osgViewer/GraphicsWindow>
|
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QEvent>
|
|
||||||
#include <QQueue>
|
|
||||||
#include <QSet>
|
|
||||||
#include <QGLWidget>
|
|
||||||
|
|
||||||
class QInputEvent;
|
|
||||||
class QGestureEvent;
|
|
||||||
|
|
||||||
namespace osgViewer {
|
|
||||||
class ViewerBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace osgQt
|
|
||||||
{
|
|
||||||
|
|
||||||
// forward declarations
|
|
||||||
class GraphicsWindowQt;
|
|
||||||
|
|
||||||
class GLWidget : public QGLWidget
|
|
||||||
{
|
|
||||||
typedef QGLWidget inherited;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
GLWidget( QWidget* parent = nullptr, const QGLWidget* shareWidget = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
|
||||||
GLWidget( QGLContext* context, QWidget* parent = nullptr, const QGLWidget* shareWidget = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
|
||||||
GLWidget( const QGLFormat& format, QWidget* parent = nullptr, const QGLWidget* shareWidget = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
|
||||||
virtual ~GLWidget();
|
|
||||||
|
|
||||||
inline void setGraphicsWindow( GraphicsWindowQt* gw ) { _gw = gw; }
|
|
||||||
inline GraphicsWindowQt* getGraphicsWindow() { return _gw; }
|
|
||||||
inline const GraphicsWindowQt* getGraphicsWindow() const { return _gw; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
int getNumDeferredEvents()
|
|
||||||
{
|
|
||||||
QMutexLocker lock(&_deferredEventQueueMutex);
|
|
||||||
return _deferredEventQueue.count();
|
|
||||||
}
|
|
||||||
void enqueueDeferredEvent(QEvent::Type eventType, QEvent::Type removeEventType = QEvent::None)
|
|
||||||
{
|
|
||||||
QMutexLocker lock(&_deferredEventQueueMutex);
|
|
||||||
|
|
||||||
if (removeEventType != QEvent::None)
|
|
||||||
{
|
|
||||||
if (_deferredEventQueue.removeOne(removeEventType))
|
|
||||||
_eventCompressor.remove(eventType);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_eventCompressor.find(eventType) == _eventCompressor.end())
|
|
||||||
{
|
|
||||||
_deferredEventQueue.enqueue(eventType);
|
|
||||||
_eventCompressor.insert(eventType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void processDeferredEvents();
|
|
||||||
|
|
||||||
friend class GraphicsWindowQt;
|
|
||||||
GraphicsWindowQt* _gw;
|
|
||||||
|
|
||||||
QMutex _deferredEventQueueMutex;
|
|
||||||
QQueue<QEvent::Type> _deferredEventQueue;
|
|
||||||
QSet<QEvent::Type> _eventCompressor;
|
|
||||||
|
|
||||||
qreal _devicePixelRatio;
|
|
||||||
|
|
||||||
void resizeEvent( QResizeEvent* event ) override;
|
|
||||||
void moveEvent( QMoveEvent* event ) override;
|
|
||||||
void glDraw() override;
|
|
||||||
bool event( QEvent* event ) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class GraphicsWindowQt : public osgViewer::GraphicsWindow
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GraphicsWindowQt( osg::GraphicsContext::Traits* traits, QWidget* parent = nullptr, const QGLWidget* shareWidget = nullptr, Qt::WindowFlags f = Qt::WindowFlags() );
|
|
||||||
GraphicsWindowQt( GLWidget* widget );
|
|
||||||
virtual ~GraphicsWindowQt();
|
|
||||||
|
|
||||||
inline GLWidget* getGLWidget() { return _widget; }
|
|
||||||
inline const GLWidget* getGLWidget() const { return _widget; }
|
|
||||||
|
|
||||||
/// deprecated
|
|
||||||
inline GLWidget* getGraphWidget() { return _widget; }
|
|
||||||
/// deprecated
|
|
||||||
inline const GLWidget* getGraphWidget() const { return _widget; }
|
|
||||||
|
|
||||||
struct WindowData : public osg::Referenced
|
|
||||||
{
|
|
||||||
WindowData( GLWidget* widget = nullptr, QWidget* parent = nullptr ): _widget(widget), _parent(parent) {}
|
|
||||||
GLWidget* _widget;
|
|
||||||
QWidget* _parent;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool init( QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f );
|
|
||||||
|
|
||||||
static QGLFormat traits2qglFormat( const osg::GraphicsContext::Traits* traits );
|
|
||||||
static void qglFormat2traits( const QGLFormat& format, osg::GraphicsContext::Traits* traits );
|
|
||||||
static osg::GraphicsContext::Traits* createTraits( const QGLWidget* widget );
|
|
||||||
|
|
||||||
bool setWindowRectangleImplementation( int x, int y, int width, int height ) override;
|
|
||||||
void getWindowRectangle( int& x, int& y, int& width, int& height ) override;
|
|
||||||
bool setWindowDecorationImplementation( bool windowDecoration ) override;
|
|
||||||
bool getWindowDecoration() const override;
|
|
||||||
void grabFocus() override;
|
|
||||||
void grabFocusIfPointerInWindow( )override;
|
|
||||||
void raiseWindow() override;
|
|
||||||
void setWindowName( const std::string& name ) override;
|
|
||||||
std::string getWindowName() override;
|
|
||||||
void useCursor( bool cursorOn ) override;
|
|
||||||
void setCursor( MouseCursor cursor ) override;
|
|
||||||
|
|
||||||
bool valid() const override;
|
|
||||||
bool realizeImplementation() override;
|
|
||||||
bool isRealizedImplementation() const override;
|
|
||||||
void closeImplementation() override;
|
|
||||||
bool makeCurrentImplementation() override;
|
|
||||||
bool releaseContextImplementation() override;
|
|
||||||
void swapBuffersImplementation() override;
|
|
||||||
void runOperations() override;
|
|
||||||
|
|
||||||
void requestWarpPointer( float x, float y ) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
friend class GLWidget;
|
|
||||||
GLWidget* _widget;
|
|
||||||
bool _ownsWidget;
|
|
||||||
QCursor _currentCursor;
|
|
||||||
bool _realized;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
615
extern/osgQt/GraphicsWindowQt.cpp
vendored
615
extern/osgQt/GraphicsWindowQt.cpp
vendored
@ -1,615 +0,0 @@
|
|||||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009 Wang Rui
|
|
||||||
*
|
|
||||||
* This library is open source and may be redistributed and/or modified under
|
|
||||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
|
||||||
* (at your option) any later version. The full license is in LICENSE file
|
|
||||||
* included with this distribution, and on the openscenegraph.org website.
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* OpenSceneGraph Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "GraphicsWindowQt"
|
|
||||||
|
|
||||||
#include <osg/DeleteHandler>
|
|
||||||
#include <osgViewer/ViewerBase>
|
|
||||||
#include <QInputEvent>
|
|
||||||
#include <QPointer>
|
|
||||||
#include <QWindow>
|
|
||||||
|
|
||||||
using namespace osgQt;
|
|
||||||
|
|
||||||
#define GETDEVICEPIXELRATIO() devicePixelRatio()
|
|
||||||
|
|
||||||
GLWidget::GLWidget( QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
|
|
||||||
: QGLWidget(parent, shareWidget, f), _gw( nullptr )
|
|
||||||
{
|
|
||||||
_devicePixelRatio = GETDEVICEPIXELRATIO();
|
|
||||||
}
|
|
||||||
|
|
||||||
GLWidget::GLWidget( QGLContext* context, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
|
|
||||||
: QGLWidget(context, parent, shareWidget, f), _gw( nullptr )
|
|
||||||
{
|
|
||||||
_devicePixelRatio = GETDEVICEPIXELRATIO();
|
|
||||||
}
|
|
||||||
|
|
||||||
GLWidget::GLWidget( const QGLFormat& format, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
|
|
||||||
: QGLWidget(format, parent, shareWidget, f), _gw( nullptr )
|
|
||||||
{
|
|
||||||
_devicePixelRatio = GETDEVICEPIXELRATIO();
|
|
||||||
}
|
|
||||||
|
|
||||||
GLWidget::~GLWidget()
|
|
||||||
{
|
|
||||||
// close GraphicsWindowQt and remove the reference to us
|
|
||||||
if( _gw )
|
|
||||||
{
|
|
||||||
_gw->close();
|
|
||||||
_gw->_widget = nullptr;
|
|
||||||
_gw = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWidget::processDeferredEvents()
|
|
||||||
{
|
|
||||||
QQueue<QEvent::Type> deferredEventQueueCopy;
|
|
||||||
{
|
|
||||||
QMutexLocker lock(&_deferredEventQueueMutex);
|
|
||||||
deferredEventQueueCopy = _deferredEventQueue;
|
|
||||||
_eventCompressor.clear();
|
|
||||||
_deferredEventQueue.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!deferredEventQueueCopy.isEmpty())
|
|
||||||
{
|
|
||||||
QEvent event(deferredEventQueueCopy.dequeue());
|
|
||||||
QGLWidget::event(&event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GLWidget::event( QEvent* event )
|
|
||||||
{
|
|
||||||
|
|
||||||
// QEvent::Hide
|
|
||||||
//
|
|
||||||
// workaround "Qt-workaround" that does glFinish before hiding the widget
|
|
||||||
// (the Qt workaround was seen at least in Qt 4.6.3 and 4.7.0)
|
|
||||||
//
|
|
||||||
// Qt makes the context current, performs glFinish, and releases the context.
|
|
||||||
// This makes the problem in OSG multithreaded environment as the context
|
|
||||||
// is active in another thread, thus it can not be made current for the purpose
|
|
||||||
// of glFinish in this thread.
|
|
||||||
|
|
||||||
// QEvent::ParentChange
|
|
||||||
//
|
|
||||||
// Reparenting GLWidget may create a new underlying window and a new GL context.
|
|
||||||
// Qt will then call doneCurrent on the GL context about to be deleted. The thread
|
|
||||||
// where old GL context was current has no longer current context to render to and
|
|
||||||
// we cannot make new GL context current in this thread.
|
|
||||||
|
|
||||||
// We workaround above problems by deferring execution of problematic event requests.
|
|
||||||
// These events has to be enqueue and executed later in a main GUI thread (GUI operations
|
|
||||||
// outside the main thread are not allowed) just before makeCurrent is called from the
|
|
||||||
// right thread. The good place for doing that is right after swap in a swapBuffersImplementation.
|
|
||||||
|
|
||||||
if (event->type() == QEvent::Hide)
|
|
||||||
{
|
|
||||||
// enqueue only the last of QEvent::Hide and QEvent::Show
|
|
||||||
enqueueDeferredEvent(QEvent::Hide, QEvent::Show);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (event->type() == QEvent::Show)
|
|
||||||
{
|
|
||||||
// enqueue only the last of QEvent::Show or QEvent::Hide
|
|
||||||
enqueueDeferredEvent(QEvent::Show, QEvent::Hide);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (event->type() == QEvent::ParentChange)
|
|
||||||
{
|
|
||||||
// enqueue only the last QEvent::ParentChange
|
|
||||||
enqueueDeferredEvent(QEvent::ParentChange);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (event->type() == QEvent::PlatformSurface && static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
|
|
||||||
{
|
|
||||||
if (_gw)
|
|
||||||
_gw->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// perform regular event handling
|
|
||||||
return QGLWidget::event( event );
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWidget::resizeEvent( QResizeEvent* event )
|
|
||||||
{
|
|
||||||
if (_gw == nullptr || !_gw->valid())
|
|
||||||
return;
|
|
||||||
const QSize& size = event->size();
|
|
||||||
|
|
||||||
int scaled_width = static_cast<int>(size.width()*_devicePixelRatio);
|
|
||||||
int scaled_height = static_cast<int>(size.height()*_devicePixelRatio);
|
|
||||||
_gw->resized( x(), y(), scaled_width, scaled_height);
|
|
||||||
_gw->getEventQueue()->windowResize( x(), y(), scaled_width, scaled_height );
|
|
||||||
_gw->requestRedraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWidget::moveEvent( QMoveEvent* event )
|
|
||||||
{
|
|
||||||
if (_gw == nullptr || !_gw->valid())
|
|
||||||
return;
|
|
||||||
const QPoint& pos = event->pos();
|
|
||||||
int scaled_width = static_cast<int>(width()*_devicePixelRatio);
|
|
||||||
int scaled_height = static_cast<int>(height()*_devicePixelRatio);
|
|
||||||
_gw->resized( pos.x(), pos.y(), scaled_width, scaled_height );
|
|
||||||
_gw->getEventQueue()->windowResize( pos.x(), pos.y(), scaled_width, scaled_height );
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWidget::glDraw()
|
|
||||||
{
|
|
||||||
_gw->requestRedraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphicsWindowQt::GraphicsWindowQt( osg::GraphicsContext::Traits* traits, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f )
|
|
||||||
: _realized(false)
|
|
||||||
{
|
|
||||||
|
|
||||||
_widget = nullptr;
|
|
||||||
_traits = traits;
|
|
||||||
init( parent, shareWidget, f );
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphicsWindowQt::GraphicsWindowQt( GLWidget* widget )
|
|
||||||
: _realized(false)
|
|
||||||
{
|
|
||||||
_widget = widget;
|
|
||||||
_traits = _widget ? createTraits( _widget ) : new osg::GraphicsContext::Traits;
|
|
||||||
init( nullptr, nullptr, Qt::WindowFlags() );
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphicsWindowQt::~GraphicsWindowQt()
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
|
|
||||||
// remove reference from GLWidget
|
|
||||||
if ( _widget )
|
|
||||||
_widget->_gw = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt::init( QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f )
|
|
||||||
{
|
|
||||||
// update _widget and parent by WindowData
|
|
||||||
WindowData* windowData = _traits.get() ? dynamic_cast<WindowData*>(_traits->inheritedWindowData.get()) : nullptr;
|
|
||||||
if ( !_widget )
|
|
||||||
_widget = windowData ? windowData->_widget : nullptr;
|
|
||||||
if ( !parent )
|
|
||||||
parent = windowData ? windowData->_parent : nullptr;
|
|
||||||
|
|
||||||
// create widget if it does not exist
|
|
||||||
_ownsWidget = _widget == nullptr;
|
|
||||||
if ( !_widget )
|
|
||||||
{
|
|
||||||
// shareWidget
|
|
||||||
if ( !shareWidget ) {
|
|
||||||
GraphicsWindowQt* sharedContextQt = dynamic_cast<GraphicsWindowQt*>(_traits->sharedContext.get());
|
|
||||||
if ( sharedContextQt )
|
|
||||||
shareWidget = sharedContextQt->getGLWidget();
|
|
||||||
}
|
|
||||||
|
|
||||||
// WindowFlags
|
|
||||||
Qt::WindowFlags flags = f | Qt::Window | Qt::CustomizeWindowHint;
|
|
||||||
if ( _traits->windowDecoration )
|
|
||||||
flags |= Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
|
|
||||||
|
|
||||||
// create widget
|
|
||||||
_widget = new GLWidget( traits2qglFormat( _traits.get() ), parent, shareWidget, flags );
|
|
||||||
}
|
|
||||||
|
|
||||||
// set widget name and position
|
|
||||||
// (do not set it when we inherited the widget)
|
|
||||||
if ( _ownsWidget )
|
|
||||||
{
|
|
||||||
_widget->setWindowTitle( _traits->windowName.c_str() );
|
|
||||||
_widget->move( _traits->x, _traits->y );
|
|
||||||
if ( !_traits->supportsResize ) _widget->setFixedSize( _traits->width, _traits->height );
|
|
||||||
else _widget->resize( _traits->width, _traits->height );
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize widget properties
|
|
||||||
_widget->setAutoBufferSwap( false );
|
|
||||||
_widget->setMouseTracking( true );
|
|
||||||
_widget->setGraphicsWindow( this );
|
|
||||||
useCursor( _traits->useCursor );
|
|
||||||
|
|
||||||
// initialize State
|
|
||||||
setState( new osg::State );
|
|
||||||
getState()->setGraphicsContext(this);
|
|
||||||
|
|
||||||
// initialize contextID
|
|
||||||
if ( _traits.valid() && _traits->sharedContext.valid() )
|
|
||||||
{
|
|
||||||
getState()->setContextID( _traits->sharedContext->getState()->getContextID() );
|
|
||||||
incrementContextIDUsageCount( getState()->getContextID() );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
getState()->setContextID( osg::GraphicsContext::createNewContextID() );
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure the event queue has the correct window rectangle size and input range
|
|
||||||
getEventQueue()->syncWindowRectangleWithGraphicsContext();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QGLFormat GraphicsWindowQt::traits2qglFormat( const osg::GraphicsContext::Traits* traits )
|
|
||||||
{
|
|
||||||
QGLFormat format( QGLFormat::defaultFormat() );
|
|
||||||
|
|
||||||
format.setAlphaBufferSize( traits->alpha );
|
|
||||||
format.setRedBufferSize( traits->red );
|
|
||||||
format.setGreenBufferSize( traits->green );
|
|
||||||
format.setBlueBufferSize( traits->blue );
|
|
||||||
format.setDepthBufferSize( traits->depth );
|
|
||||||
format.setStencilBufferSize( traits->stencil );
|
|
||||||
format.setSampleBuffers( traits->sampleBuffers );
|
|
||||||
format.setSamples( traits->samples );
|
|
||||||
|
|
||||||
format.setAlpha( traits->alpha>0 );
|
|
||||||
format.setDepth( traits->depth>0 );
|
|
||||||
format.setStencil( traits->stencil>0 );
|
|
||||||
format.setDoubleBuffer( traits->doubleBuffer );
|
|
||||||
format.setSwapInterval( traits->vsync ? 1 : 0 );
|
|
||||||
format.setStereo( traits->quadBufferStereo ? 1 : 0 );
|
|
||||||
|
|
||||||
return format;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt::qglFormat2traits( const QGLFormat& format, osg::GraphicsContext::Traits* traits )
|
|
||||||
{
|
|
||||||
traits->red = format.redBufferSize();
|
|
||||||
traits->green = format.greenBufferSize();
|
|
||||||
traits->blue = format.blueBufferSize();
|
|
||||||
traits->alpha = format.alpha() ? format.alphaBufferSize() : 0;
|
|
||||||
traits->depth = format.depth() ? format.depthBufferSize() : 0;
|
|
||||||
traits->stencil = format.stencil() ? format.stencilBufferSize() : 0;
|
|
||||||
|
|
||||||
traits->sampleBuffers = format.sampleBuffers() ? 1 : 0;
|
|
||||||
traits->samples = format.samples();
|
|
||||||
|
|
||||||
traits->quadBufferStereo = format.stereo();
|
|
||||||
traits->doubleBuffer = format.doubleBuffer();
|
|
||||||
|
|
||||||
traits->vsync = format.swapInterval() >= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::GraphicsContext::Traits* GraphicsWindowQt::createTraits( const QGLWidget* widget )
|
|
||||||
{
|
|
||||||
osg::GraphicsContext::Traits *traits = new osg::GraphicsContext::Traits;
|
|
||||||
|
|
||||||
qglFormat2traits( widget->format(), traits );
|
|
||||||
|
|
||||||
QRect r = widget->geometry();
|
|
||||||
traits->x = r.x();
|
|
||||||
traits->y = r.y();
|
|
||||||
traits->width = r.width();
|
|
||||||
traits->height = r.height();
|
|
||||||
|
|
||||||
traits->windowName = widget->windowTitle().toLocal8Bit().data();
|
|
||||||
Qt::WindowFlags f = widget->windowFlags();
|
|
||||||
traits->windowDecoration = ( f & Qt::WindowTitleHint ) &&
|
|
||||||
( f & Qt::WindowMinMaxButtonsHint ) &&
|
|
||||||
( f & Qt::WindowSystemMenuHint );
|
|
||||||
QSizePolicy sp = widget->sizePolicy();
|
|
||||||
traits->supportsResize = sp.horizontalPolicy() != QSizePolicy::Fixed ||
|
|
||||||
sp.verticalPolicy() != QSizePolicy::Fixed;
|
|
||||||
|
|
||||||
return traits;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt::setWindowRectangleImplementation( int x, int y, int width, int height )
|
|
||||||
{
|
|
||||||
if ( _widget == nullptr )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
_widget->setGeometry( x, y, width, height );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt::getWindowRectangle( int& x, int& y, int& width, int& height )
|
|
||||||
{
|
|
||||||
if ( _widget )
|
|
||||||
{
|
|
||||||
const QRect& geom = _widget->geometry();
|
|
||||||
x = geom.x();
|
|
||||||
y = geom.y();
|
|
||||||
width = geom.width();
|
|
||||||
height = geom.height();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt::setWindowDecorationImplementation( bool windowDecoration )
|
|
||||||
{
|
|
||||||
Qt::WindowFlags flags = Qt::Window|Qt::CustomizeWindowHint;//|Qt::WindowStaysOnTopHint;
|
|
||||||
if ( windowDecoration )
|
|
||||||
flags |= Qt::WindowTitleHint|Qt::WindowMinMaxButtonsHint|Qt::WindowSystemMenuHint;
|
|
||||||
_traits->windowDecoration = windowDecoration;
|
|
||||||
|
|
||||||
if ( _widget )
|
|
||||||
{
|
|
||||||
_widget->setWindowFlags( flags );
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt::getWindowDecoration() const
|
|
||||||
{
|
|
||||||
return _traits->windowDecoration;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt::grabFocus()
|
|
||||||
{
|
|
||||||
if ( _widget )
|
|
||||||
_widget->setFocus( Qt::ActiveWindowFocusReason );
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt::grabFocusIfPointerInWindow()
|
|
||||||
{
|
|
||||||
if ( _widget->underMouse() )
|
|
||||||
_widget->setFocus( Qt::ActiveWindowFocusReason );
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt::raiseWindow()
|
|
||||||
{
|
|
||||||
if ( _widget )
|
|
||||||
_widget->raise();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt::setWindowName( const std::string& name )
|
|
||||||
{
|
|
||||||
if ( _widget )
|
|
||||||
_widget->setWindowTitle( name.c_str() );
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GraphicsWindowQt::getWindowName()
|
|
||||||
{
|
|
||||||
return _widget ? _widget->windowTitle().toStdString() : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt::useCursor( bool cursorOn )
|
|
||||||
{
|
|
||||||
if ( _widget )
|
|
||||||
{
|
|
||||||
_traits->useCursor = cursorOn;
|
|
||||||
if ( !cursorOn ) _widget->setCursor( Qt::BlankCursor );
|
|
||||||
else _widget->setCursor( _currentCursor );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt::setCursor( MouseCursor cursor )
|
|
||||||
{
|
|
||||||
if ( cursor==InheritCursor && _widget )
|
|
||||||
{
|
|
||||||
_widget->unsetCursor();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ( cursor )
|
|
||||||
{
|
|
||||||
case NoCursor: _currentCursor = Qt::BlankCursor; break;
|
|
||||||
case RightArrowCursor: case LeftArrowCursor: _currentCursor = Qt::ArrowCursor; break;
|
|
||||||
case InfoCursor: _currentCursor = Qt::SizeAllCursor; break;
|
|
||||||
case DestroyCursor: _currentCursor = Qt::ForbiddenCursor; break;
|
|
||||||
case HelpCursor: _currentCursor = Qt::WhatsThisCursor; break;
|
|
||||||
case CycleCursor: _currentCursor = Qt::ForbiddenCursor; break;
|
|
||||||
case SprayCursor: _currentCursor = Qt::SizeAllCursor; break;
|
|
||||||
case WaitCursor: _currentCursor = Qt::WaitCursor; break;
|
|
||||||
case TextCursor: _currentCursor = Qt::IBeamCursor; break;
|
|
||||||
case CrosshairCursor: _currentCursor = Qt::CrossCursor; break;
|
|
||||||
case HandCursor: _currentCursor = Qt::OpenHandCursor; break;
|
|
||||||
case UpDownCursor: _currentCursor = Qt::SizeVerCursor; break;
|
|
||||||
case LeftRightCursor: _currentCursor = Qt::SizeHorCursor; break;
|
|
||||||
case TopSideCursor: case BottomSideCursor: _currentCursor = Qt::UpArrowCursor; break;
|
|
||||||
case LeftSideCursor: case RightSideCursor: _currentCursor = Qt::SizeHorCursor; break;
|
|
||||||
case TopLeftCorner: _currentCursor = Qt::SizeBDiagCursor; break;
|
|
||||||
case TopRightCorner: _currentCursor = Qt::SizeFDiagCursor; break;
|
|
||||||
case BottomRightCorner: _currentCursor = Qt::SizeBDiagCursor; break;
|
|
||||||
case BottomLeftCorner: _currentCursor = Qt::SizeFDiagCursor; break;
|
|
||||||
default: break;
|
|
||||||
};
|
|
||||||
if ( _widget ) _widget->setCursor( _currentCursor );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt::valid() const
|
|
||||||
{
|
|
||||||
return _widget && _widget->isValid();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt::realizeImplementation()
|
|
||||||
{
|
|
||||||
// save the current context
|
|
||||||
// note: this will save only Qt-based contexts
|
|
||||||
const QGLContext *savedContext = QGLContext::currentContext();
|
|
||||||
|
|
||||||
// initialize GL context for the widget
|
|
||||||
if ( !valid() )
|
|
||||||
_widget->glInit();
|
|
||||||
|
|
||||||
// make current
|
|
||||||
_realized = true;
|
|
||||||
bool result = makeCurrent();
|
|
||||||
_realized = false;
|
|
||||||
|
|
||||||
// fail if we do not have current context
|
|
||||||
if ( !result )
|
|
||||||
{
|
|
||||||
if ( savedContext )
|
|
||||||
const_cast< QGLContext* >( savedContext )->makeCurrent();
|
|
||||||
|
|
||||||
OSG_WARN << "Window realize: Can make context current." << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_realized = true;
|
|
||||||
|
|
||||||
// make sure the event queue has the correct window rectangle size and input range
|
|
||||||
getEventQueue()->syncWindowRectangleWithGraphicsContext();
|
|
||||||
|
|
||||||
// make this window's context not current
|
|
||||||
// note: this must be done as we will probably make the context current from another thread
|
|
||||||
// and it is not allowed to have one context current in two threads
|
|
||||||
if( !releaseContext() )
|
|
||||||
OSG_WARN << "Window realize: Can not release context." << std::endl;
|
|
||||||
|
|
||||||
// restore previous context
|
|
||||||
if ( savedContext )
|
|
||||||
const_cast< QGLContext* >( savedContext )->makeCurrent();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt::isRealizedImplementation() const
|
|
||||||
{
|
|
||||||
return _realized;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt::closeImplementation()
|
|
||||||
{
|
|
||||||
if ( _widget )
|
|
||||||
_widget->close();
|
|
||||||
_realized = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt::runOperations()
|
|
||||||
{
|
|
||||||
// While in graphics thread this is last chance to do something useful before
|
|
||||||
// graphics thread will execute its operations.
|
|
||||||
if (_widget->getNumDeferredEvents() > 0)
|
|
||||||
_widget->processDeferredEvents();
|
|
||||||
|
|
||||||
if (QGLContext::currentContext() != _widget->context())
|
|
||||||
_widget->makeCurrent();
|
|
||||||
|
|
||||||
GraphicsWindow::runOperations();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt::makeCurrentImplementation()
|
|
||||||
{
|
|
||||||
if (_widget->getNumDeferredEvents() > 0)
|
|
||||||
_widget->processDeferredEvents();
|
|
||||||
|
|
||||||
_widget->makeCurrent();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt::releaseContextImplementation()
|
|
||||||
{
|
|
||||||
_widget->doneCurrent();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt::swapBuffersImplementation()
|
|
||||||
{
|
|
||||||
// QOpenGLContext complains if we swap on an non-exposed QWindow
|
|
||||||
if (!_widget || !_widget->windowHandle()->isExposed())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// FIXME: the processDeferredEvents should really be executed in a GUI (main) thread context but
|
|
||||||
// I couln't find any reliable way to do this. For now, lets hope non of *GUI thread only operations* will
|
|
||||||
// be executed in a QGLWidget::event handler. On the other hand, calling GUI only operations in the
|
|
||||||
// QGLWidget event handler is an indication of a Qt bug.
|
|
||||||
if (_widget->getNumDeferredEvents() > 0)
|
|
||||||
_widget->processDeferredEvents();
|
|
||||||
|
|
||||||
// We need to call makeCurrent here to restore our previously current context
|
|
||||||
// which may be changed by the processDeferredEvents function.
|
|
||||||
_widget->makeCurrent();
|
|
||||||
_widget->swapBuffers();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt::requestWarpPointer( float x, float y )
|
|
||||||
{
|
|
||||||
if ( _widget )
|
|
||||||
QCursor::setPos( _widget->mapToGlobal(QPoint((int)x,(int)y)) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class QtWindowingSystem : public osg::GraphicsContext::WindowingSystemInterface
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
QtWindowingSystem()
|
|
||||||
{
|
|
||||||
OSG_INFO << "QtWindowingSystemInterface()" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
~QtWindowingSystem()
|
|
||||||
{
|
|
||||||
if (osg::Referenced::getDeleteHandler())
|
|
||||||
{
|
|
||||||
osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
|
|
||||||
osg::Referenced::getDeleteHandler()->flushAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Access the Qt windowing system through this singleton class.
|
|
||||||
static QtWindowingSystem* getInterface()
|
|
||||||
{
|
|
||||||
static QtWindowingSystem* qtInterface = new QtWindowingSystem;
|
|
||||||
return qtInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the number of screens present in the system
|
|
||||||
unsigned int getNumScreens( const osg::GraphicsContext::ScreenIdentifier& /*si*/ ) override
|
|
||||||
{
|
|
||||||
OSG_WARN << "osgQt: getNumScreens() not implemented yet." << std::endl;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the resolution of specified screen
|
|
||||||
// (0,0) is returned if screen is unknown
|
|
||||||
void getScreenSettings( const osg::GraphicsContext::ScreenIdentifier& /*si*/, osg::GraphicsContext::ScreenSettings & /*resolution*/ ) override
|
|
||||||
{
|
|
||||||
OSG_WARN << "osgQt: getScreenSettings() not implemented yet." << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the resolution for given screen
|
|
||||||
bool setScreenSettings( const osg::GraphicsContext::ScreenIdentifier& /*si*/, const osg::GraphicsContext::ScreenSettings & /*resolution*/ ) override
|
|
||||||
{
|
|
||||||
OSG_WARN << "osgQt: setScreenSettings() not implemented yet." << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enumerates available resolutions
|
|
||||||
void enumerateScreenSettings( const osg::GraphicsContext::ScreenIdentifier& /*screenIdentifier*/, osg::GraphicsContext::ScreenSettingsList & /*resolution*/ ) override
|
|
||||||
{
|
|
||||||
OSG_WARN << "osgQt: enumerateScreenSettings() not implemented yet." << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a graphics context with given traits
|
|
||||||
osg::GraphicsContext* createGraphicsContext( osg::GraphicsContext::Traits* traits ) override
|
|
||||||
{
|
|
||||||
if (traits->pbuffer)
|
|
||||||
{
|
|
||||||
OSG_WARN << "osgQt: createGraphicsContext - pbuffer not implemented yet." << std::endl;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
osg::ref_ptr< GraphicsWindowQt > window = new GraphicsWindowQt( traits );
|
|
||||||
if (window->valid()) return window.release();
|
|
||||||
else return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// No implementation for these
|
|
||||||
QtWindowingSystem( const QtWindowingSystem& );
|
|
||||||
QtWindowingSystem& operator=( const QtWindowingSystem& );
|
|
||||||
};
|
|
||||||
|
|
98
extern/osgQt/osgQOpenGLWidget.cpp
vendored
Normal file
98
extern/osgQt/osgQOpenGLWidget.cpp
vendored
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#include "CompositeOsgRenderer.hpp"
|
||||||
|
#include "osgQOpenGLWidget.hpp"
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <osgViewer/View>
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QScreen>
|
||||||
|
#include <QWindow>
|
||||||
|
|
||||||
|
osgQOpenGLWidget::osgQOpenGLWidget(QWidget* parent)
|
||||||
|
: QOpenGLWidget(parent)
|
||||||
|
{
|
||||||
|
m_renderer = new CompositeOsgRenderer(this);
|
||||||
|
setMouseTracking(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
osgQOpenGLWidget::osgQOpenGLWidget(osg::ArgumentParser* arguments,
|
||||||
|
QWidget* parent) :
|
||||||
|
QOpenGLWidget(parent),
|
||||||
|
_arguments(arguments)
|
||||||
|
{
|
||||||
|
m_renderer = new CompositeOsgRenderer(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
osgQOpenGLWidget::~osgQOpenGLWidget()
|
||||||
|
{
|
||||||
|
if (m_renderer) delete m_renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
osgViewer::View* osgQOpenGLWidget::getOsgView(unsigned i)
|
||||||
|
{
|
||||||
|
if (m_renderer) return m_renderer->getView(i);
|
||||||
|
else return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::mutex* osgQOpenGLWidget::mutex()
|
||||||
|
{
|
||||||
|
return &_osgMutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void osgQOpenGLWidget::initializeGL()
|
||||||
|
{
|
||||||
|
// Initializes OpenGL function resolution for the current context.
|
||||||
|
initializeOpenGLFunctions();
|
||||||
|
createRenderer();
|
||||||
|
emit initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void osgQOpenGLWidget::resizeGL(int w, int h)
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_renderer);
|
||||||
|
QScreen* screen = windowHandle()
|
||||||
|
&& windowHandle()->screen() ? windowHandle()->screen() :
|
||||||
|
qApp->screens().front();
|
||||||
|
m_renderer->resize(w * screen->devicePixelRatio(), h * screen->devicePixelRatio());
|
||||||
|
}
|
||||||
|
|
||||||
|
void osgQOpenGLWidget::paintGL()
|
||||||
|
{
|
||||||
|
std::scoped_lock locker(_osgMutex);
|
||||||
|
if (_isFirstFrame)
|
||||||
|
{
|
||||||
|
_isFirstFrame = false;
|
||||||
|
for (unsigned int i = 0; i < m_renderer->getNumViews(); ++i)
|
||||||
|
{
|
||||||
|
m_renderer->getView(i)->getCamera()->getGraphicsContext()->setDefaultFboId(defaultFramebufferObject());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_renderer->frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void osgQOpenGLWidget::setDefaultDisplaySettings()
|
||||||
|
{
|
||||||
|
osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
|
||||||
|
ds->setNvOptimusEnablement(1);
|
||||||
|
ds->setStereo(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
CompositeOsgRenderer* osgQOpenGLWidget::getCompositeViewer()
|
||||||
|
{
|
||||||
|
if (m_renderer) return m_renderer;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void osgQOpenGLWidget::setGraphicsWindowEmbedded(osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> osgWinEmb)
|
||||||
|
{
|
||||||
|
if (m_renderer) m_renderer->setGraphicsWindowEmbedded(osgWinEmb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void osgQOpenGLWidget::createRenderer()
|
||||||
|
{
|
||||||
|
// call this before creating a View...
|
||||||
|
setDefaultDisplaySettings();
|
||||||
|
if (!m_renderer) m_renderer = new CompositeOsgRenderer(this);
|
||||||
|
|
||||||
|
m_renderer->setupOSG();
|
||||||
|
}
|
70
extern/osgQt/osgQOpenGLWidget.hpp
vendored
Normal file
70
extern/osgQt/osgQOpenGLWidget.hpp
vendored
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#ifndef OSGQOPENGLWIDGET_H
|
||||||
|
#define OSGQOPENGLWIDGET_H
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <osg/GL>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <osg/ArgumentParser>
|
||||||
|
|
||||||
|
#include <QOpenGLWidget>
|
||||||
|
#include <QOpenGLFunctions>
|
||||||
|
#include <QReadWriteLock>
|
||||||
|
|
||||||
|
class CompositeOsgRenderer;
|
||||||
|
|
||||||
|
namespace osgViewer
|
||||||
|
{
|
||||||
|
class View;
|
||||||
|
class GraphicsWindowEmbedded;
|
||||||
|
}
|
||||||
|
|
||||||
|
class osgQOpenGLWidget : public QOpenGLWidget,
|
||||||
|
protected QOpenGLFunctions
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CompositeOsgRenderer* m_renderer {nullptr};
|
||||||
|
std::mutex _osgMutex;
|
||||||
|
osg::ArgumentParser* _arguments {nullptr};
|
||||||
|
bool _isFirstFrame {true};
|
||||||
|
|
||||||
|
friend class CompositeOsgRenderer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
osgQOpenGLWidget(QWidget* parent = nullptr);
|
||||||
|
osgQOpenGLWidget(osg::ArgumentParser* arguments, QWidget* parent = nullptr);
|
||||||
|
virtual ~osgQOpenGLWidget();
|
||||||
|
|
||||||
|
/** Get osgViewer View */
|
||||||
|
virtual osgViewer::View* getOsgView(unsigned i);
|
||||||
|
|
||||||
|
//! get mutex
|
||||||
|
virtual std::mutex* mutex();
|
||||||
|
|
||||||
|
CompositeOsgRenderer* getCompositeViewer();
|
||||||
|
|
||||||
|
void setGraphicsWindowEmbedded(osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> osgWinEmb);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void initialized();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//! call createRender. If overloaded, this method must send initialized signal at end
|
||||||
|
void initializeGL() override;
|
||||||
|
|
||||||
|
void resizeGL(int w, int h) override;
|
||||||
|
|
||||||
|
//! lock scene graph and call osgViewer::frame()
|
||||||
|
void paintGL() override;
|
||||||
|
|
||||||
|
//! called before creating renderer
|
||||||
|
virtual void setDefaultDisplaySettings();
|
||||||
|
|
||||||
|
void createRenderer();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // OSGQOPENGLWIDGET_H
|
Loading…
x
Reference in New Issue
Block a user