1#include <glbinding-aux/ContextInfo.h>
2#include <glbinding-aux/debug.h>
3#include <glbinding-aux/types_to_string.h>
4#include <glbinding/Binding.h>
5#include <glbinding/glbinding.h>
7#include <glbinding/Version.h>
9#include <glbinding/gl/gl.h>
11#include <globjects/globjects.h>
14#include <Gui/Viewer/Viewer.hpp>
18#include <QOpenGLContext>
20#include <QApplication>
25#define STB_IMAGE_WRITE_IMPLEMENTATION
26#include <stb/stb_image_write.h>
28#include <Core/Asset/Camera.hpp>
29#include <Core/Asset/FileData.hpp>
30#include <Core/Containers/MakeShared.hpp>
31#include <Core/Math/Math.hpp>
32#include <Core/Utils/Color.hpp>
33#include <Core/Utils/Log.hpp>
34#include <Core/Utils/StringUtils.hpp>
35#include <Engine/Data/ShaderProgramManager.hpp>
36#include <Engine/Data/ViewingParameters.hpp>
37#include <Engine/Rendering/ForwardRenderer.hpp>
38#include <Engine/Rendering/Renderer.hpp>
39#include <Engine/Scene/CameraComponent.hpp>
40#include <Engine/Scene/CameraManager.hpp>
41#include <Engine/Scene/Component.hpp>
42#include <Engine/Scene/DirLight.hpp>
43#include <Engine/Scene/EntityManager.hpp>
45#include <Gui/AboutDialog/RadiumHelpDialog.hpp>
46#include <Gui/Utils/KeyMappingManager.hpp>
47#include <Gui/Utils/Keyboard.hpp>
48#include <Gui/Utils/PickingManager.hpp>
49#include <Gui/Viewer/FlightCameraManipulator.hpp>
50#include <Gui/Viewer/Gizmo/GizmoManager.hpp>
51#include <Gui/Viewer/RotateAroundCameraManipulator.hpp>
52#include <Gui/Viewer/TrackballCameraManipulator.hpp>
53#include <Gui/Viewer/Viewer.hpp>
55#include <QApplication>
63using namespace Core::Utils;
64using namespace glbinding;
66using ViewerMapping = KeyMappingManageable<Viewer>;
68#define KMA_VALUE( x ) KeyMappingManager::KeyMappingAction Viewer::x;
75 auto keyMappingManager = KeyMappingManager::getInstance();
80 keyMappingManager->addListener(
87 m_keyMappingCallbackManager.
addEventCallback( VIEWER_TOGGLE_WIREFRAME, [
this]( QEvent* event ) {
88 if ( event->type() == QEvent::KeyPress ) m_currentRenderer->
toggleWireframe();
90 m_keyMappingCallbackManager.
addEventCallback( VIEWER_RELOAD_SHADERS, [
this]( QEvent* event ) {
94 VIEWER_PICKING_MULTI_CIRCLE, [
this]( QEvent* event ) {
95 if ( event->type() == QEvent::KeyPress ) {
96 m_isBrushPickingEnabled = !m_isBrushPickingEnabled;
97 m_currentRenderer->setBrushRadius( m_isBrushPickingEnabled ? m_brushRadius : 0 );
101 m_keyMappingCallbackManager.
addEventCallback( VIEWER_SWITCH_CAMERA, []( QEvent* event ) {
102 if ( event->type() == QEvent::KeyPress ) {
104 Engine::RadiumEngine::getInstance()->getSystem(
"DefaultCameraManager" ) );
106 if ( cameraManager->count() > 0 ) {
107 idx %= cameraManager->count();
108 cameraManager->activate( idx );
114 m_keyMappingCallbackManager.
addEventCallback( VIEWER_CAMERA_FIT_SCENE, [
this]( QEvent* event ) {
115 if ( event->type() == QEvent::KeyPress ) fitCamera();
117 m_keyMappingCallbackManager.
addEventCallback( VIEWER_HELP, [
this]( QEvent* event ) {
118 if ( event->type() == QEvent::KeyPress ) {
125void Viewer::configureKeyMapping_impl() {
126 auto keyMappingManager = KeyMappingManager::getInstance();
127 ViewerMapping::setContext( keyMappingManager->getContext(
"ViewerContext" ) );
128 if ( ViewerMapping::getContext().isInvalid() ) {
130 <<
"ViewerContext not defined (maybe the configuration file do not contains it)";
131 LOG( Ra::Core::Utils::logERROR ) <<
"ViewerContext all keymapping invalide !";
135#define KMA_VALUE( XX ) XX = keyMappingManager->getAction( ViewerMapping::getContext(), #XX );
142 m_currentRenderer( nullptr ),
143 m_pickingManager( new PickingManager() ),
144 m_isBrushPickingEnabled( false ),
147 m_gizmoManager( nullptr ),
148 m_keyMappingCallbackManager {
ViewerMapping::getContext() } {}
151 if ( m_glInitialized.load() ) {
169void Viewer::resetToDefaultCamera() {
172 Engine::RadiumEngine::getInstance()->getSystem(
"DefaultCameraManager" ) );
181 return m_currentRenderer;
185 return m_currentRenderer;
192 if ( m_glInitialized.load() ) {
195 LOG( logINFO ) <<
"[Viewer] New Renderer (" << e->getRendererName() <<
") added.";
199 LOG( logINFO ) <<
"[Viewer] New Renderer (" << e->getRendererName()
200 <<
") added with deferred init.";
201 m_pendingRenderers.push_back( e );
220 CORE_ASSERT( m_glInitialized.load(),
"OpenGL needs to be initialized before rendering." );
222 CORE_ASSERT( m_currentRenderer !=
nullptr,
"No renderer found." );
228 auto entityManager = Engine::RadiumEngine::getInstance()->getEntityManager();
229 if ( entityManager ) {
235 for (
const auto& entity : entityManager->getEntities() ) {
237 aabb.extend( entity->computeAabb() );
240 if ( !aabb.isEmpty() ) {
m_camera->getCamera()->fitZRange( aabb ); }
243 Engine::RadiumEngine::getInstance()->getSystem(
"DefaultCameraManager" ) );
246 m_camera->setCameraZNear( cameraManager->defaultCamera.getZNear() );
247 m_camera->setCameraZFar( cameraManager->defaultCamera.getZFar() );
253 if ( !m_currentRenderer->
hasLight() ) {
257 LOG( logDEBUG ) <<
"Unable to attach the head light!";
260 m_camera->getCamera()->getViewMatrix(),
m_camera->getCamera()->getProjMatrix(), dt };
261 m_currentRenderer->
render( data );
265 if ( isExposed() ) { m_context->swapBuffers(
this ); }
270 CORE_ASSERT( m_glInitialized.load(),
"OpenGL needs to be initialized before rendering." );
272 CORE_ASSERT( m_currentRenderer !=
nullptr,
"No renderer found." );
276 "There should be one result per query." );
282 if ( query.m_purpose == Engine::Rendering::Renderer::PickingPurpose::MANIPULATION ) {
291 if ( !aabb.isEmpty() ) {
292 CORE_ASSERT(
m_camera !=
nullptr,
"No camera found." );
299 else { LOG( logINFO ) <<
"Unable to fit the camera to the scene : empty Bbox."; }
302void Viewer::fitCamera() {
303 auto aabb = Ra::Engine::RadiumEngine::getInstance()->computeSceneAabb();
312 if ( renderer ) { ret.
push_back( renderer->getRendererName() ); }
322 auto writtenPixels = m_currentRenderer->
grabFrame( w, h );
324 std::string ext = Core::Utils::getFileExt( filename );
326 if ( ext ==
"bmp" ) { stbi_write_bmp( filename.
c_str(), w, h, 4, writtenPixels.get() ); }
327 else if ( ext ==
"png" ) {
328 stbi_write_png( filename.
c_str(), w, h, 4, writtenPixels.get(), w * 4 *
sizeof( uchar ) );
331 LOG( logWARNING ) <<
"Cannot write frame to " << filename <<
" : unsupported extension";
337void Viewer::enableDebug() {
338 glbinding::setCallbackMask( glbinding::CallbackMask::After |
339 glbinding::CallbackMask::ParametersAndReturnValue );
340 glbinding::setAfterCallback( [](
const glbinding::FunctionCall& call ) {
341 std::cerr << call.function->name() <<
"(";
342 for (
unsigned i = 0; i < call.parameters.size(); ++i ) {
344 if ( i < call.parameters.size() - 1 ) {
std::cerr <<
", "; }
347 if ( call.returnValue ) {
std::cerr <<
" -> " << call.returnValue.get(); }
353 CORE_ASSERT( m_glInitialized.load(),
"OpenGL needs to be initialized reload shaders." );
366 CORE_ASSERT( m_glInitialized.load(),
"OpenGL needs to be initialized to display textures." );
378 if ( m_glInitialized.load() &&
m_renderers[index] ) {
381 if ( m_currentRenderer !=
nullptr ) { m_currentRenderer->
lockRendering(); }
385 auto deviceSize =
toDevice( { width(), height() } );
386 m_currentRenderer->
resize( deviceSize.x(), deviceSize.y() );
391 LOG( logINFO ) <<
"[Viewer] Set active renderer: " << m_currentRenderer->
getRendererName();
394 if (
m_camera ) {
m_camera->getCamera()->setViewport( deviceSize.x(), deviceSize.y() ); }
414 m_backgroundColor = background;
416 renderer->setBackgroundColor( m_backgroundColor );
421void Viewer::onAboutToCompose() {
427void Viewer::onAboutToResize() {
433void Viewer::onResized() {
438void Viewer::onFrameSwapped() {
449 auto deviceSize =
toDevice( { width(), height() } );
453 gl::glViewport( 0, 0, deviceSize.x(), deviceSize.y() );
455 renderer->
initialize( deviceSize.x(), deviceSize.y() );
461 globjects::init( getProcAddress );
463 m_glInitialized =
true;
465 LOG( logINFO ) <<
"*** Radium Engine OpenGL context ***";
466 LOG( logINFO ) <<
"Renderer (glbinding) : " << glbinding::aux::ContextInfo::renderer();
467 LOG( logINFO ) <<
"Vendor (glbinding) : " << glbinding::aux::ContextInfo::vendor();
468 LOG( logINFO ) <<
"OpenGL (glbinding) : "
469 << glbinding::aux::ContextInfo::version().toString();
470 LOG( logINFO ) <<
"GLSL : "
471 << gl::glGetString( gl::GLenum( GL_SHADING_LANGUAGE_VERSION ) );
473 LOG( logINFO ) <<
"*** Radium Engine Viewer ***";
480 auto deviceSize =
toDevice( { width(), height() } );
482 m_camera = std::make_unique<TrackballCameraManipulator>();
483 m_camera->getCamera()->setViewport( deviceSize.x(), deviceSize.y() );
487 Ra::Engine::Scene::SystemEntity::getInstance(),
"headlight" );
488 headlight->setColor( Ra::Core::Utils::Color::Grey( 1.0_ra ) );
494 Engine::RadiumEngine::getInstance()->getSystem(
"DefaultCameraManager" ) );
496 [
this, size = deviceSize]( Core::Utils::Index ) {
498 m_camera->getCamera()->setViewport( size.x(), size.y() );
502 for (
auto& rptr : m_pendingRenderers ) {
505 m_pendingRenderers.clear();
511 emit glInitialized();
516 LOG( logINFO ) <<
"[Viewer] No renderer added, adding default (Forward Renderer)";
524 return m_glInitialized;
530 auto deviceSize =
toDevice( {
event->size().width(),
event->size().height() } );
531 gl::glViewport( 0, 0, deviceSize.x(), deviceSize.y() );
532 m_camera->getCamera()->setViewport( deviceSize.x(), deviceSize.y() );
533 m_currentRenderer->
resize( deviceSize.x(), deviceSize.y() );
540 if ( action == VIEWER_PICKING_VERTEX ) {
544 if ( action == VIEWER_PICKING_EDGE ) {
548 if ( action == VIEWER_PICKING_TRIANGLE ) {
556void Viewer::propagateEventToParent( QEvent* event ) {
558 if ( !isTopLevel() ) { QApplication::sendEvent( parent(), event ); }
561void Viewer::keyPressEvent( QKeyEvent* event ) {
562 keyPressed( event->key() );
563 if ( !m_glInitialized.load() || event->isAutoRepeat() || !handleKeyPressEvent( event ) )
564 propagateEventToParent( event );
569void Viewer::keyReleaseEvent( QKeyEvent* event ) {
570 if ( !m_glInitialized.load() || !handleKeyReleaseEvent( event ) )
571 propagateEventToParent( event );
574 keyReleased( event->key() );
578 if ( !m_glInitialized.load() ) {
579 propagateEventToParent( event );
583 m_currentRenderer->setMousePosition(
toDevice( {
event->pos().x(),
event->pos().y() } ) );
586 auto result = pickAtPosition(
toDevice( {
event->pos().x(), height() -
event->pos().y() } ) );
587 m_depthUnderMouse = result.getDepth();
595 handleMouseReleaseEvent( event );
601 if ( !m_glInitialized.load() ) {
606 m_currentRenderer->setMousePosition(
toDevice( {
event->pos().x(),
event->pos().y() } ) );
608 auto result = pickAtPosition(
toDevice( {
event->pos().x(), height() -
event->pos().y() } ) );
609 m_depthUnderMouse = result.getDepth();
611 handleMouseMoveEvent( event, result );
618 if ( !m_glInitialized.load() ) {
623 handleWheelEvent( event );
628void Viewer::showEvent( QShowEvent* ev ) {
629 WindowQt::showEvent( ev );
630 auto deviceSize =
toDevice( { width(), height() } );
631 m_camera->getCamera()->setViewport( deviceSize.x(), deviceSize.y() );
643Viewer::getComponentActions(
const Qt::MouseButtons& buttons,
644 const Qt::KeyboardModifiers& modifiers,
647 auto keyMap = KeyMappingManager::getInstance();
650 keyMap->getAction( keyMap->getContext(
"CameraContext" ), buttons, modifiers, key, wheel );
652 keyMap->getAction( keyMap->getContext(
"GizmoContext" ), buttons, modifiers, key, wheel );
654 keyMap->getAction( keyMap->getContext(
"ViewerContext" ), buttons, modifiers, key, wheel );
655 return { actionCamera, actionGizmo, actionViewer };
658bool Viewer::handleKeyPressEvent( QKeyEvent* event ) {
659 bool eventCatched =
false;
661 auto [actionCamera, actionGizmo, actionViewer] =
662 getComponentActions( Qt::NoButton, event->modifiers(), activeKey(),
false );
667 if ( actionCamera.isValid() ) {
668 eventCatched =
m_camera->handleKeyPressEvent( event, actionCamera );
670 else if ( actionGizmo.isValid() ) {
675 else if ( actionViewer.isValid() ) {
681bool Viewer::handleKeyReleaseEvent( QKeyEvent* event ) {
682 bool eventCatched =
false;
686 auto [actionCamera, actionGizmo, actionViewer] =
687 getComponentActions( Qt::NoButton, event->modifiers(), activeKey(),
false );
689 if ( actionCamera.isValid() ) {
690 eventCatched =
m_camera->handleKeyReleaseEvent( event, actionCamera );
692 else if ( actionViewer.isValid() ) {
710 m_activeContext.setInvalid();
712 auto keyMap = KeyMappingManager::getInstance();
714 auto buttons =
event->buttons();
715 auto modifiers =
event->modifiers();
716 auto key = activeKey();
719 if ( result.getRoIdx().isInvalid() ) {
720 if (
m_camera->handleMousePressEvent( event, buttons, modifiers, key ) ) {
721 m_activeContext =
m_camera->mappingContext();
725 m_activeContext = KeyMappingManageable::getContext();
733 event, buttons, modifiers, key, *
m_camera->getCamera() ) ) {
734 m_activeContext = GizmoManager::getContext();
736 else if (
m_camera->handleMousePressEvent( event, buttons, modifiers, key ) ) {
737 m_activeContext =
m_camera->mappingContext();
740 m_activeContext = KeyMappingManageable::getContext();
741 auto action = keyMap->getAction( m_activeContext, buttons, modifiers, key );
742 auto pickingMode = getPickingMode( action );
747 toDevice( {
event->x(), height() -
event->y() } ),
748 Engine::Rendering::Renderer::PickingPurpose::MANIPULATION,
756void Viewer::handleMouseReleaseEvent( QMouseEvent* event ) {
757 if ( m_activeContext ==
m_camera->mappingContext() ) {
758 m_camera->handleMouseReleaseEvent( event );
760 if ( m_activeContext == GizmoManager::getContext() ) {
763 m_activeContext.setInvalid();
766void Viewer::handleMouseMoveEvent( QMouseEvent* event,
769 auto keyMap = KeyMappingManager::getInstance();
770 auto buttons =
event->buttons();
771 auto modifiers =
event->modifiers();
772 auto key = activeKey();
776 if ( m_activeContext ==
m_camera->mappingContext() ) {
777 m_camera->handleMouseMoveEvent( event, buttons, modifiers, key );
779 else if ( m_activeContext == GizmoManager::getContext() ) {
781 event, buttons, modifiers, key, *
m_camera->getCamera() );
783 else if ( m_activeContext == KeyMappingManageable::getContext() ) {
784 auto action = keyMap->getAction( m_activeContext, buttons, modifiers, key );
785 auto pickingMode = getPickingMode( action );
787 Engine::Rendering::Renderer::PickingQuery query = {
788 toDevice( {
event->x(), height() -
event->y() } ),
789 Engine::Rendering::Renderer::PickingPurpose::MANIPULATION,
797void Viewer::handleWheelEvent( QWheelEvent* event ) {
799 auto keyMap = KeyMappingManager::getInstance();
800 auto buttons =
event->buttons();
801 auto modifiers =
event->modifiers();
802 auto key = activeKey();
804 keyMap->getAction( KeyMappingManageable::getContext(), buttons, modifiers, key,
true );
806 if ( action == VIEWER_SCALE_BRUSH && m_isBrushPickingEnabled ) {
808 (
event->angleDelta().y() * 0.01 + event->angleDelta().x() * 0.01 ) > 0 ? 5 : -5;
809 m_brushRadius =
std::max( m_brushRadius, Scalar( 5 ) );
810 m_currentRenderer->setBrushRadius( m_brushRadius );
812 else {
m_camera->handleWheelEvent( event, buttons, modifiers, key ); }
819 Engine::Rendering::Renderer::PickingPurpose::SELECTION,
821 {
m_camera->getCamera()->getViewMatrix(),
m_camera->getCamera()->getProjMatrix(), 0. } );
832 auto aabb = Ra::Engine::RadiumEngine::getInstance()->computeSceneAabb();
841void Viewer::displayHelpDialog() {
842 if ( !m_helpDialog ) { m_helpDialog.
reset(
new RadiumHelpDialog() ); }
843 m_helpDialog->show();
844 m_helpDialog->raise();
845 m_helpDialog->activateWindow();
int attach(Observer observer)
Result of a PickingQuery.
void render(const Data::ViewingParameters &renderData)
Tell the renderer it needs to render. This method does the following steps :
void initialize(uint width, uint height)
Initialize renderer.
PickingResult doPickingNow(const PickingQuery &query, const Data::ViewingParameters &renderData)
virtual void displayTexture(const std::string &texName)
Change the texture that is displayed on screen. Set m_displayedIsDepth to true if depth linearization...
void addPickingRequest(const PickingQuery &query)
virtual std::string getRendererName() const =0
Get the name of the renderer, e.g to be displayed in the UI.
void resize(uint width, uint height)
Resize the viewport and all the screen textures, fbos. This function must be overrided as soon as som...
void enableDebugDraw(bool enabled)
void enablePostProcess(bool enabled)
bool hasLight() const
Tell if the renderer has an usable light.
virtual void addLight(const Scene::Light *light)
int buildAllRenderTechniques() const
void setBackgroundColor(const Core::Utils::Color &color)
Update the background color (does not trigger a redraw)
virtual void reloadShaders()
virtual std::unique_ptr< uchar[]> grabFrame(size_t &w, size_t &h) const
@ C_VERTEX
Picks all vertices of a mesh within a screen space circle.
@ C_TRIANGLE
Picks all triangles of a mesh within a screen space circle.
@ C_EDGE
Picks all edges of a mesh within a screen space circle.
@ TRIANGLE
Pick a triangle of a mesh.
@ EDGE
Pick an edge of a mesh.
@ VERTEX
Pick a vertex of a mesh.
const std::vector< PickingResult > & getPickingResults() const
const std::vector< PickingQuery > & getPickingQueries() const
void resetActiveCamera()
reset the active camera data to default camera
Core::Utils::Observable< Core::Utils::Index > & activeCameraObservers()
get a ref to active camera observers to add/remove an observer
The CameraManipulator class is the generic class for camera manipulators.
virtual void resetCamera()=0
Reset the Camera settings to default values.
void updateValues() override
Retrieve the transform from the editable and update the gizmos.
virtual bool handleMouseMoveEvent(QMouseEvent *event, const Qt::MouseButtons &buttons, const Qt::KeyboardModifiers &modifiers, int key, const Core::Asset::Camera &cam)
void handlePickingResult(int drawableId)
Callback when a drawable is picked.
This class manage a collection of binding/callback associated with a context.
bool triggerEventCallback(QEvent *event, int key, bool wheel=false)
void addEventCallback(KeyMappingAction action, Callback callback)
KeyMappingManager::KeyMappingAction addActionAndCallback(const std::string &actionName, const KeyMappingManager::EventBinding &binding, Callback callback)
static void configureKeyMapping()
Inner class to store event binding.
Ra::Core::Utils::Index KeyMappingAction
handle to an action
virtual bool prepareDisplay()
void resizeGL(QResizeEvent *event) override
Resize the view port and the camera. Called by the resize event.
std::unique_ptr< CameraManipulator > m_camera
Owning pointer to the camera.
void startRendering(const Scalar dt)
Start rendering (potentially asynchronously in a separate thread)
bool initializeGL() override
void initializeRenderer(Engine::Rendering::Renderer *renderer)
Initialize renderer internal state + configure lights.
void enableDebugDraw(int enabled)
Toggle the debug drawing.
void swapBuffers()
Blocks until rendering is finished.
PickingManager * m_pickingManager
Owning Pointer to the feature picking manager.
void rendererReady()
Emitted when GL context is ready. We except call to addRenderer here.
void requestEngineOpenGLInitialization()
void enablePostProcess(int enabled)
Toggle the post-process effetcs.
void onMousePress(QMouseEvent *event)
Event sent after a mouse press event has been processed, but before emitting needUpdate()
void mouseReleaseEvent(QMouseEvent *event) override
virtual void update(const Scalar dt)
Update the internal viewer state to the (application) time dt.
void toggleBrushPicking(bool on)
Emitted when the corresponding key is released (see keyReleaseEvent)
int addRenderer(const std::shared_ptr< Engine::Rendering::Renderer > &e)
PickingManager * getPickingManager()
Access to the feature picking manager.
std::vector< std::shared_ptr< Engine::Rendering::Renderer > > m_renderers
Core::Vector2 toDevice(const Core::Vector2 &logicCoordinates)
void mouseMoveEvent(QMouseEvent *event) override
void reloadShaders()
Tell the renderer to reload all shaders.
std::vector< std::string > getRenderersName() const
Returns the names of the different registred renderers.
void mousePressEvent(QMouseEvent *event) override
KeyMappingManager::KeyMappingAction addCustomAction(const std::string &actionName, const KeyMappingManager::EventBinding &binding, std::function< void(QEvent *)> callback)
Add a custom event callback.
Viewer(QScreen *screen=nullptr)
Constructor.
bool changeRenderer(int index)
Set the renderer.
void displayTexture(const QString &tex)
Set the final display texture.
void setCameraManipulator(CameraManipulator *ci)
Set the current camera interface.
const Engine::Rendering::Renderer * getRenderer() const
Read-only access to renderer.
void onMouseRelease(QMouseEvent *event)
Event sent after a mouse release event has been processed, but before emitting needUpdate()
virtual void setupKeyMappingCallbacks()
add observers to keyMappingManager for gizmo, camera and viewer.
void grabFrame(const std::string &filename)
Write the current frame as an image. Supports either BMP or PNG file names.
void createGizmoManager()
create gizmos
void fitCameraToScene(const Core::Aabb &sceneAabb)
Moves the camera so that the whole scene is visible.
~Viewer() override
Destructor.
GizmoManager * m_gizmoManager
Owning (QObject child) pointer to gizmo manager.
void rightClickPicking(const Ra::Engine::Rendering::Renderer::PickingResult &result)
Emitted when the rendered is correctly initialized.
GizmoManager * getGizmoManager()
Access to gizmo manager.
void wheelEvent(QWheelEvent *event) override
CameraManipulator * getCameraManipulator()
Access to camera interface.
void onMouseMove(QMouseEvent *event)
Event sent after a mouse move event has been processed, but before emitting needUpdate()
void focusOutEvent(QFocusEvent *event) override
reset key pressed, in case a key is pressed when focus lost
void processPicking()
Emits signals corresponding to picking requests.
virtual void handleMousePressEvent(QMouseEvent *event, Ra::Engine::Rendering::Renderer::PickingResult &result)
Base class for OpenGL widgets, compatble with Qt and globjects/glbindings.
ScopedGLContext activateScopedContext()
QOpenGLContext * context()
hepler function to manage enum as underlying types in VariableSet
the set of viewing parameters extracted from the camera and given to the renderer