|
| 1 | +/* |
| 2 | +Copyright (C) 1997-2001 Id Software, Inc. |
| 3 | +Copyright (C) 2015 SiPlus, Chasseur de bots |
| 4 | +Copyright (C) 2017 Victor Luchits |
| 5 | +
|
| 6 | +This program is free software; you can redistribute it and/or |
| 7 | +modify it under the terms of the GNU General Public License |
| 8 | +as published by the Free Software Foundation; either version 2 |
| 9 | +of the License, or (at your option) any later version. |
| 10 | +
|
| 11 | +This program is distributed in the hope that it will be useful, |
| 12 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| 14 | +
|
| 15 | +See the GNU General Public License for more details. |
| 16 | +
|
| 17 | +You should have received a copy of the GNU General Public License |
| 18 | +along with this program; if not, write to the Free Software |
| 19 | +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 20 | +
|
| 21 | +*/ |
| 22 | + |
| 23 | + |
| 24 | +namespace CGame { |
| 25 | + |
| 26 | +namespace Input { |
| 27 | + |
| 28 | +namespace Gamepad { |
| 29 | + |
| 30 | +Cvar cg_gamepad_moveThres( "cg_gamepad_moveThres", "0.239", CVAR_ARCHIVE ); |
| 31 | +Cvar cg_gamepad_runThres( "cg_gamepad_runThres", "0.75", CVAR_ARCHIVE ); |
| 32 | +Cvar cg_gamepad_strafeThres( "cg_gamepad_strafeThres", "0.239", CVAR_ARCHIVE ); |
| 33 | +Cvar cg_gamepad_strafeRunThres( "cg_gamepad_strafeRunThres", "0.45", CVAR_ARCHIVE ); |
| 34 | +Cvar cg_gamepad_pitchThres( "cg_gamepad_pitchThres", "0.265", CVAR_ARCHIVE ); |
| 35 | +Cvar cg_gamepad_yawThres( "cg_gamepad_yawThres", "0.265", CVAR_ARCHIVE ); |
| 36 | +Cvar cg_gamepad_pitchSpeed( "cg_gamepad_pitchSpeed", "240", CVAR_ARCHIVE ); |
| 37 | +Cvar cg_gamepad_yawSpeed( "cg_gamepad_yawSpeed", "260", CVAR_ARCHIVE ); |
| 38 | +Cvar cg_gamepad_pitchInvert( "cg_gamepad_pitchInvert", "0", CVAR_ARCHIVE ); |
| 39 | +Cvar cg_gamepad_accelMax( "cg_gamepad_accelMax", "2", CVAR_ARCHIVE ); |
| 40 | +Cvar cg_gamepad_accelSpeed( "cg_gamepad_accelSpeed", "3", CVAR_ARCHIVE ); |
| 41 | +Cvar cg_gamepad_accelThres( "cg_gamepad_accelThres", "0.9", CVAR_ARCHIVE ); |
| 42 | +Cvar cg_gamepad_swapSticks( "cg_gamepad_swapSticks", "0", CVAR_ARCHIVE ); |
| 43 | + |
| 44 | +float cg_gamepadAccelPitch = 1.0f, cg_gamepadAccelYaw = 1.0f; |
| 45 | + |
| 46 | +/** |
| 47 | + * Updates time-dependent gamepad state. |
| 48 | + */ |
| 49 | +void Frame( void ) { |
| 50 | +// Add acceleration to the gamepad look above the acceleration threshold. |
| 51 | +Vec4 sticks = GetThumbsticks(); |
| 52 | + |
| 53 | +int axes = ( cg_gamepad_swapSticks.integer != 0 ? 0 : 2 ); |
| 54 | + |
| 55 | +if( cg_gamepad_accelMax.value < 0.0f ) { |
| 56 | +cg_gamepad_accelMax.set( 0.0f ); |
| 57 | +} |
| 58 | +if( cg_gamepad_accelSpeed.value < 0.0f ) { |
| 59 | +cg_gamepad_accelSpeed.set( 0.0f ); |
| 60 | +} |
| 61 | + |
| 62 | +float accelMax = cg_gamepad_accelMax.value + 1.0f; |
| 63 | +float accelSpeed = cg_gamepad_accelSpeed.value; |
| 64 | +float accelThres = cg_gamepad_accelThres.value; |
| 65 | + |
| 66 | +float value = abs( sticks[axes] ); |
| 67 | +if( value > cg_gamepad_yawThres.value ) { |
| 68 | +cg_gamepadAccelYaw += ( ( value > accelThres ) ? 1.0f : -1.0f ) * frameTime * 0.001f * accelSpeed; |
| 69 | +if( cg_gamepadAccelYaw < 1.0f ) cg_gamepadAccelYaw = 1.0f; |
| 70 | +else if( cg_gamepadAccelYaw > accelMax ) cg_gamepadAccelYaw = accelMax; |
| 71 | +} else { |
| 72 | +cg_gamepadAccelYaw = 1.0f; |
| 73 | +} |
| 74 | + |
| 75 | +value = abs( sticks[axes + 1] ); |
| 76 | +if( value > cg_gamepad_pitchThres.value ) { |
| 77 | +cg_gamepadAccelPitch += ( ( value > accelThres ) ? 1.0f : -1.0f ) * frameTime * 0.001f * accelSpeed; |
| 78 | +if( cg_gamepadAccelPitch < 1.0f ) cg_gamepadAccelPitch = 1.0f; |
| 79 | +else if( cg_gamepadAccelPitch > accelMax ) cg_gamepadAccelPitch = accelMax; |
| 80 | +} else { |
| 81 | +cg_gamepadAccelPitch = 1.0f; |
| 82 | +} |
| 83 | +} |
| 84 | + |
| 85 | +/* |
| 86 | +* ClearState |
| 87 | +*/ |
| 88 | +void ClearState( void ) { |
| 89 | +cg_gamepadAccelPitch = 1.0f; |
| 90 | +cg_gamepadAccelYaw = 1.0f; |
| 91 | +} |
| 92 | + |
| 93 | +/** |
| 94 | + * Adds view rotation from the gamepad. |
| 95 | + */ |
| 96 | +Vec3 AddViewAngles() { |
| 97 | +Vec3 viewAngles; |
| 98 | +Vec4 sticks = GetThumbsticks(); |
| 99 | + |
| 100 | +int axes = ( cg_gamepad_swapSticks.integer != 0 ? 0 : 2 ); |
| 101 | + |
| 102 | +if( ( cg_gamepad_yawThres.value <= 0.0f ) || ( cg_gamepad_yawThres.value >= 1.0f ) ) { |
| 103 | +cg_gamepad_yawThres.reset(); |
| 104 | +} |
| 105 | +if( ( cg_gamepad_pitchThres.value <= 0.0f ) || ( cg_gamepad_pitchThres.value >= 1.0f ) ) { |
| 106 | +cg_gamepad_pitchThres.reset(); |
| 107 | +} |
| 108 | + |
| 109 | +float axisValue = sticks[axes]; |
| 110 | +float threshold = cg_gamepad_yawThres.value; |
| 111 | +float value = ( abs( axisValue ) - threshold ) / ( 1.0f - threshold ); // Smoothly apply the dead zone. |
| 112 | +if( value > 0.0f ) { |
| 113 | +// Quadratic interpolation. |
| 114 | +viewAngles[YAW] -= frameTime * 0.001f * |
| 115 | + value * value * ( ( axisValue < 0.0f ) ? -1.0f : 1.0f ) * cg_gamepadAccelYaw * |
| 116 | + cg_gamepad_yawSpeed.value * GetSensitivityScale( cg_gamepad_yawSpeed.value, 0.0f ); |
| 117 | +} |
| 118 | + |
| 119 | +axisValue = sticks[axes + 1]; |
| 120 | +threshold = cg_gamepad_pitchThres.value; |
| 121 | +value = ( abs( axisValue ) - threshold ) / ( 1.0f - threshold ); |
| 122 | +if( value > 0.0f ) { |
| 123 | +viewAngles[PITCH] += frameTime * 0.001f * ( cg_gamepad_pitchInvert.integer != 0 ? -1.0f : 1.0f ) * |
| 124 | + value * value * ( ( axisValue < 0.0f ) ? -1.0f : 1.0f ) * cg_gamepadAccelPitch * |
| 125 | + cg_gamepad_pitchSpeed.value * GetSensitivityScale( cg_gamepad_pitchSpeed.value, 0.0f ); |
| 126 | +} |
| 127 | + |
| 128 | +return viewAngles; |
| 129 | +} |
| 130 | + |
| 131 | +/** |
| 132 | + * Adds movement from the gamepad. |
| 133 | + */ |
| 134 | +Vec3 AddMovement() { |
| 135 | +Vec3 movement; |
| 136 | +Vec4 sticks = GetThumbsticks(); |
| 137 | + |
| 138 | +int axes = ( cg_gamepad_swapSticks.integer != 0 ? 2 : 0 ); |
| 139 | + |
| 140 | +float value = sticks[axes]; |
| 141 | +float threshold = cg_gamepad_strafeThres.value; |
| 142 | +float runThreshold = cg_gamepad_strafeRunThres.value; |
| 143 | +float absValue = abs( value ); |
| 144 | +if( runThreshold > threshold ) { |
| 145 | +absValue = ( absValue - threshold ) / ( runThreshold - threshold ); |
| 146 | +if( absValue < 0.0f ) absValue = 0.0f; |
| 147 | +else if( absValue > 1.0f ) absValue = 1.0f; |
| 148 | +absValue *= absValue; |
| 149 | +} else { |
| 150 | +absValue = ( absValue > threshold ? 1.0 : 0.0 ); |
| 151 | +} |
| 152 | +if( absValue > cg_gamepad_strafeThres.value ) { |
| 153 | +movement[0] += absValue * ( ( value < 0.0f ) ? -1.0f : 1.0f ); |
| 154 | +} |
| 155 | + |
| 156 | +value = sticks[axes + 1]; |
| 157 | +threshold = cg_gamepad_moveThres.value; |
| 158 | +runThreshold = cg_gamepad_runThres.value; |
| 159 | +absValue = abs( value ); |
| 160 | +if( runThreshold > threshold ) { |
| 161 | +absValue = ( absValue - threshold ) / ( runThreshold - threshold ); |
| 162 | +if( absValue < 0.0f ) absValue = 0.0f; |
| 163 | +else if( absValue > 1.0f ) absValue = 1.0f; |
| 164 | +absValue *= absValue; |
| 165 | +} else { |
| 166 | +absValue = ( absValue > threshold ? 1.0 : 0.0 ); |
| 167 | +} |
| 168 | +if( absValue > cg_gamepad_moveThres.value ) { |
| 169 | +movement[1] -= absValue * ( ( value < 0.0f ) ? -1.0f : 1.0f ); |
| 170 | +} |
| 171 | + |
| 172 | +return movement; |
| 173 | +} |
| 174 | + |
| 175 | +} |
| 176 | + |
| 177 | +} |
| 178 | + |
| 179 | +} |
0 commit comments