mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-12-01 22:25:53 +01:00
414 lines
12 KiB
C++
414 lines
12 KiB
C++
|
/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */
|
||
|
|
||
|
/*
|
||
|
* Game library
|
||
|
* Copyright (c) 1997-1999, CroTeam. All rights reserved.
|
||
|
*/
|
||
|
|
||
|
#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; iAxisAction<AXIS_ACTIONS_CT; iAxisAction++) {
|
||
|
// copy it
|
||
|
ctrl_aaAxisActions[iAxisAction] = ctrlOriginal.ctrl_aaAxisActions[iAxisAction];
|
||
|
}
|
||
|
|
||
|
// copy global settings
|
||
|
ctrl_fSensitivity = ctrlOriginal.ctrl_fSensitivity;
|
||
|
ctrl_bInvertLook = ctrlOriginal.ctrl_bInvertLook;
|
||
|
ctrl_bSmoothAxes = ctrlOriginal.ctrl_bSmoothAxes;
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Switches button and axis action mounters to defaults
|
||
|
*/
|
||
|
void CControls::SwitchAxesToDefaults(void)
|
||
|
{
|
||
|
// for all axis-type actions
|
||
|
for( INDEX iAxisAction=0; iAxisAction<AXIS_ACTIONS_CT; iAxisAction++)
|
||
|
{
|
||
|
// set axis action none
|
||
|
ctrl_aaAxisActions[ iAxisAction].aa_iAxisAction = AXIS_NONE;
|
||
|
ctrl_aaAxisActions[ iAxisAction].aa_fSensitivity = 50;
|
||
|
ctrl_aaAxisActions[ iAxisAction].aa_fDeadZone = 0;
|
||
|
ctrl_aaAxisActions[ iAxisAction].aa_bInvert = FALSE;
|
||
|
ctrl_aaAxisActions[ iAxisAction].aa_bRelativeControler = TRUE;
|
||
|
ctrl_aaAxisActions[ iAxisAction].aa_bSmooth = FALSE;
|
||
|
ctrl_aaAxisActions[ iAxisAction].aa_fLastReading = 0.0f;
|
||
|
}
|
||
|
// set default controlers for some axis-type actions
|
||
|
// mouse left/right motion
|
||
|
ctrl_aaAxisActions[ AXIS_TURN_LR].aa_iAxisAction = MOUSE_X_AXIS;
|
||
|
ctrl_aaAxisActions[ AXIS_TURN_LR].aa_fSensitivity = 45;
|
||
|
ctrl_aaAxisActions[ AXIS_TURN_LR].aa_bInvert = FALSE;
|
||
|
ctrl_aaAxisActions[ AXIS_TURN_LR].aa_bRelativeControler = TRUE;
|
||
|
// mouse up/down motion
|
||
|
ctrl_aaAxisActions[ AXIS_TURN_UD].aa_iAxisAction = MOUSE_Y_AXIS;
|
||
|
ctrl_aaAxisActions[ AXIS_TURN_UD].aa_fSensitivity = 45;
|
||
|
ctrl_aaAxisActions[ AXIS_TURN_UD].aa_bInvert = TRUE;
|
||
|
ctrl_aaAxisActions[ AXIS_TURN_UD].aa_bRelativeControler = TRUE;
|
||
|
|
||
|
ctrl_fSensitivity = 50;
|
||
|
ctrl_bInvertLook = FALSE;
|
||
|
ctrl_bSmoothAxes = TRUE;
|
||
|
}
|
||
|
|
||
|
void CControls::SwitchToDefaults(void)
|
||
|
{
|
||
|
// copy controls from initial player
|
||
|
try
|
||
|
{
|
||
|
CControls ctrlDefaultControls;
|
||
|
ctrlDefaultControls.Load_t( CTString("Data\\Defaults\\InitialControls.ctl"));
|
||
|
*this = ctrlDefaultControls;
|
||
|
}
|
||
|
catch( char *strError)
|
||
|
{
|
||
|
(void) strError;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Depending on axis attributes and type (rotation or translation),
|
||
|
* calculates axis influence factors for all axis actions
|
||
|
*/
|
||
|
void CControls::CalculateInfluencesForAllAxis(void)
|
||
|
{
|
||
|
FLOAT fSensitivityGlobal = (FLOAT)pow(1.2, (ctrl_fSensitivity-50.0)*1.0/5.0);
|
||
|
FLOAT fBaseDelta; // different for rotations and translations
|
||
|
// for all axis actions
|
||
|
for( INDEX iAxisAction=0; iAxisAction<AXIS_ACTIONS_CT; iAxisAction++)
|
||
|
{
|
||
|
fBaseDelta = 1.0f;
|
||
|
// apply invert factor
|
||
|
if( ctrl_aaAxisActions[ iAxisAction].aa_bInvert ||
|
||
|
( (iAxisAction==AXIS_TURN_UD||iAxisAction==AXIS_LOOK_UD) && ctrl_bInvertLook) ) {
|
||
|
// negative factor
|
||
|
fBaseDelta = -fBaseDelta;
|
||
|
}
|
||
|
|
||
|
FLOAT fSensitivityLocal = (FLOAT)pow(2.0, (ctrl_aaAxisActions[ iAxisAction].aa_fSensitivity-50.0)*1.0/5.0);
|
||
|
|
||
|
// calculate influence for current axis
|
||
|
ctrl_aaAxisActions[ iAxisAction].aa_fAxisInfluence = fBaseDelta * fSensitivityGlobal * fSensitivityLocal;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
INDEX DIKForName( CTString strKeyName)
|
||
|
{
|
||
|
if( strKeyName == "None") return KID_NONE;
|
||
|
for( INDEX iButton=0; iButton<MAX_OVERALL_BUTTONS; iButton++)
|
||
|
{
|
||
|
if( _pInput->GetButtonName( 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;
|
||
|
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; iAxis<AXIS_ACTIONS_CT; iAxis++){
|
||
|
if( CTString(_pGame->gm_astrAxisNames[iAxis]) == achrActionName)
|
||
|
{
|
||
|
iActionAxisNo = iAxis;
|
||
|
break;
|
||
|
}
|
||
|
}}
|
||
|
// find controller axis
|
||
|
INDEX iCtrlAxisNo = -1;
|
||
|
{for( INDEX iAxis=0; iAxis<MAX_OVERALL_AXES; iAxis++) {
|
||
|
if( _pInput->GetAxisName( 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",
|
||
|
itba->ba_strName,
|
||
|
_pInput->GetButtonName( itba->ba_iFirstKey),
|
||
|
_pInput->GetButtonName( itba->ba_iSecondKey) );
|
||
|
strmFile.PutLine_t( strLine);
|
||
|
|
||
|
// export pressed command
|
||
|
strLine.PrintF(" Pressed: %s", 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", 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; iAxis<AXIS_ACTIONS_CT; iAxis++)
|
||
|
{
|
||
|
CTString strIfInverted;
|
||
|
CTString strIfRelative;
|
||
|
CTString strIfSmooth;
|
||
|
|
||
|
if( ctrl_aaAxisActions[iAxis].aa_bInvert) {
|
||
|
strIfInverted = "Inverted";
|
||
|
} else {
|
||
|
strIfInverted = "NotInverted";
|
||
|
}
|
||
|
if( ctrl_aaAxisActions[iAxis].aa_bRelativeControler) {
|
||
|
strIfRelative = "Relative";
|
||
|
} else {
|
||
|
strIfRelative = "Absolute";
|
||
|
}
|
||
|
if( ctrl_aaAxisActions[iAxis].aa_bSmooth) {
|
||
|
strIfSmooth = "Smooth";
|
||
|
} else {
|
||
|
strIfSmooth = "NotSmooth";
|
||
|
}
|
||
|
|
||
|
|
||
|
strLine.PrintF("Axis \"%s\" \"%s\" %g %g %s %s %s",
|
||
|
_pGame->gm_astrAxisNames[iAxis],
|
||
|
_pInput->GetAxisName(ctrl_aaAxisActions[iAxis].aa_iAxisAction),
|
||
|
ctrl_aaAxisActions[ iAxis].aa_fSensitivity,
|
||
|
ctrl_aaAxisActions[ iAxis].aa_fDeadZone,
|
||
|
strIfInverted,
|
||
|
strIfRelative,
|
||
|
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<AXIS_ACTIONS_CT; iAxis++)
|
||
|
{
|
||
|
if (ctrl_aaAxisActions[iAxis].aa_iAxisAction>=FIRST_JOYAXIS) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|