#include "global.h" /* ----------------------------------------------------------------------------- Class: InputMapper Desc: See Header. Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. Chris Danford ----------------------------------------------------------------------------- */ #include "InputMapper.h" #include "IniFile.h" #include "GameManager.h" #include "GameState.h" #include "RageLog.h" #include "InputFilter.h" #include "RageUtil.h" #include "PrefsManager.h" #include "RageInput.h" InputMapper* INPUTMAPPER = NULL; // global and accessable from anywhere in our program InputMapper::InputMapper() { } InputMapper::~InputMapper() { SaveMappingsToDisk(); } void InputMapper::ClearAllMappings() { for( int i=0; iGetCurrentGameDef(); for( int c=0; cm_iButtonsPerController; b++ ) { int key = pGameDef->m_iDefaultKeyboardKey[c][b]; if( key == -1 ) // "no key" marker" continue; DeviceInput DeviceI( DEVICE_KEYBOARD, key ); GameInput GameI( (GameController)c, (GameButton)b ); if( !IsMapped(DeviceI) ) // if this key isn't already being used by another user-made mapping SetInputMap( DeviceI, GameI, 2 ); } } } struct AutoJoyMapping { Game game; const char *sDeviceDescription; bool bIgnoreAxes; int numMappings; struct { int deviceButton; GameButton gb; /* If this is true, this is an auxilliary mapping assigned to the second * player. If two of the same device are found, and the device has secondary * entries, the later entries take precedence. This way, if a Pump pad is * found, it'll map P1 to the primary pad and P2 to the secondary pad. * (We can't tell if a slave pad is actually there.) Then, if a second primary * is found (DEVICE_PUMP2), 2P will be mapped to it. * * This isn't well-tested; I only have one Pump pad. */ bool SecondController; } mapping[32]; }; const AutoJoyMapping g_AutoJoyMappings[] = { { GAME_DANCE, "GIC USB Joystick", false, 4, { { JOY_16, DANCE_BUTTON_LEFT }, { JOY_14, DANCE_BUTTON_RIGHT }, { JOY_13, DANCE_BUTTON_UP }, { JOY_15, DANCE_BUTTON_DOWN }, } }, { GAME_DANCE, "4 axis 16 button joystick", // likely a PC Magic Box false, 4, { { JOY_16, DANCE_BUTTON_LEFT }, { JOY_14, DANCE_BUTTON_RIGHT }, { JOY_13, DANCE_BUTTON_UP }, { JOY_15, DANCE_BUTTON_DOWN }, } }, { GAME_DANCE, "GamePad Pro USB ", // yes, there is a space at the end false, 12, { { JOY_LEFT, DANCE_BUTTON_LEFT }, { JOY_RIGHT, DANCE_BUTTON_RIGHT }, { JOY_UP, DANCE_BUTTON_UP }, { JOY_DOWN, DANCE_BUTTON_DOWN }, { JOY_1, DANCE_BUTTON_LEFT }, { JOY_3, DANCE_BUTTON_RIGHT }, { JOY_4, DANCE_BUTTON_UP }, { JOY_2, DANCE_BUTTON_DOWN }, { JOY_5, DANCE_BUTTON_UPLEFT }, { JOY_6, DANCE_BUTTON_UPRIGHT }, { JOY_9, DANCE_BUTTON_BACK }, { JOY_10, DANCE_BUTTON_START }, } }, { GAME_PUMP, "Pump USB", false, 11, { { PUMP_UL, PUMP_BUTTON_UPLEFT }, { PUMP_UR, PUMP_BUTTON_UPRIGHT }, { PUMP_MID, PUMP_BUTTON_CENTER }, { PUMP_DL, PUMP_BUTTON_DOWNLEFT }, { PUMP_DR, PUMP_BUTTON_DOWNRIGHT }, { PUMP_ESCAPE, PUMP_BUTTON_BACK }, { PUMP_2P_UL, PUMP_BUTTON_UPLEFT, true }, { PUMP_2P_UR, PUMP_BUTTON_UPRIGHT, true }, { PUMP_2P_MID, PUMP_BUTTON_CENTER, true }, { PUMP_2P_DL, PUMP_BUTTON_DOWNLEFT, true }, { PUMP_2P_DR, PUMP_BUTTON_DOWNRIGHT, true }, } }, }; const int NUM_AUTO_JOY_MAPPINGS = sizeof(g_AutoJoyMappings) / sizeof(g_AutoJoyMappings[0]); void InputMapper::AutoMapJoysticksForCurrentGame() { vector vDevices; vector vDescriptions; PREFSMAN->m_bIgnoreJoyAxes = false; INPUTMAN->GetDevicesAndDescriptions(vDevices,vDescriptions); for( unsigned i=0; im_bIgnoreJoyAxes |= mapping.bIgnoreAxes; GameController gc = GAME_CONTROLLER_INVALID; switch( device ) { case DEVICE_JOY1: case DEVICE_JOY3: case DEVICE_PUMP1: gc = GAME_CONTROLLER_1; break; case DEVICE_JOY2: case DEVICE_JOY4: case DEVICE_PUMP2: gc = GAME_CONTROLLER_2; break; } if( gc == GAME_CONTROLLER_INVALID ) continue; for( int k=0; kWarn( "could not input mapping file \"Keymaps.ini\"." ); const IniFile::key *Key = ini.GetKey( GAMESTATE->GetCurrentGameDef()->m_szName ); if( Key ) { for( IniFile::key::const_iterator i = Key->begin(); i != Key->end(); ++i ) { CString name = i->first; CString value = i->second; GameInput GameI; GameI.fromString( name ); CStringArray sDeviceInputStrings; split( value, ",", sDeviceInputStrings, false ); for( unsigned i=0; iGetCurrentGameDef()->m_szName ); // iterate over our input map and write all mappings to the ini file for( int i=0; iGetCurrentGameDef()->m_szName, sNameString, sValueString ); } } ini.WriteFile(); } void InputMapper::SetInputMap( DeviceInput DeviceI, GameInput GameI, int iSlotIndex ) { // remove the old input ClearFromInputMap( DeviceI ); ClearFromInputMap( GameI, iSlotIndex ); m_GItoDI[GameI.controller][GameI.button][iSlotIndex] = DeviceI; UpdateTempDItoGI(); } void InputMapper::ClearFromInputMap( DeviceInput DeviceI ) { // search for where this DeviceI maps to for( int p=0; pm_CurStyle == STYLE_INVALID ) { StyleI.MakeInvalid(); return; } const StyleDef* pStyleDef = GAMESTATE->GetCurrentStyleDef(); StyleI = pStyleDef->GameInputToStyleInput( GameI ); } void InputMapper::GameToMenu( GameInput GameI, MenuInput &MenuI ) { const GameDef* pGameDef = GAMESTATE->GetCurrentGameDef(); MenuI = pGameDef->GameInputToMenuInput( GameI ); } void InputMapper::StyleToGame( StyleInput StyleI, GameInput &GameI ) { const StyleDef* pStyleDef = GAMESTATE->GetCurrentStyleDef(); GameI = pStyleDef->StyleInputToGameInput( StyleI ); } void InputMapper::MenuToGame( MenuInput MenuI, GameInput GameIout[4] ) { GameDef* pGameDef = GAMESTATE->GetCurrentGameDef(); pGameDef->MenuInputToGameInput( MenuI, GameIout ); } bool InputMapper::IsButtonDown( GameInput GameI ) { for( int i=0; iIsBeingPressed( DeviceI ) ) return true; } return false; } bool InputMapper::IsButtonDown( MenuInput MenuI ) { GameInput GameI[4]; MenuToGame( MenuI, GameI ); for( int i=0; i<4; i++ ) if( GameI[i].IsValid() && IsButtonDown(GameI[i]) ) return true; return false; } bool InputMapper::IsButtonDown( StyleInput StyleI ) { GameInput GameI; StyleToGame( StyleI, GameI ); return IsButtonDown( GameI ); } float InputMapper::GetSecsHeld( GameInput GameI ) { float fMaxSecsHeld = 0; for( int i=0; iGetSecsHeld(DeviceI) ); } return fMaxSecsHeld; } float InputMapper::GetSecsHeld( MenuInput MenuI ) { float fMaxSecsHeld = 0; GameInput GameI[4]; MenuToGame( MenuI, GameI ); for( int i=0; i<4; i++ ) if( GameI[i].IsValid() ) fMaxSecsHeld = max( fMaxSecsHeld, GetSecsHeld(GameI[i]) ); return fMaxSecsHeld; } float InputMapper::GetSecsHeld( StyleInput StyleI ) { GameInput GameI; StyleToGame( StyleI, GameI ); return GetSecsHeld( GameI ); }