Merge branch 'master' into alpha-kung

This commit is contained in:
Kung-vr
2019-01-13 15:53:59 +09:00
23 changed files with 750 additions and 285 deletions
+7 -6
View File
@@ -70,13 +70,14 @@ void AudioTabController::initStage2( OverlayController* var_parent,
notifKey.c_str(), notifKey.c_str(), &m_ulNotificationOverlayHandle );
if ( overlayError == vr::VROverlayError_None )
{
std::string notifIconPath
= QApplication::applicationDirPath().toStdString()
+ "/res/qml/ptt_notification.png";
if ( QFile::exists( QString::fromStdString( notifIconPath ) ) )
QString notifIconPath = QStandardPaths::locate(
QStandardPaths::AppDataLocation,
QStringLiteral( "/res/qml/ptt_notification.png" ) );
if ( QFile::exists( notifIconPath ) )
{
vr::VROverlay()->SetOverlayFromFile( m_ulNotificationOverlayHandle,
notifIconPath.c_str() );
vr::VROverlay()->SetOverlayFromFile(
m_ulNotificationOverlayHandle,
notifIconPath.toStdString().c_str() );
vr::VROverlay()->SetOverlayWidthInMeters(
m_ulNotificationOverlayHandle, 0.02f );
vr::HmdMatrix34_t notificationTransform
+5 -1
View File
@@ -15,8 +15,12 @@ public:
virtual void sendKeyboardInput( QString input ) = 0;
virtual void sendKeyboardEnter() = 0;
virtual void sendKeyboardBackspace( int count ) = 0;
virtual void sendKeyboardBackspace( const int count ) = 0;
virtual void sendKeyboardAltTab() = 0;
virtual void sendMediaNextSong() = 0;
virtual void sendMediaPreviousSong() = 0;
virtual void sendMediaPausePlay() = 0;
virtual void sendMediaStopSong() = 0;
};
} // namespace advsettings
+300 -204
View File
@@ -8,6 +8,7 @@ namespace advsettings
void SteamVRTabController::initStage1()
{
initMotionSmoothing();
initSupersampleOverride();
eventLoopTick();
reloadSteamVRProfiles();
}
@@ -19,106 +20,26 @@ void SteamVRTabController::initStage2( OverlayController* var_parent,
this->widget = var_widget;
}
void SteamVRTabController::reloadSteamVRProfiles()
{
steamvrProfiles.clear();
auto settings = OverlayController::appSettings();
settings->beginGroup( "steamVRSettings" );
auto profileCount = settings->beginReadArray( "steamVRProfiles" );
for ( int i = 0; i < profileCount; i++ )
{
settings->setArrayIndex( i );
steamvrProfiles.emplace_back();
auto& entry = steamvrProfiles[i];
entry.profileName
= settings->value( "profileName" ).toString().toStdString();
entry.includesSupersampling
= settings->value( "includesSupersampling", false ).toBool();
if ( entry.includesSupersampling )
{
entry.supersampling
= settings->value( "supersampling", 1.0f ).toFloat();
}
entry.includesSupersampleFiltering
= settings->value( "includesSupersampleFiltering", false ).toBool();
if ( entry.includesSupersampleFiltering )
{
entry.supersampleFiltering
= settings->value( "supersampleFiltering", true ).toBool();
}
entry.includesMotionSmoothing
= settings->value( "includesMotionSmoothing", false ).toBool();
if ( entry.includesMotionSmoothing )
{
entry.motionSmooth
= settings->value( "motionSmooth", true ).toBool();
}
}
settings->endArray();
settings->endGroup();
}
void SteamVRTabController::saveSteamVRProfiles()
{
auto settings = OverlayController::appSettings();
settings->beginGroup( "steamVRSettings" );
settings->beginWriteArray( "steamVRProfiles" );
unsigned i = 0;
for ( auto& p : steamvrProfiles )
{
settings->setArrayIndex( i );
settings->setValue( "profileName",
QString::fromStdString( p.profileName ) );
settings->setValue( "includesSupersampling", p.includesSupersampling );
if ( p.includesSupersampling )
{
settings->setValue( "supersampling", p.supersampling );
}
settings->setValue( "includesSupersampleFiltering",
p.includesSupersampleFiltering );
if ( p.includesSupersampleFiltering )
{
settings->setValue( "supersampleFiltering",
p.supersampleFiltering );
}
settings->setValue( "includesMotionSmoothing",
p.includesMotionSmoothing );
if ( p.includesMotionSmoothing )
{
settings->setValue( "motionSmooth", p.motionSmooth );
}
i++;
}
settings->endArray();
settings->endGroup();
}
Q_INVOKABLE unsigned SteamVRTabController::getSteamVRProfileCount()
{
return ( unsigned ) steamvrProfiles.size();
}
Q_INVOKABLE QString
SteamVRTabController::getSteamVRProfileName( unsigned index )
{
if ( index >= steamvrProfiles.size() )
{
return QString();
}
else
{
return QString::fromStdString( steamvrProfiles[index].profileName );
}
}
// TODO DISC does it make any sense to check these settings once every ~
// 1second. primary purpose seems to be to re-sync settings if changed via other
// means?
void SteamVRTabController::eventLoopTick()
{
if ( settingsUpdateCounter >= 50 )
{
vr::EVRSettingsError vrSettingsError;
// checks supersampling override and resynchs if necessry
// also prints error if can't find.
auto sso = vr::VRSettings()->GetBool(
vr::k_pch_SteamVR_Section,
vr::k_pch_SteamVR_SupersampleManualOverride_Bool,
&vrSettingsError );
if ( vrSettingsError != vr::VRSettingsError_None )
{
LOG( WARNING ) << "Could not read \""
<< vr::k_pch_SteamVR_SupersampleManualOverride_Bool
<< "\" setting: "
<< vr::VRSettings()->GetSettingsErrorNameFromEnum(
vrSettingsError );
}
setAllowSupersampleOverride( sso );
// checks supersampling and re-synchs if necessary
auto ss = vr::VRSettings()->GetFloat(
vr::k_pch_SteamVR_Section,
@@ -185,10 +106,192 @@ void SteamVRTabController::eventLoopTick()
}
}
void SteamVRTabController::setSuperSampling( float value, bool notify )
/* -----------------------------------------*/
/*------------------------------------------*/
/*Profile Logic Functions*/
void SteamVRTabController::addSteamVRProfile(
const QString name,
const bool includeSupersampling,
const bool includeSupersampleFiltering,
const bool includeMotionSmoothing )
{
SteamVRProfile* profile = nullptr;
for ( auto& p : steamvrProfiles )
{
if ( p.profileName.compare( name.toStdString() ) == 0 )
{
profile = &p;
break;
}
}
if ( !profile )
{
auto i = steamvrProfiles.size();
steamvrProfiles.emplace_back();
profile = &steamvrProfiles[i];
}
profile->profileName = name.toStdString();
profile->includesSupersampling = includeSupersampling;
if ( includeSupersampling )
{
profile->supersampleOverride = m_allowSupersampleOverride;
profile->supersampling = m_superSampling;
}
profile->includesSupersampleFiltering = includeSupersampleFiltering;
if ( includeSupersampleFiltering )
{
profile->supersampleFiltering = m_allowSupersampleFiltering;
}
profile->includesMotionSmoothing = includeMotionSmoothing;
if ( includeMotionSmoothing )
{
profile->motionSmooth = m_motionSmoothing;
}
saveSteamVRProfiles();
OverlayController::appSettings()->sync();
emit steamVRProfilesUpdated();
emit steamVRProfileAdded();
}
void SteamVRTabController::applySteamVRProfile( const unsigned index )
{
if ( index < steamvrProfiles.size() )
{
auto& profile = steamvrProfiles[index];
if ( profile.includesSupersampling )
{
setAllowSupersampleOverride( profile.supersampleOverride );
setSuperSampling( profile.supersampling );
}
if ( profile.includesSupersampleFiltering )
{
setAllowSupersampleFiltering( profile.supersampleFiltering );
}
if ( profile.includesMotionSmoothing )
{
setMotionSmoothing( profile.motionSmooth );
}
vr::VRSettings()->Sync( true );
}
}
void SteamVRTabController::deleteSteamVRProfile( const unsigned index )
{
if ( index < steamvrProfiles.size() )
{
auto pos = steamvrProfiles.begin() + index;
steamvrProfiles.erase( pos );
saveSteamVRProfiles();
OverlayController::appSettings()->sync();
emit steamVRProfilesUpdated();
}
}
void SteamVRTabController::reloadSteamVRProfiles()
{
steamvrProfiles.clear();
auto settings = OverlayController::appSettings();
settings->beginGroup( "steamVRSettings" );
auto profileCount = settings->beginReadArray( "steamVRProfiles" );
for ( int i = 0; i < profileCount; i++ )
{
settings->setArrayIndex( i );
steamvrProfiles.emplace_back();
auto& entry = steamvrProfiles[i];
entry.profileName
= settings->value( "profileName" ).toString().toStdString();
entry.includesSupersampling
= settings->value( "includesSupersampling", false ).toBool();
if ( entry.includesSupersampling )
{
entry.supersampleOverride
= settings->value( "supersamplingOverride", false ).toBool();
entry.supersampling
= settings->value( "supersampling", 1.0f ).toFloat();
}
entry.includesSupersampleFiltering
= settings->value( "includesSupersampleFiltering", false ).toBool();
if ( entry.includesSupersampleFiltering )
{
entry.supersampleFiltering
= settings->value( "supersampleFiltering", true ).toBool();
}
entry.includesMotionSmoothing
= settings->value( "includesMotionSmoothing", false ).toBool();
if ( entry.includesMotionSmoothing )
{
entry.motionSmooth
= settings->value( "motionSmooth", true ).toBool();
}
}
settings->endArray();
settings->endGroup();
}
void SteamVRTabController::saveSteamVRProfiles()
{
auto settings = OverlayController::appSettings();
settings->beginGroup( "steamVRSettings" );
settings->beginWriteArray( "steamVRProfiles" );
unsigned i = 0;
for ( auto& p : steamvrProfiles )
{
settings->setArrayIndex( i );
settings->setValue( "profileName",
QString::fromStdString( p.profileName ) );
settings->setValue( "includesSupersampling", p.includesSupersampling );
if ( p.includesSupersampling )
{
settings->setValue( "supersamplingOverride",
p.supersampleOverride );
settings->setValue( "supersampling", p.supersampling );
}
settings->setValue( "includesSupersampleFiltering",
p.includesSupersampleFiltering );
if ( p.includesSupersampleFiltering )
{
settings->setValue( "supersampleFiltering",
p.supersampleFiltering );
}
settings->setValue( "includesMotionSmoothing",
p.includesMotionSmoothing );
if ( p.includesMotionSmoothing )
{
settings->setValue( "motionSmooth", p.motionSmooth );
}
i++;
}
settings->endArray();
settings->endGroup();
}
int SteamVRTabController::getSteamVRProfileCount()
{
return static_cast<int>( steamvrProfiles.size() );
}
QString SteamVRTabController::getSteamVRProfileName( const unsigned index )
{
if ( index >= steamvrProfiles.size() )
{
return QString();
}
else
{
return QString::fromStdString( steamvrProfiles[index].profileName );
}
}
/* -----------------------------------------*/
/*------------------------------------------*/
/*SuperSample (value) functions*/
void SteamVRTabController::setSuperSampling( float value, const bool notify )
{
bool override = false;
if ( value <= 0.01f )
// Mirrors Desktop Clamp
if ( value <= 0.2f )
{
LOG( WARNING ) << "Encountered a supersampling value <= 0.01, setting "
"supersampling to 1.0";
@@ -215,26 +318,16 @@ float SteamVRTabController::superSampling() const
{
return m_superSampling;
}
/* -----------------------------------------*/
/*------------------------------------------*/
/*Motion Smoothing boolean/toggle functions*/
bool SteamVRTabController::motionSmoothing() const
{
return m_motionSmoothing;
}
/*
Name: setMotionSmoothing
input: bool value, bool notify
output: none
@value - value to be passed to m_motionSMoothing
@notify - whether QML is informed of change (default true)
Description:
sets value of m_motionSmoothing AND applies changes in Steam/OpenVr
*/
void SteamVRTabController::setMotionSmoothing( bool value, bool notify )
void SteamVRTabController::setMotionSmoothing( const bool value,
const bool notify )
{
if ( m_motionSmoothing != value )
{
@@ -250,21 +343,6 @@ void SteamVRTabController::setMotionSmoothing( bool value, bool notify )
}
}
/*
Name: initMotionSmoothing
input: none
output: none
description: Gets the Value of Motion Smoothing from Steam/OpenVR.
Sets the member variable of motion smoothing for UI
Adds error to log if unable to find variable.
OnError:
default value of true for motion smoothing is initialized, if user has disabled
motion smoothing on their end, they will have to toggle the variable twice to
get it to re-sync.
*/
void SteamVRTabController::initMotionSmoothing()
{
bool temporary = false;
@@ -285,13 +363,17 @@ void SteamVRTabController::initMotionSmoothing()
setMotionSmoothing( temporary, true );
}
/* -----------------------------------------*/
/*------------------------------------------*/
/*Supersample Filtering boolean/toggle functions*/
bool SteamVRTabController::allowSupersampleFiltering() const
{
return m_allowSupersampleFiltering;
}
void SteamVRTabController::setAllowSupersampleFiltering( bool value,
bool notify )
void SteamVRTabController::setAllowSupersampleFiltering( const bool value,
const bool notify )
{
if ( m_allowSupersampleFiltering != value )
{
@@ -309,6 +391,56 @@ void SteamVRTabController::setAllowSupersampleFiltering( bool value,
}
}
/* -----------------------------------------*/
/*------------------------------------------*/
/*SuperSampling Override boolean/toggle functions*/
bool SteamVRTabController::allowSupersampleOverride() const
{
return m_allowSupersampleOverride;
}
void SteamVRTabController::setAllowSupersampleOverride( const bool value,
const bool notify )
{
if ( m_allowSupersampleOverride != value )
{
m_allowSupersampleOverride = value;
vr::VRSettings()->SetBool(
vr::k_pch_SteamVR_Section,
vr::k_pch_SteamVR_SupersampleManualOverride_Bool,
m_allowSupersampleOverride );
vr::VRSettings()->Sync();
if ( notify )
{
emit allowSupersampleOverrideChanged( m_allowSupersampleOverride );
}
}
}
void SteamVRTabController::initSupersampleOverride()
{
bool temporary = false;
vr::EVRSettingsError vrSettingsError;
temporary = vr::VRSettings()->GetBool(
vr::k_pch_SteamVR_Section,
vr::k_pch_SteamVR_SupersampleManualOverride_Bool,
&vrSettingsError );
if ( vrSettingsError != vr::VRSettingsError_None )
{
LOG( WARNING ) << "Could not get SuperSampling Override State \""
<< vr::k_pch_SteamVR_SupersampleManualOverride_Bool
<< "\" setting: "
<< vr::VRSettings()->GetSettingsErrorNameFromEnum(
vrSettingsError );
}
vr::VRSettings()->Sync();
setAllowSupersampleOverride( temporary, true );
}
/*------------------------------------------*/
/* -----------------------------------------*/
void SteamVRTabController::reset()
{
vr::EVRSettingsError vrSettingsError;
@@ -339,6 +471,45 @@ void SteamVRTabController::reset()
vrSettingsError );
}
vr::VRSettings()->RemoveKeyInSection(
vr::k_pch_SteamVR_Section,
vr::k_pch_SteamVR_SupersampleManualOverride_Bool,
&vrSettingsError );
if ( vrSettingsError != vr::VRSettingsError_None )
{
LOG( WARNING ) << "Could not remove \""
<< vr::k_pch_SteamVR_SupersampleManualOverride_Bool
<< "\" setting: "
<< vr::VRSettings()->GetSettingsErrorNameFromEnum(
vrSettingsError );
}
vr::VRSettings()->RemoveKeyInSection(
vr::k_pch_SteamVR_Section,
vr::k_pch_SteamVR_SupersampleScale_Float,
&vrSettingsError );
if ( vrSettingsError != vr::VRSettingsError_None )
{
LOG( WARNING ) << "Could not remove \""
<< vr::k_pch_SteamVR_SupersampleScale_Float
<< "\" setting: "
<< vr::VRSettings()->GetSettingsErrorNameFromEnum(
vrSettingsError );
}
vr::VRSettings()->RemoveKeyInSection(
vr::k_pch_SteamVR_Section,
vr::k_pch_SteamVR_MotionSmoothing_Bool,
&vrSettingsError );
if ( vrSettingsError != vr::VRSettingsError_None )
{
LOG( WARNING ) << "Could not remove \""
<< vr::k_pch_SteamVR_MotionSmoothing_Bool
<< "\" setting: "
<< vr::VRSettings()->GetSettingsErrorNameFromEnum(
vrSettingsError );
}
vr::VRSettings()->Sync();
settingsUpdateCounter = 999; // Easiest way to get default values
}
@@ -352,79 +523,4 @@ void SteamVRTabController::restartSteamVR()
QProcess::startDetached( cmd );
}
void SteamVRTabController::addSteamVRProfile( QString name,
bool includeSupersampling,
bool includeSupersampleFiltering,
bool includeMotionSmoothing )
{
SteamVRProfile* profile = nullptr;
for ( auto& p : steamvrProfiles )
{
if ( p.profileName.compare( name.toStdString() ) == 0 )
{
profile = &p;
break;
}
}
if ( !profile )
{
auto i = steamvrProfiles.size();
steamvrProfiles.emplace_back();
profile = &steamvrProfiles[i];
}
profile->profileName = name.toStdString();
profile->includesSupersampling = includeSupersampling;
if ( includeSupersampling )
{
profile->supersampling = m_superSampling;
}
profile->includesSupersampleFiltering = includeSupersampleFiltering;
if ( includeSupersampleFiltering )
{
profile->supersampleFiltering = m_allowSupersampleFiltering;
}
profile->includesMotionSmoothing = includeMotionSmoothing;
if ( includeMotionSmoothing )
{
profile->motionSmooth = m_motionSmoothing;
}
saveSteamVRProfiles();
OverlayController::appSettings()->sync();
emit steamVRProfilesUpdated();
emit steamVRProfileAdded();
}
void SteamVRTabController::applySteamVRProfile( unsigned index )
{
if ( index < steamvrProfiles.size() )
{
auto& profile = steamvrProfiles[index];
if ( profile.includesSupersampling )
{
setSuperSampling( profile.supersampling );
}
if ( profile.includesSupersampleFiltering )
{
setAllowSupersampleFiltering( profile.supersampleFiltering );
}
if ( profile.includesMotionSmoothing )
{
setMotionSmoothing( profile.motionSmooth );
}
vr::VRSettings()->Sync( true );
}
}
void SteamVRTabController::deleteSteamVRProfile( unsigned index )
{
if ( index < steamvrProfiles.size() )
{
auto pos = steamvrProfiles.begin() + index;
steamvrProfiles.erase( pos );
saveSteamVRProfiles();
OverlayController::appSettings()->sync();
emit steamVRProfilesUpdated();
}
}
} // namespace advsettings
+10 -9
View File
@@ -21,6 +21,7 @@ struct SteamVRProfile
bool supersampleFiltering = false;
bool motionSmooth = false;
bool includesMotionSmoothing = false;
bool supersampleOverride = false;
};
class SteamVRTabController : public QObject
@@ -28,27 +29,27 @@ class SteamVRTabController : public QObject
Q_OBJECT
Q_PROPERTY( float superSampling READ superSampling WRITE setSuperSampling
NOTIFY superSamplingChanged )
/*Q_PROPERTY(
float compositorSuperSampling READ compositorSuperSampling WRITE
setCompositorSuperSampling NOTIFY compositorSuperSamplingChanged )
*/
Q_PROPERTY( bool motionSmoothing READ motionSmoothing WRITE
setMotionSmoothing NOTIFY motionSmoothingChanged )
Q_PROPERTY( bool allowSupersampleFiltering READ allowSupersampleFiltering
WRITE setAllowSupersampleFiltering NOTIFY
allowSupersampleFilteringChanged )
Q_PROPERTY(
bool allowSupersampleOverride READ allowSupersampleOverride WRITE
setAllowSupersampleOverride NOTIFY allowSupersampleOverrideChanged )
private:
OverlayController* parent;
QQuickWindow* widget;
float m_superSampling = 1.0;
// float m_compositorSuperSampling = 1.0;
bool m_motionSmoothing = true;
bool m_allowSupersampleFiltering = true;
bool m_allowSupersampleOverride = false;
void initMotionSmoothing();
void initSupersampleOverride();
std::vector<SteamVRProfile> steamvrProfiles;
@@ -61,21 +62,21 @@ public:
void eventLoopTick();
float superSampling() const;
// float compositorSuperSampling() const;
bool motionSmoothing() const;
bool allowSupersampleFiltering() const;
bool allowSupersampleOverride() const;
void reloadSteamVRProfiles();
void saveSteamVRProfiles();
Q_INVOKABLE unsigned getSteamVRProfileCount();
Q_INVOKABLE int getSteamVRProfileCount();
Q_INVOKABLE QString getSteamVRProfileName( unsigned index );
public slots:
void setSuperSampling( float value, bool notify = true );
// void setCompositorSuperSampling( float value, bool notify = true );
void setMotionSmoothing( bool value, bool notify = true );
void setAllowSupersampleFiltering( bool value, bool notify = true );
void setAllowSupersampleOverride( bool value, bool notify = true );
void addSteamVRProfile( QString name,
bool includeSupersampling,
@@ -89,9 +90,9 @@ public slots:
signals:
void superSamplingChanged( float value );
// void compositorSuperSamplingChanged( float value );
void motionSmoothingChanged( bool value );
void allowSupersampleFilteringChanged( bool value );
void allowSupersampleOverrideChanged( bool value );
void steamVRProfilesUpdated();
void steamVRProfileAdded();
+37 -17
View File
@@ -83,11 +83,28 @@ void UtilitiesTabController::sendKeyboardAltTab()
keyboardInput->sendKeyboardAltTab();
}
void UtilitiesTabController::sendKeyboardBackspace( int count )
void UtilitiesTabController::sendKeyboardBackspace( const int count )
{
keyboardInput->sendKeyboardBackspace( count );
}
void UtilitiesTabController::sendMediaNextSong()
{
keyboardInput->sendMediaNextSong();
}
void UtilitiesTabController::sendMediaPreviousSong()
{
keyboardInput->sendMediaPreviousSong();
}
void UtilitiesTabController::sendMediaPausePlay()
{
keyboardInput->sendMediaPausePlay();
}
void UtilitiesTabController::sendMediaStopSong()
{
keyboardInput->sendMediaStopSong();
}
bool UtilitiesTabController::alarmEnabled() const
{
return m_alarmEnabled;
@@ -250,6 +267,14 @@ void UtilitiesTabController::modAlarmTimeMinute( int value, bool notify )
}
}
QString getBatteryIconPath( int batteryState )
{
QString batteryPrefix = "/res/battery_";
return QStandardPaths::locate(
QStandardPaths::AppDataLocation,
batteryPrefix + QString::number( batteryState ) + ".png" );
}
vr::VROverlayHandle_t createBatteryOverlay( vr::TrackedDeviceIndex_t index )
{
vr::VROverlayHandle_t handle = vr::k_ulOverlayHandleInvalid;
@@ -259,13 +284,11 @@ vr::VROverlayHandle_t createBatteryOverlay( vr::TrackedDeviceIndex_t index )
batteryKey.c_str(), batteryKey.c_str(), &handle );
if ( overlayError == vr::VROverlayError_None )
{
std::string batteryIconPath
= QApplication::applicationDirPath().toStdString()
+ "/res/battery_0.png";
if ( QFile::exists( QString::fromStdString( batteryIconPath ) ) )
QString batteryIconPath = getBatteryIconPath( 0 );
if ( QFile::exists( batteryIconPath ) )
{
vr::VROverlay()->SetOverlayFromFile( handle,
batteryIconPath.c_str() );
vr::VROverlay()->SetOverlayFromFile(
handle, batteryIconPath.toStdString().c_str() );
vr::VROverlay()->SetOverlayWidthInMeters( handle, 0.05f );
vr::HmdMatrix34_t notificationTransform
= { { { 1.0f, 0.0f, 0.0f, 0.00f },
@@ -469,8 +492,7 @@ void UtilitiesTabController::eventLoopTick()
if ( deviceClass
== vr::ETrackedDeviceClass::TrackedDeviceClass_GenericTracker )
{
if ( m_batteryOverlayHandles[i]
== vr::k_ulOverlayHandleInvalid )
if ( m_batteryOverlayHandles[i] == 0 )
{
LOG( INFO ) << "Creating battery overlay for device " << i;
m_batteryOverlayHandles[i] = createBatteryOverlay( i );
@@ -512,17 +534,15 @@ void UtilitiesTabController::eventLoopTick()
{
LOG( INFO )
<< "Updating battery overlay for device " << i
<< " to " << batteryState << "(" << battery << "";
std::string batteryIconPath
= QApplication::applicationDirPath().toStdString()
+ "/res/battery_" + std::to_string( batteryState )
+ ".png";
if ( QFile::exists(
QString::fromStdString( batteryIconPath ) ) )
<< " to " << batteryState << "(" << battery << ")"
<< QString::number( m_batteryOverlayHandles[i] );
QString batteryIconPath
= getBatteryIconPath( batteryState );
if ( QFile::exists( batteryIconPath ) )
{
vr::VROverlay()->SetOverlayFromFile(
m_batteryOverlayHandles[i],
batteryIconPath.c_str() );
batteryIconPath.toStdString().c_str() );
}
else
{
+7 -3
View File
@@ -44,8 +44,8 @@ private:
QTime m_alarmLastCheckTime;
bool m_steamDesktopOverlayAvailable = false;
float m_steamDesktopOverlayWidth = 4.0f;
vr::VROverlayHandle_t
m_batteryOverlayHandles[vr::k_unMaxTrackedDeviceCount];
vr::VROverlayHandle_t m_batteryOverlayHandles[vr::k_unMaxTrackedDeviceCount]
= { 0 };
int m_batteryState[vr::k_unMaxTrackedDeviceCount];
bool m_batteryVisible[vr::k_unMaxTrackedDeviceCount];
@@ -69,7 +69,11 @@ public slots:
void sendKeyboardInput( QString input );
void sendKeyboardEnter();
void sendKeyboardAltTab();
void sendKeyboardBackspace( int count );
void sendKeyboardBackspace( const int count );
void sendMediaNextSong();
void sendMediaPreviousSong();
void sendMediaPausePlay();
void sendMediaStopSong();
void setAlarmEnabled( bool enabled, bool notify = true );
void setAlarmIsModal( bool modal, bool notify = true );
@@ -17,7 +17,7 @@ void KeyboardInputDummy::sendKeyboardEnter()
// noop
}
void KeyboardInputDummy::sendKeyboardBackspace( int count )
void KeyboardInputDummy::sendKeyboardBackspace( const int count )
{
// noop
UNREFERENCED_PARAMETER( count );
@@ -28,4 +28,24 @@ void KeyboardInputDummy::sendKeyboardAltTab()
// noop
}
void KeyboardInputDummy::sendMediaNextSong()
{
// noop
}
void KeyboardInputDummy::sendMediaPreviousSong()
{
// noop
}
void KeyboardInputDummy::sendMediaPausePlay()
{
// noop
}
void KeyboardInputDummy::sendMediaStopSong()
{
// noop
}
} // namespace advsettings
@@ -11,8 +11,12 @@ class KeyboardInputDummy : public KeyboardInput
public:
virtual void sendKeyboardInput( QString input ) override;
virtual void sendKeyboardEnter() override;
virtual void sendKeyboardBackspace( int count ) override;
virtual void sendKeyboardBackspace( const int count ) override;
virtual void sendKeyboardAltTab() override;
virtual void sendMediaNextSong() override;
virtual void sendMediaPreviousSong() override;
virtual void sendMediaPausePlay() override;
virtual void sendMediaStopSong() override;
};
} // namespace advsettings
@@ -4,6 +4,20 @@
namespace advsettings
{
/*!
Represents the state of a keyboard button press. Can be either Up or Down.
Implemented because neither Qt nor Windows.h included a sensible key state enum.
*/
enum class KeyStatus
{
Up,
Down,
};
/*!
Fills out an INPUT struct ip with scanCode and keyup status.
*/
void fillKiStruct( INPUT& ip, WORD scanCode, bool keyup )
{
ip.type = INPUT_KEYBOARD;
@@ -21,11 +35,18 @@ void fillKiStruct( INPUT& ip, WORD scanCode, bool keyup )
ip.ki.time = 0;
};
void sendKeyboardInputRaw( int inputCount, LPINPUT input )
/*!
Calls SendInput on an INPUT struct and has associated error handling.
inputCount can't be deduced from input because of implicit conversions from
arrays to pointers when passed as arguments.
*/
void sendKeyboardInputRaw( const int inputCount, const LPINPUT input )
{
if ( ( inputCount > 0 )
&& !SendInput(
static_cast<UINT>( inputCount ), input, sizeof( INPUT ) ) )
const auto success
= SendInput( static_cast<UINT>( inputCount ), input, sizeof( INPUT ) );
if ( ( inputCount > 0 ) && !success )
{
char* err;
auto errCode = GetLastError();
@@ -50,6 +71,62 @@ void sendKeyboardInputRaw( int inputCount, LPINPUT input )
}
}
/*!
Returns an INPUT struct with the corresponding virtualKeyCode and keyStatus set.
All fields except ki.wVk and ki.dwFlags are zero.
The INPUT struct is used with the SendInput Windows function.
Official Docs:
https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-taginput
*/
INPUT createInputStruct( const WORD virtualKeyCode, const KeyStatus keyStatus )
{
// Zero init to ensure random data doesn't muck something up.
INPUT input = {};
input.type = INPUT_KEYBOARD;
input.ki.wVk = virtualKeyCode;
if ( keyStatus == KeyStatus::Up )
{
input.ki.dwFlags = KEYEVENTF_KEYUP;
}
else if ( keyStatus == KeyStatus::Down )
{
// Struct is already zero initialized, but this is here for clarity.
// Compiler will likely sort this out, otherwise the performance hit is
// negligible.
// There is no corresponding KEYDOWN event, you just don't
// set KEYEVENTF_KEYUP.
input.ki.dwFlags = 0;
}
// The sizeof(INPUT) on MSVC is 28. Returning by value is a non-issue
// compared to the simplicity of not having to pass a ref to an already
// existing INPUT struct, and possibly forgetting to zero it out.
return input;
}
/*!
Sends a key press to Windows. The virtualKeyCode is a Windows specific define
found in <windows.h>.
Virtual Key Codes offical docs:
https://docs.microsoft.com/en-us/windows/desktop/inputdev/virtual-key-codes
*/
void sendKeyPressAndRelease( const WORD virtualKeyCode )
{
const auto press = createInputStruct( virtualKeyCode, KeyStatus::Down );
const auto release = createInputStruct( virtualKeyCode, KeyStatus::Up );
constexpr auto numberOfActions = 2;
INPUT actions[numberOfActions] = { press, release };
sendKeyboardInputRaw( numberOfActions, actions );
}
void KeyboardInputWindows::sendKeyboardInput( QString input )
{
int len = input.length();
@@ -122,44 +199,85 @@ void KeyboardInputWindows::sendKeyboardInput( QString input )
}
}
/*!
Sends a single Enter keypress to Windows.
*/
void KeyboardInputWindows::sendKeyboardEnter()
{
LPINPUT ips = new INPUT[2];
fillKiStruct( ips[0], VK_RETURN, false );
fillKiStruct( ips[1], VK_RETURN, true );
sendKeyboardInputRaw( 2, ips );
delete[] ips;
sendKeyPressAndRelease( VK_RETURN );
}
void KeyboardInputWindows::sendKeyboardBackspace( int count )
/*!
Sends count amount of backspaces to Windows. count of 0 or below will do
nothing.
*/
void KeyboardInputWindows::sendKeyboardBackspace( const int count )
{
if ( count > 0 )
// We can only send a positive amount of key presses.
if ( count <= 0 )
{
// We ensure that count is nonnegative, therefore safe cast.
LPINPUT ips = new INPUT[static_cast<unsigned int>( count ) * 2];
for ( int i = 0; i < count; i++ )
{
fillKiStruct( ips[2 * i], VK_BACK, false );
fillKiStruct( ips[2 * i + 1], VK_BACK, true );
}
return;
}
sendKeyboardInputRaw( count * 2, ips );
delete[] ips;
for ( int presses = 0; presses < count; ++presses )
{
sendKeyPressAndRelease( VK_BACK );
}
}
/*!
Sends an Alt + Tab combination to Windows.
Used for tabbing out of game windows blocking other programs on desktop while in
VR. At least one use case was tabbing out of a fullscreen game to be able to use
a music player.
*/
void KeyboardInputWindows::sendKeyboardAltTab()
{
LPINPUT ips = new INPUT[4];
// VK_MENU is alt
fillKiStruct( ips[0], VK_MENU, false );
fillKiStruct( ips[1], VK_TAB, false );
fillKiStruct( ips[2], VK_TAB, true );
fillKiStruct( ips[3], VK_MENU, true );
// VK_MENU is Alt.
const auto pressAlt = createInputStruct( VK_MENU, KeyStatus::Down );
const auto pressTab = createInputStruct( VK_TAB, KeyStatus::Down );
const auto releaseAlt = createInputStruct( VK_MENU, KeyStatus::Up );
const auto releaseTab = createInputStruct( VK_TAB, KeyStatus::Up );
sendKeyboardInputRaw( 4, ips );
delete[] ips;
constexpr auto numberOfActions = 4;
INPUT actions[numberOfActions]
= { pressAlt, pressTab, releaseAlt, releaseTab };
sendKeyboardInputRaw( numberOfActions, actions );
}
/*!
Sends a media key Next Song button to Windows.
*/
void KeyboardInputWindows::sendMediaNextSong()
{
sendKeyPressAndRelease( VK_MEDIA_NEXT_TRACK );
}
/*!
Sends a media key Previous Song button to Windows.
*/
void KeyboardInputWindows::sendMediaPreviousSong()
{
sendKeyPressAndRelease( VK_MEDIA_PREV_TRACK );
}
/*!
Sends a media key Play/Pause button to Windows.
*/
void KeyboardInputWindows::sendMediaPausePlay()
{
sendKeyPressAndRelease( VK_MEDIA_PLAY_PAUSE );
}
/*!
Sends a media key Stop button to Windows.
*/
void KeyboardInputWindows::sendMediaStopSong()
{
sendKeyPressAndRelease( VK_MEDIA_STOP );
}
} // namespace advsettings
@@ -11,8 +11,12 @@ class KeyboardInputWindows : public KeyboardInput
public:
virtual void sendKeyboardInput( QString input ) override;
virtual void sendKeyboardEnter() override;
virtual void sendKeyboardBackspace( int count ) override;
virtual void sendKeyboardBackspace( const int count ) override;
virtual void sendKeyboardAltTab() override;
virtual void sendMediaNextSong() override;
virtual void sendMediaPreviousSong() override;
virtual void sendMediaPausePlay() override;
virtual void sendMediaStopSong() override;
};
} // namespace advsettings