diff options
| author | ayuanx <ayuanx@gmail.com> | 2010-02-03 02:54:31 +0000 |
|---|---|---|
| committer | ayuanx <ayuanx@gmail.com> | 2010-02-03 02:54:31 +0000 |
| commit | fb4f0edb85823deebaa63dcd6b8389fc1e800984 (patch) | |
| tree | d7aad7db20a00bb48c8388cbe92842be0f940b5c /Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp | |
| parent | e17c872d8f6f81aeac79076faa6a55d1f9b05e78 (diff) | |
Falcon4ever prefers to keep a standalone code copy of nJoy in repository.
Nakee, please make a branch/tag after release so that the code of nJoy will be saved as a standalone plugin
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4998 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp')
| -rw-r--r-- | Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp | 425 |
1 files changed, 425 insertions, 0 deletions
diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp new file mode 100644 index 0000000000..c25f8f39c0 --- /dev/null +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp @@ -0,0 +1,425 @@ +
+// Project description
+// -------------------
+// Name: nJoy
+// Description: A Dolphin Compatible Input Plugin
+//
+// Author: Falcon4ever (nJoy@falcon4ever.com)
+// Site: www.multigesture.net
+// Copyright (C) 2003 Dolphin Project.
+//
+
+//
+// Licensetype: GNU General Public License (GPL)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+//
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+//
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+//
+
+
+
+
+// Include
+// ---------
+#include "math.h" // System
+
+#include "ConfigBox.h" // Local
+#include "../nJoy.h"
+#include "Images/controller.xpm"
+
+extern bool g_EmulatorRunning;
+
+
+
+// Set dialog items from saved values
+// ----------------
+void PADConfigDialognJoy::UpdateGUIButtonMapping(int controller)
+{
+ // http://wiki.wxwidgets.org/Converting_everything_to_and_from_wxString
+ wxString tmp;
+
+ // Update selected gamepad
+ m_Joyname[controller]->SetSelection(PadMapping[controller].ID);
+ m_Enable[controller]->SetValue(PadMapping[controller].enable);
+
+ tmp << PadMapping[controller].buttons[InputCommon::CTL_L_SHOULDER]; m_JoyShoulderL[controller]->SetValue(tmp); tmp.clear();
+ tmp << PadMapping[controller].buttons[InputCommon::CTL_R_SHOULDER]; m_JoyShoulderR[controller]->SetValue(tmp); tmp.clear();
+
+ tmp << PadMapping[controller].buttons[InputCommon::CTL_A_BUTTON]; m_JoyButtonA[controller]->SetValue(tmp); tmp.clear();
+ tmp << PadMapping[controller].buttons[InputCommon::CTL_B_BUTTON]; m_JoyButtonB[controller]->SetValue(tmp); tmp.clear();
+ tmp << PadMapping[controller].buttons[InputCommon::CTL_X_BUTTON]; m_JoyButtonX[controller]->SetValue(tmp); tmp.clear();
+ tmp << PadMapping[controller].buttons[InputCommon::CTL_Y_BUTTON]; m_JoyButtonY[controller]->SetValue(tmp); tmp.clear();
+ tmp << PadMapping[controller].buttons[InputCommon::CTL_Z_TRIGGER]; m_JoyButtonZ[controller]->SetValue(tmp); tmp.clear();
+
+ tmp << PadMapping[controller].buttons[InputCommon::CTL_START]; m_JoyButtonStart[controller]->SetValue(tmp); tmp.clear();
+ tmp << PadMapping[controller].halfpress; m_JoyButtonHalfpress[controller]->SetValue(tmp); tmp.clear();
+
+ tmp << PadMapping[controller].axis[InputCommon::CTL_MAIN_X]; m_JoyAnalogMainX[controller]->SetValue(tmp); tmp.clear();
+ tmp << PadMapping[controller].axis[InputCommon::CTL_MAIN_Y]; m_JoyAnalogMainY[controller]->SetValue(tmp); tmp.clear();
+ tmp << PadMapping[controller].axis[InputCommon::CTL_SUB_X]; m_JoyAnalogSubX[controller]->SetValue(tmp); tmp.clear();
+ tmp << PadMapping[controller].axis[InputCommon::CTL_SUB_Y]; m_JoyAnalogSubY[controller]->SetValue(tmp); tmp.clear();
+
+ // Update the deadzone and controller type controls
+ m_ControlType[controller]->SetSelection(PadMapping[controller].controllertype);
+ m_TriggerType[controller]->SetSelection(PadMapping[controller].triggertype);
+ m_Deadzone[controller]->SetSelection(PadMapping[controller].deadzone);
+ m_CoBRadius[controller]->SetValue(wxString::FromAscii(PadMapping[controller].SRadius.c_str()));
+ m_CBRadius[controller]->SetValue(PadMapping[controller].bRadiusOnOff);
+ m_CoBDiagonal[controller]->SetValue(wxString::FromAscii(PadMapping[controller].SDiagonal.c_str()));
+ m_CBS_to_C[controller]->SetValue(PadMapping[controller].bSquareToCircle);
+ // C-stick
+ m_CoBRadiusC[controller]->SetValue(wxString::FromAscii(PadMapping[controller].SRadiusC.c_str()));
+ m_CBRadiusC[controller]->SetValue(PadMapping[controller].bRadiusOnOffC);
+ m_CoBDiagonalC[controller]->SetValue(wxString::FromAscii(PadMapping[controller].SDiagonalC.c_str()));
+ m_CBS_to_CC[controller]->SetValue(PadMapping[controller].bSquareToCircleC);
+ m_AdvancedMapFilter[controller]->SetValue(g_Config.bNoTriggerFilter);
+ // Update Rumble checkbox
+ m_Rumble[controller]->SetValue(PadMapping[controller].rumble);
+
+ // Update D-Pad
+ if(PadMapping[controller].controllertype == InputCommon::CTL_DPAD_HAT)
+ {
+ tmp << PadMapping[controller].dpad; m_JoyDpadDown[controller]->SetValue(tmp); tmp.clear();
+ }
+ else
+ {
+ tmp << PadMapping[controller].dpad2[InputCommon::CTL_D_PAD_UP]; m_JoyDpadUp[controller]->SetValue(tmp); tmp.clear();
+ tmp << PadMapping[controller].dpad2[InputCommon::CTL_D_PAD_DOWN]; m_JoyDpadDown[controller]->SetValue(tmp); tmp.clear();
+ tmp << PadMapping[controller].dpad2[InputCommon::CTL_D_PAD_LEFT]; m_JoyDpadLeft[controller]->SetValue(tmp); tmp.clear();
+ tmp << PadMapping[controller].dpad2[InputCommon::CTL_D_PAD_RIGHT]; m_JoyDpadRight[controller]->SetValue(tmp); tmp.clear();
+ }
+
+}
+
+/* Populate the PadMapping array with the dialog items settings (for example
+ selected joystick and so on) */
+void PADConfigDialognJoy::SaveButtonMapping(int controller, bool DontChangeId, int FromSlot)
+{
+ // Temporary storage
+ wxString tmp;
+ long value;
+
+ // Save from or to the same or different slots
+ if (FromSlot == -1) FromSlot = controller;
+
+ // Replace "" with "-1" in the GUI controls
+ ToBlank(false);
+
+ // Set other settings
+ if(!DontChangeId) PadMapping[controller].ID = m_Joyname[FromSlot]->GetSelection();
+ PadMapping[controller].enable = m_Enable[FromSlot]->IsChecked();
+ PadMapping[controller].controllertype = m_ControlType[FromSlot]->GetSelection();
+ PadMapping[controller].triggertype = m_TriggerType[FromSlot]->GetSelection();
+ PadMapping[controller].deadzone = m_Deadzone[FromSlot]->GetSelection();
+ PadMapping[controller].SRadius = m_CoBRadius[FromSlot]->GetLabel().mb_str();
+ PadMapping[controller].bRadiusOnOff = m_CBRadius[FromSlot]->IsChecked();
+ PadMapping[controller].SDiagonal = m_CoBDiagonal[FromSlot]->GetLabel().mb_str();
+ PadMapping[controller].bSquareToCircle = m_CBS_to_C[FromSlot]->IsChecked();
+ // C-stick
+ PadMapping[controller].SRadiusC = m_CoBRadiusC[FromSlot]->GetLabel().mb_str();
+ PadMapping[controller].bRadiusOnOffC = m_CBRadiusC[FromSlot]->IsChecked();
+ PadMapping[controller].SDiagonalC = m_CoBDiagonalC[FromSlot]->GetLabel().mb_str();
+ PadMapping[controller].bSquareToCircleC = m_CBS_to_CC[FromSlot]->IsChecked();
+
+ // The analog buttons
+ m_JoyAnalogMainX[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].axis[InputCommon::CTL_MAIN_X] = value; tmp.clear();
+ m_JoyAnalogMainY[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].axis[InputCommon::CTL_MAIN_Y] = value; tmp.clear();
+ m_JoyAnalogSubX[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].axis[InputCommon::CTL_SUB_X] = value; tmp.clear();
+ m_JoyAnalogSubY[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].axis[InputCommon::CTL_SUB_Y] = value; tmp.clear();
+
+ // The shoulder buttons
+ m_JoyShoulderL[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[InputCommon::CTL_L_SHOULDER] = value;
+ m_JoyShoulderR[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[InputCommon::CTL_R_SHOULDER] = value;
+
+ // The digital buttons
+ m_JoyButtonA[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[InputCommon::CTL_A_BUTTON] = value; tmp.clear();
+ m_JoyButtonB[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[InputCommon::CTL_B_BUTTON] = value; tmp.clear();
+ m_JoyButtonX[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[InputCommon::CTL_X_BUTTON] = value; tmp.clear();
+ m_JoyButtonY[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[InputCommon::CTL_Y_BUTTON] = value; tmp.clear();
+ m_JoyButtonZ[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[InputCommon::CTL_Z_TRIGGER] = value; tmp.clear();
+ m_JoyButtonStart[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].buttons[InputCommon::CTL_START] = value; tmp.clear();
+
+ // The halfpress button
+ m_JoyButtonHalfpress[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].halfpress = value; tmp.clear();
+
+ // The digital pad
+ if(PadMapping[controller].controllertype == InputCommon::CTL_DPAD_HAT)
+ {
+ m_JoyDpadDown[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].dpad = value; tmp.clear();
+ }
+ else
+ {
+ m_JoyDpadUp[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].dpad2[InputCommon::CTL_D_PAD_UP] = value; tmp.clear();
+ m_JoyDpadDown[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].dpad2[InputCommon::CTL_D_PAD_DOWN] = value; tmp.clear();
+ m_JoyDpadLeft[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].dpad2[InputCommon::CTL_D_PAD_LEFT] = value; tmp.clear();
+ m_JoyDpadRight[FromSlot]->GetValue().ToLong(&value); PadMapping[controller].dpad2[InputCommon::CTL_D_PAD_RIGHT] = value; tmp.clear();
+ }
+
+ // Replace "-1" with ""
+ ToBlank();
+}
+
+// Update the textbox for the buttons
+// ----------------
+void PADConfigDialognJoy::SetButtonText(int id, const char *text, int Page)
+{
+ // Set controller value
+ int controller;
+ if (Page == -1) controller = notebookpage; else controller = Page;
+
+ switch(id)
+ {
+ case IDB_DPAD_RIGHT: m_JoyDpadRight[controller]->SetValue(wxString::FromAscii(text)); break;
+ case IDB_DPAD_UP: m_JoyDpadUp[controller]->SetValue(wxString::FromAscii(text)); break;
+ case IDB_DPAD_DOWN: m_JoyDpadDown[controller]->SetValue(wxString::FromAscii(text)); break;
+ case IDB_DPAD_LEFT: m_JoyDpadLeft[controller]->SetValue(wxString::FromAscii(text)); break;
+
+ case IDB_ANALOG_MAIN_X: m_JoyAnalogMainX[controller]->SetValue(wxString::FromAscii(text)); break;
+ case IDB_ANALOG_MAIN_Y: m_JoyAnalogMainY[controller]->SetValue(wxString::FromAscii(text)); break;
+ case IDB_ANALOG_SUB_X: m_JoyAnalogSubX[controller]->SetValue(wxString::FromAscii(text)); break;
+ case IDB_ANALOG_SUB_Y: m_JoyAnalogSubY[controller]->SetValue(wxString::FromAscii(text)); break;
+
+ case IDB_SHOULDER_L: m_JoyShoulderL[controller]->SetValue(wxString::FromAscii(text)); break;
+ case IDB_SHOULDER_R: m_JoyShoulderR[controller]->SetValue(wxString::FromAscii(text)); break;
+
+ case IDB_BUTTON_A: m_JoyButtonA[controller]->SetValue(wxString::FromAscii(text)); break;
+ case IDB_BUTTON_B: m_JoyButtonB[controller]->SetValue(wxString::FromAscii(text)); break;
+ case IDB_BUTTON_X: m_JoyButtonX[controller]->SetValue(wxString::FromAscii(text)); break;
+ case IDB_BUTTON_Y: m_JoyButtonY[controller]->SetValue(wxString::FromAscii(text)); break;
+ case IDB_BUTTON_Z: m_JoyButtonZ[controller]->SetValue(wxString::FromAscii(text)); break;
+ case IDB_BUTTONSTART: m_JoyButtonStart[controller]->SetValue(wxString::FromAscii(text)); break;
+
+ case IDB_BUTTONHALFPRESS: m_JoyButtonHalfpress[controller]->SetValue(wxString::FromAscii(text)); break;
+ default: break;
+ }
+}
+
+// Get the text in the textbox for the buttons
+// ----------------
+wxString PADConfigDialognJoy::GetButtonText(int id, int Page)
+{
+ // Set controller value
+ int controller;
+ if (Page == -1) controller = notebookpage; else controller = Page;
+
+ switch(id)
+ {
+ // D-Pad
+ case IDB_DPAD_RIGHT: return m_JoyDpadRight[controller]->GetValue();
+ case IDB_DPAD_UP: return m_JoyDpadUp[controller]->GetValue();
+ case IDB_DPAD_DOWN: return m_JoyDpadDown[controller]->GetValue();
+ case IDB_DPAD_LEFT: return m_JoyDpadLeft[controller]->GetValue();
+
+ // Analog Stick
+ case IDB_ANALOG_MAIN_X: return m_JoyAnalogMainX[controller]->GetValue();
+ case IDB_ANALOG_MAIN_Y: return m_JoyAnalogMainY[controller]->GetValue();
+ case IDB_ANALOG_SUB_X: return m_JoyAnalogSubX[controller]->GetValue();
+ case IDB_ANALOG_SUB_Y: return m_JoyAnalogSubY[controller]->GetValue();
+
+ // Shoulder Buttons
+ case IDB_SHOULDER_L: return m_JoyShoulderL[controller]->GetValue();
+ case IDB_SHOULDER_R: return m_JoyShoulderR[controller]->GetValue();
+
+ // Buttons
+ case IDB_BUTTON_A: return m_JoyButtonA[controller]->GetValue();
+ case IDB_BUTTON_B: return m_JoyButtonB[controller]->GetValue();
+ case IDB_BUTTON_X: return m_JoyButtonX[controller]->GetValue();
+ case IDB_BUTTON_Y: return m_JoyButtonY[controller]->GetValue();
+ case IDB_BUTTON_Z: return m_JoyButtonZ[controller]->GetValue();
+ case IDB_BUTTONSTART: return m_JoyButtonStart[controller]->GetValue();
+
+ case IDB_BUTTONHALFPRESS: return m_JoyButtonHalfpress[controller]->GetValue();
+ default: return wxString();
+ }
+}
+
+
+
+// Configure button mapping
+// ----------
+
+
+// Wait for button press
+// ---------------------
+/* Loop or timer: There are basically two ways to do this. With a while() or for() loop, or with a
+ timer. The downside with the while() or for() loop is that there is no way to stop it if the user
+ should select to configure another button while we are still in an old loop. What will happen then
+ is that we start another parallel loop (at least in Windows) that blocks the old loop. And our only
+ option to wait for the old loop to finish is with a new loop, and that will block the old loop for as
+ long as it's going on. Therefore a timer is easier to control. */
+void PADConfigDialognJoy::GetButtons(wxCommandEvent& event)
+{
+ DoGetButtons(event.GetId());
+}
+
+void PADConfigDialognJoy::DoGetButtons(int GetId)
+{
+ // =============================================
+ // Collect the starting values
+ // ----------------
+
+ // Get the current controller
+ int Controller = notebookpage;
+ int PadID = PadMapping[Controller].ID;
+
+ // Create a shortcut for the pad handle
+ SDL_Joystick *joy = PadState[Controller].joy;
+
+ // Get the number of axes, hats and buttons
+ int Buttons = SDL_JoystickNumButtons(joy);
+ int Axes = SDL_JoystickNumAxes(joy);
+ int Hats = SDL_JoystickNumHats(joy);
+
+ INFO_LOG(CONSOLE, "PadID: %i Axes: %i\n", PadID, joyinfo[PadID].NumAxes, joyinfo[PadID].joy);
+
+ // Get the controller and trigger type
+ int ControllerType = PadMapping[Controller].controllertype;
+ int TriggerType = PadMapping[Controller].triggertype;
+
+ // Collect the accepted buttons for this slot
+ bool LeftRight = (GetId == IDB_SHOULDER_L || GetId == IDB_SHOULDER_R);
+
+ bool Axis = (GetId >= IDB_ANALOG_MAIN_X && GetId <= IDB_SHOULDER_R)
+ // Don't allow SDL input for the triggers when XInput is selected
+ && !(TriggerType == InputCommon::CTL_TRIGGER_XINPUT && (GetId == IDB_SHOULDER_L || GetId == IDB_SHOULDER_R) );
+
+ bool XInput = (TriggerType == InputCommon::CTL_TRIGGER_XINPUT);
+
+ bool Button = (GetId >= IDB_BUTTON_A && GetId <= IDB_BUTTONHALFPRESS) // All digital buttons
+ || (GetId == IDB_SHOULDER_L || GetId == IDB_SHOULDER_R) // both shoulder buttons
+ || (GetId >= IDB_DPAD_UP && GetId <= IDB_DPAD_RIGHT && ControllerType == InputCommon::CTL_DPAD_CUSTOM); // Or the custom hat mode
+
+ bool Hat = (GetId >= IDB_DPAD_UP && GetId <= IDB_DPAD_RIGHT) // All DPads
+ && (PadMapping[Controller].controllertype == InputCommon::CTL_DPAD_HAT); // Not with the hat option defined
+
+ bool NoTriggerFilter = g_Config.bNoTriggerFilter;
+
+ // Values used in this function
+ char format[128];
+ int Seconds = 4; // Seconds to wait for
+ int TimesPerSecond = 40; // How often to run the check
+
+ // Values returned from InputCommon::GetButton()
+ int value; // Axis value
+ int type; // Button type
+ int pressed = 0;
+ bool Succeed = false;
+ bool Stop = false; // Stop the timer
+ // =======================
+
+ // If the Id has changed or the timer is not running we should start one
+ if( GetButtonWaitingID != GetId || !m_ButtonMappingTimer->IsRunning() )
+ {
+ if(m_ButtonMappingTimer->IsRunning())
+ {
+ m_ButtonMappingTimer->Stop();
+ GetButtonWaitingTimer = 0;
+
+ // Update the old textbox
+ SetButtonText(GetButtonWaitingID, "");
+ }
+
+ // Save the button Id
+ GetButtonWaitingID = GetId;
+
+ // Reset the key in case we happen to have an old one
+ g_Pressed = 0;
+
+ // Update the text box
+ sprintf(format, "[ %d ]", Seconds);
+ SetButtonText(GetId, format);
+
+ // Start the timer
+ #if wxUSE_TIMER
+ m_ButtonMappingTimer->Start(1000 / TimesPerSecond);
+ #endif
+ }
+
+ // ===============================================
+ // Check for buttons
+ // ----------------
+
+ // If there is a timer but we should not create a new one
+ else
+ {
+ InputCommon::GetButton(
+ joy, PadID, Buttons, Axes, Hats,
+ g_Pressed, value, type, pressed, Succeed, Stop,
+ LeftRight, Axis, XInput, Button, Hat, NoTriggerFilter);
+ }
+ // ========================= Check for keys
+
+
+ // ===============================================
+ // Process results
+ // ----------------
+
+ // Count each time
+ GetButtonWaitingTimer++;
+
+ // This is run every second
+ if(GetButtonWaitingTimer % TimesPerSecond == 0)
+ {
+ // Current time
+ int TmpTime = Seconds - (GetButtonWaitingTimer / TimesPerSecond);
+
+ // Update text
+ sprintf(format, "[ %d ]", TmpTime);
+ SetButtonText(GetId, format);
+ }
+
+ // Time's up
+ if( (GetButtonWaitingTimer / TimesPerSecond) >= Seconds )
+ {
+ Stop = true;
+ // Leave a blank mapping
+ if(g_Config.bSaveByID) SetButtonTextAll(GetId, "-1"); else SetButtonText(GetId, "-1");
+ }
+
+ // If we got a button
+ if(Succeed)
+ {
+ Stop = true;
+ // Write the number of the pressed button to the text box
+ sprintf(format, "%d", pressed);
+ if(g_Config.bSaveByID) SetButtonTextAll(GetId, format); else SetButtonText(GetId, format);
+ }
+
+ // Stop the timer
+ if(Stop)
+ {
+ m_ButtonMappingTimer->Stop();
+ GetButtonWaitingTimer = 0;
+
+ /* Update the button mapping for all slots that use this device. (It doesn't make sense to have several slots
+ controlled by the same device, but several DirectInput instances of different but identical devices may possible
+ have the same id, I don't know. So we have to do this. The user may also have selected the same device for
+ several disabled slots. */
+ if(g_Config.bSaveByID) SaveButtonMappingAll(Controller); else SaveButtonMapping(Controller);
+ }
+
+ // If we got a bad button
+ if(g_Pressed == -1)
+ {
+ // Update text
+ if(g_Config.bSaveByID) SetButtonTextAll(GetId, "-1"); else SetButtonText(GetId, "-1");
+
+ // Notify the user
+ wxMessageBox(wxString::Format(
+ wxT("You selected a key with a to low key code (%i), please")
+ wxT(" select another key with a higher key code."), pressed)
+ , wxT("Notice"), wxICON_INFORMATION);
+ }
+}
|
