Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

895 lines
26 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. #include "cbase.h"
  3. #ifdef SIXENSE
  4. #include "in_sixense_gesture_bindings.h"
  5. #include "filesystem.h"
  6. #ifdef TF_CLIENT_DLL
  7. #include "tf_gamerules.h"
  8. #endif
  9. #include <isixense.h>
  10. #include <sixense_math.hpp>
  11. #include <sixense_utils/interfaces.hpp>
  12. SixenseGestureBindings::SixenseGestureBindings()
  13. {
  14. }
  15. // Help deallocate a binding
  16. void SixenseGestureBindings::FreeStrings( GestureBinding binding )
  17. {
  18. if( binding.m_pActivateCommand )
  19. {
  20. free( binding.m_pActivateCommand );
  21. }
  22. if( binding.m_pDeactivateCommand )
  23. {
  24. free( binding.m_pDeactivateCommand );
  25. }
  26. }
  27. // add a binding to the list. Calls should be in the form:
  28. // AddBinding( "left", "button_press", "start", "+dota_camera_follow", "" );
  29. //
  30. // args:
  31. // hand_str = "left" or "right"
  32. // action_str = 'button_press' 'trigger_press' 'tilt_gesture' 'point_gesture' 'velocity_gesture' or 'joystick_move'
  33. // argument_str depends on action_str, see below for details
  34. // press_command_str is the concommand executed on start of the action (ie button press) and release_command_str on stop (ie button release)
  35. // release_command_str can be the empty string if no stop action is desired
  36. // if the press_command_str begins with "+", an equivalent "-" is set to the release_command automatically
  37. void SixenseGestureBindings::AddBinding( CUtlString hand_str, CUtlString action_str, CUtlString argument_str, CUtlString press_command_str, CUtlString release_command_str )
  38. {
  39. GestureBinding binding;
  40. // Convert from strings to enums
  41. sixenseUtils::IButtonStates::ActionType action;
  42. if( !ActionFromString( action_str, &action ) )
  43. {
  44. return;
  45. }
  46. binding.m_Action = action;
  47. int hand;
  48. if( !HandFromString( hand_str, &hand ) ) {
  49. return;
  50. }
  51. binding.m_iHand = hand;
  52. // handle argument_str per-action type
  53. if( action == sixenseUtils::IButtonStates::ACTION_BUTTON_PRESS )
  54. {
  55. // button_press takes a button argument
  56. unsigned short button_token;
  57. if( !ButtonMaskFromString( argument_str, &button_token ) )
  58. {
  59. return;
  60. }
  61. binding.m_iArgument = button_token;
  62. }
  63. else if( action == sixenseUtils::IButtonStates::ACTION_TRIGGER_PRESS )
  64. {
  65. // trigger press has no argument
  66. binding.m_iArgument = 0;
  67. }
  68. else
  69. {
  70. // all other actions take a direction
  71. sixenseUtils::IButtonStates::Direction dir;
  72. if( !DirectionFromString( argument_str, &dir ) )
  73. {
  74. return;
  75. }
  76. binding.m_iArgument = dir;
  77. }
  78. // copy the activate command
  79. binding.m_pActivateCommand = strdup( press_command_str.String() );
  80. binding.m_bAutoMirrored = false;
  81. // if there is an explicit release_command, use it
  82. if ( !release_command_str.IsEmpty() )
  83. {
  84. binding.m_pDeactivateCommand = strdup( release_command_str.String() );
  85. }
  86. else
  87. {
  88. // otherwise try to generate a release command
  89. // see if it starts with a +, if so, add an off command
  90. if( press_command_str[0] == '+' )
  91. {
  92. binding.m_pDeactivateCommand = strdup( press_command_str.String() );
  93. binding.m_pDeactivateCommand[0] = '-';
  94. binding.m_bAutoMirrored = true;
  95. }
  96. else
  97. {
  98. // Just leave release command null
  99. binding.m_pDeactivateCommand = NULL;
  100. }
  101. }
  102. // Try to keep a single binding per 'action' 'hand' 'arg' pair, ie one per button.
  103. // We may want to allow multiple if people think it would be useful...
  104. FOR_EACH_LL( m_GestureBindingList, it )
  105. {
  106. GestureBinding existing_binding = m_GestureBindingList[it];
  107. if( binding.m_Action == existing_binding.m_Action &&
  108. binding.m_iArgument == existing_binding.m_iArgument &&
  109. binding.m_iHand == existing_binding.m_iHand )
  110. {
  111. // Already the same binding active, delete it
  112. FreeStrings( existing_binding );
  113. m_GestureBindingList.Remove( it );
  114. break;
  115. }
  116. }
  117. // add to the list of bindings
  118. m_GestureBindingList.AddToTail( binding );
  119. }
  120. // just return the binding count
  121. int SixenseGestureBindings::GetNumBindings()
  122. {
  123. return m_GestureBindingList.Count();
  124. }
  125. // pretty print all the bindings to the console
  126. void SixenseGestureBindings::ListBindings()
  127. {
  128. const int strbuflen=256;
  129. char strbuf[strbuflen];
  130. // Just go through all the bindings, use helpers to convert from tokens to strings, and print.
  131. int i=0;
  132. FOR_EACH_LL( m_GestureBindingList, it )
  133. {
  134. GestureBinding binding = m_GestureBindingList[it];
  135. if( HandTokenToStr( binding.m_iHand, strbuf, strbuflen ) )
  136. {
  137. Msg("%d)\t%s", i, strbuf);
  138. }
  139. if( ActionTokenToStr( (sixenseUtils::IButtonStates::ActionType)binding.m_Action, strbuf, strbuflen ) )
  140. {
  141. Msg("\t%s", strbuf);
  142. }
  143. if( binding.m_Action == sixenseUtils::IButtonStates::ACTION_BUTTON_PRESS )
  144. {
  145. if( ButtonTokenToStr( binding.m_iArgument, strbuf, strbuflen ) )
  146. {
  147. Msg("\t%s", strbuf);
  148. }
  149. }
  150. // these all have the same arguments (left, right, up...)
  151. else if( binding.m_Action == sixenseUtils::IButtonStates::ACTION_JOYSTICK_MOVE ||
  152. binding.m_Action == sixenseUtils::IButtonStates::ACTION_POINT_GESTURE ||
  153. binding.m_Action == sixenseUtils::IButtonStates::ACTION_VELOCITY_GESTURE ||
  154. binding.m_Action == sixenseUtils::IButtonStates::ACTION_TILT_GESTURE )
  155. {
  156. if( DirectionTokenToStr( binding.m_iArgument, strbuf, strbuflen ) )
  157. {
  158. Msg("\t%s", strbuf);
  159. }
  160. } else if( binding.m_Action == sixenseUtils::IButtonStates::ACTION_TRIGGER_PRESS )
  161. {
  162. Msg("\t"); // no argument
  163. }
  164. Msg("\t\"%s\"", binding.m_pActivateCommand);
  165. if( binding.m_pDeactivateCommand && !binding.m_bAutoMirrored ) // only print deactivated command if we didn't generate it.
  166. {
  167. Msg("\t\"%s\"", binding.m_pDeactivateCommand);
  168. }
  169. Msg("\n");
  170. i++;
  171. }
  172. }
  173. // Write the current set of bindings to a file, formatted so that the file can be 'exec'ed.
  174. void SixenseGestureBindings::WriteBindings( CUtlString filename_str )
  175. {
  176. FileHandle_t hFile;
  177. const int filenamelen = 1024;
  178. char filename[filenamelen];
  179. // If no filename was provided, use "cfg/sixense_bindings.cfg"
  180. if( !filename_str.IsEmpty() )
  181. {
  182. Q_snprintf( filename, filenamelen, "%s\\cfg\\%s", engine->GetGameDirectory(), filename_str.String() );
  183. }
  184. else
  185. {
  186. Q_snprintf( filename, filenamelen, "%s\\cfg\\sixense_bindings.cfg", engine->GetGameDirectory() );
  187. }
  188. Msg("writing bindings to %s\n", filename );
  189. hFile = filesystem->Open( filename, "wt" );
  190. if( !hFile )
  191. {
  192. return;
  193. }
  194. const int strbuflen=256;
  195. char strbuf[strbuflen];
  196. char writebuf[strbuflen];
  197. // Go through all the bindings, convert from tokens to strings, build up the command string and write it to the file
  198. FOR_EACH_LL( m_GestureBindingList, it )
  199. {
  200. GestureBinding binding = m_GestureBindingList[it];
  201. if( HandTokenToStr( binding.m_iHand, strbuf, strbuflen ) )
  202. {
  203. Q_snprintf( writebuf, strbuflen, "sixense_bind \"%s\"", strbuf);
  204. filesystem->Write( writebuf, strlen(writebuf), hFile );
  205. }
  206. if( ActionTokenToStr( (sixenseUtils::IButtonStates::ActionType)binding.m_Action, strbuf, strbuflen ) )
  207. {
  208. Q_snprintf( writebuf, strbuflen, " \"%s\"", strbuf);
  209. filesystem->Write( writebuf, strlen(writebuf), hFile );
  210. }
  211. if( binding.m_Action == sixenseUtils::IButtonStates::ACTION_BUTTON_PRESS ) {
  212. if( ButtonTokenToStr( binding.m_iArgument, strbuf, strbuflen ) )
  213. {
  214. Q_snprintf( writebuf, strbuflen, " \"%s\"", strbuf);
  215. filesystem->Write( writebuf, strlen(writebuf), hFile );
  216. }
  217. }
  218. // these all have the same arguments (left, right, up...)
  219. else if( binding.m_Action == sixenseUtils::IButtonStates::ACTION_JOYSTICK_MOVE ||
  220. binding.m_Action == sixenseUtils::IButtonStates::ACTION_POINT_GESTURE ||
  221. binding.m_Action == sixenseUtils::IButtonStates::ACTION_VELOCITY_GESTURE ||
  222. binding.m_Action == sixenseUtils::IButtonStates::ACTION_TILT_GESTURE )
  223. {
  224. if( DirectionTokenToStr( binding.m_iArgument, strbuf, strbuflen ) )
  225. {
  226. Q_snprintf( writebuf, strbuflen, " \"%s\"", strbuf);
  227. filesystem->Write( writebuf, strlen(writebuf), hFile );
  228. }
  229. } else if( binding.m_Action == sixenseUtils::IButtonStates::ACTION_TRIGGER_PRESS )
  230. {
  231. Q_snprintf( writebuf, strbuflen, " \"\""); // no argument
  232. filesystem->Write( writebuf, strlen(writebuf), hFile );
  233. }
  234. Q_snprintf( writebuf, strbuflen, " \"%s\"", binding.m_pActivateCommand);
  235. filesystem->Write( writebuf, strlen(writebuf), hFile );
  236. if( binding.m_pDeactivateCommand && !binding.m_bAutoMirrored ) // only print deactivated command if we didn't generate it.
  237. {
  238. Q_snprintf( writebuf, strbuflen, " \"%s\"", binding.m_pDeactivateCommand);
  239. filesystem->Write( writebuf, strlen(writebuf), hFile );
  240. }
  241. Q_snprintf( writebuf, strbuflen, "\n");
  242. filesystem->Write( writebuf, strlen(writebuf), hFile );
  243. }
  244. filesystem->Close( hFile );
  245. }
  246. // Erase all the bindings. Right now this will cause code in in_sixense.cpp to detect the lack of bindings and immediately
  247. // create defaults. I think that's good.
  248. void SixenseGestureBindings::ClearBindings()
  249. {
  250. FOR_EACH_LL( m_GestureBindingList, it )
  251. {
  252. FreeStrings( m_GestureBindingList[it] );
  253. }
  254. m_GestureBindingList.RemoveAll();
  255. }
  256. // Delete a specific binding by index. 'sixense_list_bindings' prints the indicies that can be passed to delete.
  257. void SixenseGestureBindings::DeleteBinding( int num )
  258. {
  259. if( num < 0 || num > m_GestureBindingList.Count()-1 ) return;
  260. int count=0;
  261. FOR_EACH_LL( m_GestureBindingList, it )
  262. {
  263. if( count == num )
  264. {
  265. FreeStrings( m_GestureBindingList[it] );
  266. m_GestureBindingList.Remove(it);
  267. Msg("Removed %d\n", count );
  268. break;
  269. }
  270. count++;
  271. }
  272. }
  273. void SixenseGestureBindings::CreateDefaultBindings()
  274. {
  275. ClearBindings();
  276. #if defined ( CSTRIKE_DLL ) && !defined( TERROR )
  277. AddBinding( "left", "tilt_gesture", "ccw", "+reload", "" );
  278. AddBinding( "left", "tilt_gesture", "down", "+duck", "" );
  279. AddBinding( "left", "tilt_gesture", "up", "+jump", "" );
  280. AddBinding( "left", "trigger_press", "", "+attack2", "" );
  281. AddBinding( "left", "button_press", "start", "cancelselect", "" );
  282. AddBinding( "left", "button_press", "bumper", "+duck", "" );
  283. AddBinding( "left", "button_press", "joystick", "drop", "" );
  284. AddBinding( "left", "button_press", "1", "autobuy", "" );
  285. AddBinding( "left", "button_press", "2", "rebuy", "" );
  286. AddBinding( "left", "button_press", "3", "impulse 201", "" );
  287. AddBinding( "left", "button_press", "4", "chooseteam", "" );
  288. AddBinding( "left", "point_gesture", "up", "slot3", "" );
  289. AddBinding( "left", "point_gesture", "down", "slot4", "" );
  290. AddBinding( "right", "joystick_move", "up", "buymenu", "buymenu 0" );
  291. AddBinding( "right", "joystick_move", "left", "invprev", "" );
  292. AddBinding( "right", "joystick_move", "right", "invnext", "" );
  293. AddBinding( "right", "joystick_move", "down", "nightvision", "" );
  294. AddBinding( "right", "button_press", "1", "+sixense_ratchet", "" );
  295. AddBinding( "right", "button_press", "2", "+use", "" );
  296. AddBinding( "right", "button_press", "3", "+speed", "" );
  297. AddBinding( "right", "button_press", "4", "+voicerecord", "" );
  298. AddBinding( "right", "button_press", "joystick", "impulse 100", "" );
  299. AddBinding( "right", "button_press", "bumper", "+jump", "" );
  300. AddBinding( "right", "trigger_press", "", "+attack", "" );
  301. AddBinding( "right", "button_press", "start", "+showscores", "" );
  302. #elif defined( TERROR )
  303. AddBinding( "left", "tilt_gesture", "ccw", "+reload", "" );
  304. AddBinding( "left", "tilt_gesture", "down", "+duck", "" );
  305. AddBinding( "left", "tilt_gesture", "up", "+jump", "" );
  306. AddBinding( "left", "trigger_press", "", "+attack2", "" );
  307. AddBinding( "left", "button_press", "start", "cancelselect", "" );
  308. AddBinding( "left", "button_press", "bumper", "+sixense_left_point_gesture", "" );
  309. AddBinding( "left", "button_press", "joystick", "+use", "" );
  310. AddBinding( "left", "point_gesture", "left", "invprev", "" );
  311. AddBinding( "left", "point_gesture", "right", "invnext", "" );
  312. AddBinding( "left", "point_gesture", "up", "slot3", "" );
  313. AddBinding( "left", "point_gesture", "down", "slot4", "" );
  314. AddBinding( "left", "button_press", "2", "phys_swap", "" );
  315. AddBinding( "left", "button_press", "1", "+sixense_ratchet", "" );
  316. AddBinding( "left", "button_press", "3", "+speed", "" );
  317. AddBinding( "left", "button_press", "4", "+voicerecord", "" );
  318. AddBinding( "right", "joystick_move", "up", "+zoom", "" );
  319. AddBinding( "right", "joystick_move", "left", "invprev", "" );
  320. AddBinding( "right", "joystick_move", "right", "invnext", "" );
  321. AddBinding( "right", "joystick_move", "down", "lastinv", "" );
  322. AddBinding( "right", "button_press", "2", "Vote no", "" );
  323. AddBinding( "right", "button_press", "1", "Vote yes", "" );
  324. AddBinding( "right", "button_press", "3", "askconnect_accept", "" );
  325. AddBinding( "right", "button_press", "4", "jpeg", "" );
  326. AddBinding( "right", "button_press", "joystick", "impulse 100", "" );
  327. AddBinding( "right", "button_press", "bumper", "+duck", "" );
  328. AddBinding( "right", "trigger_press", "", "+attack", "" );
  329. AddBinding( "right", "button_press", "1", "+sixense_ratchet", "" );
  330. #elif defined( DOTA_DLL )
  331. AddBinding( "left", "button_press", "start", "+dota_camera_follow", "" );
  332. AddBinding( "left", "button_press", "3", "dota_ability_execute 0", "" );
  333. AddBinding( "left", "button_press", "1", "dota_ability_execute 1", "" );
  334. AddBinding( "left", "button_press", "2", "dota_ability_execute 2", "" );
  335. AddBinding( "left", "button_press", "4", "dota_ability_execute 5", "" );
  336. AddBinding( "left", "joystick_move", "left", "dota_ability_execute 3", "" );
  337. AddBinding( "left", "joystick_move", "right", "dota_ability_execute 4", "" );
  338. AddBinding( "left", "joystick_move", "up", "mc_attack", "" );
  339. AddBinding( "left", "joystick_move", "down", "+sixense_left_alt", "" ); // ping
  340. AddBinding( "left", "trigger_press", "", "+sixense_camera_pan", "" );
  341. AddBinding( "left", "button_press", "bumper", "+sixense_camera_drag", "" );
  342. AddBinding( "right", "button_press", "bumper", "+sixense_left_shift", "" ); // queue
  343. AddBinding( "right", "button_press", "joystick", "sixense_mouse_set_origin", "" );
  344. AddBinding( "right", "button_press", "start", "toggleshoppanel", "" );
  345. AddBinding( "right", "joystick_move", "down", "+sixense_left_ctrl", "" ); // ??
  346. AddBinding( "right", "joystick_move", "up", "+showscores", "" );
  347. AddBinding( "right", "button_press", "3", "+attack", "" );
  348. AddBinding( "right", "button_press", "1", "+attack2", "" );
  349. AddBinding( "right", "button_press", "4", "+voicerecord", "" );
  350. AddBinding( "right", "button_press", "3", "+sixense_left_click", "" );
  351. AddBinding( "right", "button_press", "1", "+sixense_right_click", "" );
  352. AddBinding( "right", "trigger_press", "", "+sixense_grid 0", "" );
  353. AddBinding( "right", "button_press", "2", "+sixense_grid 1", "" );
  354. #elif defined( TF_CLIENT_DLL )
  355. AddBinding( "left", "tilt_gesture", "ccw", "+reload", "" );
  356. AddBinding( "left", "tilt_gesture", "down", "+duck", "" );
  357. AddBinding( "left", "tilt_gesture", "up", "+jump", "" );
  358. AddBinding( "left", "tilt_gesture", "right", "impulse 201", "" );
  359. AddBinding( "left", "trigger_press", "", "+attack2", "" );
  360. AddBinding( "left", "button_press", "start", "cancelselect", "" );
  361. AddBinding( "left", "button_press", "bumper", "+duck", "" );
  362. AddBinding( "left", "point_gesture", "up", "slot3", "" );
  363. AddBinding( "left", "point_gesture", "down", "slot4", "" );
  364. AddBinding( "left", "button_press", "3", "open_charinfo_direct", "" );
  365. AddBinding( "left", "button_press", "1", "changeclass", "" );
  366. AddBinding( "left", "button_press", "2", "changeteam", "" );
  367. AddBinding( "left", "button_press", "4", "lastdisguise", "" );
  368. AddBinding( "left", "button_press", "joystick", "voicemenu 0 0", "" );
  369. AddBinding( "right", "joystick_move", "up", "+context_action", "" );
  370. AddBinding( "right", "joystick_move", "left", "invprev", "" );
  371. AddBinding( "right", "joystick_move", "right", "invnext", "" );
  372. AddBinding( "right", "joystick_move", "down", "lastinv", "" );
  373. AddBinding( "right", "button_press", "1", "+sixense_ratchet", "" );
  374. AddBinding( "right", "button_press", "2", "cl_decline_first_notification", "" );
  375. AddBinding( "right", "button_press", "3", "+voicerecord", "" );
  376. AddBinding( "right", "button_press", "4", "cl_trigger_first_notification", "" );
  377. AddBinding( "right", "button_press", "joystick", "dropitem", "" );
  378. AddBinding( "right", "button_press", "bumper", "taunt", "" );
  379. AddBinding( "right", "trigger_press", "", "+attack", "" );
  380. AddBinding( "right", "button_press", "start", "+showscores", "" );
  381. #else
  382. AddBinding( "left", "tilt_gesture", "ccw", "+reload", "" );
  383. AddBinding( "left", "tilt_gesture", "down", "+duck", "" );
  384. AddBinding( "left", "tilt_gesture", "up", "+jump", "" );
  385. AddBinding( "left", "trigger_press", "", "+attack2", "" );
  386. AddBinding( "left", "button_press", "start", "cancelselect", "" );
  387. AddBinding( "left", "button_press", "bumper", "+sixense_left_point_gesture", "" );
  388. AddBinding( "left", "button_press", "joystick", "+use", "" );
  389. AddBinding( "left", "point_gesture", "left", "invprev", "" );
  390. AddBinding( "left", "point_gesture", "right", "invnext", "" );
  391. AddBinding( "left", "point_gesture", "up", "slot3", "" );
  392. AddBinding( "left", "point_gesture", "down", "slot4", "" );
  393. AddBinding( "right", "joystick_move", "up", "+zoom", "" );
  394. AddBinding( "right", "joystick_move", "left", "invprev", "" );
  395. AddBinding( "right", "joystick_move", "right", "invnext", "" );
  396. AddBinding( "right", "joystick_move", "down", "lastinv", "" );
  397. AddBinding( "right", "button_press", "2", "phys_swap", "" );
  398. AddBinding( "right", "button_press", "1", "+sixense_ratchet", "" );
  399. AddBinding( "right", "button_press", "3", "+speed", "" );
  400. AddBinding( "right", "button_press", "4", "+voicerecord", "" );
  401. AddBinding( "right", "button_press", "joystick", "impulse 100", "" );
  402. AddBinding( "right", "button_press", "bumper", "+duck", "" );
  403. AddBinding( "right", "trigger_press", "", "+attack", "" );
  404. #endif
  405. }
  406. // Called each frame with the latest controller info. sixenseUtils::IButtonStates are sixenseUtils classes that look for various transitions of
  407. // controller state, whether it's 'buttonJustPressed', or analog joysticks 'joystickJustPushed(up)'. It now has support for motion triggers like
  408. // 'controllerJustTilted(left)'
  409. void SixenseGestureBindings::UpdateBindings( sixenseUtils::IButtonStates *pLeftButtonStates, sixenseUtils::IButtonStates *pRightButtonStates, bool bIsMenuVisible )
  410. {
  411. // go through all the bindings and see if any of the desired actions just transitioned on or off
  412. FOR_EACH_LL( m_GestureBindingList, it )
  413. {
  414. GestureBinding binding = m_GestureBindingList[it];
  415. if( binding.m_iHand == 0 )
  416. {
  417. // left hand
  418. // just started?
  419. if( pLeftButtonStates->justStarted( (sixenseUtils::IButtonStates::ActionType)binding.m_Action, binding.m_iArgument ) )
  420. {
  421. if( binding.m_pActivateCommand )
  422. {
  423. // Allow per-game authorization of commmands when the menu is up
  424. if( bIsMenuVisible && !AllowMenuCommand( binding.m_pActivateCommand ) )
  425. {
  426. continue;
  427. }
  428. // Allow per-game authorization of commmands
  429. if( !AllowCommand( binding.m_pActivateCommand ) )
  430. {
  431. continue;
  432. }
  433. engine->ClientCmd_Unrestricted( binding.m_pActivateCommand );
  434. //Msg("activate: %s\n", binding.m_pActivateCommand );
  435. }
  436. }
  437. // just stopped?
  438. if( pLeftButtonStates->justStopped( (sixenseUtils::IButtonStates::ActionType)binding.m_Action, binding.m_iArgument ) )
  439. {
  440. if( binding.m_pDeactivateCommand )
  441. {
  442. engine->ClientCmd_Unrestricted( binding.m_pDeactivateCommand );
  443. //Msg("deactivate: %s\n", binding.m_pDeactivateCommand );
  444. }
  445. }
  446. }
  447. else
  448. {
  449. // right hand
  450. // just started?
  451. if( pRightButtonStates->justStarted( (sixenseUtils::IButtonStates::ActionType)binding.m_Action, binding.m_iArgument ) )
  452. {
  453. if( binding.m_pActivateCommand )
  454. {
  455. // Allow per-game authorization of commmands when the menu is up
  456. if( bIsMenuVisible && !AllowMenuCommand( binding.m_pActivateCommand ) )
  457. {
  458. continue;
  459. }
  460. // Allow per-game authorization of commmands
  461. if( !AllowCommand( binding.m_pActivateCommand ) )
  462. {
  463. continue;
  464. }
  465. engine->ClientCmd_Unrestricted( binding.m_pActivateCommand );
  466. //Msg("activate: %s\n", binding.m_pActivateCommand );
  467. }
  468. }
  469. // just stopped?
  470. if( pRightButtonStates->justStopped( (sixenseUtils::IButtonStates::ActionType)binding.m_Action, binding.m_iArgument ) )
  471. {
  472. if( binding.m_pDeactivateCommand )
  473. {
  474. engine->ClientCmd_Unrestricted( binding.m_pDeactivateCommand );
  475. //Msg("deactivate: %s\n", binding.m_pDeactivateCommand );
  476. }
  477. }
  478. }
  479. }
  480. }
  481. // Give games an opportunity to block commands
  482. bool SixenseGestureBindings::AllowCommand( char *pActivateCommand )
  483. {
  484. #ifdef TF_CLIENT_DLL
  485. if ( TFGameRules() && TFGameRules()->IsInTraining() && TFGameRules()->IsWaitingForTrainingContinue() )
  486. {
  487. if( Q_strcmp( pActivateCommand, "+jump" ) == 0 )
  488. {
  489. return false;
  490. }
  491. }
  492. #endif
  493. return true;
  494. }
  495. // If the menu is up, most bindings are blocked. Allow some of them to be activated...
  496. bool SixenseGestureBindings::AllowMenuCommand( char *pActivateCommand )
  497. {
  498. #ifdef TF_CLIENT_DLL
  499. if( Q_strcmp( pActivateCommand, "+showscores" ) == 0 )
  500. {
  501. // Allow for showscores when in-menu
  502. return true;
  503. }
  504. #endif
  505. return false;
  506. }
  507. // from here down are just helper funcs to convert between enums and strings and back
  508. bool SixenseGestureBindings::DirectionFromString( CUtlString dir_str, sixenseUtils::IButtonStates::Direction *dir )
  509. {
  510. if( dir_str == "up" )
  511. {
  512. *dir = sixenseUtils::IButtonStates::DIR_UP;
  513. }
  514. else if( dir_str == "down" )
  515. {
  516. *dir = sixenseUtils::IButtonStates::DIR_DOWN;
  517. }
  518. else if( dir_str == "left" )
  519. {
  520. *dir = sixenseUtils::IButtonStates::DIR_LEFT;
  521. }
  522. else if( dir_str == "right" )
  523. {
  524. *dir = sixenseUtils::IButtonStates::DIR_RIGHT;
  525. }
  526. else if( dir_str == "cw" )
  527. {
  528. *dir = sixenseUtils::IButtonStates::DIR_CW;
  529. }
  530. else if( dir_str == "ccw" )
  531. {
  532. *dir = sixenseUtils::IButtonStates::DIR_CCW;
  533. }
  534. else
  535. {
  536. Msg( "Unknown direction %s, shoud be 'up' 'down' 'left' 'right' 'cw' or 'ccw'\n", dir_str.String() );
  537. return false;
  538. }
  539. return true;
  540. }
  541. bool SixenseGestureBindings::ButtonMaskFromString( CUtlString button, unsigned short *button_token )
  542. {
  543. if ( button == "1" )
  544. {
  545. *button_token = SIXENSE_BUTTON_1;
  546. }
  547. else if ( button == "2" )
  548. {
  549. *button_token = SIXENSE_BUTTON_2;
  550. }
  551. else if ( button == "3" )
  552. {
  553. *button_token = SIXENSE_BUTTON_3;
  554. }
  555. else if ( button == "4" )
  556. {
  557. *button_token = SIXENSE_BUTTON_4;
  558. }
  559. else if ( button == "start" )
  560. {
  561. *button_token = SIXENSE_BUTTON_START;
  562. }
  563. else if ( button == "bumper" )
  564. {
  565. *button_token = SIXENSE_BUTTON_BUMPER;
  566. }
  567. else if ( button == "joystick" )
  568. {
  569. *button_token = SIXENSE_BUTTON_JOYSTICK;
  570. }
  571. else
  572. {
  573. Msg( "Unknown button %s, shoud be '1' '2' '3' '4' 'start' 'trigger' or 'joystick'\n", button.String() );
  574. return false;
  575. }
  576. return true;
  577. }
  578. bool SixenseGestureBindings::ActionFromString( CUtlString action_str, sixenseUtils::IButtonStates::ActionType *action )
  579. {
  580. if( action_str == "button_press" )
  581. {
  582. *action = sixenseUtils::IButtonStates::ACTION_BUTTON_PRESS;
  583. return true;
  584. }
  585. else if( action_str == "trigger_press" )
  586. {
  587. *action = sixenseUtils::IButtonStates::ACTION_TRIGGER_PRESS;
  588. return true;
  589. }
  590. else if( action_str == "tilt_gesture" )
  591. {
  592. *action = sixenseUtils::IButtonStates::ACTION_TILT_GESTURE;
  593. return true;
  594. }
  595. else if( action_str == "point_gesture" )
  596. {
  597. *action = sixenseUtils::IButtonStates::ACTION_POINT_GESTURE;
  598. return true;
  599. }
  600. else if( action_str == "velocity_gesture" )
  601. {
  602. *action = sixenseUtils::IButtonStates::ACTION_VELOCITY_GESTURE;
  603. return true;
  604. }
  605. else if( action_str == "joystick_move" )
  606. {
  607. *action = sixenseUtils::IButtonStates::ACTION_JOYSTICK_MOVE;
  608. return true;
  609. }
  610. else
  611. {
  612. Msg( "Unknown action %s, shoud be 'button_press' 'trigger_press' 'tilt_gesture' 'point_gesture' 'velocity_gesture' or 'joystick_move'\n", action_str.String() );
  613. *action = sixenseUtils::IButtonStates::ACTION_BUTTON_PRESS;
  614. return false;
  615. }
  616. }
  617. bool SixenseGestureBindings::HandFromString( CUtlString hand_str, int *hand )
  618. {
  619. if( hand_str == "left" )
  620. {
  621. *hand = 0;
  622. }
  623. else if( hand_str == "right" )
  624. {
  625. *hand = 1;
  626. }
  627. else
  628. {
  629. Msg( "Unknown controller %s, should be 'left' or 'right'\n", hand_str.String() );
  630. return false;
  631. }
  632. return true;
  633. }
  634. bool SixenseGestureBindings::HandTokenToStr( int hand, char *buf, int buflen )
  635. {
  636. if( buflen < 10 ) return false;
  637. if( hand == 0 ) {
  638. Q_snprintf( buf, buflen, "left" );
  639. }
  640. else if( hand == 1 )
  641. {
  642. Q_snprintf( buf, buflen, "right" );
  643. }
  644. else
  645. {
  646. return false;
  647. }
  648. return true;
  649. }
  650. bool SixenseGestureBindings::ButtonTokenToStr( int arg, char *buf, int buflen )
  651. {
  652. if( buflen < 10 ) return false;
  653. if( arg == SIXENSE_BUTTON_1 )
  654. {
  655. Q_snprintf( buf, buflen, "1" );
  656. }
  657. else if( arg == SIXENSE_BUTTON_2 )
  658. {
  659. Q_snprintf( buf, buflen, "2" );
  660. }
  661. else if( arg == SIXENSE_BUTTON_3 )
  662. {
  663. Q_snprintf( buf, buflen, "3" );
  664. }
  665. else if( arg == SIXENSE_BUTTON_4 )
  666. {
  667. Q_snprintf( buf, buflen, "4" );
  668. }
  669. else if( arg == SIXENSE_BUTTON_START )
  670. {
  671. Q_snprintf( buf, buflen, "start" );
  672. }
  673. else if( arg == SIXENSE_BUTTON_BUMPER )
  674. {
  675. Q_snprintf( buf, buflen, "bumper" );
  676. }
  677. else if( arg == SIXENSE_BUTTON_JOYSTICK )
  678. {
  679. Q_snprintf( buf, buflen, "joystick" );
  680. }
  681. else
  682. {
  683. return false;
  684. }
  685. return true;
  686. }
  687. bool SixenseGestureBindings::DirectionTokenToStr( int arg, char *buf, int buflen )
  688. {
  689. if( buflen < 10 ) return false;
  690. if( arg == sixenseUtils::IButtonStates::DIR_LEFT )
  691. {
  692. Q_snprintf( buf, buflen, "left" );
  693. }
  694. else if( arg == sixenseUtils::IButtonStates::DIR_RIGHT )
  695. {
  696. Q_snprintf( buf, buflen, "right" );
  697. }
  698. else if( arg == sixenseUtils::IButtonStates::DIR_UP )
  699. {
  700. Q_snprintf( buf, buflen, "up" );
  701. }
  702. else if( arg == sixenseUtils::IButtonStates::DIR_DOWN )
  703. {
  704. Q_snprintf( buf, buflen, "down" );
  705. }
  706. else if( arg == sixenseUtils::IButtonStates::DIR_CW )
  707. {
  708. Q_snprintf( buf, buflen, "cw" );
  709. }
  710. else if( arg == sixenseUtils::IButtonStates::DIR_CCW )
  711. {
  712. Q_snprintf( buf, buflen, "ccw" );
  713. }
  714. else if( arg == sixenseUtils::IButtonStates::DIR_FORWARD )
  715. {
  716. Q_snprintf( buf, buflen, "forward" );
  717. }
  718. else if( arg == sixenseUtils::IButtonStates::DIR_BACKWARD )
  719. {
  720. Q_snprintf( buf, buflen, "backward" );
  721. }
  722. else
  723. {
  724. return false;
  725. }
  726. return true;
  727. }
  728. bool SixenseGestureBindings::ActionTokenToStr( sixenseUtils::IButtonStates::ActionType action, char *buf, int buflen )
  729. {
  730. if( buflen < 20 ) return false;
  731. if( action == sixenseUtils::IButtonStates::ACTION_BUTTON_PRESS )
  732. {
  733. Q_snprintf( buf, buflen, "button_press" );
  734. }
  735. else if( action == sixenseUtils::IButtonStates::ACTION_JOYSTICK_MOVE )
  736. {
  737. Q_snprintf( buf, buflen, "joystick_move" );
  738. }
  739. else if( action == sixenseUtils::IButtonStates::ACTION_POINT_GESTURE )
  740. {
  741. Q_snprintf( buf, buflen, "point_gesture" );
  742. }
  743. else if( action == sixenseUtils::IButtonStates::ACTION_VELOCITY_GESTURE )
  744. {
  745. Q_snprintf( buf, buflen, "velocity_gesture" );
  746. }
  747. else if( action == sixenseUtils::IButtonStates::ACTION_TILT_GESTURE )
  748. {
  749. Q_snprintf( buf, buflen, "tilt_gesture" );
  750. }
  751. else if( action == sixenseUtils::IButtonStates::ACTION_TRIGGER_PRESS )
  752. {
  753. Q_snprintf( buf, buflen, "trigger_press" );
  754. }
  755. else
  756. {
  757. return false;
  758. }
  759. return true;
  760. }
  761. #endif