diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 1c76af5d4f..f1d9a27816 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,7 @@ -June 26, 2009 (Changes by Graf Zahl) +June 26, 2009 +- Added joystick axis -> button mapping. + +June 26, 2009 (Changes by Graf Zahl) - Added Gez's actor replacement per skill submission. June 25, 2009 diff --git a/src/c_bind.cpp b/src/c_bind.cpp index 438f18edab..f1dcdb6b13 100644 --- a/src/c_bind.cpp +++ b/src/c_bind.cpp @@ -246,6 +246,11 @@ const char *KeyNames[NUM_KEYS] = "mwheelup", "mwheeldown", // the mouse wheel "mwheelright", "mwheelleft", + + "axis1plus","axis1minus","axis2plus","axis2minus", // joystick axes as buttons + "axis3plus","axis3minus","axis4plus","axis4minus", + "axis5plus","axis5minus","axis6plus","axis6minus", + "axis7plus","axis7minus","axis8plus","axis8minus", }; static FString Bindings[NUM_KEYS]; diff --git a/src/doomdef.h b/src/doomdef.h index ec20b23395..6c5d7ce1d7 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -102,7 +102,7 @@ enum ESkillLevels // // DOOM keyboard definition. Everything below 0x100 matches -// a DirectInput key code. +// a mode 1 keyboard scan code. // #define KEY_PAUSE 0xc5 // DIK_PAUSE #define KEY_RIGHTARROW 0xcd // DIK_RIGHT @@ -170,7 +170,25 @@ enum ESkillLevels #define KEY_MWHEELRIGHT 0x19A #define KEY_MWHEELLEFT 0x19B -#define NUM_KEYS 0x19C +#define KEY_JOYAXIS1PLUS 0x19C +#define KEY_JOYAXIS1MINUS 0x19D +#define KEY_JOYAXIS2PLUS 0x19E +#define KEY_JOYAXIS2MINUS 0x19F +#define KEY_JOYAXIS3PLUS 0x1A0 +#define KEY_JOYAXIS3MINUS 0x1A1 +#define KEY_JOYAXIS4PLUS 0x1A2 +#define KEY_JOYAXIS4MINUS 0x1A3 +#define KEY_JOYAXIS5PLUS 0x1A4 +#define KEY_JOYAXIS5MINUS 0x1A5 +#define KEY_JOYAXIS6PLUS 0x1A6 +#define KEY_JOYAXIS6MINUS 0x1A7 +#define KEY_JOYAXIS7PLUS 0x1A8 +#define KEY_JOYAXIS7MINUS 0x1A9 +#define KEY_JOYAXIS8PLUS 0x1AA +#define KEY_JOYAXIS8MINUS 0x1AB +#define NUM_JOYAXISBUTTONS 8 + +#define NUM_KEYS 0x1AC enum EJoyAxis { diff --git a/src/win32/i_dijoy.cpp b/src/win32/i_dijoy.cpp index 55f3698868..a05172888e 100644 --- a/src/win32/i_dijoy.cpp +++ b/src/win32/i_dijoy.cpp @@ -118,6 +118,8 @@ public: // MACROS ------------------------------------------------------------------ +#define DEFAULT_DEADZONE 0.25f + // TYPES ------------------------------------------------------------------- class FDInputJoystick : public FInputDevice, IJoystickConfig @@ -157,10 +159,11 @@ protected: DWORD Type; DWORD Ofs; LONG Min, Max; - LONG Value; + float Value; float DeadZone; float Multiplier; EJoyAxis GameAxis; + BYTE ButtonValue; }; struct ButtonInfo { @@ -189,6 +192,7 @@ protected: bool ReorderAxisPair(const GUID &x, const GUID &y, int pos); HRESULT SetDataFormat(); bool SetConfigSection(bool create); + void GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base); friend class FDInputJoystickManager; }; @@ -369,11 +373,42 @@ void FDInputJoystick::ProcessInput() return; } - // Copy axis values. They will be returned in a separate call. + // Convert axis values to floating point and save them for a later call + // to AddAxes(). Axes that are past their dead zone will also be translated + // into button presses. for (i = 0; i < Axes.Size(); ++i) { AxisInfo *info = &Axes[i]; - info->Value = *(LONG *)(state + info->Ofs); + LONG value = *(LONG *)(state + info->Ofs); + double deadzone = info->DeadZone; + double axisval; + BYTE buttonstate; + + // Scale to [-1.0, 1.0] + axisval = (value - info->Min) * 2.0 / (info->Max - info->Min) - 1.0; + // Cancel out dead zone + if (fabs(axisval) < deadzone) + { + axisval = 0; + buttonstate = 0; + } + // Make the dead zone the new 0 + else if (axisval < 0) + { + axisval = (axisval + deadzone) / (1.0 - deadzone); + buttonstate = 2; // button minus + } + else + { + axisval = (axisval - deadzone) / (1.0 - deadzone); + buttonstate = 1; // button plus + } + info->Value = float(axisval); + if (i < NUM_JOYAXISBUTTONS) + { + GenerateButtonEvents(info->ButtonValue, buttonstate, 2, KEY_JOYAXIS1PLUS + i*2); + } + info->ButtonValue = buttonstate; } // Compare button states and generate events for buttons that have changed. @@ -397,7 +432,7 @@ void FDInputJoystick::ProcessInput() { ButtonInfo *info = &POVs[i]; DWORD povangle = *(DWORD *)(state + info->Ofs); - int pov, changed; + int pov; // Smoosh POV angles down into octants. 8 is centered. pov = (LOWORD(povangle) == 0xFFFF) ? 8 : ((povangle + 2250) % 36000) / 4500; @@ -406,20 +441,31 @@ void FDInputJoystick::ProcessInput() pov = POVButtons[pov]; // Send events for POV "buttons" that have changed. - changed = pov ^ info->Value; - if (changed != 0) + GenerateButtonEvents(info->Value, pov, 4, KEY_JOYPOV1_UP + i*4); + info->Value = pov; + } +} + +//=========================================================================== +// +// FDInputJoystick :: GenerateButtonEvents +// +//=========================================================================== + +void FDInputJoystick::GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base) +{ + int changed = oldbuttons ^ newbuttons; + if (changed != 0) + { + event_t ev = { 0 }; + int mask = 1; + for (int j = 0; j < 4; mask <<= 1, ++j) { - int j, mask; - info->Value = pov; - mask = 1; - for (j = 0; j < 4; mask <<= 1, ++j) + if (changed & mask) { - if (changed & mask) - { - ev.data1 = KEY_JOYPOV1_UP + i*4 + j; - ev.type = (pov & mask) ? EV_KeyDown : EV_KeyUp; - D_PostEvent(&ev); - } + ev.data1 = base + j; + ev.type = (newbuttons & mask) ? EV_KeyDown : EV_KeyUp; + D_PostEvent(&ev); } } } @@ -443,27 +489,8 @@ void FDInputJoystick::AddAxes(float axes[NUM_JOYAXIS]) for (unsigned i = 0; i < Axes.Size(); ++i) { - double axisval = Axes[i].Value; - float deadzone = Axes[i].DeadZone; - - // Scale to [-1.0, 1.0] - axisval = (Axes[i].Value - Axes[i].Min) * 2.0 / (Axes[i].Max - Axes[i].Min) - 1.0; - // Cancel out dead zone - if (fabs(axisval) < deadzone) - { - continue; - } - // Make the dead zone the new 0 - if (axisval < 0) - { - axisval = (axisval + deadzone) / (1.0 - deadzone); - } - else - { - axisval = (axisval - deadzone) / (1.0 - deadzone); - } // Add to the game axis. - axes[Axes[i].GameAxis] -= float(axisval * mul * Axes[i].Multiplier); + axes[Axes[i].GameAxis] -= float(Axes[i].Value * mul * Axes[i].Multiplier); } } @@ -540,7 +567,8 @@ BOOL CALLBACK FDInputJoystick::EnumObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpd info.Min = diprg.lMin; info.Max = diprg.lMax; info.GameAxis = JOYAXIS_None; - info.Value = (diprg.lMin + diprg.lMax) / 2; + info.Value = 0; + info.ButtonValue = 0; joy->Axes.Push(info); } return DIENUM_CONTINUE; @@ -808,7 +836,7 @@ void FDInputJoystick::SetDefaultConfig() Multiplier = 1; for (unsigned i = 0; i < Axes.Size(); ++i) { - Axes[i].DeadZone = 0.25f; + Axes[i].DeadZone = DEFAULT_DEADZONE; Axes[i].Multiplier = 1; } // Triggers on a 360 controller have a much smaller deadzone.