Controls.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. /*
  13. * Game library
  14. * Copyright (c) 1997-1999, CroTeam.
  15. */
  16. #include "stdafx.h"
  17. extern CGame *_pGame;
  18. /*
  19. * Default constructor
  20. */
  21. CControls::CControls(void)
  22. {
  23. // buttons are all none anyway (empty list)
  24. // switch axes actions to defaults
  25. SwitchAxesToDefaults();
  26. }
  27. /*
  28. * Default destructor
  29. */
  30. CControls::~CControls(void)
  31. {
  32. // for each action in the original list
  33. FORDELETELIST(CButtonAction, ba_lnNode, ctrl_lhButtonActions, itButtonAction)
  34. {
  35. // delete button action
  36. delete( &*itButtonAction);
  37. }
  38. }
  39. // Assignment operator.
  40. CControls &CControls::operator=(CControls &ctrlOriginal)
  41. {
  42. // remove old button actions
  43. {FORDELETELIST(CButtonAction, ba_lnNode, ctrl_lhButtonActions, itButtonAction) {
  44. delete &*itButtonAction;
  45. }}
  46. // for each action in the original list
  47. {FOREACHINLIST(CButtonAction, ba_lnNode, ctrlOriginal.ctrl_lhButtonActions, itButtonAction) {
  48. // create and copy button action
  49. AddButtonAction() = *itButtonAction;
  50. }}
  51. // for all axis-type actions
  52. for( INDEX iAxisAction=0; iAxisAction<AXIS_ACTIONS_CT; iAxisAction++) {
  53. // copy it
  54. ctrl_aaAxisActions[iAxisAction] = ctrlOriginal.ctrl_aaAxisActions[iAxisAction];
  55. }
  56. // copy global settings
  57. ctrl_fSensitivity = ctrlOriginal.ctrl_fSensitivity;
  58. ctrl_bInvertLook = ctrlOriginal.ctrl_bInvertLook;
  59. ctrl_bSmoothAxes = ctrlOriginal.ctrl_bSmoothAxes;
  60. return *this;
  61. }
  62. /*
  63. * Switches button and axis action mounters to defaults
  64. */
  65. void CControls::SwitchAxesToDefaults(void)
  66. {
  67. // for all axis-type actions
  68. for( INDEX iAxisAction=0; iAxisAction<AXIS_ACTIONS_CT; iAxisAction++)
  69. {
  70. // set axis action none
  71. ctrl_aaAxisActions[ iAxisAction].aa_iAxisAction = AXIS_NONE;
  72. ctrl_aaAxisActions[ iAxisAction].aa_fSensitivity = 50;
  73. ctrl_aaAxisActions[ iAxisAction].aa_fDeadZone = 0;
  74. ctrl_aaAxisActions[ iAxisAction].aa_bInvert = FALSE;
  75. ctrl_aaAxisActions[ iAxisAction].aa_bRelativeControler = TRUE;
  76. ctrl_aaAxisActions[ iAxisAction].aa_bSmooth = FALSE;
  77. ctrl_aaAxisActions[ iAxisAction].aa_fLastReading = 0.0f;
  78. }
  79. // set default controlers for some axis-type actions
  80. // mouse left/right motion
  81. ctrl_aaAxisActions[ AXIS_TURN_LR].aa_iAxisAction = MOUSE_X_AXIS;
  82. ctrl_aaAxisActions[ AXIS_TURN_LR].aa_fSensitivity = 45;
  83. ctrl_aaAxisActions[ AXIS_TURN_LR].aa_bInvert = FALSE;
  84. ctrl_aaAxisActions[ AXIS_TURN_LR].aa_bRelativeControler = TRUE;
  85. // mouse up/down motion
  86. ctrl_aaAxisActions[ AXIS_TURN_UD].aa_iAxisAction = MOUSE_Y_AXIS;
  87. ctrl_aaAxisActions[ AXIS_TURN_UD].aa_fSensitivity = 45;
  88. ctrl_aaAxisActions[ AXIS_TURN_UD].aa_bInvert = TRUE;
  89. ctrl_aaAxisActions[ AXIS_TURN_UD].aa_bRelativeControler = TRUE;
  90. ctrl_fSensitivity = 50;
  91. ctrl_bInvertLook = FALSE;
  92. ctrl_bSmoothAxes = TRUE;
  93. }
  94. void CControls::SwitchToDefaults(void)
  95. {
  96. // copy controls from initial player
  97. try
  98. {
  99. CControls ctrlDefaultControls;
  100. ctrlDefaultControls.Load_t( CTString("Data\\Defaults\\InitialControls.ctl"));
  101. *this = ctrlDefaultControls;
  102. }
  103. catch( char *strError)
  104. {
  105. (void) strError;
  106. }
  107. }
  108. /*
  109. * Depending on axis attributes and type (rotation or translation),
  110. * calculates axis influence factors for all axis actions
  111. */
  112. void CControls::CalculateInfluencesForAllAxis(void)
  113. {
  114. FLOAT fSensitivityGlobal = (FLOAT)pow(1.2, (ctrl_fSensitivity-50.0)*1.0/5.0);
  115. FLOAT fBaseDelta; // different for rotations and translations
  116. // for all axis actions
  117. for( INDEX iAxisAction=0; iAxisAction<AXIS_ACTIONS_CT; iAxisAction++)
  118. {
  119. fBaseDelta = 1.0f;
  120. // apply invert factor
  121. if( ctrl_aaAxisActions[ iAxisAction].aa_bInvert ||
  122. ( (iAxisAction==AXIS_TURN_UD||iAxisAction==AXIS_LOOK_UD) && ctrl_bInvertLook) ) {
  123. // negative factor
  124. fBaseDelta = -fBaseDelta;
  125. }
  126. FLOAT fSensitivityLocal = (FLOAT)pow(2.0, (ctrl_aaAxisActions[ iAxisAction].aa_fSensitivity-50.0)*1.0/5.0);
  127. // calculate influence for current axis
  128. ctrl_aaAxisActions[ iAxisAction].aa_fAxisInfluence = fBaseDelta * fSensitivityGlobal * fSensitivityLocal;
  129. }
  130. }
  131. INDEX DIKForName( CTString strKeyName)
  132. {
  133. if( strKeyName == "None") return KID_NONE;
  134. for( INDEX iButton=0; iButton<MAX_OVERALL_BUTTONS; iButton++)
  135. {
  136. if( _pInput->GetButtonName( iButton) == strKeyName) return iButton;
  137. }
  138. return KID_NONE;
  139. }
  140. CTString ReadTextLine(CTStream &strm, const CTString &strKeyword, BOOL bTranslate)
  141. {
  142. CTString strLine;
  143. strm.GetLine_t(strLine);
  144. strLine.TrimSpacesLeft();
  145. if (!strLine.RemovePrefix(strKeyword)) {
  146. return "???";
  147. }
  148. strLine.TrimSpacesLeft();
  149. if (bTranslate) {
  150. strLine.RemovePrefix("TTRS");
  151. }
  152. strLine.TrimSpacesLeft();
  153. strLine.TrimSpacesRight();
  154. return strLine;
  155. }
  156. void CControls::Load_t( CTFileName fnFile)
  157. {
  158. char achrLine[ 1024];
  159. char achrName[ 1024];
  160. char achrID[ 1024];
  161. char achrActionName[ 1024];
  162. // open script file for reading
  163. CTFileStream strmFile;
  164. strmFile.Open_t( fnFile);
  165. // if file can be opened for reading remove old button actions
  166. {FORDELETELIST(CButtonAction, ba_lnNode, ctrl_lhButtonActions, itButtonAction) {
  167. delete &*itButtonAction;
  168. }}
  169. do
  170. {
  171. achrLine[0] = 0;
  172. achrID[0] = 0;
  173. strmFile.GetLine_t( achrLine, 1024);
  174. sscanf( achrLine, "%s", achrID);
  175. // if name
  176. if( CTString( achrID) == "Name") {
  177. // name is obsolete, just skip it
  178. sscanf( achrLine, "%*[^\"]\"%1024[^\"]\"", achrName);
  179. // if this is button action
  180. } else if( CTString( achrID) == "Button") {
  181. // create and read button action
  182. CButtonAction &baNew = AddButtonAction();
  183. baNew.ba_strName = ReadTextLine(strmFile, "Name:", TRUE);
  184. baNew.ba_iFirstKey = DIKForName( ReadTextLine(strmFile, "Key1:", FALSE));
  185. baNew.ba_iSecondKey = DIKForName( ReadTextLine(strmFile, "Key2:", FALSE));
  186. baNew.ba_strCommandLineWhenPressed = ReadTextLine(strmFile, "Pressed:", FALSE);
  187. baNew.ba_strCommandLineWhenReleased = ReadTextLine(strmFile, "Released:", FALSE);
  188. // if this is axis action
  189. } else if( CTString( achrID) == "Axis") {
  190. char achrAxis[ 1024];
  191. achrAxis[ 0] = 0;
  192. char achrIfInverted[ 1024];
  193. achrIfInverted[ 0] = 0;
  194. char achrIfRelative[ 1024];
  195. achrIfRelative[ 0] = 0;
  196. char achrIfSmooth[ 1024];
  197. achrIfSmooth[ 0] = 0;
  198. achrActionName[ 0] = 0;
  199. FLOAT fSensitivity = 50;
  200. FLOAT fDeadZone = 0;
  201. sscanf( achrLine, "%*[^\"]\"%1024[^\"]\"%*[^\"]\"%1024[^\"]\" %g %g %1024s %1024s",
  202. achrActionName, achrAxis, &fSensitivity, &fDeadZone, achrIfInverted, achrIfRelative, achrIfSmooth);
  203. // find action axis
  204. INDEX iActionAxisNo = -1;
  205. {for( INDEX iAxis=0; iAxis<AXIS_ACTIONS_CT; iAxis++){
  206. if( CTString(_pGame->gm_astrAxisNames[iAxis]) == achrActionName)
  207. {
  208. iActionAxisNo = iAxis;
  209. break;
  210. }
  211. }}
  212. // find controller axis
  213. INDEX iCtrlAxisNo = -1;
  214. {for( INDEX iAxis=0; iAxis<MAX_OVERALL_AXES; iAxis++) {
  215. if( _pInput->GetAxisName( iAxis) == achrAxis)
  216. {
  217. iCtrlAxisNo = iAxis;
  218. break;
  219. }
  220. }}
  221. // if valid axis found
  222. if( iActionAxisNo!=-1 && iCtrlAxisNo!=-1) {
  223. // set it
  224. ctrl_aaAxisActions[ iActionAxisNo].aa_iAxisAction = iCtrlAxisNo;
  225. ctrl_aaAxisActions[ iActionAxisNo].aa_fSensitivity = fSensitivity;
  226. ctrl_aaAxisActions[ iActionAxisNo].aa_fDeadZone = fDeadZone;
  227. ctrl_aaAxisActions[ iActionAxisNo].aa_bInvert = ( CTString( "Inverted") == achrIfInverted);
  228. ctrl_aaAxisActions[ iActionAxisNo].aa_bRelativeControler = ( CTString( "Relative") == achrIfRelative);
  229. ctrl_aaAxisActions[ iActionAxisNo].aa_bSmooth = ( CTString( "Smooth") == achrIfRelative);
  230. }
  231. // read global parameters
  232. } else if( CTString( achrID) == "GlobalInvertLook") {
  233. ctrl_bInvertLook = TRUE;
  234. } else if( CTString( achrID) == "GlobalDontInvertLook") {
  235. ctrl_bInvertLook = FALSE;
  236. } else if( CTString( achrID) == "GlobalSmoothAxes") {
  237. ctrl_bSmoothAxes = TRUE;
  238. } else if( CTString( achrID) == "GlobalDontSmoothAxes") {
  239. ctrl_bSmoothAxes = FALSE;
  240. } else if( CTString( achrID) == "GlobalSensitivity") {
  241. sscanf( achrLine, "GlobalSensitivity %g", &ctrl_fSensitivity);
  242. }
  243. }
  244. while( !strmFile.AtEOF());
  245. /*
  246. // search for talk button
  247. BOOL bHasTalk = FALSE;
  248. BOOL bHasT = FALSE;
  249. FOREACHINLIST( CButtonAction, ba_lnNode, ctrl_lhButtonActions, itba) {
  250. CButtonAction &ba = *itba;
  251. if (ba.ba_strName=="Talk") {
  252. bHasTalk = TRUE;
  253. }
  254. if (ba.ba_iFirstKey==KID_T) {
  255. bHasT = TRUE;
  256. }
  257. if (ba.ba_iSecondKey==KID_T) {
  258. bHasT = TRUE;
  259. }
  260. }
  261. // if talk button not found
  262. if (!bHasTalk) {
  263. // add it
  264. CButtonAction &baNew = AddButtonAction();
  265. baNew.ba_strName = "Talk";
  266. baNew.ba_iFirstKey = KID_NONE;
  267. baNew.ba_iSecondKey = KID_NONE;
  268. baNew.ba_strCommandLineWhenPressed = " con_bTalk=1;";
  269. baNew.ba_strCommandLineWhenReleased = "";
  270. // if T key is not bound to anything
  271. if (!bHasT) {
  272. // bind it to talk
  273. baNew.ba_iFirstKey = KID_T;
  274. // if we couldn't bind it
  275. } else {
  276. // put it to the top of the list
  277. baNew.ba_lnNode.Remove();
  278. ctrl_lhButtonActions.AddHead(baNew.ba_lnNode);
  279. }
  280. }
  281. */
  282. CalculateInfluencesForAllAxis();
  283. }
  284. void CControls::Save_t( CTFileName fnFile)
  285. {
  286. CTString strLine;
  287. // create file
  288. CTFileStream strmFile;
  289. strmFile.Create_t( fnFile, CTStream::CM_TEXT);
  290. // write button actions
  291. FOREACHINLIST( CButtonAction, ba_lnNode, ctrl_lhButtonActions, itba)
  292. {
  293. strLine.PrintF("Button\n Name: TTRS %s\n Key1: %s\n Key2: %s",
  294. itba->ba_strName,
  295. _pInput->GetButtonName( itba->ba_iFirstKey),
  296. _pInput->GetButtonName( itba->ba_iSecondKey) );
  297. strmFile.PutLine_t( strLine);
  298. // export pressed command
  299. strLine.PrintF(" Pressed: %s", itba->ba_strCommandLineWhenPressed);
  300. {for( INDEX iLetter = 0; strLine[ iLetter] != 0; iLetter++)
  301. {
  302. // delete EOL-s
  303. if( (strLine[ iLetter] == 0x0d) || (strLine[ iLetter] == 0x0a) )
  304. {
  305. ((char*)(const char*)strLine)[ iLetter] = ' ';
  306. }
  307. }}
  308. strmFile.PutLine_t( strLine);
  309. // export released command
  310. strLine.PrintF(" Released: %s", itba->ba_strCommandLineWhenReleased);
  311. {for( INDEX iLetter = 0; strLine[ iLetter] != 0; iLetter++)
  312. {
  313. // delete EOL-s
  314. if( (strLine[ iLetter] == 0x0d) || (strLine[ iLetter] == 0x0a) )
  315. {
  316. ((char*)(const char*)strLine)[ iLetter] = ' ';
  317. }
  318. }}
  319. strmFile.PutLine_t( strLine);
  320. }
  321. // write axis actions
  322. for( INDEX iAxis=0; iAxis<AXIS_ACTIONS_CT; iAxis++)
  323. {
  324. CTString strIfInverted;
  325. CTString strIfRelative;
  326. CTString strIfSmooth;
  327. if( ctrl_aaAxisActions[iAxis].aa_bInvert) {
  328. strIfInverted = "Inverted";
  329. } else {
  330. strIfInverted = "NotInverted";
  331. }
  332. if( ctrl_aaAxisActions[iAxis].aa_bRelativeControler) {
  333. strIfRelative = "Relative";
  334. } else {
  335. strIfRelative = "Absolute";
  336. }
  337. if( ctrl_aaAxisActions[iAxis].aa_bSmooth) {
  338. strIfSmooth = "Smooth";
  339. } else {
  340. strIfSmooth = "NotSmooth";
  341. }
  342. strLine.PrintF("Axis \"%s\" \"%s\" %g %g %s %s %s",
  343. _pGame->gm_astrAxisNames[iAxis],
  344. _pInput->GetAxisName(ctrl_aaAxisActions[iAxis].aa_iAxisAction),
  345. ctrl_aaAxisActions[ iAxis].aa_fSensitivity,
  346. ctrl_aaAxisActions[ iAxis].aa_fDeadZone,
  347. strIfInverted,
  348. strIfRelative,
  349. strIfSmooth);
  350. strmFile.PutLine_t( strLine);
  351. }
  352. // write global parameters
  353. if (ctrl_bInvertLook) {
  354. strmFile.PutLine_t( "GlobalInvertLook");
  355. } else {
  356. strmFile.PutLine_t( "GlobalDontInvertLook");
  357. }
  358. if (ctrl_bSmoothAxes) {
  359. strmFile.PutLine_t( "GlobalSmoothAxes");
  360. } else {
  361. strmFile.PutLine_t( "GlobalDontSmoothAxes");
  362. }
  363. strmFile.FPrintF_t("GlobalSensitivity %g\n", ctrl_fSensitivity);
  364. }
  365. // check if these controls use any joystick
  366. BOOL CControls::UsesJoystick(void)
  367. {
  368. // for each button
  369. FOREACHINLIST( CButtonAction, ba_lnNode, ctrl_lhButtonActions, itba) {
  370. CButtonAction &ba = *itba;
  371. if (ba.ba_iFirstKey>=FIRST_JOYBUTTON || ba.ba_iSecondKey>=FIRST_JOYBUTTON) {
  372. return TRUE;
  373. }
  374. }
  375. // write axis actions
  376. for( INDEX iAxis=0; iAxis<AXIS_ACTIONS_CT; iAxis++)
  377. {
  378. if (ctrl_aaAxisActions[iAxis].aa_iAxisAction>=FIRST_JOYAXIS) {
  379. return TRUE;
  380. }
  381. }
  382. return FALSE;
  383. }