add automatic mapping of joysticks

This commit is contained in:
Chris Danford
2003-05-28 02:35:05 +00:00
parent 9ec65e3509
commit 4d182f85a4
19 changed files with 183 additions and 11 deletions
+3
View File
@@ -48,6 +48,9 @@ NEW FEATURE: New parameters for background changes: rate, fade old, loop,
rewind.
CHANGE: Background playback speed scaled by song rate, so movies stay in
sync (although syncing isn't very accurate at some song rates).
NEW FEATURE: Automatic mapping of joysticks.
NEW FEATURE: Automatically adujst graphic detail on first run.
NEW FEATURE: #DISPLAYBPM tag for SM and DWI files.
----------------------- Version 3.01 ---------------------------
CHANGE: Simplified NoteSkin tap graphic format. Old NoteSkins will need to
+1
View File
@@ -1787,6 +1787,7 @@ AttackDurationSeconds=0
[ScreenInputOptions]
HelpText=&UP; &DOWN; to change line &LEFT; &RIGHT; to select between options::START to accept changes BACK to discard changes
AutoMapJoysticks=&oq;ON&cq; will cause StepMania automatically create::mappings for the joysticks attached to your computer::at the time the program starts. This will::override any manually defined mappings.
IgnoreJoyAxes=&oq;ON&cq; will cause StepMania to ignore all input from::joystick directional pads. This is useful for the DirectPad Pro driver::and some brands of USB convertors.
MenuButtons=The default setting allows the dance pad's panels to navigate::the menus. Changing this to &oq;dedicated only&cq; will restrict::menu navigation to only the Menu* set of buttons. Be sure to map::the Menu* set of buttons before setting this to &oq;dedicated&cq;!
AutoPlay=This option is useful for those who would like to play::without using a pad. However, you will not be able to set::high scores or earn extra stages while this options is ON.
+109
View File
@@ -17,6 +17,8 @@
#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
@@ -63,6 +65,113 @@ void InputMapper::AddDefaultMappingsForCurrentGameIfUnmapped()
}
}
struct AutoJoyMapping
{
Game game;
char sDeviceDescription[64];
bool bIgnoreAxes;
int numMappings;
struct {
int deviceButton;
GameButton gb;
} 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 },
}
},
};
const int NUM_AUTO_JOY_MAPPINGS = sizeof(g_AutoJoyMappings) / sizeof(g_AutoJoyMappings[0]);
void InputMapper::AutoMapJoysticksForCurrentGame()
{
vector<InputDevice> vDevices;
vector<CString> vDescriptions;
PREFSMAN->m_bIgnoreJoyAxes = false;
INPUTMAN->GetDevicesAndDescriptions(vDevices,vDescriptions);
for( unsigned i=0; i<vDevices.size(); i++ )
{
InputDevice device = vDevices[i];
CString sDescription = vDescriptions[i];
for( unsigned j=0; j<NUM_AUTO_JOY_MAPPINGS; j++ )
{
const AutoJoyMapping& mapping = g_AutoJoyMappings[j];
if( sDescription == mapping.sDeviceDescription )
{
PREFSMAN->m_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( unsigned k=0; k<mapping.numMappings; k++ )
{
DeviceInput di( device, mapping.mapping[k].deviceButton );
GameInput gi( gc, mapping.mapping[k].gb );
SetInputMap( di, gi, 1 );
}
break;
}
}
}
}
void InputMapper::ReadMappingsFromDisk()
{
ASSERT( GAMEMAN != NULL );
+1
View File
@@ -40,6 +40,7 @@ public:
void ClearFromInputMap( GameInput GameI, int iSlotIndex );
void AddDefaultMappingsForCurrentGameIfUnmapped();
void AutoMapJoysticksForCurrentGame();
bool IsMapped( DeviceInput DeviceI );
bool IsMapped( GameInput GameI );
+3
View File
@@ -96,6 +96,7 @@ PrefsManager::PrefsManager()
m_fDancePointsAccumulated = 0;
m_bUseUnlockSystem = false;
m_bFirstRun = true;
m_bAutoMapJoysticks = true;
/* DDR Extreme-style extra stage support.
* Default off so people used to the current behavior (or those with extra
@@ -205,6 +206,7 @@ void PrefsManager::ReadGlobalPrefsFromDisk( bool bSwitchToLastPlayedGame )
ini.GetValueF( "Options", "DancePointsAccumulated", m_fDancePointsAccumulated );
ini.GetValueB( "Options", "UseUnlockSystem", m_bUseUnlockSystem );
ini.GetValueB( "Options", "FirstRun", m_bFirstRun );
ini.GetValueB( "Options", "AutoMapJoysticks", m_bAutoMapJoysticks );
m_asAdditionalSongFolders.clear();
CString sAdditionalSongFolders;
@@ -291,6 +293,7 @@ void PrefsManager::SaveGlobalPrefsToDisk()
ini.SetValueF( "Options", "DancePointsAccumulated", m_fDancePointsAccumulated );
ini.SetValueB( "Options", "UseUnlockSystem", m_bUseUnlockSystem );
ini.SetValueB( "Options", "FirstRun", m_bFirstRun );
ini.SetValueB( "Options", "AutoMapJoysticks", m_bAutoMapJoysticks );
/* Only write these if they aren't the default. This ensures that we can change
+1
View File
@@ -79,6 +79,7 @@ public:
float m_fDancePointsAccumulated;
bool m_bUseUnlockSystem;
bool m_bFirstRun;
bool m_bAutoMapJoysticks;
/* 0 = no; 1 = yes; -1 = auto (do whatever is appropriate for the arch). */
int m_iBoostAppPriority;
+5
View File
@@ -44,3 +44,8 @@ void RageInput::Update( float fDeltaTime )
Devices[i]->Update(fDeltaTime);
}
void RageInput::GetDevicesAndDescriptions(vector<InputDevice>& vDevicesOut, vector<CString>& vDescriptionsOut)
{
for(unsigned i = 0; i < Devices.size(); ++i)
Devices[i]->GetDevicesAndDescriptions( vDevicesOut, vDescriptionsOut );
}
+1
View File
@@ -21,6 +21,7 @@ public:
~RageInput();
void Update( float fDeltaTime );
void GetDevicesAndDescriptions(vector<InputDevice>& vDevicesOut, vector<CString>& vDescriptionsOut);
};
extern RageInput* INPUTMAN; // global and accessable from anywhere in our program
+5 -1
View File
@@ -24,7 +24,8 @@
enum {
IO_IGNORE_AXES = 0,
IO_AUTO_MAP_JOYSTICKS = 0,
IO_IGNORE_AXES,
IO_DEDICATED_MENU_BUTTONS,
IO_AUTOPLAY,
IO_DELAYED_ESCAPE,
@@ -36,6 +37,7 @@ enum {
/* Hmm. Ignore JoyAxes and Back Delayed probably belong in "key/joy config",
* preferably alongside button configuration. */
OptionRow g_InputOptionsLines[NUM_INPUT_OPTIONS_LINES] = {
OptionRow( "Auto Map\nJoysticks", "OFF","ON (recommended)" ),
OptionRow( "Ignore\nJoy Axes", "OFF","ON (for NTPad or DirectPad)" ),
OptionRow( "Menu\nButtons", "USE GAMEPLAY BUTTONS","ONLY DEDICATED BUTTONS" ),
OptionRow( "AutoPlay", "OFF","ON" ),
@@ -61,6 +63,7 @@ ScreenInputOptions::ScreenInputOptions() :
void ScreenInputOptions::ImportOptions()
{
m_iSelectedOption[0][IO_AUTO_MAP_JOYSTICKS] = PREFSMAN->m_bAutoMapJoysticks ? 1:0;
m_iSelectedOption[0][IO_IGNORE_AXES] = PREFSMAN->m_bIgnoreJoyAxes ? 1:0;
m_iSelectedOption[0][IO_DEDICATED_MENU_BUTTONS] = PREFSMAN->m_bOnlyDedicatedMenuButtons ? 1:0;
m_iSelectedOption[0][IO_AUTOPLAY] = PREFSMAN->m_bAutoPlay;
@@ -74,6 +77,7 @@ void ScreenInputOptions::ImportOptions()
void ScreenInputOptions::ExportOptions()
{
PREFSMAN->m_bAutoMapJoysticks = m_iSelectedOption[0][IO_AUTO_MAP_JOYSTICKS] == 1;
PREFSMAN->m_bIgnoreJoyAxes = m_iSelectedOption[0][IO_IGNORE_AXES] == 1;
PREFSMAN->m_bOnlyDedicatedMenuButtons= m_iSelectedOption[0][IO_DEDICATED_MENU_BUTTONS] == 1;
PREFSMAN->m_bDelayedEscape = m_iSelectedOption[0][IO_DELAYED_ESCAPE] == 1;
+3 -1
View File
@@ -153,6 +153,9 @@ void ResetGame()
else
SCREENMAN->SetNewScreen( THEME->GetMetric("Common","InitialScreen") );
PREFSMAN->m_bFirstRun = false;
if( PREFSMAN->m_bAutoMapJoysticks )
INPUTMAPPER->AutoMapJoysticksForCurrentGame();
}
static void GameLoop();
@@ -402,7 +405,6 @@ int main(int argc, char* argv[])
SONGINDEX = new SongCacheIndex;
/* depends on SONGINDEX: */
SONGMAN = new SongManager( loading_window ); // this takes a long time to load
delete loading_window; // destroy this before init'ing Display
PREFSMAN->ReadGlobalPrefsFromDisk( true );
+7 -3
View File
@@ -64,7 +64,7 @@ IntDir=.\../Debug6
TargetDir=\stepmania\stepmania
TargetName=StepMania-debug
SOURCE="$(InputPath)"
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi ia32.vdi
# End Special Build Tool
@@ -104,7 +104,7 @@ IntDir=.\StepMania___Xbox_Debug___VC6
TargetDir=.\StepMania___Xbox_Debug___VC6
TargetName=StepMania
SOURCE="$(InputPath)"
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi ia32.vdi
# End Special Build Tool
@@ -144,7 +144,7 @@ IntDir=.\../Release6
TargetDir=\stepmania\stepmania
TargetName=StepMania
SOURCE="$(InputPath)"
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi ia32.vdi
# End Special Build Tool
@@ -336,6 +336,10 @@ SOURCE=.\RageInput.cpp
# End Source File
# Begin Source File
SOURCE=.\RageInput.h
# End Source File
# Begin Source File
SOURCE=.\RageInputDevice.cpp
!IF "$(CFG)" == "StepMania - Win32 Debug"
+6 -6
View File
@@ -31,9 +31,9 @@
RuntimeLibrary="2"
UsePrecompiledHeader="2"
PrecompiledHeaderFile="$(IntDir)/StepMania.pch"
AssemblerListingLocation=".\../Debug_OGL/"
ObjectFile=".\../Debug_OGL/"
ProgramDataBaseFileName=".\../Debug_OGL/"
AssemblerListingLocation=".\../Debug/"
ObjectFile=".\../Debug/"
ProgramDataBaseFileName=".\../Debug/"
BrowseInformation="0"
WarningLevel="4"
SuppressStartupBanner="TRUE"
@@ -110,9 +110,9 @@ cl /Zl /nologo /c verstub.cpp /Fo&quot;$(IntDir)&quot;\
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="global.h"
PrecompiledHeaderFile="$(IntDir)/StepMania.pch"
AssemblerListingLocation=".\../Release_OGL/"
ObjectFile=".\../Release_OGL/"
ProgramDataBaseFileName=".\../Release_OGL/"
AssemblerListingLocation=".\../Release/"
ObjectFile=".\../Release/"
ProgramDataBaseFileName=".\../Release/"
BrowseInformation="1"
WarningLevel="4"
SuppressStartupBanner="TRUE"
@@ -22,12 +22,14 @@
* input for the same device; we have no method to allocate device numbers.
* We don't need this now; I'll write it if it becomes needed.)
*/
#include "RageInputDevice.h" // for InputDevice
class InputHandler
{
public:
virtual void Update(float fDeltaTime) { }
virtual ~InputHandler() { }
virtual void GetDevicesAndDescriptions(vector<InputDevice>& vDevicesOut, vector<CString>& vDescriptionsOut) = 0;
};
#endif
@@ -132,6 +132,22 @@ void InputHandler_SDL::Update(float fDeltaTime)
}
}
void InputHandler_SDL::GetDevicesAndDescriptions(vector<InputDevice>& vDevicesOut, vector<CString>& vDescriptionsOut)
{
vDevicesOut.push_back( DEVICE_KEYBOARD );
vDescriptionsOut.push_back( "Keyboard" );
for( int i=0; i<SDL_NumJoysticks(); i++ )
{
if( SDL_JoystickOpened(i) )
{
vDevicesOut.push_back( InputDevice(DEVICE_JOY1+i) );
vDescriptionsOut.push_back( SDL_JoystickName(i) );
}
}
}
/*
-----------------------------------------------------------------------------
Copyright (c) 2001-2003 by the person(s) listed below. All rights reserved.
@@ -14,6 +14,7 @@ public:
void Update(float fDeltaTime);
InputHandler_SDL();
~InputHandler_SDL();
void GetDevicesAndDescriptions(vector<InputDevice>& vDevicesOut, vector<CString>& vDescriptionsOut);
};
@@ -46,6 +46,18 @@ void InputHandler_Win32_Pump::Update(float fDeltaTime)
}
}
void InputHandler_Win32_Pump::GetDevicesAndDescriptions(vector<InputDevice>& vDevicesOut, vector<CString>& vDescriptionsOut)
{
for(int i = 0; i < NUM_PUMPS; ++i)
{
if( dev[i].IsOpen() )
{
vDevicesOut.push_back( InputDevice(DEVICE_PUMP1+i) );
vDescriptionsOut.push_back( "Pump USB" );
}
}
}
/*
-----------------------------------------------------------------------------
Copyright (c) 2002-2003 by the person(s) listed below. All rights reserved.
@@ -12,6 +12,7 @@ public:
void Update(float fDeltaTime);
InputHandler_Win32_Pump();
~InputHandler_Win32_Pump();
void GetDevicesAndDescriptions(vector<InputDevice>& vDevicesOut, vector<CString>& vDescriptionsOut);
};
#endif
+5
View File
@@ -108,6 +108,11 @@ bool USBDevice::Open(int VID, int PID, int num)
return h != INVALID_HANDLE_VALUE;
}
bool USBDevice::IsOpen()
{
return h != INVALID_HANDLE_VALUE;
}
int USBDevice::GetPadEvent()
{
if(h == INVALID_HANDLE_VALUE)
+1
View File
@@ -8,6 +8,7 @@ public:
~USBDevice();
int GetPadEvent();
bool Open(int VID, int PID, int num);
bool IsOpen();
private:
HANDLE h;