/* Copyright (c) 2002-2012 Croteam Ltd. This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* * Game library * Copyright (c) 1997-1999, CroTeam. */ #include "StdAfx.h" extern CGame *_pGame; /* * Default constructor */ CControls::CControls(void) { // buttons are all none anyway (empty list) // switch axes actions to defaults SwitchAxesToDefaults(); } /* * Default destructor */ CControls::~CControls(void) { // for each action in the original list FORDELETELIST(CButtonAction, ba_lnNode, ctrl_lhButtonActions, itButtonAction) { // delete button action delete( &*itButtonAction); } } // Assignment operator. CControls &CControls::operator=(CControls &ctrlOriginal) { // remove old button actions {FORDELETELIST(CButtonAction, ba_lnNode, ctrl_lhButtonActions, itButtonAction) { delete &*itButtonAction; }} // for each action in the original list {FOREACHINLIST(CButtonAction, ba_lnNode, ctrlOriginal.ctrl_lhButtonActions, itButtonAction) { // create and copy button action AddButtonAction() = *itButtonAction; }} // for all axis-type actions for( INDEX iAxisAction=0; iAxisActionGetButtonName( iButton) == strKeyName) return iButton; } return KID_NONE; } CTString ReadTextLine(CTStream &strm, const CTString &strKeyword, BOOL bTranslate) { CTString strLine; strm.GetLine_t(strLine); strLine.TrimSpacesLeft(); if (!strLine.RemovePrefix(strKeyword)) { return "???"; } strLine.TrimSpacesLeft(); if (bTranslate) { strLine.RemovePrefix("TTRS"); } strLine.TrimSpacesLeft(); strLine.TrimSpacesRight(); return strLine; } void CControls::Load_t( CTFileName fnFile) { char achrLine[ 1024]; char achrName[ 1024]; char achrID[ 1024]; char achrActionName[ 1024]; // open script file for reading CTFileStream strmFile; strmFile.Open_t( fnFile); // if file can be opened for reading remove old button actions {FORDELETELIST(CButtonAction, ba_lnNode, ctrl_lhButtonActions, itButtonAction) { delete &*itButtonAction; }} do { achrLine[0] = 0; achrID[0] = 0; strmFile.GetLine_t( achrLine, 1024); sscanf( achrLine, "%s", achrID); // if name if( CTString( achrID) == "Name") { // name is obsolete, just skip it sscanf( achrLine, "%*[^\"]\"%1024[^\"]\"", achrName); // if this is button action } else if( CTString( achrID) == "Button") { // create and read button action CButtonAction &baNew = AddButtonAction(); baNew.ba_strName = ReadTextLine(strmFile, "Name:", TRUE); baNew.ba_iFirstKey = DIKForName( ReadTextLine(strmFile, "Key1:", FALSE)); baNew.ba_iSecondKey = DIKForName( ReadTextLine(strmFile, "Key2:", FALSE)); baNew.ba_strCommandLineWhenPressed = ReadTextLine(strmFile, "Pressed:", FALSE); baNew.ba_strCommandLineWhenReleased = ReadTextLine(strmFile, "Released:", FALSE); // if this is axis action } else if( CTString( achrID) == "Axis") { char achrAxis[ 1024]; achrAxis[ 0] = 0; char achrIfInverted[ 1024]; achrIfInverted[ 0] = 0; char achrIfRelative[ 1024]; achrIfRelative[ 0] = 0; char achrIfSmooth[ 1024]; achrIfSmooth[ 0] = 0; achrActionName[ 0] = 0; FLOAT fSensitivity = 50; FLOAT fDeadZone = 0; // FIXME DG: gcc and clang say the followign has too many arguments for the given format sscanf( achrLine, "%*[^\"]\"%1024[^\"]\"%*[^\"]\"%1024[^\"]\" %g %g %1024s %1024s", achrActionName, achrAxis, &fSensitivity, &fDeadZone, achrIfInverted, achrIfRelative, achrIfSmooth); // find action axis INDEX iActionAxisNo = -1; {for( INDEX iAxis=0; iAxisgm_astrAxisNames[iAxis]) == achrActionName) { iActionAxisNo = iAxis; break; } }} // find controller axis INDEX iCtrlAxisNo = -1; {for( INDEX iAxis=0; iAxisGetAxisName( iAxis) == achrAxis) { iCtrlAxisNo = iAxis; break; } }} // if valid axis found if( iActionAxisNo!=-1 && iCtrlAxisNo!=-1) { // set it ctrl_aaAxisActions[ iActionAxisNo].aa_iAxisAction = iCtrlAxisNo; ctrl_aaAxisActions[ iActionAxisNo].aa_fSensitivity = fSensitivity; ctrl_aaAxisActions[ iActionAxisNo].aa_fDeadZone = fDeadZone; ctrl_aaAxisActions[ iActionAxisNo].aa_bInvert = ( CTString( "Inverted") == achrIfInverted); ctrl_aaAxisActions[ iActionAxisNo].aa_bRelativeControler = ( CTString( "Relative") == achrIfRelative); ctrl_aaAxisActions[ iActionAxisNo].aa_bSmooth = ( CTString( "Smooth") == achrIfRelative); } // read global parameters } else if( CTString( achrID) == "GlobalInvertLook") { ctrl_bInvertLook = TRUE; } else if( CTString( achrID) == "GlobalDontInvertLook") { ctrl_bInvertLook = FALSE; } else if( CTString( achrID) == "GlobalSmoothAxes") { ctrl_bSmoothAxes = TRUE; } else if( CTString( achrID) == "GlobalDontSmoothAxes") { ctrl_bSmoothAxes = FALSE; } else if( CTString( achrID) == "GlobalSensitivity") { sscanf( achrLine, "GlobalSensitivity %g", &ctrl_fSensitivity); } } while( !strmFile.AtEOF()); /* // search for talk button BOOL bHasTalk = FALSE; BOOL bHasT = FALSE; FOREACHINLIST( CButtonAction, ba_lnNode, ctrl_lhButtonActions, itba) { CButtonAction &ba = *itba; if (ba.ba_strName=="Talk") { bHasTalk = TRUE; } if (ba.ba_iFirstKey==KID_T) { bHasT = TRUE; } if (ba.ba_iSecondKey==KID_T) { bHasT = TRUE; } } // if talk button not found if (!bHasTalk) { // add it CButtonAction &baNew = AddButtonAction(); baNew.ba_strName = "Talk"; baNew.ba_iFirstKey = KID_NONE; baNew.ba_iSecondKey = KID_NONE; baNew.ba_strCommandLineWhenPressed = " con_bTalk=1;"; baNew.ba_strCommandLineWhenReleased = ""; // if T key is not bound to anything if (!bHasT) { // bind it to talk baNew.ba_iFirstKey = KID_T; // if we couldn't bind it } else { // put it to the top of the list baNew.ba_lnNode.Remove(); ctrl_lhButtonActions.AddHead(baNew.ba_lnNode); } } */ CalculateInfluencesForAllAxis(); } void CControls::Save_t( CTFileName fnFile) { CTString strLine; // create file CTFileStream strmFile; strmFile.Create_t( fnFile, CTStream::CM_TEXT); // write button actions FOREACHINLIST( CButtonAction, ba_lnNode, ctrl_lhButtonActions, itba) { strLine.PrintF("Button\n Name: TTRS %s\n Key1: %s\n Key2: %s", (const char *) itba->ba_strName, (const char *) _pInput->GetButtonName( itba->ba_iFirstKey), (const char *) _pInput->GetButtonName( itba->ba_iSecondKey) ); strmFile.PutLine_t( strLine); // export pressed command strLine.PrintF(" Pressed: %s", (const char *) itba->ba_strCommandLineWhenPressed); {for( INDEX iLetter = 0; strLine[ iLetter] != 0; iLetter++) { // delete EOL-s if( (strLine[ iLetter] == 0x0d) || (strLine[ iLetter] == 0x0a) ) { ((char*)(const char*)strLine)[ iLetter] = ' '; } }} strmFile.PutLine_t( strLine); // export released command strLine.PrintF(" Released: %s", (const char *) itba->ba_strCommandLineWhenReleased); {for( INDEX iLetter = 0; strLine[ iLetter] != 0; iLetter++) { // delete EOL-s if( (strLine[ iLetter] == 0x0d) || (strLine[ iLetter] == 0x0a) ) { ((char*)(const char*)strLine)[ iLetter] = ' '; } }} strmFile.PutLine_t( strLine); } // write axis actions for( INDEX iAxis=0; iAxisgm_astrAxisNames[iAxis], (const char *) _pInput->GetAxisName(ctrl_aaAxisActions[iAxis].aa_iAxisAction), ctrl_aaAxisActions[ iAxis].aa_fSensitivity, ctrl_aaAxisActions[ iAxis].aa_fDeadZone, (const char *) strIfInverted, (const char *) strIfRelative, (const char *) strIfSmooth); strmFile.PutLine_t( strLine); } // write global parameters if (ctrl_bInvertLook) { strmFile.PutLine_t( "GlobalInvertLook"); } else { strmFile.PutLine_t( "GlobalDontInvertLook"); } if (ctrl_bSmoothAxes) { strmFile.PutLine_t( "GlobalSmoothAxes"); } else { strmFile.PutLine_t( "GlobalDontSmoothAxes"); } strmFile.FPrintF_t("GlobalSensitivity %g\n", ctrl_fSensitivity); } // check if these controls use any joystick BOOL CControls::UsesJoystick(void) { // for each button FOREACHINLIST( CButtonAction, ba_lnNode, ctrl_lhButtonActions, itba) { CButtonAction &ba = *itba; if (ba.ba_iFirstKey>=FIRST_JOYBUTTON || ba.ba_iSecondKey>=FIRST_JOYBUTTON) { return TRUE; } } // write axis actions for( INDEX iAxis=0; iAxis=FIRST_JOYAXIS) { return TRUE; } } return FALSE; }