2016-04-30 10:35:01 +00:00
|
|
|
//====== Copyright Valve Corporation, All rights reserved. =======
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "openvroverlaycontroller.h"
|
2016-12-03 04:03:14 +01:00
|
|
|
#include "trayiconcontroller.h"
|
2016-04-30 10:35:01 +00:00
|
|
|
|
|
|
|
|
#include <QOpenGLFramebufferObjectFormat>
|
|
|
|
|
#include <QOpenGLFunctions>
|
|
|
|
|
#include <QMouseEvent>
|
|
|
|
|
#include <QCursor>
|
|
|
|
|
#include <QCoreApplication>
|
|
|
|
|
|
|
|
|
|
using namespace vr;
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Purpose:
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
COpenVROverlayController *s_pSharedVRController = NULL;
|
|
|
|
|
|
|
|
|
|
COpenVROverlayController *COpenVROverlayController::SharedInstance()
|
|
|
|
|
{
|
|
|
|
|
if ( !s_pSharedVRController )
|
|
|
|
|
{
|
|
|
|
|
s_pSharedVRController = new COpenVROverlayController();
|
|
|
|
|
}
|
|
|
|
|
return s_pSharedVRController;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Purpose:
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
COpenVROverlayController::COpenVROverlayController()
|
|
|
|
|
: BaseClass()
|
|
|
|
|
, m_eLastHmdError( vr::VRInitError_None )
|
|
|
|
|
, m_eCompositorError( vr::VRInitError_None )
|
|
|
|
|
, m_eOverlayError( vr::VRInitError_None )
|
|
|
|
|
, m_strVRDriver( "No Driver" )
|
|
|
|
|
, m_strVRDisplay( "No Display" )
|
|
|
|
|
, m_pOpenGLContext( NULL )
|
|
|
|
|
, m_pRenderControl( NULL )
|
|
|
|
|
, m_pOffscreenSurface ( NULL )
|
|
|
|
|
, m_pFbo( NULL )
|
|
|
|
|
, m_pWindow( NULL )
|
|
|
|
|
, m_pPumpEventsTimer( NULL )
|
|
|
|
|
, m_lastMouseButtons( 0 )
|
|
|
|
|
, m_ulOverlayHandle( vr::k_ulOverlayHandleInvalid )
|
2016-09-15 15:59:56 +02:00
|
|
|
, m_bGamepadFocus( false )
|
2016-12-03 02:18:13 +01:00
|
|
|
, m_bLoading( false )
|
2016-04-30 10:35:01 +00:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Purpose:
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
COpenVROverlayController::~COpenVROverlayController()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Purpose: Helper to get a string from a tracked device property and turn it
|
|
|
|
|
// into a QString
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
QString GetTrackedDeviceString( vr::IVRSystem *pHmd, vr::TrackedDeviceIndex_t unDevice, vr::TrackedDeviceProperty prop )
|
|
|
|
|
{
|
|
|
|
|
char buf[128];
|
|
|
|
|
vr::TrackedPropertyError err;
|
|
|
|
|
pHmd->GetStringTrackedDeviceProperty( unDevice, prop, buf, sizeof( buf ), &err );
|
|
|
|
|
if( err != vr::TrackedProp_Success )
|
|
|
|
|
{
|
|
|
|
|
return QString( "Error Getting String: " ) + pHmd->GetPropErrorNameFromEnum( err );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Purpose:
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
bool COpenVROverlayController::Init()
|
|
|
|
|
{
|
|
|
|
|
bool bSuccess = true;
|
|
|
|
|
|
2016-04-30 13:54:33 +00:00
|
|
|
m_strName = "revive";
|
2016-04-30 10:35:01 +00:00
|
|
|
|
|
|
|
|
QStringList arguments = qApp->arguments();
|
|
|
|
|
|
|
|
|
|
int nNameArg = arguments.indexOf( "-name" );
|
|
|
|
|
if( nNameArg != -1 && nNameArg + 2 <= arguments.size() )
|
|
|
|
|
{
|
|
|
|
|
m_strName = arguments.at( nNameArg + 1 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QSurfaceFormat format;
|
|
|
|
|
// Qt Quick may need a depth and stencil buffer. Always make sure these are available.
|
|
|
|
|
format.setDepthBufferSize(16);
|
|
|
|
|
format.setStencilBufferSize(8);
|
|
|
|
|
|
|
|
|
|
m_pOpenGLContext = new QOpenGLContext();
|
|
|
|
|
m_pOpenGLContext->setFormat( format );
|
|
|
|
|
bSuccess = m_pOpenGLContext->create();
|
|
|
|
|
if( !bSuccess )
|
2016-09-16 17:07:03 +02:00
|
|
|
{
|
|
|
|
|
qDebug( "Failed to create OpenGL context" );
|
2016-04-30 10:35:01 +00:00
|
|
|
return false;
|
2016-09-16 17:07:03 +02:00
|
|
|
}
|
2016-04-30 10:35:01 +00:00
|
|
|
|
|
|
|
|
// create an offscreen surface to attach the context and FBO to
|
|
|
|
|
m_pOffscreenSurface = new QOffscreenSurface();
|
|
|
|
|
// Pass m_context->format(), not format. Format does not specify and color buffer
|
|
|
|
|
// sizes, while the context, that has just been created, reports a format that has
|
|
|
|
|
// these values filled in. Pass this to the offscreen surface to make sure it will be
|
|
|
|
|
// compatible with the context's configuration.
|
|
|
|
|
m_pOffscreenSurface->setFormat(m_pOpenGLContext->format());
|
|
|
|
|
m_pOffscreenSurface->create();
|
|
|
|
|
m_pOpenGLContext->makeCurrent( m_pOffscreenSurface );
|
|
|
|
|
|
|
|
|
|
m_pRenderControl = new QQuickRenderControl();
|
|
|
|
|
|
|
|
|
|
// Create a QQuickWindow that is associated with out render control. Note that this
|
|
|
|
|
// window never gets created or shown, meaning that it will never get an underlying
|
|
|
|
|
// native (platform) window.
|
|
|
|
|
m_pWindow = new QQuickWindow(m_pRenderControl);
|
|
|
|
|
|
2016-05-19 20:57:50 +02:00
|
|
|
// Load the thumbnail
|
|
|
|
|
QImage image(":/revive_overlay.png");
|
|
|
|
|
m_pThumbnailTexture = new QOpenGLTexture(image);
|
|
|
|
|
|
2016-04-30 22:45:21 +00:00
|
|
|
// When Quick says there is a need to render, we will not render immediately. Instead,
|
|
|
|
|
// a timer with a small interval is used to get better performance.
|
|
|
|
|
m_pUpdateTimer = new QTimer( this );
|
|
|
|
|
m_pUpdateTimer->setSingleShot( true );
|
|
|
|
|
m_pUpdateTimer->setInterval( 5 );
|
|
|
|
|
connect( m_pUpdateTimer, &QTimer::timeout, this, &COpenVROverlayController::OnSceneChanged );
|
|
|
|
|
|
|
|
|
|
connect( m_pRenderControl, &QQuickRenderControl::renderRequested, this, &COpenVROverlayController::OnRequestUpdate);
|
|
|
|
|
connect( m_pRenderControl, &QQuickRenderControl::sceneChanged, this, &COpenVROverlayController::OnRequestUpdate);
|
2016-04-30 10:35:01 +00:00
|
|
|
|
|
|
|
|
// Loading the OpenVR Runtime
|
|
|
|
|
bSuccess = ConnectToVRRuntime();
|
2016-09-16 17:07:03 +02:00
|
|
|
if( !bSuccess )
|
|
|
|
|
{
|
|
|
|
|
qDebug( "Failed to connect to OpenVR Runtime" );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-04-30 10:35:01 +00:00
|
|
|
|
2016-09-16 17:07:03 +02:00
|
|
|
// Check if the compositor is ready
|
2016-04-30 10:35:01 +00:00
|
|
|
bSuccess = bSuccess && vr::VRCompositor() != NULL;
|
2016-09-16 17:07:03 +02:00
|
|
|
if( !bSuccess )
|
|
|
|
|
{
|
|
|
|
|
qDebug( "Failed to connect to the compositor" );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-04-30 10:35:01 +00:00
|
|
|
|
|
|
|
|
if( vr::VROverlay() )
|
|
|
|
|
{
|
2016-04-30 13:54:33 +00:00
|
|
|
std::string sKey = m_strName.toStdString() + std::string( ".overlay" );
|
2016-04-30 10:35:01 +00:00
|
|
|
vr::VROverlayError overlayError = vr::VROverlay()->CreateDashboardOverlay( sKey.c_str(), m_strName.toStdString().c_str(), &m_ulOverlayHandle, &m_ulOverlayThumbnailHandle );
|
|
|
|
|
bSuccess = bSuccess && overlayError == vr::VROverlayError_None;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-16 17:07:03 +02:00
|
|
|
if( !bSuccess )
|
|
|
|
|
{
|
|
|
|
|
qDebug( "Failed to create the dashboard overlay (is it already running?)" );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-30 10:35:01 +00:00
|
|
|
if( bSuccess )
|
|
|
|
|
{
|
|
|
|
|
vr::VROverlay()->SetOverlayWidthInMeters( m_ulOverlayHandle, 3.0f );
|
2016-04-30 13:54:33 +00:00
|
|
|
vr::VROverlay()->SetOverlayAlpha( m_ulOverlayHandle, 0.9f );
|
2016-04-30 10:35:01 +00:00
|
|
|
vr::VROverlay()->SetOverlayInputMethod( m_ulOverlayHandle, vr::VROverlayInputMethod_Mouse );
|
2016-05-14 22:13:48 +00:00
|
|
|
vr::VROverlay()->SetOverlayFlag( m_ulOverlayHandle, VROverlayFlags_SendVRScrollEvents, true );
|
2016-09-15 15:59:56 +02:00
|
|
|
vr::VROverlay()->SetOverlayFlag( m_ulOverlayHandle, VROverlayFlags_AcceptsGamepadEvents, true );
|
2017-08-21 12:17:35 +02:00
|
|
|
vr::VROverlay()->SetOverlayFlag( m_ulOverlayHandle, VROverlayFlags_ShowGamepadFocus, true );
|
2016-05-14 22:13:48 +00:00
|
|
|
|
2016-04-30 10:35:01 +00:00
|
|
|
m_pPumpEventsTimer = new QTimer( this );
|
|
|
|
|
connect(m_pPumpEventsTimer, SIGNAL( timeout() ), this, SLOT( OnTimeoutPumpEvents() ) );
|
|
|
|
|
m_pPumpEventsTimer->setInterval( 20 );
|
|
|
|
|
m_pPumpEventsTimer->start();
|
|
|
|
|
|
|
|
|
|
}
|
2016-09-16 17:07:03 +02:00
|
|
|
return bSuccess;
|
2016-04-30 10:35:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Purpose:
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void COpenVROverlayController::Shutdown()
|
|
|
|
|
{
|
|
|
|
|
DisconnectFromVRRuntime();
|
|
|
|
|
|
2016-05-01 20:58:39 +00:00
|
|
|
delete m_pWindow;
|
2016-04-30 10:35:01 +00:00
|
|
|
delete m_pRenderControl;
|
|
|
|
|
delete m_pFbo;
|
|
|
|
|
delete m_pOffscreenSurface;
|
2016-05-14 22:13:48 +00:00
|
|
|
delete m_pThumbnailTexture;
|
2016-04-30 10:35:01 +00:00
|
|
|
|
|
|
|
|
if( m_pOpenGLContext )
|
|
|
|
|
{
|
|
|
|
|
// m_pOpenGLContext->destroy();
|
|
|
|
|
delete m_pOpenGLContext;
|
|
|
|
|
m_pOpenGLContext = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Purpose:
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void COpenVROverlayController::OnSceneChanged()
|
|
|
|
|
{
|
|
|
|
|
// skip rendering if the overlay isn't visible
|
|
|
|
|
if( !vr::VROverlay() ||
|
|
|
|
|
!vr::VROverlay()->IsOverlayVisible( m_ulOverlayHandle ) && !vr::VROverlay()->IsOverlayVisible( m_ulOverlayThumbnailHandle ) )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!m_pOpenGLContext->makeCurrent( m_pOffscreenSurface ))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Polish, synchronize and render the next frame (into our fbo). In this example
|
|
|
|
|
// everything happens on the same thread and therefore all three steps are performed
|
|
|
|
|
// in succession from here. In a threaded setup the render() call would happen on a
|
|
|
|
|
// separate thread.
|
|
|
|
|
m_pRenderControl->polishItems();
|
|
|
|
|
m_pRenderControl->sync();
|
|
|
|
|
m_pRenderControl->render();
|
|
|
|
|
|
|
|
|
|
m_pWindow->resetOpenGLState();
|
|
|
|
|
QOpenGLFramebufferObject::bindDefault();
|
|
|
|
|
|
|
|
|
|
m_pOpenGLContext->functions()->glFlush();
|
|
|
|
|
|
|
|
|
|
GLuint unTexture = m_pFbo->texture();
|
|
|
|
|
if( unTexture != 0 )
|
|
|
|
|
{
|
2017-04-11 19:07:19 +02:00
|
|
|
vr::Texture_t texture = {(void*)unTexture, vr::TextureType_OpenGL, vr::ColorSpace_Auto };
|
2016-04-30 10:35:01 +00:00
|
|
|
vr::VROverlay()->SetOverlayTexture( m_ulOverlayHandle, &texture );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-04-30 22:45:21 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Purpose:
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void COpenVROverlayController::OnRequestUpdate()
|
|
|
|
|
{
|
|
|
|
|
if (!m_pUpdateTimer->isActive())
|
|
|
|
|
m_pUpdateTimer->start();
|
2016-05-14 22:13:48 +00:00
|
|
|
UpdateThumbnail();
|
2016-04-30 22:45:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-04-30 10:35:01 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Purpose:
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void COpenVROverlayController::OnTimeoutPumpEvents()
|
|
|
|
|
{
|
|
|
|
|
if( !vr::VRSystem() )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
vr::VREvent_t vrEvent;
|
|
|
|
|
while( vr::VROverlay()->PollNextOverlayEvent( m_ulOverlayHandle, &vrEvent, sizeof( vrEvent ) ) )
|
|
|
|
|
{
|
|
|
|
|
switch( vrEvent.eventType )
|
|
|
|
|
{
|
|
|
|
|
case vr::VREvent_MouseMove:
|
|
|
|
|
{
|
|
|
|
|
QPointF ptNewMouse( vrEvent.data.mouse.x, vrEvent.data.mouse.y );
|
|
|
|
|
QPoint ptGlobal = ptNewMouse.toPoint();
|
|
|
|
|
QMouseEvent mouseEvent( QEvent::MouseMove,
|
|
|
|
|
ptNewMouse,
|
|
|
|
|
ptGlobal,
|
|
|
|
|
Qt::NoButton,
|
|
|
|
|
m_lastMouseButtons,
|
|
|
|
|
0 );
|
|
|
|
|
|
|
|
|
|
m_ptLastMouse = ptNewMouse;
|
|
|
|
|
|
2016-04-30 22:45:21 +00:00
|
|
|
QCoreApplication::sendEvent( m_pWindow, &mouseEvent );
|
|
|
|
|
OnRequestUpdate();
|
2016-04-30 10:35:01 +00:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case vr::VREvent_MouseButtonDown:
|
|
|
|
|
{
|
|
|
|
|
Qt::MouseButton button = vrEvent.data.mouse.button == vr::VRMouseButton_Right ? Qt::RightButton : Qt::LeftButton;
|
|
|
|
|
|
|
|
|
|
m_lastMouseButtons |= button;
|
|
|
|
|
|
|
|
|
|
QPoint ptGlobal = m_ptLastMouse.toPoint();
|
|
|
|
|
QMouseEvent mouseEvent( QEvent::MouseButtonPress,
|
|
|
|
|
m_ptLastMouse,
|
|
|
|
|
ptGlobal,
|
|
|
|
|
button,
|
|
|
|
|
m_lastMouseButtons,
|
|
|
|
|
0 );
|
|
|
|
|
|
|
|
|
|
QCoreApplication::sendEvent( m_pWindow, &mouseEvent );
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case vr::VREvent_MouseButtonUp:
|
|
|
|
|
{
|
|
|
|
|
Qt::MouseButton button = vrEvent.data.mouse.button == vr::VRMouseButton_Right ? Qt::RightButton : Qt::LeftButton;
|
|
|
|
|
m_lastMouseButtons &= ~button;
|
|
|
|
|
|
|
|
|
|
QPoint ptGlobal = m_ptLastMouse.toPoint();
|
|
|
|
|
QMouseEvent mouseEvent( QEvent::MouseButtonRelease,
|
|
|
|
|
m_ptLastMouse,
|
|
|
|
|
ptGlobal,
|
|
|
|
|
button,
|
|
|
|
|
m_lastMouseButtons,
|
|
|
|
|
0 );
|
|
|
|
|
|
|
|
|
|
QCoreApplication::sendEvent( m_pWindow, &mouseEvent );
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2016-05-14 22:13:48 +00:00
|
|
|
case vr::VREvent_Scroll:
|
|
|
|
|
{
|
2016-09-16 17:38:16 +02:00
|
|
|
// Wheel speed is defined in 1/8 of a degree
|
|
|
|
|
QPoint ptNewWheel( vrEvent.data.scroll.xdelta * 360.0f * 8.0f, vrEvent.data.scroll.ydelta * 360.0f * 8.0f );
|
2016-05-14 22:13:48 +00:00
|
|
|
QPoint ptGlobal = m_ptLastMouse.toPoint();
|
|
|
|
|
QWheelEvent wheelEvent( m_ptLastMouse,
|
|
|
|
|
ptGlobal,
|
|
|
|
|
QPoint(),
|
|
|
|
|
ptNewWheel,
|
|
|
|
|
0,
|
|
|
|
|
Qt::Vertical,
|
|
|
|
|
m_lastMouseButtons,
|
|
|
|
|
0 );
|
|
|
|
|
|
|
|
|
|
QCoreApplication::sendEvent( m_pWindow, &wheelEvent );
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2016-04-30 10:35:01 +00:00
|
|
|
case vr::VREvent_OverlayShown:
|
|
|
|
|
{
|
|
|
|
|
m_pWindow->update();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2017-12-13 19:22:18 +01:00
|
|
|
case vr::VREvent_OverlayHidden:
|
|
|
|
|
{
|
|
|
|
|
m_lastMouseButtons = 0;
|
|
|
|
|
|
|
|
|
|
QPoint ptGlobal = m_ptLastMouse.toPoint();
|
|
|
|
|
QMouseEvent mouseEvent( QEvent::MouseButtonRelease,
|
|
|
|
|
m_ptLastMouse,
|
|
|
|
|
ptGlobal,
|
|
|
|
|
Qt::LeftButton,
|
|
|
|
|
m_lastMouseButtons,
|
|
|
|
|
0 );
|
|
|
|
|
|
|
|
|
|
QCoreApplication::sendEvent( m_pWindow, &mouseEvent );
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2016-09-15 15:59:56 +02:00
|
|
|
case vr::VREvent_OverlayGamepadFocusGained:
|
|
|
|
|
m_bGamepadFocus = true;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case vr::VREvent_OverlayGamepadFocusLost:
|
|
|
|
|
m_bGamepadFocus = false;
|
|
|
|
|
break;
|
|
|
|
|
|
2016-04-30 10:35:01 +00:00
|
|
|
case vr::VREvent_Quit:
|
2016-12-03 04:03:14 +01:00
|
|
|
vr::VRSystem()->AcknowledgeQuit_Exiting();
|
2016-12-05 14:58:19 +01:00
|
|
|
CTrayIconController::SharedInstance()->quit();
|
2016-04-30 10:35:01 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-03 02:18:13 +01:00
|
|
|
while( vr::VRSystem()->PollNextEvent( &vrEvent, sizeof( vrEvent ) ) )
|
|
|
|
|
{
|
|
|
|
|
switch( vrEvent.eventType )
|
|
|
|
|
{
|
|
|
|
|
case vr::VREvent_SceneApplicationChanged:
|
2016-12-03 02:33:11 +01:00
|
|
|
// Ignore changed-to-compositor event
|
|
|
|
|
if (vrEvent.data.process.pid != 0)
|
2017-02-22 15:01:25 +01:00
|
|
|
SetLoading(false);
|
2016-12-03 02:33:11 +01:00
|
|
|
break;
|
2016-12-03 04:03:14 +01:00
|
|
|
|
2017-02-22 15:01:25 +01:00
|
|
|
case vr::VREvent_ApplicationTransitionStarted:
|
2016-12-03 02:18:13 +01:00
|
|
|
case vr::VREvent_ApplicationTransitionNewAppStarted:
|
2017-02-22 15:01:25 +01:00
|
|
|
SetLoading(true);
|
2016-12-03 02:18:13 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-30 10:35:01 +00:00
|
|
|
if( m_ulOverlayThumbnailHandle != vr::k_ulOverlayHandleInvalid )
|
|
|
|
|
{
|
|
|
|
|
while( vr::VROverlay()->PollNextOverlayEvent( m_ulOverlayThumbnailHandle, &vrEvent, sizeof( vrEvent) ) )
|
|
|
|
|
{
|
|
|
|
|
switch( vrEvent.eventType )
|
|
|
|
|
{
|
|
|
|
|
case vr::VREvent_OverlayShown:
|
|
|
|
|
{
|
|
|
|
|
m_pWindow->update();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Purpose:
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void COpenVROverlayController::SetQuickItem( QQuickItem *pItem )
|
|
|
|
|
{
|
2016-04-30 22:45:21 +00:00
|
|
|
m_pFbo = new QOpenGLFramebufferObject( pItem->width(), pItem->height(), QOpenGLFramebufferObject::CombinedDepthStencil );
|
2016-04-30 10:35:01 +00:00
|
|
|
m_pWindow->setRenderTarget(m_pFbo);
|
|
|
|
|
|
|
|
|
|
// The root item is ready. Associate it with the window.
|
|
|
|
|
pItem->setParentItem(m_pWindow->contentItem());
|
|
|
|
|
m_pWindow->setGeometry(0, 0, pItem->width(), pItem->height());
|
|
|
|
|
|
|
|
|
|
// Initialize the render control and our OpenGL resources.
|
|
|
|
|
m_pOpenGLContext->makeCurrent(m_pOffscreenSurface);
|
|
|
|
|
m_pRenderControl->initialize(m_pOpenGLContext);
|
|
|
|
|
|
|
|
|
|
if( vr::VROverlay() )
|
|
|
|
|
{
|
|
|
|
|
vr::HmdVector2_t vecWindowSize =
|
|
|
|
|
{
|
|
|
|
|
(float)pItem->width(),
|
|
|
|
|
(float)pItem->height()
|
|
|
|
|
};
|
|
|
|
|
vr::VROverlay()->SetOverlayMouseScale( m_ulOverlayHandle, &vecWindowSize );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Purpose:
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
bool COpenVROverlayController::ConnectToVRRuntime()
|
|
|
|
|
{
|
|
|
|
|
m_eLastHmdError = vr::VRInitError_None;
|
|
|
|
|
vr::IVRSystem *pVRSystem = vr::VR_Init( &m_eLastHmdError, vr::VRApplication_Overlay );
|
|
|
|
|
|
|
|
|
|
if ( m_eLastHmdError != vr::VRInitError_None )
|
|
|
|
|
{
|
|
|
|
|
m_strVRDriver = "No Driver";
|
|
|
|
|
m_strVRDisplay = "No Display";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_strVRDriver = GetTrackedDeviceString(pVRSystem, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_TrackingSystemName_String);
|
|
|
|
|
m_strVRDisplay = GetTrackedDeviceString(pVRSystem, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SerialNumber_String);
|
2016-11-03 22:44:06 +01:00
|
|
|
m_strRuntimeURL = QUrl::fromLocalFile(vr::VR_RuntimePath()).url();
|
2017-06-03 18:23:16 +02:00
|
|
|
if (!m_strRuntimeURL.endsWith('/'))
|
|
|
|
|
m_strRuntimeURL.append('/');
|
2016-11-03 22:44:06 +01:00
|
|
|
emit RuntimeChanged();
|
2016-04-30 10:35:01 +00:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void COpenVROverlayController::DisconnectFromVRRuntime()
|
|
|
|
|
{
|
|
|
|
|
vr::VR_Shutdown();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Purpose:
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
QString COpenVROverlayController::GetVRDriverString()
|
|
|
|
|
{
|
|
|
|
|
return m_strVRDriver;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Purpose:
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
QString COpenVROverlayController::GetVRDisplayString()
|
|
|
|
|
{
|
|
|
|
|
return m_strVRDisplay;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Purpose:
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
bool COpenVROverlayController::BHMDAvailable()
|
|
|
|
|
{
|
|
|
|
|
return vr::VRSystem() != NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Purpose:
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
vr::HmdError COpenVROverlayController::GetLastHmdError()
|
|
|
|
|
{
|
|
|
|
|
return m_eLastHmdError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-05-14 22:13:48 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Purpose:
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
void COpenVROverlayController::UpdateThumbnail()
|
|
|
|
|
{
|
|
|
|
|
GLuint unThumbnail = m_pThumbnailTexture->textureId();
|
|
|
|
|
if( unThumbnail != 0 )
|
|
|
|
|
{
|
2017-04-11 19:07:19 +02:00
|
|
|
vr::Texture_t thumbnail = {(void*)unThumbnail, vr::TextureType_OpenGL, vr::ColorSpace_Auto };
|
2016-05-14 22:13:48 +00:00
|
|
|
vr::VROverlay()->SetOverlayTexture( m_ulOverlayThumbnailHandle, &thumbnail );
|
|
|
|
|
}
|
|
|
|
|
}
|