Exclusive Input + Documentation Changes (#514)

* added input block code

* added exclusive Input action

* test ready exclusive

* working test state

* clean-up and add setting

* removed auto saved file

* added code to set required key

* fixed qml connection issues

* updated readme

* updated documentation

* updated version string

* updated for better directory navigation

* removed un-used code
This commit is contained in:
ykeara
2020-09-01 10:30:33 -05:00
committed by GitHub
parent b6f81a542c
commit 7d0823f83c
11 changed files with 220 additions and 40 deletions
+46 -5
View File
@@ -142,6 +142,7 @@ SteamIVRInput::SteamIVRInput()
m_keyPressSystem( action_keys::keyPressSystem ),
m_chaperoneToggle( action_keys::chaperoneToggle ),
m_pushToTalk( action_keys::pushToTalk ),
m_exclusiveInputToggle( action_keys::exclusiveInputToggle ),
m_leftHaptic( action_keys::hapticsLeft ),
m_rightHaptic( action_keys::hapticsRight ),
m_addLeftHapticClick( action_keys::addLeftHapticClick ),
@@ -152,7 +153,9 @@ SteamIVRInput::SteamIVRInput()
m_music.activeActionSet(),
m_motion.activeActionSet(),
m_misc.activeActionSet(),
m_system.activeActionSet() } )
m_system.activeActionSet() } ),
m_systemActionSets(
{ m_haptics.activeActionSet(), m_system.activeActionSet() } )
{
}
/*!
@@ -359,6 +362,35 @@ bool SteamIVRInput::keyPressSystem()
{
return isDigitalActionActivatedConstant( m_keyPressSystem );
}
bool SteamIVRInput::exclusiveInputToggle()
{
return isDigitalActionActivatedOnce( m_exclusiveInputToggle );
}
// Controls which action Sets are active, false = all, true = system + haptics
// Adjusts in update state call.
void SteamIVRInput::systemActionSetOnlyEnabled( bool value )
{
m_exclusiveInputSetToggle = value;
}
// Sets Action Set Priority
void SteamIVRInput::actionSetPriorityToggle( bool value )
{
if ( value )
{
for ( unsigned int i = 0; i < action_sets::numberOfSets; i++ )
{
m_sets.at( i ).nPriority = 0x01000001;
}
}
else
{
for ( unsigned int i = 0; i < action_sets::numberOfSets; i++ )
{
m_sets.at( i ).nPriority = 0;
}
}
}
/*!
Returns the action handle of the Left Haptic Action
@@ -400,10 +432,19 @@ update state.
*/
void SteamIVRInput::UpdateStates()
{
const auto error
= vr::VRInput()->UpdateActionState( m_sets.data(),
sizeof( vr::VRActiveActionSet_t ),
action_sets::numberOfSets );
vr::EVRInputError error;
if ( !m_exclusiveInputSetToggle )
{
error = vr::VRInput()->UpdateActionState(
m_sets.data(),
sizeof( vr::VRActiveActionSet_t ),
action_sets::numberOfSets );
}
else
{
error = vr::VRInput()->UpdateActionState(
m_systemActionSets.data(), sizeof( vr::VRActiveActionSet_t ), 2 );
}
if ( error != vr::EVRInputError::VRInputError_None )
{
+16
View File
@@ -6,6 +6,7 @@
#include "ivrinput_action_set.h"
#include "ivrinput_input_source.h"
#include <array>
#include <atomic>
namespace input
{
@@ -58,6 +59,9 @@ namespace action_keys
constexpr auto keyPressMisc = "/actions/misc/in/KeyPressMisc";
constexpr auto keyPressSystem = "/actions/system/in/KeyPressSystem";
constexpr auto exclusiveInputToggle
= "/actions/system/in/ExclusiveInputToggle";
constexpr auto hapticsLeft = "/actions/haptic/out/HapticsLeft";
constexpr auto hapticsRight = "/actions/haptic/out/HapticsRight";
constexpr auto proxSensor = "/actions/haptic/in/ProxSensor";
@@ -157,12 +161,20 @@ public:
bool pushToTalk();
bool exclusiveInputToggle();
bool keyboardOne();
bool keyboardTwo();
bool keyboardThree();
bool keyPressMisc();
bool keyPressSystem();
void systemActionSetOnlyEnabled( bool value );
void actionSetPriorityToggle( bool value );
// false is all Sets, True IS System + haptics
std::atomic<bool> m_exclusiveInputSetToggle = false;
vr::VRActionHandle_t leftHapticActionHandle();
vr::VRActionHandle_t rightHapticActionHandle();
@@ -238,6 +250,9 @@ private:
// Push To Talk
DigitalAction m_pushToTalk;
// Exclusive Input Toggle
DigitalAction m_exclusiveInputToggle;
// haptic bindings
DigitalAction m_leftHaptic;
DigitalAction m_rightHaptic;
@@ -253,6 +268,7 @@ private:
// Initialize the set of actions after everything else.
ActiveActionSets m_sets;
ActiveActionSets m_systemActionSets;
};
} // namespace input
+5
View File
@@ -25,6 +25,11 @@ public:
= vr::k_ulInvalidInputValueHandle;
m_activeActionSet.nPriority = 0;
}
void setPriority( int32_t priority )
{
m_activeActionSet.nPriority = priority;
}
vr::VRActiveActionSet_t activeActionSet()
{
return m_activeActionSet;
+89 -32
View File
@@ -429,8 +429,9 @@ void OverlayController::SetWidget( QQuickItem* quickItem,
<< thumbiconFilename << "\"";
}
// Too many render calls in too short time overwhelm Qt and an assertion
// gets thrown. Therefore we use an timer to delay render calls
// Too many render calls in too short time overwhelm Qt and an
// assertion gets thrown. Therefore we use an timer to delay render
// calls
m_pRenderTimer.reset( new QTimer() );
m_pRenderTimer->setSingleShot( true );
m_pRenderTimer->setInterval( 5 );
@@ -520,8 +521,8 @@ void OverlayController::renderOverlay()
if ( unTexture != 0 )
{
#if defined _WIN64 || defined _LP64
// To avoid any compiler warning because of cast to a larger pointer
// type (warning C4312 on VC)
// To avoid any compiler warning because of cast to a larger
// pointer type (warning C4312 on VC)
vr::Texture_t texture = { reinterpret_cast<void*>(
static_cast<uint64_t>( unTexture ) ),
vr::TextureType_OpenGL,
@@ -584,9 +585,9 @@ void OverlayController::processMediaKeyBindings()
void OverlayController::processMotionBindings()
{
// Execution order for moveCenterTabController actions is important. Don't
// reorder these. Override actions must always come after normal because
// active priority is set based on which action is "newest"
// Execution order for moveCenterTabController actions is important.
// Don't reorder these. Override actions must always come after normal
// because active priority is set based on which action is "newest"
// normal actions:
m_moveCenterTabController.leftHandSpaceDrag(
m_actions.leftHandSpaceDrag() );
@@ -653,8 +654,8 @@ void OverlayController::processPushToTalkBindings()
m_audioTabController.setMicMuted( true );
return;
}
// strictly speaking this is not the most elegant solution, but should
// work well enough.
// strictly speaking this is not the most elegant solution, but
// should work well enough.
else if ( !pushToTalkEnabled )
{
m_audioTabController.setMicMuted( false );
@@ -736,6 +737,17 @@ void OverlayController::processKeyboardBindings()
m_keyPressTwoState = false;
}
}
void OverlayController::processExclusiveInputBinding()
{
if ( m_actions.exclusiveInputToggle() && exclusiveInputEnabled() )
{
m_exclusiveState = !m_exclusiveState;
m_actions.systemActionSetOnlyEnabled( !m_exclusiveState );
m_actions.actionSetPriorityToggle( m_exclusiveState );
}
}
void OverlayController::processRotationBindings()
{
if ( m_actions.autoTurnToggle() )
@@ -745,11 +757,13 @@ void OverlayController::processRotationBindings()
}
}
/*!
Checks if an action has been activated and dispatches the related action if it
has been.
Checks if an action has been activated and dispatches the related action if
it has been.
*/
void OverlayController::processInputBindings()
{
processExclusiveInputBinding();
processMediaKeyBindings();
processMotionBindings();
@@ -763,6 +777,47 @@ void OverlayController::processInputBindings()
processRotationBindings();
}
bool OverlayController::exclusiveInputEnabled() const
{
return settings::getSetting(
settings::BoolSetting::APPLICATION_enableExclusiveInput );
}
void OverlayController::setExclusiveInputEnabled( bool value, bool notify )
{
settings::setSetting(
settings::BoolSetting::APPLICATION_enableExclusiveInput, value );
// Note: These Calls technically modify data that could be accessed
// elsewhere and cause threading issues. Since this should only be
// accessible in dashboard, and input is disabled while dashboard is up,
// there should be no reason to lock it. If it becomes an issue this needs
// to be locked with a mutex or similiar against the
// processexclusivebindings
if ( value )
{
// Re-Enable Required SteamVR key every toggle just in case.
ovr_settings_wrapper::setBool(
vr::k_pch_SteamVR_Section,
vr::k_pch_SteamVR_AllowGlobalActionSetPriority,
value );
// To setup Exclusive Input OVRAS actions should be off besides System
// (+haptics) which are always on.
m_actions.systemActionSetOnlyEnabled( true );
}
else
{
// Enable All Action Sets
m_actions.systemActionSetOnlyEnabled( false );
// Remove All priority
m_actions.actionSetPriorityToggle( false );
}
if ( notify )
{
emit exclusiveInputEnabledChanged( value );
}
}
bool OverlayController::crashRecoveryDisabled() const
{
return settings::getSetting(
@@ -908,8 +963,8 @@ void OverlayController::setCustomTickRateMs( int value, bool notify )
// vsync implementation:
// this function triggers every 1ms
// this function should remain lightweight and only check if it's time to run
// mainEventLoop() or not.
// this function should remain lightweight and only check if it's time to
// run mainEventLoop() or not.
void OverlayController::OnTimeoutPumpEvents()
{
if ( vsyncDisabled() )
@@ -937,21 +992,22 @@ void OverlayController::OnTimeoutPumpEvents()
if ( m_currentFrame > m_lastFrame )
{
// If the frame has advanced since last check, it's time for our
// main event loop. (this function should trigger about every 11ms
// assuming 90fps compositor)
// main event loop. (this function should trigger about every
// 11ms assuming 90fps compositor)
mainEventLoop();
updateRate.incrementCounter();
// wait for the next frame after executing our main event loop once.
// wait for the next frame after executing our main event loop
// once.
m_lastFrame = m_currentFrame;
m_vsyncTooLateCounter = 0;
}
else if ( m_vsyncTooLateCounter >= k_nonVsyncTickRate )
{
mainEventLoop();
// m_lastFrame = m_currentFrame + 1 skips the next vsync frame in
// case it was just about to trigger, to prevent double updates
// faster than 11ms.
// m_lastFrame = m_currentFrame + 1 skips the next vsync frame
// in case it was just about to trigger, to prevent double
// updates faster than 11ms.
m_lastFrame = m_currentFrame + 1;
m_vsyncTooLateCounter = 0;
}
@@ -1352,11 +1408,12 @@ void OverlayController::AddOffsetToCollisionBounds( unsigned axisId,
void OverlayController::AddOffsetToCollisionBounds( float offset[3],
bool commit )
{
// Apparently Valve sanity-checks the y-coordinates of the collision bounds
// (and only the y-coordinates) I can move the bounds on the xz-plane, I can
// make the "ceiling" of the chaperone cage lower/higher, but when I dare to
// set one single lower corner to something non-zero, every corner gets its
// y-coordinates reset to the defaults.
// Apparently Valve sanity-checks the y-coordinates of the collision
// bounds (and only the y-coordinates) I can move the bounds on the
// xz-plane, I can make the "ceiling" of the chaperone cage
// lower/higher, but when I dare to set one single lower corner to
// something non-zero, every corner gets its y-coordinates reset to the
// defaults.
if ( commit )
{
vr::VRChaperoneSetup()->HideWorkingSetPreview();
@@ -1377,10 +1434,10 @@ void OverlayController::AddOffsetToCollisionBounds( float offset[3],
{
collisionBounds[b].vCorners[c].v[0] += offset[0];
// keep the lower corners on the ground so it doesn't reset all
// y cooridinates. this causes the caperone to "grow" up instead
// of not moving up at all. note that Valve still forces a
// minimum height so we can't go into the ground
// keep the lower corners on the ground so it doesn't reset
// all y cooridinates. this causes the caperone to "grow" up
// instead of not moving up at all. note that Valve still
// forces a minimum height so we can't go into the ground
if ( collisionBounds[b].vCorners[c].v[1] != 0 )
{
collisionBounds[b].vCorners[c].v[1] += offset[1];
@@ -1563,8 +1620,8 @@ void OverlayController::OnNetworkReply( QNetworkReply* reply )
.toString();
// this is a little convoluted to ensure if our local version is
// somehow higher than remote, it doesn't detect an update from just
// higher remote "minor" or "patch" values.
// somehow higher than remote, it doesn't detect an update from
// just higher remote "minor" or "patch" values.
if ( ( m_remoteVersionMajor > m_localVersionMajor )
|| ( m_remoteVersionMajor == m_localVersionMajor
&& m_remoteVersionMinor > m_localVersionMinor )
@@ -1598,8 +1655,8 @@ void OverlayController::OnNetworkReply( QNetworkReply* reply )
setVersionCheckText( m_optionalMessage );
}
setNewVersionDetected( false );
LOG( INFO )
<< "Version Check: Installed version is latest release.";
LOG( INFO ) << "Version Check: Installed version is latest "
"release.";
}
}
else
+8
View File
@@ -90,6 +90,9 @@ class OverlayController : public QObject
setCustomTickRateMs NOTIFY customTickRateMsChanged )
Q_PROPERTY( int debugState READ debugState WRITE setDebugState NOTIFY
debugStateChanged )
Q_PROPERTY(
bool exclusiveInputEnabled READ exclusiveInputEnabled WRITE
setExclusiveInputEnabled NOTIFY exclusiveInputEnabledChanged )
private:
vr::VROverlayHandle_t m_ulOverlayHandle = vr::k_ulOverlayHandleInvalid;
@@ -166,7 +169,9 @@ private:
void processChaperoneBindings();
void processKeyboardBindings();
void processRotationBindings();
void processExclusiveInputBinding();
bool m_exclusiveState = false;
bool m_keyPressOneState = false;
bool m_keyPressTwoState = false;
@@ -232,6 +237,7 @@ public:
void mainEventLoop();
bool crashRecoveryDisabled() const;
bool exclusiveInputEnabled() const;
bool enableDebug() const;
bool disableVersionCheck() const;
bool newVersionDetected() const;
@@ -256,6 +262,7 @@ public slots:
void cancelAlarm01Sound();
void setCrashRecoveryDisabled( bool value, bool notify = true );
void setExclusiveInputEnabled( bool value, bool notify = true );
void setEnableDebug( bool value, bool notify = true );
void setDisableVersionCheck( bool value, bool notify = true );
void setNewVersionDetected( bool value, bool notify = true );
@@ -267,6 +274,7 @@ public slots:
signals:
void keyBoardInputSignal( QString input, unsigned long userValue = 0 );
void crashRecoveryDisabledChanged( bool value );
void exclusiveInputEnabledChanged( bool value );
void enableDebugChanged( bool value );
void disableVersionCheckChanged( bool value );
void newVersionDetectedChanged( bool value );
+6
View File
@@ -179,6 +179,11 @@
"name": "/actions/system/in/PushToTalk",
"requirement": "optional",
"type": "boolean"
},
{
"name": "/actions/system/in/ExclusiveInputToggle",
"requirement": "optional",
"type": "boolean"
},
{
"name": "/actions/misc/in/ChaperoneToggle",
@@ -284,6 +289,7 @@
"/actions/misc/in/YAxisLockToggle" : "Y-Axis Lock Toggle",
"/actions/misc/in/ZAxisLockToggle" : "Z-Axis Lock Toggle",
"/actions/system/in/PushToTalk" : "Push To Talk",
"/actions/system/in/ExclusiveInputToggle" : "Exclusive Input Toggle",
"/actions/misc/in/ChaperoneToggle" : "Chaperone Toggle",
"/actions/haptic/in/ProxSensor" : "Proximity Sensor",
"/actions/misc/in/KeyboardOne" : "Keyboard Shortcut One",
+11
View File
@@ -90,6 +90,13 @@ MyStackViewPage {
SettingsTabController.setOculusSdkToggle(this.checked, true)
}
}
MyToggleButton {
id: exclusiveInputToggleButton
text: "Exclusive Input Toggle (This enables Key Binding to Toggle state)"
onCheckedChanged: {
OverlayController.setExclusiveInputEnabled(this.checked, true)
}
}
MyToggleButton {
id: spaceAdjustChaperoneToggle
text: "Adjust Chaperone"
@@ -256,6 +263,7 @@ MyStackViewPage {
disableVersionCheckToggle.checked = OverlayController.disableVersionCheck
nativeChaperoneToggleButton.checked = SettingsTabController.nativeChaperoneToggle
oculusSdkToggleButton.checked = SettingsTabController.oculusSdkToggle
exclusiveInputToggleButton.checked = OverlayController.exclusiveInputEnabled
seatedOldExternalWarning.visible = MoveCenterTabController.allowExternalEdits && MoveCenterTabController.oldStyleMotion && MoveCenterTabController.enableSeatedMotion
spaceAdjustChaperoneToggle.checked = MoveCenterTabController.adjustChaperone
@@ -322,6 +330,9 @@ MyStackViewPage {
onDisableVersionCheckChanged: {
disableVersionCheckToggle.checked = OverlayController.disableVersionCheck
}
onExclusiveInputEnabledChanged:{
exclusiveInputToggleButton.checked = OverlayController.exclusiveInputEnabled
}
}
} // end scroll
}
+4 -1
View File
@@ -302,7 +302,10 @@ private:
SettingCategory::Application,
QtInfo{ "enableDebug" },
false },
BoolSettingValue{ BoolSetting::APPLICATION_enableExclusiveInput,
SettingCategory::Application,
QtInfo{ "enableExclusiveInput" },
false },
BoolSettingValue{ BoolSetting::AUDIO_pttEnabled,
SettingCategory::Audio,
QtInfo{ "pttEnabled" },
+1
View File
@@ -29,6 +29,7 @@ enum class BoolSetting
APPLICATION_vsyncDisabled,
APPLICATION_crashRecoveryDisabled,
APPLICATION_enableDebug,
APPLICATION_enableExclusiveInput,
AUDIO_pttEnabled,
AUDIO_pttShowNotification,