#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" #include "arch/arch.h" InputMapper* INPUTMAPPER = NULL; // global and accessable from anywhere in our program #define KEYMAPS_PATH BASE_PATH "Data" SLASH "Keymaps.ini" 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 *szDeviceDescription; // reported by InputHandler const char *szControllerName; // the product name of the controller bool bIgnoreAxes; struct { int iSlotIndex; // -1 == end marker 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; } maps[32]; }; const AutoJoyMapping g_AutoJoyMappings[] = { { GAME_DANCE, "GIC USB Joystick", "Boom USB convertor (black/gray)", false, { { 0, JOY_16, DANCE_BUTTON_LEFT }, { 0, JOY_14, DANCE_BUTTON_RIGHT }, { 0, JOY_13, DANCE_BUTTON_UP }, { 0, JOY_15, DANCE_BUTTON_DOWN }, {-1, NULL, NULL }, } }, { GAME_DANCE, "4 axis 16 button joystick", "PC Magic Box", false, { { 0, JOY_16, DANCE_BUTTON_LEFT }, { 0, JOY_14, DANCE_BUTTON_RIGHT }, { 0, JOY_13, DANCE_BUTTON_UP }, { 0, JOY_15, DANCE_BUTTON_DOWN }, {-1, NULL, NULL }, } }, { GAME_DANCE, "GamePad Pro USB ", // yes, there is a space at the end "GamePad Pro USB", false, { { 0, JOY_LEFT, DANCE_BUTTON_LEFT }, { 0, JOY_RIGHT, DANCE_BUTTON_RIGHT }, { 0, JOY_UP, DANCE_BUTTON_UP }, { 0, JOY_DOWN, DANCE_BUTTON_DOWN }, { 1, JOY_1, DANCE_BUTTON_LEFT }, { 1, JOY_3, DANCE_BUTTON_RIGHT }, { 1, JOY_4, DANCE_BUTTON_UP }, { 1, JOY_2, DANCE_BUTTON_DOWN }, { 0, JOY_5, DANCE_BUTTON_UPLEFT }, { 0, JOY_6, DANCE_BUTTON_UPRIGHT }, { 0, JOY_9, DANCE_BUTTON_BACK }, { 0, JOY_10, DANCE_BUTTON_START }, {-1, NULL, NULL }, } }, { GAME_DANCE, "4 axis 12 button joystick with hat switch", "Super Joy Box 5", false, { { 0, JOY_HAT_LEFT, DANCE_BUTTON_LEFT }, { 0, JOY_HAT_RIGHT, DANCE_BUTTON_RIGHT }, { 0, JOY_HAT_UP, DANCE_BUTTON_UP }, { 0, JOY_HAT_DOWN, DANCE_BUTTON_DOWN }, { 1, JOY_4, DANCE_BUTTON_LEFT }, { 1, JOY_2, DANCE_BUTTON_RIGHT }, { 1, JOY_1, DANCE_BUTTON_UP }, { 1, JOY_3, DANCE_BUTTON_DOWN }, { 0, JOY_5, DANCE_BUTTON_UPLEFT }, { 0, JOY_6, DANCE_BUTTON_UPRIGHT }, { 1, JOY_7, DANCE_BUTTON_UPLEFT }, { 1, JOY_8, DANCE_BUTTON_UPRIGHT }, { 0, JOY_10, DANCE_BUTTON_BACK }, { 0, JOY_9, DANCE_BUTTON_START }, {-1, NULL, NULL }, } }, { GAME_DANCE, "MP-8866 Dual USB Joypad", "Super Dual Box", false, { { 0, JOY_HAT_LEFT, DANCE_BUTTON_LEFT }, { 0, JOY_HAT_RIGHT, DANCE_BUTTON_RIGHT }, { 0, JOY_HAT_UP, DANCE_BUTTON_UP }, { 0, JOY_HAT_DOWN, DANCE_BUTTON_DOWN }, { 1, JOY_4, DANCE_BUTTON_LEFT }, { 1, JOY_2, DANCE_BUTTON_RIGHT }, { 1, JOY_1, DANCE_BUTTON_UP }, { 1, JOY_3, DANCE_BUTTON_DOWN }, { 0, JOY_5, DANCE_BUTTON_UPLEFT }, { 0, JOY_6, DANCE_BUTTON_UPRIGHT }, { 1, JOY_7, DANCE_BUTTON_UPLEFT }, { 1, JOY_8, DANCE_BUTTON_UPRIGHT }, { 0, JOY_10, DANCE_BUTTON_BACK }, { 0, JOY_9, DANCE_BUTTON_START }, {-1, NULL, NULL }, } }, { GAME_DANCE, "XBOX Gamepad Plugin V0.01", "X-Box gamepad", false, { { 0, JOY_HAT_LEFT, DANCE_BUTTON_LEFT }, { 0, JOY_HAT_RIGHT, DANCE_BUTTON_RIGHT }, { 0, JOY_HAT_UP, DANCE_BUTTON_UP }, { 0, JOY_HAT_DOWN, DANCE_BUTTON_DOWN }, { 1, JOY_1, DANCE_BUTTON_DOWN }, // A { 1, JOY_2, DANCE_BUTTON_RIGHT }, // B { 1, JOY_3, DANCE_BUTTON_LEFT }, // X { 1, JOY_4, DANCE_BUTTON_UP }, // Y { 0, JOY_7, DANCE_BUTTON_UPLEFT }, // L shoulder { 0, JOY_8, DANCE_BUTTON_UPRIGHT }, // R shoulder { 0, JOY_9, DANCE_BUTTON_START }, { 0, JOY_10, DANCE_BUTTON_BACK }, {-1, NULL, NULL }, } }, { GAME_PUMP, "Pump USB", "Pump USB pad", false, { { 0, PUMP_UL, PUMP_BUTTON_UPLEFT }, { 0, PUMP_UR, PUMP_BUTTON_UPRIGHT }, { 0, PUMP_MID, PUMP_BUTTON_CENTER }, { 0, PUMP_DL, PUMP_BUTTON_DOWNLEFT }, { 0, PUMP_DR, PUMP_BUTTON_DOWNRIGHT }, { 0, PUMP_ESCAPE, PUMP_BUTTON_BACK }, { 0, PUMP_2P_UL, PUMP_BUTTON_UPLEFT, true }, { 0, PUMP_2P_UR, PUMP_BUTTON_UPRIGHT, true }, { 0, PUMP_2P_MID, PUMP_BUTTON_CENTER, true }, { 0, PUMP_2P_DL, PUMP_BUTTON_DOWNLEFT, true }, { 0, PUMP_2P_DR, PUMP_BUTTON_DOWNRIGHT, true }, {-1, NULL, NULL }, } }, }; void InputMapper::AutoMapJoysticksForCurrentGame() { vector vDevices; vector vDescriptions; PREFSMAN->m_bIgnoreJoyAxes = false; INPUTMAN->GetDevicesAndDescriptions(vDevices,vDescriptions); int iNumJoysticksMapped = 0; for( unsigned i=0; i= GAME_CONTROLLER_INVALID ) break; // stop mapping. We already mapped one device for each game controller. LOG->Info( "Applying default joystick mapping #%d for device '%s' (%s)", iNumJoysticksMapped+1, mapping.szDeviceDescription, mapping.szControllerName ); PREFSMAN->m_bIgnoreJoyAxes |= mapping.bIgnoreAxes; for( int k=0; mapping.maps[k].iSlotIndex != -1; k++ ) { if( mapping.maps[k].SecondController ) gc = GAME_CONTROLLER_2; DeviceInput di( device, mapping.maps[k].deviceButton ); GameInput gi( gc, mapping.maps[k].gb ); SetInputMap( di, gi, mapping.maps[k].iSlotIndex ); } iNumJoysticksMapped++; } } } } void InputMapper::ReadMappingsFromDisk() { ASSERT( GAMEMAN != NULL ); ClearAllMappings(); IniFile ini; ini.SetPath( KEYMAPS_PATH ); if( !ini.ReadFile() ) LOG->Warn( "could not input mapping file '%s'.", KEYMAPS_PATH ); 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 ); }