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:
+46
-5
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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" },
|
||||
|
||||
@@ -29,6 +29,7 @@ enum class BoolSetting
|
||||
APPLICATION_vsyncDisabled,
|
||||
APPLICATION_crashRecoveryDisabled,
|
||||
APPLICATION_enableDebug,
|
||||
APPLICATION_enableExclusiveInput,
|
||||
|
||||
AUDIO_pttEnabled,
|
||||
AUDIO_pttShowNotification,
|
||||
|
||||
Reference in New Issue
Block a user