From aecb3eeb673de789e8b59e085040d66489d4e2d0 Mon Sep 17 00:00:00 2001 From: Petr Bartos Date: Fri, 24 Feb 2023 19:47:22 +0100 Subject: [PATCH] Use gesture --- .../jni/src/Lambda1VR/L1VR_SurfaceView.c | 4 ++ Projects/Android/jni/src/Lambda1VR/VrCommon.h | 1 + Projects/Android/jni/src/Lambda1VR/VrCvars.h | 2 + .../Android/jni/src/Lambda1VR/VrInputAlt.c | 45 ++++++++++++++++++- .../Android/jni/src/Lambda1VR/VrInputAlt2.c | 45 ++++++++++++++++++- .../Android/jni/src/Lambda1VR/VrInputCommon.c | 1 + .../jni/src/Lambda1VR/VrInputDefault.c | 45 ++++++++++++++++++- .../jni/src/Lambda1VR/VrInputOneController.c | 43 ++++++++++++++++++ .../jni/src/Xash3D/xash3d/common/const.h | 5 +++ .../jni/src/Xash3D/xash3d/common/usercmd.h | 2 +- .../Xash3D/xash3d/engine/common/net_encode.c | 8 ++++ .../Xash3D/xash3d/mainui/menus/Controls.cpp | 18 ++++++++ 12 files changed, 215 insertions(+), 4 deletions(-) diff --git a/Projects/Android/jni/src/Lambda1VR/L1VR_SurfaceView.c b/Projects/Android/jni/src/Lambda1VR/L1VR_SurfaceView.c index e430d10..7a345c5 100644 --- a/Projects/Android/jni/src/Lambda1VR/L1VR_SurfaceView.c +++ b/Projects/Android/jni/src/Lambda1VR/L1VR_SurfaceView.c @@ -1376,6 +1376,8 @@ convar_t *vr_highlight_actionables; convar_t *vr_headtorch; convar_t *vr_quick_crouchjump; convar_t *vr_stereo_side; +convar_t *vr_gesture_triggered_use; +convar_t *vr_use_gesture_boundary; void Android_Vibrate( float duration, int channel, float intensity ) { @@ -1439,6 +1441,8 @@ void VR_Init() vr_highlight_actionables = Cvar_Get( "vr_highlight_actionables", "1", CVAR_ARCHIVE, "Set to 0 to disable highlighting of actionable objects/entities" ); vr_headtorch = Cvar_Get( "vr_headtorch", "0", CVAR_ARCHIVE, "Set to 1 to enable head-torch flashlight mode" ); vr_quick_crouchjump = Cvar_Get( "vr_quick_crouchjump", "1", CVAR_ARCHIVE, "Set to 0 to disable quick crouch-jump mode (double clicking jump button triggers duck)" ); + vr_gesture_triggered_use = Cvar_Get( "vr_gesture_triggered_use", "0", CVAR_ARCHIVE, "Set to 0 to disable use gesture, 1 to enable" ); + vr_use_gesture_boundary = Cvar_Get( "vr_use_gesture_boundary", "0.35", CVAR_ARCHIVE, "Use gesture boundary" ); //Not to be changed by users, as it will be overwritten anyway vr_stereo_side = Cvar_Get( "vr_stereo_side", "0", CVAR_READ_ONLY, "Eye being drawn" ); diff --git a/Projects/Android/jni/src/Lambda1VR/VrCommon.h b/Projects/Android/jni/src/Lambda1VR/VrCommon.h index aa5fc4e..8ad073f 100644 --- a/Projects/Android/jni/src/Lambda1VR/VrCommon.h +++ b/Projects/Android/jni/src/Lambda1VR/VrCommon.h @@ -58,6 +58,7 @@ extern vec3_t flashlightoffset; extern int ducked; extern bool player_moving; +extern int use_gesture_state; bool isMultiplayer(); bool isScopeEngaged(); diff --git a/Projects/Android/jni/src/Lambda1VR/VrCvars.h b/Projects/Android/jni/src/Lambda1VR/VrCvars.h index 6ac7fe2..e135165 100644 --- a/Projects/Android/jni/src/Lambda1VR/VrCvars.h +++ b/Projects/Android/jni/src/Lambda1VR/VrCvars.h @@ -26,6 +26,8 @@ extern convar_t *vr_controller_tracking_haptic; extern convar_t *vr_highlight_actionables; extern convar_t *vr_headtorch; extern convar_t *vr_quick_crouchjump; +extern convar_t *vr_gesture_triggered_use; +extern convar_t *vr_use_gesture_boundary; //Used and updated continuously during rendering extern convar_t *vr_stereo_side; \ No newline at end of file diff --git a/Projects/Android/jni/src/Lambda1VR/VrInputAlt.c b/Projects/Android/jni/src/Lambda1VR/VrInputAlt.c index 0f5061f..76196c1 100644 --- a/Projects/Android/jni/src/Lambda1VR/VrInputAlt.c +++ b/Projects/Android/jni/src/Lambda1VR/VrInputAlt.c @@ -198,7 +198,50 @@ void HandleInput_Alt( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, ovr weaponangles[MELEE][YAW] += (cl.refdef.cl_viewangles[YAW] - hmdorientation[YAW]); weaponangles[MELEE][PITCH] *= -1.0f; - //Use (Action) + // Use (Action gesture) + if (vr_gesture_triggered_use->integer) { + bool gestureUseAllowed = !vr_weapon_stabilised->value; + // Off-hand gesture + float xOffset = hmdPosition[0] - pOffTracking->HeadPose.Pose.Position.x; + float zOffset = hmdPosition[2] - pOffTracking->HeadPose.Pose.Position.z; + float distanceToBody = sqrtf((xOffset * xOffset) + (zOffset * zOffset)); + if (gestureUseAllowed && (distanceToBody > vr_use_gesture_boundary->value)) { + if (!(use_gesture_state & VR_USE_GESTURE_OFF_HAND)) { + sendButtonAction("+use2", true); + } + use_gesture_state |= VR_USE_GESTURE_OFF_HAND; + } else { + if (use_gesture_state & VR_USE_GESTURE_OFF_HAND) { + sendButtonAction("+use2", false); + } + use_gesture_state &= ~VR_USE_GESTURE_OFF_HAND; + } + // Weapon-hand gesture + xOffset = hmdPosition[0] - pDominantTracking->HeadPose.Pose.Position.x; + zOffset = hmdPosition[2] - pDominantTracking->HeadPose.Pose.Position.z; + distanceToBody = sqrtf((xOffset * xOffset) + (zOffset * zOffset)); + if (gestureUseAllowed && (distanceToBody > vr_use_gesture_boundary->value)) { + if (!(use_gesture_state & VR_USE_GESTURE_WEAPON_HAND)) { + sendButtonAction("+use", true); + } + use_gesture_state |= VR_USE_GESTURE_WEAPON_HAND; + } else { + if (use_gesture_state & VR_USE_GESTURE_WEAPON_HAND) { + sendButtonAction("+use", false); + } + use_gesture_state &= ~VR_USE_GESTURE_WEAPON_HAND; + } + } else { + if (use_gesture_state & VR_USE_GESTURE_OFF_HAND) { + sendButtonAction("+use2", false); + } + if (use_gesture_state & VR_USE_GESTURE_WEAPON_HAND) { + sendButtonAction("+use", false); + } + use_gesture_state = 0; + } + + // Use (Action button) if ((pDominantTrackedRemoteNew->Buttons & ovrButton_Joystick) != (pDominantTrackedRemoteOld->Buttons & ovrButton_Joystick)) { diff --git a/Projects/Android/jni/src/Lambda1VR/VrInputAlt2.c b/Projects/Android/jni/src/Lambda1VR/VrInputAlt2.c index 48db491..2a26246 100644 --- a/Projects/Android/jni/src/Lambda1VR/VrInputAlt2.c +++ b/Projects/Android/jni/src/Lambda1VR/VrInputAlt2.c @@ -209,7 +209,50 @@ void HandleInput_Alt2( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, ov weaponangles[MELEE][YAW] += (cl.refdef.cl_viewangles[YAW] - hmdorientation[YAW]); weaponangles[MELEE][PITCH] *= -1.0f; - //Use (Action) + // Use (Action gesture) + if (vr_gesture_triggered_use->integer) { + bool gestureUseAllowed = !vr_weapon_stabilised->value; + // Off-hand gesture + float xOffset = hmdPosition[0] - pOffTracking->HeadPose.Pose.Position.x; + float zOffset = hmdPosition[2] - pOffTracking->HeadPose.Pose.Position.z; + float distanceToBody = sqrtf((xOffset * xOffset) + (zOffset * zOffset)); + if (gestureUseAllowed && (distanceToBody > vr_use_gesture_boundary->value)) { + if (!(use_gesture_state & VR_USE_GESTURE_OFF_HAND)) { + sendButtonAction("+use2", true); + } + use_gesture_state |= VR_USE_GESTURE_OFF_HAND; + } else { + if (use_gesture_state & VR_USE_GESTURE_OFF_HAND) { + sendButtonAction("+use2", false); + } + use_gesture_state &= ~VR_USE_GESTURE_OFF_HAND; + } + // Weapon-hand gesture + xOffset = hmdPosition[0] - pDominantTracking->HeadPose.Pose.Position.x; + zOffset = hmdPosition[2] - pDominantTracking->HeadPose.Pose.Position.z; + distanceToBody = sqrtf((xOffset * xOffset) + (zOffset * zOffset)); + if (gestureUseAllowed && (distanceToBody > vr_use_gesture_boundary->value)) { + if (!(use_gesture_state & VR_USE_GESTURE_WEAPON_HAND)) { + sendButtonAction("+use", true); + } + use_gesture_state |= VR_USE_GESTURE_WEAPON_HAND; + } else { + if (use_gesture_state & VR_USE_GESTURE_WEAPON_HAND) { + sendButtonAction("+use", false); + } + use_gesture_state &= ~VR_USE_GESTURE_WEAPON_HAND; + } + } else { + if (use_gesture_state & VR_USE_GESTURE_OFF_HAND) { + sendButtonAction("+use2", false); + } + if (use_gesture_state & VR_USE_GESTURE_WEAPON_HAND) { + sendButtonAction("+use", false); + } + use_gesture_state = 0; + } + + // Use (Action button) if ((pDominantTrackedRemoteNew->Buttons & ovrButton_Joystick) != (pDominantTrackedRemoteOld->Buttons & ovrButton_Joystick)) { diff --git a/Projects/Android/jni/src/Lambda1VR/VrInputCommon.c b/Projects/Android/jni/src/Lambda1VR/VrInputCommon.c index b8d3d85..db58d1e 100644 --- a/Projects/Android/jni/src/Lambda1VR/VrInputCommon.c +++ b/Projects/Android/jni/src/Lambda1VR/VrInputCommon.c @@ -50,6 +50,7 @@ vec3_t flashlightoffset; int ducked; bool player_moving; +int use_gesture_state; bool stabiliseScope; char * g_pszBackpackWeapon; diff --git a/Projects/Android/jni/src/Lambda1VR/VrInputDefault.c b/Projects/Android/jni/src/Lambda1VR/VrInputDefault.c index 7027ca2..a4c6654 100644 --- a/Projects/Android/jni/src/Lambda1VR/VrInputDefault.c +++ b/Projects/Android/jni/src/Lambda1VR/VrInputDefault.c @@ -210,7 +210,50 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, weaponangles[MELEE][YAW] += (cl.refdef.cl_viewangles[YAW] - hmdorientation[YAW]); weaponangles[MELEE][PITCH] *= -1.0f; - //Use (Action) + // Use (Action gesture) + if (vr_gesture_triggered_use->integer) { + bool gestureUseAllowed = !vr_weapon_stabilised->value; + // Off-hand gesture + float xOffset = hmdPosition[0] - pOffTracking->HeadPose.Pose.Position.x; + float zOffset = hmdPosition[2] - pOffTracking->HeadPose.Pose.Position.z; + float distanceToBody = sqrtf((xOffset * xOffset) + (zOffset * zOffset)); + if (gestureUseAllowed && (distanceToBody > vr_use_gesture_boundary->value)) { + if (!(use_gesture_state & VR_USE_GESTURE_OFF_HAND)) { + sendButtonAction("+use2", true); + } + use_gesture_state |= VR_USE_GESTURE_OFF_HAND; + } else { + if (use_gesture_state & VR_USE_GESTURE_OFF_HAND) { + sendButtonAction("+use2", false); + } + use_gesture_state &= ~VR_USE_GESTURE_OFF_HAND; + } + // Weapon-hand gesture + xOffset = hmdPosition[0] - pDominantTracking->HeadPose.Pose.Position.x; + zOffset = hmdPosition[2] - pDominantTracking->HeadPose.Pose.Position.z; + distanceToBody = sqrtf((xOffset * xOffset) + (zOffset * zOffset)); + if (gestureUseAllowed && (distanceToBody > vr_use_gesture_boundary->value)) { + if (!(use_gesture_state & VR_USE_GESTURE_WEAPON_HAND)) { + sendButtonAction("+use", true); + } + use_gesture_state |= VR_USE_GESTURE_WEAPON_HAND; + } else { + if (use_gesture_state & VR_USE_GESTURE_WEAPON_HAND) { + sendButtonAction("+use", false); + } + use_gesture_state &= ~VR_USE_GESTURE_WEAPON_HAND; + } + } else { + if (use_gesture_state & VR_USE_GESTURE_OFF_HAND) { + sendButtonAction("+use2", false); + } + if (use_gesture_state & VR_USE_GESTURE_WEAPON_HAND) { + sendButtonAction("+use", false); + } + use_gesture_state = 0; + } + + // Use (Action button) if ((pDominantTrackedRemoteNew->Buttons & ovrButton_Joystick) != (pDominantTrackedRemoteOld->Buttons & ovrButton_Joystick)) { diff --git a/Projects/Android/jni/src/Lambda1VR/VrInputOneController.c b/Projects/Android/jni/src/Lambda1VR/VrInputOneController.c index ffbd672..d20905f 100644 --- a/Projects/Android/jni/src/Lambda1VR/VrInputOneController.c +++ b/Projects/Android/jni/src/Lambda1VR/VrInputOneController.c @@ -426,6 +426,49 @@ void HandleInput_OneController( ovrInputStateTrackedRemote *pDominantTrackedRemo } } + // Use (Action gesture) + if (vr_gesture_triggered_use->integer) { + bool gestureUseAllowed = !vr_weapon_stabilised->value; + // Off-hand gesture + float xOffset = hmdPosition[0] - pOffTracking->HeadPose.Pose.Position.x; + float zOffset = hmdPosition[2] - pOffTracking->HeadPose.Pose.Position.z; + float distanceToBody = sqrtf((xOffset * xOffset) + (zOffset * zOffset)); + if (gestureUseAllowed && (distanceToBody > vr_use_gesture_boundary->value)) { + if (!(use_gesture_state & VR_USE_GESTURE_OFF_HAND)) { + sendButtonAction("+use2", true); + } + use_gesture_state |= VR_USE_GESTURE_OFF_HAND; + } else { + if (use_gesture_state & VR_USE_GESTURE_OFF_HAND) { + sendButtonAction("+use2", false); + } + use_gesture_state &= ~VR_USE_GESTURE_OFF_HAND; + } + // Weapon-hand gesture + xOffset = hmdPosition[0] - pDominantTracking->HeadPose.Pose.Position.x; + zOffset = hmdPosition[2] - pDominantTracking->HeadPose.Pose.Position.z; + distanceToBody = sqrtf((xOffset * xOffset) + (zOffset * zOffset)); + if (gestureUseAllowed && (distanceToBody > vr_use_gesture_boundary->value)) { + if (!(use_gesture_state & VR_USE_GESTURE_WEAPON_HAND)) { + sendButtonAction("+use", true); + } + use_gesture_state |= VR_USE_GESTURE_WEAPON_HAND; + } else { + if (use_gesture_state & VR_USE_GESTURE_WEAPON_HAND) { + sendButtonAction("+use", false); + } + use_gesture_state &= ~VR_USE_GESTURE_WEAPON_HAND; + } + } else { + if (use_gesture_state & VR_USE_GESTURE_OFF_HAND) { + sendButtonAction("+use2", false); + } + if (use_gesture_state & VR_USE_GESTURE_WEAPON_HAND) { + sendButtonAction("+use", false); + } + use_gesture_state = 0; + } + sendButtonAction("+speed", running ? 1 : 0); } } diff --git a/Projects/Android/jni/src/Xash3D/xash3d/common/const.h b/Projects/Android/jni/src/Xash3D/xash3d/common/const.h index ec18de9..b24975c 100644 --- a/Projects/Android/jni/src/Xash3D/xash3d/common/const.h +++ b/Projects/Android/jni/src/Xash3D/xash3d/common/const.h @@ -676,6 +676,7 @@ #define IN_RELOAD (1U << 13) #define IN_ALT1 (1U << 14) #define IN_SCORE (1U << 15) // Used by client.dll for when scoreboard is held down +#define IN_USE2 (1U << 16) // Break Model Defines #define BREAK_TYPEMASK 0x4F @@ -703,6 +704,10 @@ #define TE_BOUNCE_SHELL 1 #define TE_BOUNCE_SHOTSHELL 2 +// VR use gesture flags +#define VR_USE_GESTURE_OFF_HAND 1 +#define VR_USE_GESTURE_WEAPON_HAND 2 + // Rendering constants enum { diff --git a/Projects/Android/jni/src/Xash3D/xash3d/common/usercmd.h b/Projects/Android/jni/src/Xash3D/xash3d/common/usercmd.h index 96e3c91..55d0d3a 100644 --- a/Projects/Android/jni/src/Xash3D/xash3d/common/usercmd.h +++ b/Projects/Android/jni/src/Xash3D/xash3d/common/usercmd.h @@ -27,7 +27,7 @@ typedef struct usercmd_s float sidemove; // Sideways velocity float upmove; // Upward velocity byte lightlevel; // Light level at spot where we are standing. - unsigned short buttons; // Attack and move buttons + int buttons; // Attack and move buttons byte impulse; // Impulse command issued byte weaponselect; // Current weapon id diff --git a/Projects/Android/jni/src/Xash3D/xash3d/engine/common/net_encode.c b/Projects/Android/jni/src/Xash3D/xash3d/engine/common/net_encode.c index 8df8cb0..040a4ba 100644 --- a/Projects/Android/jni/src/Xash3D/xash3d/engine/common/net_encode.c +++ b/Projects/Android/jni/src/Xash3D/xash3d/engine/common/net_encode.c @@ -677,6 +677,14 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt *delta_script = COM_ParseFile( *delta_script, token ); if( token[0] != ',' ) *delta_script = oldpos; // not a ',' + // Ugly hack, but we need bigger size of buttons fields to be able to pass additional "use2" command state. + // Based on tests should not cause problems with multiplayer, but allow this to be disabled just in case. + int forceCompatibility = Cvar_Get("vr_force_network_compatibility", "0", CVAR_LATCH, "")->integer; + if (!forceCompatibility && !Q_strcmp( pField->name, "buttons" )) { + pField->flags = 8; // DT_INTEGER + pField->bits = 17; + } + return true; } diff --git a/Projects/Android/jni/src/Xash3D/xash3d/mainui/menus/Controls.cpp b/Projects/Android/jni/src/Xash3D/xash3d/mainui/menus/Controls.cpp index 507d79b..776b83c 100644 --- a/Projects/Android/jni/src/Xash3D/xash3d/mainui/menus/Controls.cpp +++ b/Projects/Android/jni/src/Xash3D/xash3d/mainui/menus/Controls.cpp @@ -68,7 +68,9 @@ private: CMenuCheckBox headTorch; CMenuCheckBox handModels; CMenuCheckBox quickCrouchJump; + CMenuCheckBox useGesture; CMenuSlider snapTurnAngle; + CMenuSlider useGestureBoundary; CMenuTable controllerList; CMenuControllerModesModel controllerListModel; @@ -117,6 +119,10 @@ void CMenuControls::_Init( void ) headTorch.SetCoord( 320, 570 ); headTorch.LinkCvar( "vr_headtorch" ); + useGesture.SetNameAndStatus( "Gesture Triggered Use", "Toggles triggering of use action by gesture" ); + useGesture.SetCoord( 720, 570 ); + useGesture.LinkCvar( "vr_gesture_triggered_use" ); + snapTurnAngle.SetNameAndStatus( "Snap/Smooth Turn: %.1f degrees", "Controller turn angle, < 10 is smooth turning per frame" ); snapTurnAngle.Setup( 0.0, 90.0, 1.0f ); snapTurnAngle.onChanged = CMenuEditable::WriteCvarCb; @@ -125,6 +131,14 @@ void CMenuControls::_Init( void ) snapTurnAngle.SetDrawValue(true); snapTurnAngle.LinkCvar("vr_snapturn_angle"); + useGestureBoundary.SetNameAndStatus( "Use Gesture Boundary", "Configures how far you need to reach to activate use gesture" ); + useGestureBoundary.Setup( 0.2, 0.5, 0.01f ); + useGestureBoundary.onChanged = CMenuEditable::WriteCvarCb; + useGestureBoundary.SetCoord( 320, 750 ); + useGestureBoundary.SetSize( 520, 40 ); + useGestureBoundary.SetDrawValue(true); + useGestureBoundary.LinkCvar("vr_use_gesture_boundary"); + AddItem( controllerList ); AddItem( hmdWalkDirection ); AddItem( quickCrouchJump ); @@ -132,6 +146,8 @@ void CMenuControls::_Init( void ) AddItem( headTorch ); AddItem( handModels ); AddItem( snapTurnAngle ); + AddItem( useGesture ); + AddItem( useGestureBoundary ); } @@ -162,6 +178,8 @@ void CMenuControls::SetConfig( ) headTorch.WriteCvar(); handModels.WriteCvar(); snapTurnAngle.WriteCvar(); + useGesture.WriteCvar(); + useGestureBoundary.WriteCvar(); // We're done now, just close Hide();