Merge branch 'master' into alpha-kung
This commit is contained in:
+5
-2
@@ -411,8 +411,11 @@ int main( int argc, char* argv[] )
|
||||
advsettings::OverlayController controller(
|
||||
desktopMode, noSound, qmlEngine );
|
||||
|
||||
QQmlComponent component(
|
||||
&qmlEngine, QUrl::fromLocalFile( "res/qml/mainwidget.qml" ) );
|
||||
QString path = QStandardPaths::locate(
|
||||
QStandardPaths::AppDataLocation,
|
||||
QStringLiteral( "res/qml/mainwidget.qml" ) );
|
||||
|
||||
QQmlComponent component( &qmlEngine, QUrl::fromLocalFile( path ) );
|
||||
auto errors = component.errors();
|
||||
for ( auto& e : errors )
|
||||
{
|
||||
|
||||
@@ -85,8 +85,9 @@ OverlayController::OverlayController( bool desktopMode,
|
||||
<< focusChangedSoundFile;
|
||||
}
|
||||
|
||||
QString alarm01SoundFile = QApplication::applicationDirPath().append(
|
||||
"/res/sounds/alarm01.wav" );
|
||||
QString alarm01SoundFile
|
||||
= QStandardPaths::locate( QStandardPaths::AppDataLocation,
|
||||
QStringLiteral( "res/sounds/alarm01.wav" ) );
|
||||
QFileInfo alarm01SoundFileInfo( alarm01SoundFile );
|
||||
if ( alarm01SoundFileInfo.exists() && alarm01SoundFileInfo.isFile() )
|
||||
{
|
||||
@@ -433,13 +434,14 @@ void OverlayController::SetWidget( QQuickItem* quickItem,
|
||||
m_ulOverlayHandle, vr::VROverlayInputMethod_Mouse );
|
||||
vr::VROverlay()->SetOverlayFlag(
|
||||
m_ulOverlayHandle, vr::VROverlayFlags_SendVRScrollEvents, true );
|
||||
std::string thumbIconPath
|
||||
= QApplication::applicationDirPath().toStdString()
|
||||
+ "\\res\\thumbicon.png";
|
||||
if ( QFile::exists( QString::fromStdString( thumbIconPath ) ) )
|
||||
QString thumbIconPath
|
||||
= QStandardPaths::locate( QStandardPaths::AppDataLocation,
|
||||
QStringLiteral( "res/thumbicon.png" ) );
|
||||
if ( QFile::exists( thumbIconPath ) )
|
||||
{
|
||||
vr::VROverlay()->SetOverlayFromFile( m_ulOverlayThumbnailHandle,
|
||||
thumbIconPath.c_str() );
|
||||
vr::VROverlay()->SetOverlayFromFile(
|
||||
m_ulOverlayThumbnailHandle,
|
||||
thumbIconPath.toStdString().c_str() );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -183,6 +183,7 @@ MyStackViewPage {
|
||||
}
|
||||
|
||||
MyPushButton2 {
|
||||
id: steamvrSupersampleDecrement
|
||||
text: "-"
|
||||
Layout.preferredWidth: 40
|
||||
onClicked: {
|
||||
@@ -192,7 +193,7 @@ MyStackViewPage {
|
||||
|
||||
MySlider {
|
||||
id: steamvrSupersamplingSlider
|
||||
from: 0.1
|
||||
from: 0.2
|
||||
to: 5.0
|
||||
stepSize: 0.1
|
||||
value: 1.0
|
||||
@@ -208,6 +209,7 @@ MyStackViewPage {
|
||||
}
|
||||
|
||||
MyPushButton2 {
|
||||
id: steamvrSupersampleIncrement
|
||||
text: "+"
|
||||
Layout.preferredWidth: 40
|
||||
onClicked: {
|
||||
@@ -239,6 +241,24 @@ MyStackViewPage {
|
||||
}
|
||||
}
|
||||
}
|
||||
MyToggleButton {
|
||||
id: steamvrAllowSupersampleOverrideToggle
|
||||
text: "Enable Manual Supersampling Override"
|
||||
onCheckedChanged: {
|
||||
SteamVRTabController.setAllowSupersampleOverride(this.checked, false)
|
||||
if(!this.checked){
|
||||
steamvrSupersamplingText.enabled = false
|
||||
steamvrSupersamplingSlider.enabled = false
|
||||
steamvrSupersampleIncrement.enabled = false
|
||||
steamvrSupersampleDecrement.enabled = false
|
||||
}else{
|
||||
steamvrSupersamplingText.enabled = true
|
||||
steamvrSupersamplingSlider.enabled = true
|
||||
steamvrSupersampleIncrement.enabled = true
|
||||
steamvrSupersampleDecrement.enabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
MyToggleButton {
|
||||
id: steamvrAllowSupersampleFilteringToggle
|
||||
text: "Enable Advanced Supersample Filtering"
|
||||
@@ -286,8 +306,16 @@ MyStackViewPage {
|
||||
if (s1 <= steamvrSupersamplingSlider.to) {
|
||||
steamvrSupersamplingSlider.value = s1
|
||||
}
|
||||
steamvrAllowSupersampleOverrideToggle.checked = SteamVRTabController.allowSupersampleOverride
|
||||
steamvrAllowSupersampleFilteringToggle.checked = SteamVRTabController.allowSupersampleFiltering
|
||||
steamvrMotionSmoothingToggle.checked = SteamVRTabController.motionSmoothing
|
||||
if(!steamvrAllowSupersampleOverrideToggle.checked){
|
||||
steamvrSupersamplingText.enabled = false
|
||||
steamvrSupersamplingSlider.enabled = false
|
||||
steamvrSupersampleIncrement.enabled = false
|
||||
steamvrSupersampleDecrement.enabled = false
|
||||
}
|
||||
|
||||
reloadSteamVRProfiles()
|
||||
}
|
||||
|
||||
@@ -300,6 +328,9 @@ MyStackViewPage {
|
||||
}
|
||||
steamvrSupersamplingText.text = s1
|
||||
}
|
||||
onAllowSupersampleOverrideChanged: {
|
||||
steamvrAllowSupersampleOverrideToggle.checked = SteamVRTabController.allowSupersampleOverride
|
||||
}
|
||||
onAllowSupersampleFilteringChanged: {
|
||||
steamvrAllowSupersampleFilteringToggle.checked = SteamVRTabController.allowSupersampleFiltering
|
||||
}
|
||||
|
||||
@@ -320,6 +320,155 @@ MyStackViewPage {
|
||||
}
|
||||
}
|
||||
|
||||
GroupBox {
|
||||
id: mediaKeysGroupBox
|
||||
Layout.fillWidth: true
|
||||
|
||||
label: MyText {
|
||||
leftPadding: 10
|
||||
text: "Media Control Keys"
|
||||
bottomPadding: -10
|
||||
}
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
border.color: "#ffffff"
|
||||
radius: 8
|
||||
}
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
Rectangle {
|
||||
color: "#ffffff"
|
||||
height: 1
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: 5
|
||||
}
|
||||
|
||||
|
||||
RowLayout {
|
||||
property bool playButtonIsPlay: false
|
||||
MyPushButton2 {
|
||||
id: previousSongButton
|
||||
Layout.preferredHeight: 48
|
||||
Layout.preferredWidth: 48
|
||||
contentItem: Image {
|
||||
source: "media_keys/outline_skip_previous_white_24dp.svg"
|
||||
sourceSize: Qt.size( imgSP.sourceSize.width*2, imgSP.sourceSize.height*2 )
|
||||
Image{
|
||||
id: imgSP
|
||||
source: parent.source
|
||||
width:0
|
||||
height:0
|
||||
}
|
||||
anchors.fill: parent
|
||||
}
|
||||
onClicked: {
|
||||
UtilitiesTabController.sendMediaPreviousSong()
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
opacity: parent.down ? 1.0 : (parent.activeFocus ? 0.5 : 0.0)
|
||||
color: "#406288"
|
||||
radius: 4
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
MyPushButton2 {
|
||||
id: stopSongButton
|
||||
Layout.preferredHeight: 48
|
||||
Layout.preferredWidth: 48
|
||||
|
||||
contentItem: Image {
|
||||
source: "media_keys/outline_stop_white_24dp.svg"
|
||||
sourceSize: Qt.size( imgS.sourceSize.width*2, imgS.sourceSize.height*2 )
|
||||
Image{
|
||||
id: imgS
|
||||
source: parent.source
|
||||
width:0
|
||||
height:0
|
||||
}
|
||||
anchors.fill: parent
|
||||
}
|
||||
onClicked: {
|
||||
UtilitiesTabController.sendMediaStopSong()
|
||||
playPauseSongButton.contentItem.source = "media_keys/outline_play_arrow_white_24dp.svg"
|
||||
parent.playButtonIsPlay = true
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
opacity: parent.down ? 1.0 : (parent.activeFocus ? 0.5 : 0.0)
|
||||
color: "#406288"
|
||||
radius: 4
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
MyPushButton2 {
|
||||
id: playPauseSongButton
|
||||
Layout.preferredHeight: 48
|
||||
Layout.preferredWidth: 48
|
||||
contentItem: Image {
|
||||
// Assume that music is playing when people enter VR.
|
||||
source: "media_keys/outline_pause_white_24dp.svg"
|
||||
sourceSize: Qt.size( imgP.sourceSize.width*2, imgP.sourceSize.height*2 )
|
||||
Image{
|
||||
id: imgP
|
||||
source: parent.source
|
||||
width:0
|
||||
height:0
|
||||
}
|
||||
|
||||
anchors.fill: parent
|
||||
}
|
||||
onClicked: {
|
||||
UtilitiesTabController.sendMediaPausePlay()
|
||||
if (parent.playButtonIsPlay) {
|
||||
playPauseSongButton.contentItem.source = "media_keys/outline_pause_white_24dp.svg"
|
||||
parent.playButtonIsPlay = false
|
||||
} else {
|
||||
playPauseSongButton.contentItem.source = "media_keys/outline_play_arrow_white_24dp.svg"
|
||||
parent.playButtonIsPlay = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
opacity: parent.down ? 1.0 : (parent.activeFocus ? 0.5 : 0.0)
|
||||
color: "#406288"
|
||||
radius: 4
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
MyPushButton2 {
|
||||
id: nextSongButton
|
||||
Layout.preferredHeight: 48
|
||||
Layout.preferredWidth: 48
|
||||
|
||||
contentItem: Image {
|
||||
source: "media_keys/outline_skip_next_white_24dp.svg"
|
||||
sourceSize: Qt.size( imgSN.sourceSize.width*2, imgSN.sourceSize.height*2 )
|
||||
Image{
|
||||
id: imgSN
|
||||
source: parent.source
|
||||
width:0
|
||||
height:0
|
||||
}
|
||||
anchors.fill: parent
|
||||
}
|
||||
onClicked: {
|
||||
UtilitiesTabController.sendMediaNextSong()
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
opacity: parent.down ? 1.0 : (parent.activeFocus ? 0.5 : 0.0)
|
||||
color: "#406288"
|
||||
radius: 4
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="white" d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></svg>
|
||||
|
After Width: | Height: | Size: 184 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="white" d="M10 8.64L15.27 12 10 15.36V8.64M8 5v14l11-7L8 5z"/></svg>
|
||||
|
After Width: | Height: | Size: 201 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="white" d="M6 18l8.5-6L6 6v12zm2-8.14L11.03 12 8 14.14V9.86zM16 6h2v12h-2z"/></svg>
|
||||
|
After Width: | Height: | Size: 216 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="white" d="M6 6h2v12H6zm3.5 6l8.5 6V6l-8.5 6zm6.5 2.14L12.97 12 16 9.86v4.28z"/></svg>
|
||||
|
After Width: | Height: | Size: 219 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path fill="white" d="M16 8v8H8V8h8m2-2H6v12h12V6z"/></svg>
|
||||
|
After Width: | Height: | Size: 181 B |
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user