diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index c6d45b1844..b34f6f6f4e 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -353,6 +353,8 @@ THREAD_RETURN EmuThread(void *pArg) PADInitialize.hWnd = g_pWindowHandle; PADInitialize.pLog = Callback_PADLog; PADInitialize.padNumber = i; + // This is may be needed to avoid a SDL problem + //Plugins.FreeWiimote(); // Check if we should init the plugin if (Plugins.OkayToInitPlugin(i)) { diff --git a/Source/Core/Core/Src/PluginManager.cpp b/Source/Core/Core/Src/PluginManager.cpp index 6dfd67e1c0..c81cbac080 100644 --- a/Source/Core/Core/Src/PluginManager.cpp +++ b/Source/Core/Core/Src/PluginManager.cpp @@ -457,11 +457,19 @@ void CPluginManager::FreeDSP() delete m_dsp; m_dsp = NULL; } -void CPluginManager::FreePad(u32 pad) +void CPluginManager::FreePad(u32 Pad) { - if (pad < MAXPADS) { - delete m_pad[pad]; - m_pad[pad] = NULL; + if (Pad < MAXPADS) { + delete m_pad[Pad]; + m_pad[Pad] = NULL; + } +} +void CPluginManager::FreeWiimote(u32 Wiimote) +{ + if (Wiimote < MAXWIIMOTES) + { + delete m_wiimote[Wiimote]; + m_wiimote[Wiimote] = NULL; } } /////////////////////////////////////////// diff --git a/Source/Core/Core/Src/PluginManager.h b/Source/Core/Core/Src/PluginManager.h index d20ac9b076..e3b4aebbeb 100644 --- a/Source/Core/Core/Src/PluginManager.h +++ b/Source/Core/Core/Src/PluginManager.h @@ -54,7 +54,8 @@ public: void FreeVideo(); void FreeDSP(); - void FreePad(u32 pad); + void FreePad(u32 Pad); + void FreeWiimote(u32 Wiimote); bool InitPlugins(); void ShutdownPlugins(); diff --git a/Source/Core/InputCommon/Src/SDL.cpp b/Source/Core/InputCommon/Src/SDL.cpp index 286ccf0fc1..67c4b97b31 100644 --- a/Source/Core/InputCommon/Src/SDL.cpp +++ b/Source/Core/InputCommon/Src/SDL.cpp @@ -231,4 +231,134 @@ void GetJoyState(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, in + +////////////////////////////////////////////////////////////////////////////////////////// +// Configure button mapping +// ŻŻŻŻŻŻŻŻŻŻ + +// Avoid extreme axis values +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +/* Function: We have to avoid very big values to becuse some triggers are -0x8000 in the + unpressed state (and then go from -0x8000 to 0x8000 as they are fully pressed) */ +bool AvoidValues(int value) +{ + // Avoid detecting very small or very big (for triggers) values + if( (value > -0x2000 && value < 0x2000) // Small values + || (value < -0x6000 || value > 0x6000)) // Big values + return true; // Avoid + else + return false; // Keep +} + + +// Detect a pressed button +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void GetButton(SDL_Joystick *joy, int ControllerID, int buttons, int axes, int hats, + int &KeyboardKey, int &value, int &type, int &pressed, bool &Succeed, bool &Stop, + bool LeftRight, bool Axis, bool XInput, bool Button, bool Hat) +{ + // It needs the wxWidgets excape keycode + static const int WXK_ESCAPE = 27; + + // Update the internal status + SDL_JoystickUpdate(); + + // For the triggers we accept both a digital or an analog button + if(Axis) + { + for(int i = 0; i < axes; i++) + { + value = SDL_JoystickGetAxis(joy, i); + + if(AvoidValues(value)) continue; // Avoid values + + pressed = i + (LeftRight ? 1000 : 0); // Identify the analog triggers + type = InputCommon::CTL_AXIS; + Succeed = true; + } + Console::Print("Id: %i\n", joy); + } + + // Check for a hat + if(Hat) + { + for(int i = 0; i < hats; i++) + { + if(SDL_JoystickGetHat(joy, i)) + { + pressed = i; + type = InputCommon::CTL_HAT; + Succeed = true; + } + } + } + + // Check for a button + if(Button) + { + for(int i = 0; i < buttons; i++) + { + // Some kind of bug in SDL 1.3 would give button 9 and 10 (nonexistent) the value 48 on the 360 pad + if (SDL_JoystickGetButton(joy, i) > 1) continue; + + if(SDL_JoystickGetButton(joy, i)) + { + pressed = i; + type = InputCommon::CTL_BUTTON; + Succeed = true; + } + } + } + + // Check for a XInput trigger + #ifdef _WIN32 + if(XInput) + { + for(int i = 0; i <= InputCommon::XI_TRIGGER_R; i++) + { + if(XInput::GetXI(0, i)) + { + pressed = i + 1000; + type = InputCommon::CTL_AXIS; + Succeed = true; + } + } + } + #endif + + // Check for keyboard action + if (KeyboardKey) + { + if(Button) + { + // Todo: Add a separate keyboard vector to remove this restriction + if(KeyboardKey >= buttons) + { + pressed = KeyboardKey; + type = InputCommon::CTL_BUTTON; + Succeed = true; + KeyboardKey = 0; + if(pressed == WXK_ESCAPE) pressed = -1; // Check for the escape key + } + // Else show the error message + else + { + pressed = KeyboardKey; + KeyboardKey = -1; + Stop = true; + } + } + // Only accept the escape key + else + { + Succeed = true; + KeyboardKey = 0; + pressed = -1; + } + } +} +/////////////////////////////////////////////////////////// Configure button mapping + + + } // InputCommon \ No newline at end of file diff --git a/Source/Core/InputCommon/Src/SDL.h b/Source/Core/InputCommon/Src/SDL.h index 02305df771..3fb9d8b06d 100644 --- a/Source/Core/InputCommon/Src/SDL.h +++ b/Source/Core/InputCommon/Src/SDL.h @@ -41,6 +41,7 @@ #include // Externals #include "Common.h" // Common +#include "ConsoleWindow.h" //////////////////////////// @@ -148,6 +149,34 @@ enum XI_TRIGGER_L = 0, XI_TRIGGER_R }; + + +struct PadAxis +{ + int Lx; + int Ly; + int Rx; + int Ry; + int Tl; // Triggers + int Tr; +}; +struct CONTROLLER_STATE_NEW // GC PAD INFO/STATE +{ + PadAxis Axis; // 6 Axes (Main, Sub, Triggers) + SDL_Joystick *joy; // SDL joystick device +}; + +struct CONTROLLER_MAPPING_NEW // GC PAD MAPPING +{ + PadAxis Axis; // (See above) + bool enabled; // Pad attached? + int deadzone; // Deadzone... what else? + int ID; // SDL joystick device ID + int controllertype; // D-Pad type: Hat or custom buttons + int triggertype; // SDL or XInput trigger + std::string SDiagonal; + bool bSquareToCircle; +}; //////////////////////////// @@ -158,6 +187,7 @@ enum // General functions bool SearchDevices(std::vector &_joyinfo, int &NumPads, int &NumGoodPads); void GetJoyState(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, int controller, int NumButtons); +void GetButton(SDL_Joystick*, int,int,int,int, int&,int&,int&,int&,bool&,bool&, bool,bool,bool,bool,bool); // Value conversion int Pad_Convert(int _val); diff --git a/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj b/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj index cd2b348ed1..0e0ebf7c0e 100644 --- a/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj +++ b/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj @@ -550,6 +550,10 @@ RelativePath=".\Src\EmuMain.h" > + + @@ -610,6 +614,10 @@ RelativePath=".\Src\ConfigDlg.h" > + + diff --git a/Source/Plugins/Plugin_Wiimote/Src/Config.cpp b/Source/Plugins/Plugin_Wiimote/Src/Config.cpp index 5ac786b58c..bcdf87cdb1 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/Config.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/Config.cpp @@ -18,7 +18,9 @@ #include "Common.h" #include "IniFile.h" + #include "Config.h" +#include "EmuDefinitions.h" // for PadMapping Config g_Config; @@ -27,7 +29,7 @@ Config::Config() memset(this, 0, sizeof(Config)); } -void Config::Load() +void Config::Load(bool ChangePad) { std::string temp; IniFile iniFile; @@ -49,6 +51,49 @@ void Config::Load() iniFile.Get("Real", "AccNunNeutralX", &iAccNunNeutralX, 0); iniFile.Get("Real", "AccNunNeutralY", &iAccNunNeutralY, 0); iniFile.Get("Real", "AccNunNeutralZ", &iAccNunNeutralZ, 0); + + + for (int i = 0; i < 1; i++) + { + // ================================================================== + // Slot specific settings + // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ + std::string SectionName = StringFromFormat("Wiimote%i", i + 1); + + // Don't update this when we are loading settings from the ConfigBox + if(!ChangePad) + { + iniFile.Get(SectionName.c_str(), "DeviceID", &WiiMoteEmu::PadMapping[i].ID, 0); + iniFile.Get(SectionName.c_str(), "Enabled", &WiiMoteEmu::PadMapping[i].enabled, true); + } + // =================== + + // ================================================================== + // Joypad specific settings + // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ + // Current joypad device ID: PadMapping[i].ID + // Current joypad name: joyinfo[PadMapping[i].ID].Name + + /* Prevent a crash from illegal access to joyinfo that will only have values for + the current amount of connected PadMapping */ + if(WiiMoteEmu::PadMapping[i].ID >= SDL_NumJoysticks()) continue; + + // Create a section name + SectionName = WiiMoteEmu::joyinfo[WiiMoteEmu::PadMapping[i].ID].Name; + + iniFile.Get(SectionName.c_str(), "left_x", &WiiMoteEmu::PadMapping[i].Axis.Lx, 0); + iniFile.Get(SectionName.c_str(), "left_y", &WiiMoteEmu::PadMapping[i].Axis.Ly, 1); + iniFile.Get(SectionName.c_str(), "right_x", &WiiMoteEmu::PadMapping[i].Axis.Rx, 2); + iniFile.Get(SectionName.c_str(), "right_y", &WiiMoteEmu::PadMapping[i].Axis.Ry, 3); + iniFile.Get(SectionName.c_str(), "l_trigger", &WiiMoteEmu::PadMapping[i].Axis.Tl, 4); + iniFile.Get(SectionName.c_str(), "r_trigger", &WiiMoteEmu::PadMapping[i].Axis.Tr, 5); + iniFile.Get(SectionName.c_str(), "DeadZone", &WiiMoteEmu::PadMapping[i].deadzone, 0); + iniFile.Get(SectionName.c_str(), "TriggerType", &WiiMoteEmu::PadMapping[i].triggertype, 0); + iniFile.Get(SectionName.c_str(), "Diagonal", &WiiMoteEmu::PadMapping[i].SDiagonal, "100%"); + iniFile.Get(SectionName.c_str(), "SquareToCircle", &WiiMoteEmu::PadMapping[i].bSquareToCircle, false); + } + // ============================= + Console::Print("Load()\n"); } void Config::Save() @@ -70,5 +115,47 @@ void Config::Save() iniFile.Set("Real", "AccNunNeutralY", iAccNunNeutralY); iniFile.Set("Real", "AccNunNeutralZ", iAccNunNeutralZ); + + for (int i = 0; i < 1; i++) + { + // ================================================================== + // Slot specific settings + // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ + std::string SectionName = StringFromFormat("Wiimote%i", i + 1); + iniFile.Set(SectionName.c_str(), "Enabled", WiiMoteEmu::PadMapping[i].enabled); + + // Save the physical device ID number + iniFile.Set(SectionName.c_str(), "DeviceID", WiiMoteEmu::PadMapping[i].ID); + // =================== + + // ================================================================== + // Joypad specific settings + // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ + // Current joypad device ID: PadMapping[i].ID + // Current joypad name: joyinfo[PadMapping[i].ID].Name + + /* Save joypad specific settings. Check for "PadMapping[i].ID < SDL_NumJoysticks()" to + avoid reading a joyinfo that does't exist */ + if(WiiMoteEmu::PadMapping[i].ID >= SDL_NumJoysticks()) continue; + + // Create a new section name after the joypad name + SectionName = WiiMoteEmu::joyinfo[WiiMoteEmu::PadMapping[i].ID].Name; + + iniFile.Set(SectionName.c_str(), "left_x", WiiMoteEmu::PadMapping[i].Axis.Lx); + iniFile.Set(SectionName.c_str(), "left_y", WiiMoteEmu::PadMapping[i].Axis.Ly); + iniFile.Set(SectionName.c_str(), "right_x", WiiMoteEmu::PadMapping[i].Axis.Rx); + iniFile.Set(SectionName.c_str(), "right_y", WiiMoteEmu::PadMapping[i].Axis.Ry); + iniFile.Set(SectionName.c_str(), "l_trigger", WiiMoteEmu::PadMapping[i].Axis.Tl); + iniFile.Set(SectionName.c_str(), "r_trigger", WiiMoteEmu::PadMapping[i].Axis.Tr); + + //iniFile.Set(SectionName.c_str(), "deadzone", PadMapping[i].deadzone); + //iniFile.Set(SectionName.c_str(), "controllertype", PadMapping[i].controllertype); + iniFile.Set(SectionName.c_str(), "TriggerType", WiiMoteEmu::PadMapping[i].triggertype); + //iniFile.Set(SectionName.c_str(), "Diagonal", PadMapping[i].SDiagonal); + //iniFile.Set(SectionName.c_str(), "SquareToCircle", PadMapping[i].bSquareToCircle); + // ====================================== + } + iniFile.Save(FULL_CONFIG_DIR "Wiimote.ini"); + Console::Print("Save()\n"); } diff --git a/Source/Plugins/Plugin_Wiimote/Src/Config.h b/Source/Plugins/Plugin_Wiimote/Src/Config.h index 30a0a77e94..5e10225603 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/Config.h +++ b/Source/Plugins/Plugin_Wiimote/Src/Config.h @@ -21,7 +21,7 @@ struct Config { Config(); - void Load(); + void Load(bool ChangePad = false); void Save(); // Emulated Wiimote diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp index a835dac77d..1896cd28cd 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp @@ -66,6 +66,7 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog) EVT_CHECKBOX(ID_UPDATE_REAL, ConfigDialog::GeneralSettingsChanged) EVT_CHOICE(ID_NEUTRAL_CHOICE, ConfigDialog::GeneralSettingsChanged) + // Recording EVT_CHOICE(IDC_RECORD + 1, ConfigDialog::GeneralSettingsChanged) EVT_CHOICE(IDC_RECORD + 2, ConfigDialog::GeneralSettingsChanged) EVT_CHOICE(IDC_RECORD + 3, ConfigDialog::GeneralSettingsChanged) @@ -98,9 +99,21 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog) EVT_BUTTON(IDB_RECORD + 14, ConfigDialog::RecordMovement) EVT_BUTTON(IDB_RECORD + 15, ConfigDialog::RecordMovement) + // Gamepad + EVT_COMBOBOX(ID_TRIGGER_TYPE, ConfigDialog::GeneralSettingsChanged) + + EVT_BUTTON(IDB_ANALOG_LEFT_X, ConfigDialog::GetButtons) + EVT_BUTTON(IDB_ANALOG_LEFT_Y, ConfigDialog::GetButtons) + EVT_BUTTON(IDB_ANALOG_RIGHT_X, ConfigDialog::GetButtons) + EVT_BUTTON(IDB_ANALOG_RIGHT_Y, ConfigDialog::GetButtons) + EVT_BUTTON(IDB_TRIGGER_L, ConfigDialog::GetButtons) + EVT_BUTTON(IDB_TRIGGER_R, ConfigDialog::GetButtons) + EVT_TIMER(IDTM_UPDATE, ConfigDialog::Update) EVT_TIMER(IDTM_UPDATE_ONCE, ConfigDialog::UpdateOnce) EVT_TIMER(IDTM_SHUTDOWN, ConfigDialog::ShutDown) + EVT_TIMER(IDTM_BUTTON, ConfigDialog::OnButtonTimer) + EVT_TIMER(IDTM_UPDATE_PAD, ConfigDialog::UpdatePad) END_EVENT_TABLE() ////////////////////////////////////// @@ -116,9 +129,17 @@ ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &titl m_TimeoutTimer = new wxTimer(this, IDTM_UPDATE); m_ShutDownTimer = new wxTimer(this, IDTM_SHUTDOWN); m_TimeoutOnce = new wxTimer(this, IDTM_UPDATE_ONCE); + m_ButtonMappingTimer = new wxTimer(this, IDTM_BUTTON); + m_UpdatePad = new wxTimer(this, IDTM_UPDATE_PAD); + // Reset values m_bWaitForRecording = false; m_bRecording = false; + GetButtonWaitingID = 0; GetButtonWaitingTimer = 0; + + // Start the permanent timer + const int TimesPerSecond = 30; + m_UpdatePad->Start( floor((double)(1000 / TimesPerSecond)) ); #endif ControlsCreated = false; @@ -134,6 +155,9 @@ ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &titl wxTheApp->Connect(wxID_ANY, wxEVT_KEY_DOWN, // Keyboard wxKeyEventHandler(ConfigDialog::OnKeyDown), (wxObject*)0, this); + wxTheApp->Connect(wxID_ANY, wxEVT_KEY_UP, + wxKeyEventHandler(ConfigDialog::OnKeyDown), + (wxObject*)0, this); } ConfigDialog::~ConfigDialog() @@ -144,6 +168,9 @@ void ConfigDialog::OnKeyDown(wxKeyEvent& event) { event.Skip(); + // Save the key + g_Pressed = event.GetKeyCode(); + // Escape a recording event if (event.GetKeyCode() == WXK_ESCAPE) { @@ -156,6 +183,7 @@ void ConfigDialog::OnKeyDown(wxKeyEvent& event) void ConfigDialog::OnClose(wxCloseEvent& event) { g_FrameOpen = false; + m_UpdatePad->Stop(); SaveFile(); g_Config.Save(); //SuccessAlert("Saved\n"); @@ -195,6 +223,8 @@ void ConfigDialog::CloseClick(wxCommandEvent& event) } break; case ID_APPLY: + SaveButtonMappingAll(Page); + g_Config.Save(); SaveFile(); WiiMoteEmu::LoadRecordedMovements(); break; @@ -329,20 +359,23 @@ void ConfigDialog::CreateGUIControls() // General and basic Settings // ---------------- + // Configuration controls + static const int TxtW = 50, TxtH = 19, ChW = 245; + // Basic Settings - m_WiimoteOnline[i] = new wxCheckBox(m_Controller[i], IDC_JOYATTACH, wxT("Wiimote On"), wxDefaultPosition, wxSize(263, -1)); + m_WiimoteOnline[i] = new wxCheckBox(m_Controller[i], IDC_JOYATTACH, wxT("Wiimote On"), wxDefaultPosition, wxSize(ChW, -1)); // Emulated Wiimote - m_SidewaysDPad[i] = new wxCheckBox(m_Controller[i], ID_SIDEWAYSDPAD, wxT("Sideways D-Pad"), wxDefaultPosition, wxSize(263, -1)); + m_SidewaysDPad[i] = new wxCheckBox(m_Controller[i], ID_SIDEWAYSDPAD, wxT("Sideways D-Pad"), wxDefaultPosition, wxSize(ChW, -1)); m_WideScreen[i] = new wxCheckBox(m_Controller[i], ID_WIDESCREEN, wxT("WideScreen Mode (for correct aiming)")); // Extension - m_WiiMotionPlusConnected[i] = new wxCheckBox(m_Controller[i], wxID_ANY, wxT("Wii Motion Plus Connected"), wxDefaultPosition, wxSize(263, -1), 0, wxDefaultValidator); + m_WiiMotionPlusConnected[i] = new wxCheckBox(m_Controller[i], wxID_ANY, wxT("Wii Motion Plus Connected"), wxDefaultPosition, wxSize(ChW, -1), 0, wxDefaultValidator); m_NunchuckConnected[i] = new wxCheckBox(m_Controller[i], ID_NUNCHUCKCONNECTED, wxT("Nunchuck Connected")); m_ClassicControllerConnected[i] = new wxCheckBox(m_Controller[i], ID_CLASSICCONTROLLERCONNECTED, wxT("Classic Controller Connected")); m_BalanceBoardConnected[i] = new wxCheckBox(m_Controller[i], wxID_ANY, wxT("Balance Board Connected")); m_GuitarHeroGuitarConnected[i] = new wxCheckBox(m_Controller[i], wxID_ANY, wxT("Guitar Hero Guitar Connected")); m_GuitarHeroWorldTourDrumsConnected[i] = new wxCheckBox(m_Controller[i], wxID_ANY, wxT("Guitar Hero World Tour Drums Connected")); // Real Wiimote - m_ConnectRealWiimote[i] = new wxCheckBox(m_Controller[i], ID_CONNECT_REAL, wxT("Connect Real Wiimote"), wxDefaultPosition, wxSize(263, -1)); + m_ConnectRealWiimote[i] = new wxCheckBox(m_Controller[i], ID_CONNECT_REAL, wxT("Connect Real Wiimote"), wxDefaultPosition, wxSize(ChW, -1)); m_UseRealWiimote[i] = new wxCheckBox(m_Controller[i], ID_USE_REAL, wxT("Use Real Wiimote")); // Default values @@ -416,7 +449,7 @@ void ConfigDialog::CreateGUIControls() // ----------------------------- /**/ // Controls - m_Joyname[i] = new wxComboBox(m_Controller[i], IDC_JOYNAME, StrJoyname[0], wxDefaultPosition, wxSize(445, -1), StrJoyname, wxCB_READONLY); + m_Joyname[i] = new wxComboBox(m_Controller[i], IDC_JOYNAME, StrJoyname[0], wxDefaultPosition, wxSize(225, -1), StrJoyname, wxCB_READONLY); m_gJoyname[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Gamepad")); m_gJoyname[i]->Add(m_Joyname[i], 0, wxALIGN_CENTER | (wxLEFT | wxRIGHT | wxDOWN), 5); @@ -440,48 +473,129 @@ void ConfigDialog::CreateGUIControls() m_gTilt[i] = new wxStaticBoxSizer (wxVERTICAL, m_Controller[i], wxT("Tilt Wiimote")); - m_gTilt[i]->Add(m_TiltCombo[i], 0, (wxLEFT | wxRIGHT | wxDOWN), 5); - m_gTilt[i]->Add(m_TiltHoriz[i], 0, (wxLEFT | wxRIGHT), 5); + m_gTilt[i]->AddStretchSpacer(); + m_gTilt[i]->Add(m_TiltCombo[i], 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5); + m_gTilt[i]->Add(m_TiltHoriz[i], 0, wxEXPAND | (wxLEFT | wxRIGHT), 5); + m_gTilt[i]->AddStretchSpacer(); // Tooltips m_TiltCombo[i]->SetToolTip(wxT("Control tilting by an analog gamepad stick, an analog trigger or the keyboard.")); - // Sizers for both the connected pads and tilt + // -------------------------------------------------------------------- + // Analog triggers + // ----------------------------- + /**/ + m_gTrigger[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Triggers")); + + m_TriggerStatusL[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("Left: ")); + m_TriggerStatusR[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("Right: ")); + m_TriggerStatusLx[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("000"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); + m_TriggerStatusRx[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("000"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); + + m_tAnalogTriggerInput[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Input")); + m_tAnalogTriggerL[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Left")); + m_tAnalogTriggerR[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Right")); + + m_AnalogTriggerL[i] = new wxTextCtrl(m_Controller[i], ID_TRIGGER_L, wxT(""), wxDefaultPosition, wxSize(TxtW, TxtH), wxTE_READONLY | wxTE_CENTRE); + m_AnalogTriggerR[i] = new wxTextCtrl(m_Controller[i], ID_TRIGGER_R, wxT(""), wxDefaultPosition, wxSize(TxtW, TxtH), wxTE_READONLY | wxTE_CENTRE); + + m_AnalogTriggerL[i]->Enable(false); + m_AnalogTriggerR[i]->Enable(false); + + m_bAnalogTriggerL[i] = new wxButton(m_Controller[i], IDB_TRIGGER_L, wxEmptyString, wxDefaultPosition, wxSize(21, 14)); + m_bAnalogTriggerR[i] = new wxButton(m_Controller[i], IDB_TRIGGER_R, wxEmptyString, wxDefaultPosition, wxSize(21, 14)); + + m_TriggerType[i] = new wxComboBox(m_Controller[i], ID_TRIGGER_TYPE, StrTriggerType[0], wxDefaultPosition, wxDefaultSize, StrTriggerType, wxCB_READONLY); + + m_SizeAnalogTriggerStatusBox[i] = new wxGridBagSizer(0, 0); + m_SizeAnalogTriggerHorizConfig[i] = new wxGridBagSizer(0, 0); + m_SizeAnalogTriggerVertLeft[i] = new wxBoxSizer(wxVERTICAL); + m_SizeAnalogTriggerVertRight[i] = new wxBoxSizer(wxVERTICAL); + m_SizeAnalogTriggerHorizInput[i] = new wxBoxSizer(wxHORIZONTAL); + + // The status text boxes + m_SizeAnalogTriggerStatusBox[i]->Add(m_TriggerStatusL[i], wxGBPosition(0, 0), wxGBSpan(1, 1), (wxUP), 0); + m_SizeAnalogTriggerStatusBox[i]->Add(m_TriggerStatusLx[i], wxGBPosition(0, 1), wxGBSpan(1, 1), (wxUP), 0); + m_SizeAnalogTriggerStatusBox[i]->Add(m_TriggerStatusR[i], wxGBPosition(1, 0), wxGBSpan(1, 1), (wxUP), 0); + m_SizeAnalogTriggerStatusBox[i]->Add(m_TriggerStatusRx[i], wxGBPosition(1, 1), wxGBSpan(1, 1), (wxUP), 0); + + m_SizeAnalogTriggerHorizConfig[i]->Add(m_tAnalogTriggerL[i], wxGBPosition(0, 0), wxGBSpan(1, 1), (wxUP), 2); + m_SizeAnalogTriggerHorizConfig[i]->Add(m_AnalogTriggerL[i], wxGBPosition(0, 1), wxGBSpan(1, 1), (wxLEFT | wxRIGHT), 2); + m_SizeAnalogTriggerHorizConfig[i]->Add(m_bAnalogTriggerL[i], wxGBPosition(0, 2), wxGBSpan(1, 1), (wxUP), 2); + m_SizeAnalogTriggerHorizConfig[i]->Add(m_tAnalogTriggerR[i], wxGBPosition(1, 0), wxGBSpan(1, 1), (wxUP), 4); + m_SizeAnalogTriggerHorizConfig[i]->Add(m_AnalogTriggerR[i], wxGBPosition(1, 1), wxGBSpan(1, 1), (wxLEFT | wxUP | wxRIGHT), 2); + m_SizeAnalogTriggerHorizConfig[i]->Add(m_bAnalogTriggerR[i], wxGBPosition(1, 2), wxGBSpan(1, 1), (wxUP), 5); + + // The choice box and its name label + m_SizeAnalogTriggerHorizInput[i]->Add(m_tAnalogTriggerInput[i], 0, (wxUP), 2); + m_SizeAnalogTriggerHorizInput[i]->Add(m_TriggerType[i], 0, (wxLEFT), 2); + + // The status text boxes + m_SizeAnalogTriggerVertLeft[i]->AddStretchSpacer(); + m_SizeAnalogTriggerVertLeft[i]->Add(m_SizeAnalogTriggerStatusBox[i]); + m_SizeAnalogTriggerVertLeft[i]->AddStretchSpacer(); + + // The config grid and the input type choice box + m_SizeAnalogTriggerVertRight[i]->Add(m_SizeAnalogTriggerHorizConfig[i], 0, (wxUP), 0); + m_SizeAnalogTriggerVertRight[i]->Add(m_SizeAnalogTriggerHorizInput[i], 0, (wxUP | wxDOWN), 4); + + m_gTrigger[i]->Add(m_SizeAnalogTriggerVertLeft[i], 0, wxEXPAND | (wxLEFT | wxRIGHT), 5); + m_gTrigger[i]->Add(m_SizeAnalogTriggerVertRight[i], 0, (wxLEFT | wxRIGHT), 5); + + + // -------------------------------------------------------------------- + // Row 2 Sizers: Connected pads, tilt, triggers + // ----------------------------- m_HorizControllerTilt[i] = new wxBoxSizer(wxHORIZONTAL); m_HorizControllerTilt[i]->Add(m_gJoyname[i], 0, wxALIGN_CENTER | wxEXPAND, 0); - m_HorizControllerTilt[i]->Add(m_gTilt[i], 0, (wxLEFT), 5); + m_HorizControllerTilt[i]->Add(m_gTilt[i], 0, wxEXPAND | (wxLEFT), 5); + m_HorizControllerTilt[i]->Add(m_gTrigger[i], 0, (wxLEFT), 5); m_HorizControllerTiltParent[i] = new wxBoxSizer(wxBOTH); m_HorizControllerTiltParent[i]->Add(m_HorizControllerTilt[i]); + + // -------------------------------------------------------------------- // Analog sticks // ----------------------------- - /**/ - m_pInStatus[i] = new wxPanel(m_Controller[i], wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_bmpSquare[i] = new wxStaticBitmap(m_pInStatus[i], wxID_ANY, CreateBitmap(), wxDefaultPosition, wxDefaultSize); - m_bmpDot[i] = new wxStaticBitmap(m_pInStatus[i], wxID_ANY, CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize); + + // Status panels + m_TStatusLeftIn[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("In")); + m_TStatusLeftOut[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Out")); + m_TStatusRightIn[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("In")); + m_TStatusRightOut[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Out")); - m_pRightStatus[i] = new wxPanel(m_Controller[i], wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_bmpSquareRight[i] = new wxStaticBitmap(m_pRightStatus[i], wxID_ANY, CreateBitmap(), wxDefaultPosition, wxDefaultSize); - m_bmpDotRight[i] = new wxStaticBitmap(m_pRightStatus[i], wxID_ANY, CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize); + m_pLeftInStatus[i] = new wxPanel(m_Controller[i], wxID_ANY, wxDefaultPosition, wxDefaultSize); + m_bmpSquareLeftIn[i] = new wxStaticBitmap(m_pLeftInStatus[i], wxID_ANY, CreateBitmap(), wxDefaultPosition, wxDefaultSize); + m_bmpDotLeftIn[i] = new wxStaticBitmap(m_pLeftInStatus[i], wxID_ANY, CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize); - static const int TxtW = 50; static const int TxtH = 19; + m_pLeftOutStatus[i] = new wxPanel(m_Controller[i], wxID_ANY, wxDefaultPosition, wxDefaultSize); + m_bmpSquareLeftOut[i] = new wxStaticBitmap(m_pLeftOutStatus[i], wxID_ANY, CreateBitmap(), wxDefaultPosition, wxDefaultSize); + m_bmpDotLeftOut[i] = new wxStaticBitmap(m_pLeftOutStatus[i], wxID_ANY, CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize); - m_AnalogLeftX[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_LEFT, wxT(""), wxDefaultPosition, wxSize(TxtW, TxtH), wxTE_READONLY | wxTE_CENTRE); - m_AnalogLeftY[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_LEFT, wxT(""), wxDefaultPosition, wxSize(TxtW, TxtH), wxTE_READONLY | wxTE_CENTRE); - m_AnalogRightX[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_RIGHT, wxT(""), wxDefaultPosition, wxSize(TxtW, TxtH), wxTE_READONLY | wxTE_CENTRE); - m_AnalogRightY[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_RIGHT, wxT(""), wxDefaultPosition, wxSize(TxtW, TxtH), wxTE_READONLY | wxTE_CENTRE); + m_pRightInStatus[i] = new wxPanel(m_Controller[i], wxID_ANY, wxDefaultPosition, wxDefaultSize); + m_bmpSquareRightIn[i] = new wxStaticBitmap(m_pRightInStatus[i], wxID_ANY, CreateBitmap(), wxDefaultPosition, wxDefaultSize); + m_bmpDotRightIn[i] = new wxStaticBitmap(m_pRightInStatus[i], wxID_ANY, CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize); + + m_pRightOutStatus[i] = new wxPanel(m_Controller[i], wxID_ANY, wxDefaultPosition, wxDefaultSize); + m_bmpSquareRightOut[i] = new wxStaticBitmap(m_pRightOutStatus[i], wxID_ANY, CreateBitmap(), wxDefaultPosition, wxDefaultSize); + m_bmpDotRightOut[i] = new wxStaticBitmap(m_pRightOutStatus[i], wxID_ANY, CreateBitmapDot(), wxPoint(BoxW / 2, BoxH / 2), wxDefaultSize); + + m_AnalogLeftX[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_LEFT_X, wxT(""), wxDefaultPosition, wxSize(TxtW, TxtH), wxTE_READONLY | wxTE_CENTRE); + m_AnalogLeftY[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_LEFT_Y, wxT(""), wxDefaultPosition, wxSize(TxtW, TxtH), wxTE_READONLY | wxTE_CENTRE); + m_AnalogRightX[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_RIGHT_X, wxT(""), wxDefaultPosition, wxSize(TxtW, TxtH), wxTE_READONLY | wxTE_CENTRE); + m_AnalogRightY[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_RIGHT_Y, wxT(""), wxDefaultPosition, wxSize(TxtW, TxtH), wxTE_READONLY | wxTE_CENTRE); m_AnalogLeftX[i]->Enable(false); m_AnalogLeftY[i]->Enable(false); m_AnalogRightX[i]->Enable(false); m_AnalogRightY[i]->Enable(false); - m_bAnalogLeftX[i] = new wxButton(m_Controller[i], IDB_ANALOG_LEFT, wxEmptyString, wxDefaultPosition, wxSize(21, 14)); - m_bAnalogLeftY[i] = new wxButton(m_Controller[i], IDB_ANALOG_LEFT, wxEmptyString, wxDefaultPosition, wxSize(21, 14)); - m_bAnalogRightX[i] = new wxButton(m_Controller[i], IDB_ANALOG_RIGHT, wxEmptyString, wxDefaultPosition, wxSize(21, 14)); - m_bAnalogRightY[i] = new wxButton(m_Controller[i], IDB_ANALOG_RIGHT, wxEmptyString, wxDefaultPosition, wxSize(21, 14)); + m_bAnalogLeftX[i] = new wxButton(m_Controller[i], IDB_ANALOG_LEFT_X, wxEmptyString, wxDefaultPosition, wxSize(21, 14)); + m_bAnalogLeftY[i] = new wxButton(m_Controller[i], IDB_ANALOG_LEFT_Y, wxEmptyString, wxDefaultPosition, wxSize(21, 14)); + m_bAnalogRightX[i] = new wxButton(m_Controller[i], IDB_ANALOG_RIGHT_X, wxEmptyString, wxDefaultPosition, wxSize(21, 14)); + m_bAnalogRightY[i] = new wxButton(m_Controller[i], IDB_ANALOG_RIGHT_Y, wxEmptyString, wxDefaultPosition, wxSize(21, 14)); m_SizeAnalogLeft[i] = new wxBoxSizer(wxVERTICAL); m_SizeAnalogLeftHorizX[i] = new wxBoxSizer(wxHORIZONTAL); m_SizeAnalogLeftHorizY[i] = new wxBoxSizer(wxHORIZONTAL); m_SizeAnalogRight[i] = new wxBoxSizer(wxVERTICAL); m_SizeAnalogRightHorizX[i] = new wxBoxSizer(wxHORIZONTAL); m_SizeAnalogRightHorizY[i] = new wxBoxSizer(wxHORIZONTAL); @@ -491,6 +605,7 @@ void ConfigDialog::CreateGUIControls() m_tAnalogY[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Y-Axis")); m_tAnalogY[i + 4] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Y-Axis")); + // Configuration sizers m_SizeAnalogLeftHorizX[i]->Add(m_tAnalogX[i], 0, (wxUP), 2); m_SizeAnalogLeftHorizX[i]->Add(m_AnalogLeftX[i], 0, (wxRIGHT), 2); m_SizeAnalogLeftHorizX[i]->Add(m_bAnalogLeftX[i], 0, (wxUP), 2); @@ -514,76 +629,34 @@ void ConfigDialog::CreateGUIControls() m_SizeAnalogRight[i]->Add(m_SizeAnalogRightHorizY[i], 0, (wxUP), 0); m_SizeAnalogRight[i]->AddStretchSpacer(); - m_gAnalogLeft[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Analog 1")); - m_gAnalogLeft[i]->Add(m_pInStatus[i], 0, (wxLEFT | wxRIGHT), 5); + // Status sizers + m_GridLeftStick[i] = new wxGridBagSizer(0, 0); + m_GridLeftStick[i]->Add(m_pLeftInStatus[i], wxGBPosition(0, 0), wxGBSpan(1, 1), wxALL, 0); + m_GridLeftStick[i]->Add(m_pLeftOutStatus[i], wxGBPosition(0, 1), wxGBSpan(1, 1), wxLEFT, 5); + m_GridLeftStick[i]->Add(m_TStatusLeftIn[i], wxGBPosition(1, 0), wxGBSpan(1, 1), wxALL, 0); + m_GridLeftStick[i]->Add(m_TStatusLeftOut[i], wxGBPosition(1, 1), wxGBSpan(1, 1), wxLEFT, 5); + + m_GridRightStick[i] = new wxGridBagSizer(0, 0); + m_GridRightStick[i]->Add(m_pRightInStatus[i], wxGBPosition(0, 0), wxGBSpan(1, 1), wxALL, 0); + m_GridRightStick[i]->Add(m_pRightOutStatus[i], wxGBPosition(0, 1), wxGBSpan(1, 1), wxLEFT, 5); + m_GridRightStick[i]->Add(m_TStatusRightIn[i], wxGBPosition(1, 0), wxGBSpan(1, 1), wxALL, 0); + m_GridRightStick[i]->Add(m_TStatusRightOut[i], wxGBPosition(1, 1), wxGBSpan(1, 1), wxLEFT, 5); + + m_gAnalogLeft[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Analog 1 (In) (Out)")); + m_gAnalogLeft[i]->Add(m_GridLeftStick[i], 0, (wxLEFT | wxRIGHT), 5); m_gAnalogLeft[i]->Add(m_SizeAnalogLeft[i], 0, wxEXPAND | wxALIGN_CENTER_VERTICAL, 0); - m_gAnalogRight[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Analog 2")); - m_gAnalogRight[i]->Add(m_pRightStatus[i], 0, (wxLEFT | wxRIGHT), 5); + m_gAnalogRight[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Analog 2 (In) (Out)")); + m_gAnalogRight[i]->Add(m_GridRightStick[i], 0, (wxLEFT | wxRIGHT), 5); m_gAnalogRight[i]->Add(m_SizeAnalogRight[i], 0, wxEXPAND | wxALIGN_CENTER_VERTICAL, 0); - // -------------------------------------------------------------------- - // Analog triggers - // ----------------------------- - /**/ - m_gTrigger[i] = new wxStaticBoxSizer (wxHORIZONTAL, m_Controller[i], wxT("Triggers")); - m_TriggerStatusL[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("Left: ")); - m_TriggerStatusR[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("Right: ")); - m_TriggerStatusLx[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("000")); - m_TriggerStatusRx[i]= new wxStaticText(m_Controller[i], wxID_ANY, wxT("000")); - - m_tAnalogTriggerInput[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Input")); - m_tAnalogTriggerL[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Left")); - m_tAnalogTriggerR[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Right")); - - m_AnalogTriggerL[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_LEFT, wxT(""), wxDefaultPosition, wxSize(TxtW, TxtH), wxTE_READONLY | wxTE_CENTRE); - m_AnalogTriggerR[i] = new wxTextCtrl(m_Controller[i], ID_ANALOG_LEFT, wxT(""), wxDefaultPosition, wxSize(TxtW, TxtH), wxTE_READONLY | wxTE_CENTRE); - - m_AnalogTriggerL[i]->Enable(false); - m_AnalogTriggerR[i]->Enable(false); - - m_bAnalogTriggerL[i] = new wxButton(m_Controller[i], IDB_ANALOG_LEFT, wxEmptyString, wxDefaultPosition, wxSize(21, 14)); - m_bAnalogTriggerR[i] = new wxButton(m_Controller[i], IDB_ANALOG_LEFT, wxEmptyString, wxDefaultPosition, wxSize(21, 14)); - - m_TriggerType[i] = new wxComboBox(m_Controller[i], wxID_ANY, StrTriggerType[0], wxDefaultPosition, wxDefaultSize, StrTriggerType, wxCB_READONLY); - - m_SizeAnalogTriggerStatusBox[i] = new wxGridBagSizer(0, 0); - m_SizeAnalogTriggerHorizConfig[i] = new wxGridBagSizer(0, 0); - m_SizeAnalogTriggerVertLeft[i] = new wxBoxSizer(wxVERTICAL); - m_SizeAnalogTriggerVertRight[i] = new wxBoxSizer(wxVERTICAL); - m_SizeAnalogTriggerHorizInput[i] = new wxBoxSizer(wxHORIZONTAL); - - m_SizeAnalogTriggerStatusBox[i]->Add(m_TriggerStatusL[i], wxGBPosition(0, 0), wxGBSpan(1, 1), (wxUP), 0); - m_SizeAnalogTriggerStatusBox[i]->Add(m_TriggerStatusLx[i], wxGBPosition(0, 1), wxGBSpan(1, 1), (wxUP), 0); - m_SizeAnalogTriggerStatusBox[i]->Add(m_TriggerStatusR[i], wxGBPosition(1, 0), wxGBSpan(1, 1), (wxUP), 0); - m_SizeAnalogTriggerStatusBox[i]->Add(m_TriggerStatusRx[i], wxGBPosition(1, 1), wxGBSpan(1, 1), (wxUP), 0); - - m_SizeAnalogTriggerHorizConfig[i]->Add(m_tAnalogTriggerL[i], wxGBPosition(0, 0), wxGBSpan(1, 1), (wxUP), 2); - m_SizeAnalogTriggerHorizConfig[i]->Add(m_AnalogTriggerL[i], wxGBPosition(0, 1), wxGBSpan(1, 1), (wxLEFT | wxRIGHT), 2); - m_SizeAnalogTriggerHorizConfig[i]->Add(m_bAnalogTriggerL[i], wxGBPosition(0, 2), wxGBSpan(1, 1), (wxUP), 2); - m_SizeAnalogTriggerHorizConfig[i]->Add(m_tAnalogTriggerR[i], wxGBPosition(1, 0), wxGBSpan(1, 1), (wxUP), 4); - m_SizeAnalogTriggerHorizConfig[i]->Add(m_AnalogTriggerR[i], wxGBPosition(1, 1), wxGBSpan(1, 1), (wxLEFT | wxUP | wxRIGHT), 2); - m_SizeAnalogTriggerHorizConfig[i]->Add(m_bAnalogTriggerR[i], wxGBPosition(1, 2), wxGBSpan(1, 1), (wxUP), 5); - - m_SizeAnalogTriggerHorizInput[i]->Add(m_tAnalogTriggerInput[i], 0, (wxUP), 2); - m_SizeAnalogTriggerHorizInput[i]->Add(m_TriggerType[i], 0, (wxLEFT), 2); - - m_SizeAnalogTriggerVertLeft[i]->AddStretchSpacer(); - m_SizeAnalogTriggerVertLeft[i]->Add(m_SizeAnalogTriggerStatusBox[i]); - m_SizeAnalogTriggerVertLeft[i]->AddStretchSpacer(); - - m_SizeAnalogTriggerVertRight[i]->Add(m_SizeAnalogTriggerHorizConfig[i], 0, (wxUP), 1); - m_SizeAnalogTriggerVertRight[i]->Add(m_SizeAnalogTriggerHorizInput[i], 0, (wxUP | wxDOWN), 4); - - m_gTrigger[i]->Add(m_SizeAnalogTriggerVertLeft[i], 0, wxEXPAND | (wxLEFT | wxRIGHT), 5); - m_gTrigger[i]->Add(m_SizeAnalogTriggerVertRight[i], 0, (wxLEFT | wxRIGHT), 5); - - // Sizers + // -------------------------------------------------------------------- + // Row 3 Sizers + // ----------------------------- m_HorizControllers[i] = new wxBoxSizer(wxHORIZONTAL); m_HorizControllers[i]->Add(m_gAnalogLeft[i]); m_HorizControllers[i]->Add(m_gAnalogRight[i], 0, (wxLEFT), 5); - m_HorizControllers[i]->Add(m_gTrigger[i], 0, (wxLEFT), 5); /////////////////////////// @@ -927,6 +1000,12 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event) DoExtensionConnectedDisconnected(); break; + ////////////////////////// + // Gamepad + // ----------- + case ID_TRIGGER_TYPE: + WiiMoteEmu::PadMapping[Page].triggertype = m_TriggerType[Page]->GetSelection(); + break; ////////////////////////// // Recording @@ -983,6 +1062,9 @@ void ConfigDialog::UpdateGUI() { //Console::Print("UpdateGUI: \n"); + // Update the gamepad settings + UpdateGUIButtonMapping(Page); + /* We only allow a change of extension if we are not currently using the real Wiimote, if it's in use the status will be updated from the data scanning functions in main.cpp */ bool AllowExtensionChange = !(g_RealWiiMotePresent && g_Config.bConnectRealWiimote && g_Config.bUseRealWiimote && g_EmulatorRunning); diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h index 29960f4e1d..36ecc09bc0 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h @@ -44,10 +44,13 @@ class ConfigDialog : public wxDialog // General open, close and event functions void CloseClick(wxCommandEvent& event); - void UpdateGUI(); + void UpdateGUI(); void UpdateGUIButtonMapping(int controller); void OnKeyDown(wxKeyEvent& event); void LoadFile(); void SaveFile(); + // Timers + wxTimer *m_TimeoutTimer, *m_ShutDownTimer, *m_TimeoutOnce, *m_ButtonMappingTimer, *m_UpdatePad; + // General status wxStaticText * m_TextUpdateRate; @@ -60,15 +63,18 @@ class ConfigDialog : public wxDialog void DoRecordMovement(u8 _x, u8 _y, u8 _z, const u8 *_IR, int IRBytes); void DoRecordA(bool Pressed); void ConvertToString(); - wxTimer *m_TimeoutTimer, *m_ShutDownTimer, *m_TimeoutOnce; void Update(wxTimerEvent& WXUNUSED(event)); void ShutDown(wxTimerEvent& WXUNUSED(event)); void UpdateOnce(wxTimerEvent& event); + // Gamepad configuration + void OnButtonTimer(wxTimerEvent& WXUNUSED(event)) { DoGetButtons(GetButtonWaitingID); } + void UpdatePad(wxTimerEvent& WXUNUSED(event)); + private: DECLARE_EVENT_TABLE(); - bool ControlsCreated, m_bEnableUseRealWiimote; int Page, BoxW, BoxH; + bool ControlsCreated, m_bEnableUseRealWiimote; int Page, BoxW, BoxH, g_Pressed; wxNotebook *m_Notebook; wxPanel *m_Controller[4], *m_PageRecording; @@ -81,13 +87,15 @@ class ConfigDialog : public wxDialog *m_HorizControllers[4], *m_HorizControllerTiltParent[4], *m_HorizControllerTilt[4], *m_TiltHoriz[4], *m_SizeAnalogLeft[4], *m_SizeAnalogLeftHorizX[4], *m_SizeAnalogLeftHorizY[4], *m_SizeAnalogRight[4], *m_SizeAnalogRightHorizX[4], *m_SizeAnalogRightHorizY[4], *m_SizeAnalogTriggerVertLeft[4], *m_SizeAnalogTriggerVertRight[4], *m_SizeAnalogTriggerHorizInput[4]; - wxGridBagSizer *m_SizeAnalogTriggerHorizConfig[4], *m_SizeAnalogTriggerStatusBox[4]; + wxGridBagSizer *m_SizeAnalogTriggerHorizConfig[4], *m_SizeAnalogTriggerStatusBox[4], + *m_GridLeftStick[4], *m_GridRightStick[4]; wxStaticBoxSizer *m_SizeBasic[4], *m_SizeEmu[4], *m_SizeReal[4], *m_SizeExtensions[4], *m_gTilt[4], *m_gJoyname[4]; wxTextCtrl *m_AnalogLeftX[4], *m_AnalogLeftY[4], *m_AnalogRightX[4], *m_AnalogRightY[4], *m_AnalogTriggerL[4], *m_AnalogTriggerR[4]; wxButton *m_bAnalogLeftX[4], *m_bAnalogLeftY[4], *m_bAnalogRightX[4], *m_bAnalogRightY[4], *m_bAnalogTriggerL[4], *m_bAnalogTriggerR[4]; wxStaticText *m_tAnalogX[8], *m_tAnalogY[8], *m_TiltText[4], + *m_TStatusLeftIn[4], *m_TStatusLeftOut[4], *m_TStatusRightIn[4], *m_TStatusRightOut[4], *m_TriggerStatusL[4], *m_TriggerStatusR[4], *m_TriggerStatusLx[4], *m_TriggerStatusRx[4], *m_tAnalogTriggerInput[4], *m_tAnalogTriggerL[4], *m_tAnalogTriggerR[4]; @@ -101,8 +109,9 @@ class ConfigDialog : public wxDialog wxCheckBox *m_ConnectRealWiimote[4], *m_UseRealWiimote[4], *m_UpdateMeters; wxChoice *m_AccNeutralChoice[3], *m_AccNunNeutralChoice[3]; - wxPanel *m_pInStatus[4], *m_pRightStatus[4]; - wxStaticBitmap *m_bmpDot[4], *m_bmpSquare[4], *m_bmpDotRight[4], *m_bmpSquareRight[4]; + wxPanel *m_pLeftInStatus[4], *m_pLeftOutStatus[4], *m_pRightInStatus[4], *m_pRightOutStatus[4]; + wxStaticBitmap *m_bmpDotLeftIn[4], *m_bmpDotLeftOut[4], *m_bmpDotRightIn[4], *m_bmpDotRightOut[4], + *m_bmpSquareLeftIn[4], *m_bmpSquareLeftOut[4], *m_bmpSquareRightIn[4], *m_bmpSquareRightOut[4]; wxStaticBoxSizer *m_gAnalogLeft[4], *m_gAnalogRight[4], *m_gTrigger[4]; wxBitmap CreateBitmapDot(), CreateBitmap(); @@ -131,7 +140,7 @@ class ConfigDialog : public wxDialog ID_CLOSE = 1000, ID_APPLY, ID_ABOUTOGL, - IDTM_EXIT, IDTM_UPDATE, IDTM_SHUTDOWN, IDTM_UPDATE_ONCE, // Timer + IDTM_EXIT, IDTM_UPDATE, IDTM_SHUTDOWN, IDTM_UPDATE_ONCE, IDTM_BUTTON, IDTM_UPDATE_PAD, // Timer ID_NOTEBOOK, ID_CONTROLLERPAGE1, ID_CONTROLLERPAGE2, ID_CONTROLLERPAGE3, ID_CONTROLLERPAGE4, ID_PAGE_RECORDING, @@ -140,8 +149,17 @@ class ConfigDialog : public wxDialog ID_NUNCHUCKCONNECTED, ID_CLASSICCONTROLLERCONNECTED, IDC_JOYNAME, IDC_JOYATTACH, ID_TILT_COMBO, ID_TILT_CHECK, - ID_ANALOG_LEFT, IDB_ANALOG_LEFT, ID_ANALOG_RIGHT, IDB_ANALOG_RIGHT, - ID_TRIGGER, IDB_TRIGGER, + // Gamepad + IDB_ANALOG_LEFT_X, IDB_ANALOG_LEFT_Y, + IDB_ANALOG_RIGHT_X, IDB_ANALOG_RIGHT_Y, + IDB_TRIGGER_L, IDB_TRIGGER_R, + + ID_ANALOG_LEFT_X, ID_ANALOG_LEFT_Y, + ID_ANALOG_RIGHT_X, ID_ANALOG_RIGHT_Y, + ID_TRIGGER_L, ID_TRIGGER_R, + + // Gamepad settings + ID_TRIGGER_TYPE, // Real ID_CONNECT_REAL, ID_USE_REAL, ID_UPDATE_REAL, IDT_STATUS, ID_NEUTRAL_CHOICE, @@ -154,13 +172,23 @@ class ConfigDialog : public wxDialog void CreateGUIControls(); void CreateGUIControlsRecording(); void AboutClick(wxCommandEvent& event); + void GeneralSettingsChanged(wxCommandEvent& event); void DoConnectReal(); // Real void DoUseReal(); void DoExtensionConnectedDisconnected(int Extension = -1); // Emulated - void GeneralSettingsChanged(wxCommandEvent& event); + // Gamepad configuration + void SetButtonText(int id, char text[128], int _Page = -1); void SetButtonTextAll(int id, char text[128]); + wxString GetButtonText(int id, int Page = -1); + void GetButtons(wxCommandEvent& event); void DoGetButtons(int); + void SaveButtonMapping(int controller, bool DontChangeId = false, int FromSlot = -1); void SaveButtonMappingAll(int Slot); + void ToBlank(bool ToBlank = true); + void PadGetStatus(); + + // Configure buttons + int GetButtonWaitingID, GetButtonWaitingTimer; }; extern ConfigDialog *frame; diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigGamepad.cpp b/Source/Plugins/Plugin_Wiimote/Src/ConfigGamepad.cpp new file mode 100644 index 0000000000..e745bca5e5 --- /dev/null +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigGamepad.cpp @@ -0,0 +1,554 @@ +// Copyright (C) 2003-2008 Dolphin Project. + +// 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/ + + +////////////////////////////////////////////////////////////////////////////////////////// +// Includes +// ŻŻŻŻŻŻŻŻŻŻŻŻŻ +//#include "Common.h" // for u16 +#include "CommonTypes.h" // for u16 +#include "IniFile.h" +#include "Timer.h" + +#include "wiimote_real.h" // Local +#include "wiimote_hid.h" +#include "main.h" +#include "ConfigDlg.h" +#include "Config.h" +#include "EmuMain.h" // for LoadRecordedMovements() +#include "EmuSubroutines.h" // for WmRequestStatus +#include "EmuDefinitions.h" // for joyinfo +////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////////// +// Change settings +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void ConfigDialog::SetButtonTextAll(int id, char text[128]) +{ + for (int i = 0; i < 1; i++) + { + // Safety check to avoid crash + if(WiiMoteEmu::joyinfo.size() > WiiMoteEmu::PadMapping[i].ID) + if (WiiMoteEmu::joyinfo[WiiMoteEmu::PadMapping[i].ID].Name == WiiMoteEmu::joyinfo[WiiMoteEmu::PadMapping[Page].ID].Name) + SetButtonText(id, text, i); + }; +} + + +void ConfigDialog::SaveButtonMappingAll(int Slot) +{ + for (int i = 0; i < 4; i++) + { + // This can occur when no gamepad is detected + if(WiiMoteEmu::joyinfo.size() > WiiMoteEmu::PadMapping[i].ID) + if (WiiMoteEmu::joyinfo[WiiMoteEmu::PadMapping[i].ID].Name == WiiMoteEmu::joyinfo[WiiMoteEmu::PadMapping[Slot].ID].Name) + SaveButtonMapping(i, false, Slot); + } +} + +// Set dialog items from saved values +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void ConfigDialog::UpdateGUIButtonMapping(int controller) +{ + // Temporary storage + wxString tmp; + + // Update selected gamepad + m_Joyname[controller]->SetSelection(WiiMoteEmu::PadMapping[controller].ID); + + // Update the enabled checkbox + //m_Joyattach[controller]->SetValue(PadMapping[controller].enabled == 1 ? true : false); + + tmp << WiiMoteEmu::PadMapping[controller].Axis.Lx; m_AnalogLeftX[controller]->SetValue(tmp); tmp.clear(); + tmp << WiiMoteEmu::PadMapping[controller].Axis.Ly; m_AnalogLeftY[controller]->SetValue(tmp); tmp.clear(); + tmp << WiiMoteEmu::PadMapping[controller].Axis.Rx; m_AnalogRightX[controller]->SetValue(tmp); tmp.clear(); + tmp << WiiMoteEmu::PadMapping[controller].Axis.Ry; m_AnalogRightY[controller]->SetValue(tmp); tmp.clear(); + + tmp << WiiMoteEmu::PadMapping[controller].Axis.Tl; m_AnalogTriggerL[controller]->SetValue(tmp); tmp.clear(); + tmp << WiiMoteEmu::PadMapping[controller].Axis.Tr; m_AnalogTriggerR[controller]->SetValue(tmp); tmp.clear(); + + // Update the deadzone and controller type controls + m_TriggerType[controller]->SetSelection(WiiMoteEmu::PadMapping[controller].triggertype); + //m_Deadzone[controller]->SetSelection(PadMapping[controller].deadzone); + //m_CoBDiagonal[controller]->SetValue(wxString::FromAscii(PadMapping[controller].SDiagonal.c_str())); + //m_CBS_to_C[controller]->SetValue(PadMapping[controller].bSquareToCircle); + + //LogMsg("m_TriggerType[%i] = %i\n", controller, PadMapping[controller].triggertype); +} + +/* Populate the PadMapping array with the dialog items settings (for example + selected joystick, enabled or disabled status and so on) */ +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void ConfigDialog::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 enabled or disable status and other settings + if(!DontChangeId) WiiMoteEmu::PadMapping[controller].ID = m_Joyname[FromSlot]->GetSelection(); + if(FromSlot == controller) WiiMoteEmu::PadMapping[controller].enabled = true; //m_Joyattach[FromSlot]->GetValue(); // Only enable one + //WiiMoteEmu::PadMapping[controller].controllertype = m_ControlType[FromSlot]->GetSelection(); + WiiMoteEmu::PadMapping[controller].triggertype = m_TriggerType[FromSlot]->GetSelection(); + //WiiMoteEmu::PadMapping[controller].deadzone = m_Deadzone[FromSlot]->GetSelection(); + //WiiMoteEmu::PadMapping[controller].SDiagonal = m_CoBDiagonal[FromSlot]->GetLabel().mb_str(); + //WiiMoteEmu::PadMapping[controller].bSquareToCircle = m_CBS_to_C[FromSlot]->IsChecked(); + + // The analog buttons + m_AnalogLeftX[FromSlot]->GetValue().ToLong(&value); WiiMoteEmu::PadMapping[controller].Axis.Lx = value; tmp.clear(); + m_AnalogLeftY[FromSlot]->GetValue().ToLong(&value); WiiMoteEmu::PadMapping[controller].Axis.Ly = value; tmp.clear(); + m_AnalogRightX[FromSlot]->GetValue().ToLong(&value); WiiMoteEmu::PadMapping[controller].Axis.Rx = value; tmp.clear(); + m_AnalogRightY[FromSlot]->GetValue().ToLong(&value); WiiMoteEmu::PadMapping[controller].Axis.Ry = value; tmp.clear(); + + // The shoulder buttons + m_AnalogTriggerL[FromSlot]->GetValue().ToLong(&value); WiiMoteEmu::PadMapping[controller].Axis.Tl = value; + m_AnalogTriggerR[FromSlot]->GetValue().ToLong(&value); WiiMoteEmu::PadMapping[controller].Axis.Tr = value; + + //LogMsg("WiiMoteEmu::PadMapping[%i].triggertype = %i, m_TriggerType[%i]->GetSelection() = %i\n", + // controller, WiiMoteEmu::PadMapping[controller].triggertype, FromSlot, m_TriggerType[FromSlot]->GetSelection()); + + // Replace "-1" with "" + ToBlank(); +} + +// Replace the harder to understand -1 with "" for the sake of user friendliness +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void ConfigDialog::ToBlank(bool ToBlank) +{ + if (!ControlsCreated) return; + + for (int j = 0; j < 4; j++) + { + if(ToBlank) + { + for(int i = IDB_ANALOG_LEFT_X; i <= IDB_TRIGGER_R; i++) + #ifndef _WIN32 + if(GetButtonText(i, j).ToAscii() == "-1") SetButtonText(i, "", j); + #else + if(GetButtonText(i, j) == "-1") SetButtonText(i, "", j); + #endif + } + else + { + for(int i = IDB_ANALOG_LEFT_X; i <= IDB_TRIGGER_R; i++) + if(GetButtonText(i, j).IsEmpty()) SetButtonText(i, "-1", j); + } + } +} +////////////////////////////////////// + + + + +// Update the textbox for the buttons +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void ConfigDialog::SetButtonText(int id, char text[128], int _Page) +{ + // Set controller value + int controller; + if (_Page == -1) controller = Page; else controller = _Page; + + switch(id) + { + case IDB_ANALOG_LEFT_X: m_AnalogLeftX[controller]->SetValue(wxString::FromAscii(text)); break; + case IDB_ANALOG_LEFT_Y: m_AnalogLeftY[controller]->SetValue(wxString::FromAscii(text)); break; + case IDB_ANALOG_RIGHT_X: m_AnalogRightX[controller]->SetValue(wxString::FromAscii(text)); break; + case IDB_ANALOG_RIGHT_Y: m_AnalogRightY[controller]->SetValue(wxString::FromAscii(text)); break; + + case IDB_TRIGGER_L: m_AnalogTriggerL[controller]->SetValue(wxString::FromAscii(text)); break; + case IDB_TRIGGER_R: m_AnalogTriggerR[controller]->SetValue(wxString::FromAscii(text)); break; + default: break; + } + //Console::Print("SetButtonText: %s\n", text); +} + +// Get the text in the textbox for the buttons +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +wxString ConfigDialog::GetButtonText(int id, int _Page) +{ + //Console::Print("GetButtonText: %i\n", id); + + // Set controller value + int controller; + if (_Page == -1) controller = Page; else controller = _Page; + + switch(id) + { + // Analog Stick + case IDB_ANALOG_LEFT_X: return m_AnalogLeftX[controller]->GetValue(); + case IDB_ANALOG_LEFT_Y: return m_AnalogLeftY[controller]->GetValue(); + case IDB_ANALOG_RIGHT_X: return m_AnalogRightX[controller]->GetValue(); + case IDB_ANALOG_RIGHT_Y: return m_AnalogRightY[controller]->GetValue(); + + // Shoulder Buttons + case IDB_TRIGGER_L: return m_AnalogTriggerL[controller]->GetValue(); + case IDB_TRIGGER_R: return m_AnalogTriggerR[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 ConfigDialog::GetButtons(wxCommandEvent& event) +{ + DoGetButtons(event.GetId()); +} + +void ConfigDialog::DoGetButtons(int GetId) +{ + // ============================================= + // Collect the starting values + // ---------------- + + // Get the current controller + int Controller = Page; + int PadID = WiiMoteEmu::PadMapping[Controller].ID; + + // Get the controller and trigger type + int TriggerType = WiiMoteEmu::PadMapping[Controller].triggertype; + + // Collect the accepted buttons for this slot + bool LeftRight = (GetId == IDB_TRIGGER_L || GetId == IDB_TRIGGER_R); + + bool Axis = (GetId >= IDB_ANALOG_LEFT_X && GetId <= IDB_TRIGGER_R) + // Don't allow SDL axis input for the shoulder buttons if XInput is selected + && !(TriggerType == InputCommon::CTL_TRIGGER_XINPUT && (GetId == IDB_TRIGGER_L || GetId == IDB_TRIGGER_R) ); + + bool XInput = (TriggerType == InputCommon::CTL_TRIGGER_XINPUT); + + bool Button = false; // No digital buttons allowed + + bool Hat = false; // No hats allowed + + // 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 + // ======================= + + //Console::Print("Before (%i) Id:%i %i IsRunning:%i\n", + // GetButtonWaitingTimer, GetButtonWaitingID, GetId, m_ButtonMappingTimer->IsRunning()); + + // 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( floor((double)(1000 / TimesPerSecond)) ); + #endif + Console::Print("Timer Started for Pad:%i GetId:%i\n" + "Allowed input is Axis:%i LeftRight:%i XInput:%i Button:%i Hat:%i\n", + WiiMoteEmu::PadMapping[Controller].ID, GetId, + Axis, LeftRight, XInput, Button, Hat); + } + + // =============================================== + // Check for buttons + // ---------------- + + // If there is a timer but we should not create a new one + else + { + InputCommon::GetButton( + WiiMoteEmu::joyinfo[PadID].joy, PadID, WiiMoteEmu::joyinfo[PadID].NumButtons, WiiMoteEmu::joyinfo[PadID].NumAxes, WiiMoteEmu::joyinfo[PadID].NumHats, + g_Pressed, value, type, pressed, Succeed, Stop, + LeftRight, Axis, XInput, Button, Hat); + } + // ========================= 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); + + /* Debug */ + Console::Print("Keyboard: %i\n", g_Pressed); + } + + // Time's up + if( (GetButtonWaitingTimer / TimesPerSecond) >= Seconds ) + { + Stop = true; + // Leave a blank mapping + SetButtonTextAll(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); + SetButtonTextAll(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. */ + SaveButtonMappingAll(Controller); + } + + // If we got a bad button + if(g_Pressed == -1) + { + // Update text + SetButtonTextAll(GetId, "-1"); + + // Notify the user + wxMessageBox(wxString::Format(wxT( + "You selected a key with a to low key code (%i), please" + " select another key with a higher key code."), pressed) + , wxT("Notice"), wxICON_INFORMATION); + } + // ======================== Process results + + // Debugging + /* + Console::Print("Change: %i %i %i %i '%s' '%s' '%s' '%s'\n", + WiiMoteEmu::PadMapping[0].halfpress, WiiMoteEmu::PadMapping[1].halfpress, WiiMoteEmu::PadMapping[2].halfpress, WiiMoteEmu::PadMapping[3].halfpress, + m_JoyButtonHalfpress[0]->GetValue().c_str(), m_JoyButtonHalfpress[1]->GetValue().c_str(), m_JoyButtonHalfpress[2]->GetValue().c_str(), m_JoyButtonHalfpress[3]->GetValue().c_str() + );*/ +} +/////////////////////////////////////////////////////////// Configure button mapping + + +////////////////////////////////////////////////////////////////////////////////////////// +// Show current input status +// ŻŻŻŻŻŻŻŻŻŻ + +// Update the input status boxes +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void ConfigDialog::PadGetStatus() +{ + // Return if it's not detected + if(WiiMoteEmu::PadMapping[Page].ID >= SDL_NumJoysticks()) + { + m_TStatusLeftIn[Page]->SetLabel(wxT("Not connected")); + m_TStatusLeftOut[Page]->SetLabel(wxT("Not connected")); + m_TStatusRightIn[Page]->SetLabel(wxT("Not connected")); + m_TStatusRightOut[Page]->SetLabel(wxT("Not connected")); + m_TriggerStatusLx[Page]->SetLabel(wxT("0")); + m_TriggerStatusRx[Page]->SetLabel(wxT("0")); + return; + } + + // Return if it's not enabled + if (!WiiMoteEmu::PadMapping[Page].enabled) + { + m_TStatusLeftIn[Page]->SetLabel(wxT("Not enabled")); + m_TStatusLeftOut[Page]->SetLabel(wxT("Not enabled")); + m_TStatusRightIn[Page]->SetLabel(wxT("Not enabled")); + m_TStatusRightOut[Page]->SetLabel(wxT("Not enabled")); + m_TriggerStatusLx[Page]->SetLabel(wxT("0")); + m_TriggerStatusRx[Page]->SetLabel(wxT("0")); + return; + } + + // Get physical device status + int PhysicalDevice = WiiMoteEmu::PadMapping[Page].ID; + int TriggerType = WiiMoteEmu::PadMapping[Page].triggertype; + + // Check that Dolphin is in focus, otherwise don't update the pad status + if (IsFocus()) + WiiMoteEmu::GetJoyState(WiiMoteEmu::PadState[Page], WiiMoteEmu::PadMapping[Page], Page, WiiMoteEmu::joyinfo[WiiMoteEmu::PadMapping[Page].ID].NumButtons); + + + ////////////////////////////////////// + // Analog stick + // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ + // Set Deadzones perhaps out of function + //int deadzone = (int)(((float)(128.00/100.00)) * (float)(PadMapping[_numPAD].deadzone+1)); + //int deadzone2 = (int)(((float)(-128.00/100.00)) * (float)(PadMapping[_numPAD].deadzone+1)); + + // Get original values + int main_x = WiiMoteEmu::PadState[Page].Axis.Lx; + int main_y = WiiMoteEmu::PadState[Page].Axis.Ly; + int right_x = WiiMoteEmu::PadState[Page].Axis.Rx; + int right_y = WiiMoteEmu::PadState[Page].Axis.Ry; + + // Get adjusted values + int main_x_after = main_x, main_y_after = main_y; + int right_x_after = right_x, right_y_after = right_y; + /* + if(WiiMoteEmu::PadMapping[notebookpage].bSquareToCircle) + { + std::vector main_xy = InputCommon::Pad_Square_to_Circle(main_x, main_y, notebookpage, PadMapping[notebookpage]); + main_x_after = main_xy.at(0); + main_y_after = main_xy.at(1); + } + */ + + // + float f_x = main_x / 32767.0; + float f_y = main_y / 32767.0; + float f_x_aft = main_x_after / 32767.0; + float f_y_aft = main_y_after / 32767.0; + + float f_Rx = right_x / 32767.0; + float f_Ry = right_y / 32767.0; + float f_Rx_aft = right_x_after / 32767.0; + float f_Ry_aft = right_y_after / 32767.0; + + m_TStatusLeftIn[Page]->SetLabel(wxString::Format( + wxT("x:%1.2f y:%1.2f"), f_x, f_y + )); + m_TStatusLeftOut[Page]->SetLabel(wxString::Format( + wxT("x:%1.2f y:%1.2f"), f_x_aft, f_y_aft + )); + m_TStatusRightIn[Page]->SetLabel(wxString::Format( + wxT("x:%1.2f y:%1.2f"), f_Rx, f_Ry + )); + m_TStatusRightOut[Page]->SetLabel(wxString::Format( + wxT("x:%1.2f y:%1.2f"), f_Rx_aft, f_Ry_aft + )); + + // Adjust the values for the plot + int BoxW_ = BoxW - 2; int BoxH_ = BoxH - 2; // Border adjustment + + main_x = (BoxW_ / 2) + (main_x * BoxW_ / (32767 * 2)); + main_y = (BoxH_ / 2) + (main_y * BoxH_ / (32767 * 2)); + + right_x = (BoxW_ / 2) + (right_x * BoxW_ / (32767 * 2)); + right_y = (BoxH_ / 2) + (right_y * BoxH_ / (32767 * 2)); + + int main_x_out = (BoxW_ / 2) + (main_x_after * BoxW_ / (32767 * 2)); + int main_y_out = (BoxH_ / 2) + (main_y_after * BoxH_ / (32767 * 2)); + + int right_x_out = (BoxW_ / 2) + (right_x_after * BoxW_ / (32767 * 2)); + int right_y_out = (BoxH_ / 2) + (right_y_after * BoxH_ / (32767 * 2)); + + // Adjust the dot + m_bmpDotLeftIn[Page]->SetPosition(wxPoint(main_x, main_y)); + m_bmpDotLeftOut[Page]->SetPosition(wxPoint(main_x_out, main_y_out)); + m_bmpDotRightIn[Page]->SetPosition(wxPoint(right_x, right_y)); + m_bmpDotRightOut[Page]->SetPosition(wxPoint(right_x_out, right_y_out)); + ///////////////////// Analog stick + + + ////////////////////////////////////// + // Triggers + // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ + int TriggerValue = 0; + + // Get the selected keys + long Left, Right; + m_AnalogTriggerL[Page]->GetValue().ToLong(&Left); + m_AnalogTriggerR[Page]->GetValue().ToLong(&Right); + + // Get the trigger values + int TriggerLeft = WiiMoteEmu::PadState[Page].Axis.Tl; + int TriggerRight = WiiMoteEmu::PadState[Page].Axis.Tr; + + // Convert the triggers values + if (WiiMoteEmu::PadMapping[Page].triggertype == InputCommon::CTL_TRIGGER_SDL) + { + TriggerLeft = InputCommon::Pad_Convert(TriggerLeft); + TriggerRight = InputCommon::Pad_Convert(TriggerRight); + } + + m_TriggerStatusLx[Page]->SetLabel(wxString::Format( + wxT("%03i"), TriggerLeft)); + m_TriggerStatusRx[Page]->SetLabel(wxString::Format( + wxT("%03i"), TriggerRight)); + ///////////////////// Triggers +} + +// Populate the advanced tab +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +void ConfigDialog::UpdatePad(wxTimerEvent& WXUNUSED(event)) +{ + // Show the current status + /**/ + #ifdef SHOW_PAD_STATUS + m_pStatusBar->SetLabel(wxString::Format( + "%s", ShowStatus(notebookpage).c_str() + )); + #endif + + //LogMsg("Abc%s\n", ShowStatus(notebookpage).c_str()); + + PadGetStatus(); + + //Console::Print("a\n"); +} +///////////////////////////////////////////////////// \ No newline at end of file diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp index f054eef27a..84bb275137 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp @@ -63,8 +63,8 @@ bool g_Encryption; // Encryption on or off // Gamepad input int NumPads = 0, NumGoodPads = 0; // Number of goods pads std::vector joyinfo; -InputCommon::CONTROLLER_STATE PadState[4]; -InputCommon::CONTROLLER_MAPPING PadMapping[4]; +InputCommon::CONTROLLER_STATE_NEW PadState[4]; +InputCommon::CONTROLLER_MAPPING_NEW PadMapping[4]; } // namespace diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h index b743624ed9..a0abd73792 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h @@ -173,8 +173,8 @@ static const u8 partially_id[] = // Gamepad input extern int NumPads, NumGoodPads; // Number of goods pads extern std::vector joyinfo; -extern InputCommon::CONTROLLER_STATE PadState[4]; -extern InputCommon::CONTROLLER_MAPPING PadMapping[4]; +extern InputCommon::CONTROLLER_STATE_NEW PadState[4]; +extern InputCommon::CONTROLLER_MAPPING_NEW PadMapping[4]; } // namespace diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp index a41a54c843..6a86ef0b3b 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp @@ -19,8 +19,6 @@ ////////////////////////////////////////////////////////////////////////////////////////// // Includes // ŻŻŻŻŻŻŻŻŻŻŻŻŻ -#include "pluginspecs_wiimote.h" - #include #include @@ -30,6 +28,7 @@ #include "Common.h" // Common #include "StringUtil.h" // for ArrayToString() #include "IniFile.h" +#include "pluginspecs_wiimote.h" #include "EmuDefinitions.h" // Local #include "main.h" @@ -130,7 +129,7 @@ void LoadRecordedMovements() for(int i = 0; i < RECORDING_ROWS; i++) { // Logging - Console::Print("Recording%i ", i + 1); + //Console::Print("Recording%i ", i + 1); // Get row name std::string SaveName = StringFromFormat("Recording%i", i + 1); @@ -216,10 +215,11 @@ void LoadRecordedMovements() else TmpIRLog = ""; + /* Console::Print("Size:%i HotKey:%i Speed:%i IR: %s\n", VRecording.at(i).Recording.size(), VRecording.at(i).HotKey, VRecording.at(i).PlaybackSpeed, TmpIRLog.c_str() - ); + );*/ // --------------------- } } @@ -302,36 +302,6 @@ void SetDefaultExtensionRegistry() } -// =================================================== -// Fill joyinfo with the current connected devices -// ---------------- -bool Search_Devices(std::vector &_joyinfo, int &_NumPads, int &_NumGoodPads) -{ - bool Success = InputCommon::SearchDevices(_joyinfo, _NumPads, _NumGoodPads); - - // Warn the user if no gamepads are detected - if (_NumGoodPads == 0 && g_EmulatorRunning) - { - //PanicAlert("nJoy: No Gamepad Detected"); - //return false; - } - - // Load PadMapping[] etc - g_Config.Load(); - - // Update the PadState[].joy handle - for (int i = 0; i < 4; i++) - { - if (PadMapping[i].enabled && joyinfo.size() > PadMapping[i].ID) - if(joyinfo.at(PadMapping[i].ID).Good) - PadState[i].joy = SDL_JoystickOpen(PadMapping[i].ID); - } - - return Success; -} -// =========================== - - // =================================================== /* Write initial values to Eeprom and registers. */ // ---------------- @@ -389,7 +359,29 @@ void DoState(void* ptr, int mode) these variables. */ void Shutdown(void) { + Console::Print("ShutDown\n"); + ResetVariables(); + + /* Close all devices carefully. We must check that we are not accessing any undefined + vector elements or any bad devices */ + for (int i = 0; i < 1; i++) + { + if (PadMapping[i].enabled && joyinfo.size() > PadMapping[i].ID) + if (joyinfo.at(PadMapping[i].ID).Good) + { + Console::Print("ShutDown: %i\n", PadState[i].joy); + /* SDL_JoystickClose() crashes for some reason so I avoid this for now, SDL_Quit() should + close the pads to I think */ + //if(SDL_JoystickOpened(PadMapping[i].ID)) SDL_JoystickClose(PadState[i].joy); + } + } + + // Clear the physical device info + joyinfo.clear(); + + // Finally close SDL + if (SDL_WasInit(0)) SDL_Quit(); } diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h index f5b5a2035b..f375b548e7 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h @@ -18,9 +18,14 @@ #ifndef WIIMOTE_EMU_H #define WIIMOTE_EMU_H -#include "wiimote_hid.h" + #include +#include "../../../Core/InputCommon/Src/SDL.h" // Core + +#include "wiimote_hid.h" +#include "EmuDefinitions.h" + namespace WiiMoteEmu { @@ -43,6 +48,9 @@ void LoadRecordedMovements(); void UpdateEeprom(); void SetDefaultExtensionRegistry(); +// Gamepad +bool Search_Devices(std::vector &_joyinfo, int &_NumPads, int &_NumGoodPads); +void GetJoyState(InputCommon::CONTROLLER_STATE_NEW &_PadState, InputCommon::CONTROLLER_MAPPING_NEW _PadMapping, int controller, int NumButtons); }; #endif diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuPad.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuPad.cpp new file mode 100644 index 0000000000..bb351dab95 --- /dev/null +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuPad.cpp @@ -0,0 +1,129 @@ +// Copyright (C) 2003-2008 Dolphin Project. + +// 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/ + + +////////////////////////////////////////////////////////////////////////////////////////// +// Includes +// ŻŻŻŻŻŻŻŻŻŻŻŻŻ +#include +#include + +#include "../../../Core/InputCommon/Src/SDL.h" // Core +#include "../../../Core/InputCommon/Src/XInput.h" + +#include "Common.h" // Common +#include "StringUtil.h" // for ArrayToString() +#include "IniFile.h" +#include "pluginspecs_wiimote.h" + +#include "EmuDefinitions.h" // Local +#include "main.h" +#include "wiimote_hid.h" +#include "EmuSubroutines.h" +#include "EmuMain.h" +#include "Encryption.h" // for extension encryption +#include "Logging.h" // for startConsoleWin, Console::Print, GetConsoleHwnd +#include "Config.h" // for g_Config +//////////////////////////////////// + +extern SWiimoteInitialize g_WiimoteInitialize; + +namespace WiiMoteEmu +{ + +// =================================================== +// Fill joyinfo with the current connected devices +// ---------------- +bool Search_Devices(std::vector &_joyinfo, int &_NumPads, int &_NumGoodPads) +{ + bool Success = InputCommon::SearchDevices(_joyinfo, _NumPads, _NumGoodPads); + + // Warn the user if no gamepads are detected + if (_NumGoodPads == 0 && g_EmulatorRunning) + { + //PanicAlert("nJoy: No Gamepad Detected"); + //return false; + } + + // Load PadMapping[] etc + g_Config.Load(); + + // Update the PadState[].joy handle + for (int i = 0; i < 1; i++) + { + if (PadMapping[i].enabled && joyinfo.size() > PadMapping[i].ID) + if(joyinfo.at(PadMapping[i].ID).Good) + PadState[i].joy = SDL_JoystickOpen(PadMapping[i].ID); + } + + return Success; +} +// =========================== + + +// Request joystick state. +// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ +/* Called from: PAD_GetStatus() + Input: The virtual device 0, 1, 2 or 3 + Function: Updates the PadState struct with the current pad status. The input value "controller" is + for a virtual controller 0 to 3. */ + +void GetJoyState(InputCommon::CONTROLLER_STATE_NEW &_PadState, InputCommon::CONTROLLER_MAPPING_NEW _PadMapping, int controller, int NumButtons) +{ + // Update the gamepad status + SDL_JoystickUpdate(); + + // Update axis states. It doesn't hurt much if we happen to ask for nonexisting axises here. + _PadState.Axis.Lx = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.Axis.Lx); + _PadState.Axis.Ly = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.Axis.Ly); + _PadState.Axis.Rx = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.Axis.Rx); + _PadState.Axis.Ry = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.Axis.Ry); + + // Update the analog trigger axis values +#ifdef _WIN32 + if (_PadMapping.triggertype == InputCommon::CTL_TRIGGER_SDL) + { +#endif + // If we are using SDL analog triggers the buttons have to be mapped as 1000 or up, otherwise they are not used + _PadState.Axis.Tl = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.Axis.Tl - 1000); + _PadState.Axis.Tr = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.Axis.Tr - 1000); +#ifdef _WIN32 + } + else + { + _PadState.Axis.Tl = XInput::GetXI(0, _PadMapping.Axis.Tl - 1000); + _PadState.Axis.Tr = XInput::GetXI(0, _PadMapping.Axis.Tr - 1000); + } +#endif + + /* Debugging */ + Console::ClearScreen(); + Console::Print( + "Controller and handle: %i %i\n" + + "Triggers:%i %i %i %i %i\n", + + controller, (int)_PadState.joy, + + _PadMapping.triggertype, + _PadMapping.Axis.Tl, _PadMapping.Axis.Tr, + _PadState.Axis.Tl, _PadState.Axis.Tr + ); +} + + +} // end of namespace WiiMoteEmu \ No newline at end of file diff --git a/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp b/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp index 71970916f8..40739c8b0d 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp @@ -77,7 +77,7 @@ void handle_event(struct wiimote_t* wm) { //Console::Print("\n\n--- EVENT [id %i] ---\n", wm->unid); - /* if a button is pressed, report it */ + // if a button is pressed, report it if (IS_PRESSED(wm, WIIMOTE_BUTTON_A)) Console::Print("A pressed\n"); if (IS_PRESSED(wm, WIIMOTE_BUTTON_B)) Console::Print("B pressed\n"); if (IS_PRESSED(wm, WIIMOTE_BUTTON_UP)) Console::Print("UP pressed\n"); @@ -91,10 +91,9 @@ void handle_event(struct wiimote_t* wm) if (IS_PRESSED(wm, WIIMOTE_BUTTON_TWO)) Console::Print("TWO pressed\n"); if (IS_PRESSED(wm, WIIMOTE_BUTTON_HOME)) Console::Print("HOME pressed\n"); - /* - * Pressing minus will tell the wiimote we are no longer interested in movement. - * This is useful because it saves battery power. - */ + + // Pressing minus will tell the wiimote we are no longer interested in movement. + // This is useful because it saves battery power. if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_MINUS)) { wiiuse_motion_sensing(wm, 0); @@ -112,16 +111,16 @@ void handle_event(struct wiimote_t* wm) if (g_MotionSensing && !WIIUSE_USING_IR(wm)) wiiuse_set_ir(wm, 1); - /* Print battery status */ + // Print battery status if(frame && g_Config.bUpdateRealWiimote) frame->m_GaugeBattery->SetValue((int)floor((wm->battery_level * 100) + 0.5)); - /* Create shortcut to the nunchuck */ + // Create shortcut to the nunchuck struct nunchuk_t* nc = NULL; if (wm->exp.type == EXP_NUNCHUK) nc = (nunchuk_t*)&wm->exp.nunchuk; - /* If the accelerometer is turned on then print angles */ + // If the accelerometer is turned on then print angles if (WIIUSE_USING_ACC(wm) && WIIUSE_USING_IR(wm)) { std::string Tmp; @@ -333,7 +332,7 @@ void ReadWiimote() break; case WIIUSE_GUITAR_HERO_3_CTRL_INSERTED: - /* some expansion was inserted */ + // some expansion was inserted //handle_ctrl_status(wiimotes[i]); Console::Print("Guitar Hero 3 controller inserted.\n"); break; @@ -341,7 +340,7 @@ void ReadWiimote() case WIIUSE_NUNCHUK_REMOVED: case WIIUSE_CLASSIC_CTRL_REMOVED: case WIIUSE_GUITAR_HERO_3_CTRL_REMOVED: - /* some expansion was removed */ + // some expansion was removed //handle_ctrl_status(wiimotes[i]); Console::Print("An expansion was removed.\n"); break; diff --git a/Source/Plugins/Plugin_Wiimote/Src/SConscript b/Source/Plugins/Plugin_Wiimote/Src/SConscript index ca5ca92c92..ec7951ad95 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/SConscript +++ b/Source/Plugins/Plugin_Wiimote/Src/SConscript @@ -11,6 +11,7 @@ files = [ "DataReports.cpp", "EmuDefinitions.cpp", "EmuMain.cpp", + "EmuPad.cpp", "EmuSubroutines.cpp", "Encryption.cpp", "main.cpp", @@ -18,6 +19,7 @@ files = [ if wmenv['HAVE_WX']: files += [ "ConfigDlg.cpp", + "ConfigGamepad.cpp", "ConfigRecording.cpp", "Logging.cpp", "FillReport.cpp", diff --git a/Source/Plugins/Plugin_Wiimote/Src/main.cpp b/Source/Plugins/Plugin_Wiimote/Src/main.cpp index bc7bbed4d8..a584618630 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/main.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/main.cpp @@ -382,10 +382,13 @@ extern "C" unsigned int Wiimote_GetAttachedControllers() bool IsFocus() { #ifdef _WIN32 - HWND Parent = GetParent(g_WiimoteInitialize.hWnd); + HWND RenderingWindow = g_WiimoteInitialize.hWnd; + HWND Parent = GetParent(RenderingWindow); HWND TopLevel = GetParent(Parent); + // Allow updates when the config window is in focus to + HWND Config = NULL; if (frame) Config = (HWND)frame->GetHWND(); // Support both rendering to main window and not - if (GetForegroundWindow() == TopLevel || GetForegroundWindow() == g_WiimoteInitialize.hWnd) + if (GetForegroundWindow() == TopLevel || GetForegroundWindow() == RenderingWindow || GetForegroundWindow() == Config) return true; else return false; diff --git a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp index 99c0749bc8..8ea12c102f 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp @@ -20,16 +20,16 @@ // Includes // ŻŻŻŻŻŻŻŻŻŻŻŻŻ #include // System -#include "pluginspecs_wiimote.h" +#include #include "wiiuse.h" -#include #include "Common.h" #include "Thread.h" #include "StringUtil.h" #include "ConsoleWindow.h" #include "Timer.h" +#include "pluginspecs_wiimote.h" #include "wiimote_hid.h" #include "main.h" @@ -148,7 +148,7 @@ void ReadData() { //Console::Print("Writing data to the Wiimote\n"); SEvent& rEvent = m_EventWriteQueue.front(); - wiiuse_io_write(m_pWiiMote, (byte*)rEvent.m_PayLoad, MAX_PAYLOAD); + wiiuse_io_write(m_pWiiMote, (byte*)rEvent.m_PayLoad, MAX_PAYLOAD); m_EventWriteQueue.pop(); #ifdef _WIN32 @@ -346,7 +346,7 @@ int Initialize() // Call Wiiuse.dll g_WiiMotesFromWiiUse = wiiuse_init(MAX_WIIMOTES); - g_NumberOfWiiMotes = wiiuse_find(g_WiiMotesFromWiiUse, MAX_WIIMOTES, 5); + g_NumberOfWiiMotes = wiiuse_find(g_WiiMotesFromWiiUse, MAX_WIIMOTES, 5); if (g_NumberOfWiiMotes > 0) g_RealWiiMotePresent = true; Console::Print("Found No of Wiimotes: %i\n", g_NumberOfWiiMotes); diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigAdvanced.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigAdvanced.cpp index 88827eca93..66389302f4 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigAdvanced.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigAdvanced.cpp @@ -194,6 +194,10 @@ std::string ShowStatus(int VirtualController) int Hats = joyinfo[PhysicalDevice].NumHats; int Buttons = joyinfo[PhysicalDevice].NumButtons; + // Get version + SDL_version Version; + SDL_GetVersion(&Version); + // Update the internal values SDL_JoystickUpdate(); @@ -215,7 +219,7 @@ std::string ShowStatus(int VirtualController) } return StringFromFormat( - "PadMapping\n" + "Version: %i.%i.%i\n" "Enabled: %i %i %i %i\n" "ID: %i %i %i %i\n" "Controllertype: %i %i %i %i\n" @@ -227,6 +231,7 @@ std::string ShowStatus(int VirtualController) "Hats: %s\n" "But: %s\n" "Device: Ax: %i Balls:%i Hats:%i But:%i", + Version.major, Version.minor, Version.patch, PadMapping[0].enabled, PadMapping[1].enabled, PadMapping[2].enabled, PadMapping[3].enabled, PadMapping[0].ID, PadMapping[1].ID, PadMapping[2].ID, PadMapping[3].ID, PadMapping[0].controllertype, PadMapping[1].controllertype, PadMapping[2].controllertype, PadMapping[3].controllertype, @@ -247,10 +252,12 @@ std::string ShowStatus(int VirtualController) void ConfigBox::Update() { // Show the current status - /* - m_pStatusBar->SetLabel(wxString::Format( - "%s", ShowStatus(notebookpage).c_str() - ));*/ + /**/ + #ifdef SHOW_PAD_STATUS + m_pStatusBar->SetLabel(wxString::Format( + "%s", ShowStatus(notebookpage).c_str() + )); + #endif //LogMsg("Abc%s\n", ShowStatus(notebookpage).c_str()); @@ -263,6 +270,10 @@ void ConfigBox::Update() // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ void ConfigBox::CreateAdvancedControls(int i) { + m_TStatusIn[i] = new wxStaticText(m_Controller[i], IDT_STATUS_IN, wxT("In")); + m_TStatusOut[i] = new wxStaticText(m_Controller[i], IDT_STATUS_OUT, wxT("Out")); + m_gStatusIn[i] = new wxStaticBoxSizer( wxHORIZONTAL, m_Controller[i], wxT("Main-stick (In) (Out)")); + m_pInStatus[i] = new wxPanel(m_Controller[i], ID_INSTATUS1 + i, wxDefaultPosition, wxDefaultSize); m_bmpSquare[i] = new wxStaticBitmap(m_pInStatus[i], ID_STATUSBMP1 + i, CreateBitmap(), //wxPoint(4, 15), wxSize(70,70)); diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.cpp index a92dc18710..438877fd2c 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.cpp @@ -472,7 +472,7 @@ void ConfigBox::UpdateGUI(int _notebookpage) } // Update the GUI from PadMapping[] - UpdateGUIKeys(_notebookpage); + UpdateGUIButtonMapping(_notebookpage); // Collect status bool Hat = (PadMapping[_notebookpage].controllertype == InputCommon::CTL_DPAD_HAT); @@ -857,17 +857,13 @@ void ConfigBox::CreateGUIControls() // Advanced settings // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ - // Populate input status - /**/ + // Input status controls // Input status text - m_TStatusIn[i] = new wxStaticText(m_Controller[i], IDT_STATUS_IN, wxT("In")); - m_TStatusOut[i] = new wxStaticText(m_Controller[i], IDT_STATUS_OUT, wxT("Out")); - - m_gStatusIn[i] = new wxStaticBoxSizer( wxHORIZONTAL, m_Controller[i], wxT("Main-stick (In) (Out)")); CreateAdvancedControls(i); - m_GBAdvancedMainStick[i] = new wxGridBagSizer(0, 0); + // Sizers + m_GBAdvancedMainStick[i] = new wxGridBagSizer(0, 0); m_GBAdvancedMainStick[i]->Add(m_pInStatus[i], wxGBPosition(0, 0), wxGBSpan(1, 1), wxALL, 0); m_GBAdvancedMainStick[i]->Add(m_pOutStatus[i], wxGBPosition(0, 1), wxGBSpan(1, 1), wxLEFT, 5); m_GBAdvancedMainStick[i]->Add(m_TStatusIn[i], wxGBPosition(1, 0), wxGBSpan(1, 1), wxALL, 0); @@ -979,7 +975,9 @@ void ConfigBox::CreateGUIControls() // -------------------------------------------------------------------- // Debugging // ----------------------------- - //m_pStatusBar = new wxStaticText(this, IDT_DEBUGGING, wxT("Debugging"), wxPoint(135, 100), wxDefaultSize); + #ifdef SHOW_PAD_STATUS + m_pStatusBar = new wxStaticText(this, IDT_DEBUGGING, wxT("Debugging"), wxPoint(135, 100), wxDefaultSize); + #endif //m_pStatusBar2 = new wxStaticText(this, IDT_DEBUGGING2, wxT("Debugging2"), wxPoint(125, 200), wxDefaultSize); //m_pStatusBar->SetLabel(wxString::Format("Debugging text")); diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.h b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.h index 80823dc868..bfc022a9b6 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.h +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigBox.h @@ -48,6 +48,7 @@ #include #include +#include "../nJoy.h" class ConfigBox : public wxDialog { @@ -317,7 +318,7 @@ class ConfigBox : public wxDialog wxBitmap CreateBitmap(); wxBitmap CreateBitmapDot(); void PadGetStatus(); void Update(); - void UpdateGUIKeys(int controller); + void UpdateGUIButtonMapping(int controller); void SaveButtonMapping(int controller, bool DontChangeId = false, int FromSlot = -1); void SaveButtonMappingAll(int Slot); void UpdateGUIAll(int Slot); diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp index 0c697a6aaf..51646b7859 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp @@ -45,7 +45,7 @@ extern bool g_EmulatorRunning; // Set dialog items from saved values // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -void ConfigBox::UpdateGUIKeys(int controller) +void ConfigBox::UpdateGUIButtonMapping(int controller) { // http://wiki.wxwidgets.org/Converting_everything_to_and_from_wxString wxString tmp; @@ -244,22 +244,6 @@ wxString ConfigBox::GetButtonText(int id, int Page) // ŻŻŻŻŻŻŻŻŻŻ -// Avoid extreme axis values -// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ -/* Function: We have to avoid very big values to becuse some triggers are -0x8000 in the - unpressed state (and then go from -0x8000 to 0x8000 as they are fully pressed) */ -bool AvoidValues(int value) -{ - // Avoid detecting very small or very big (for triggers) values - // for the record, the only accepted value's were between -6000 & -2000 and between 2000 & 6000 - if( (value > -0x2000 && value < 0x2000)) // Small values - //|| (value < -0x6000 || value > 0x6000)) // Big values. might intervene with alot of controllers as they go way above 6000 - return true; // Avoid - else - return false; // Keep -} - - // Wait for button press // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ /* Loop or timer: There are basically two ways to do this. With a while() or for() loop, or with a @@ -272,6 +256,7 @@ void ConfigBox::GetButtons(wxCommandEvent& event) { DoGetButtons(event.GetId()); } + void ConfigBox::DoGetButtons(int GetId) { // ============================================= @@ -280,6 +265,16 @@ void ConfigBox::DoGetButtons(int GetId) // Get the current controller int Controller = notebookpage; + int PadID = PadMapping[Controller].ID; + + /* Open a new joystick. Joysticks[controller].GetId is the system GetId of the physical joystick + that is mapped to controller, for example 0, 1, 2, 3 for the first four PadMapping */ + SDL_Joystick *joy = SDL_JoystickOpen(0); + + // Get the number of axes, hats and buttons + int buttons = SDL_JoystickNumButtons(joy); + int axes = SDL_JoystickNumAxes(joy); + int hats = SDL_JoystickNumHats(joy); // Get the controller and trigger type int ControllerType = PadMapping[Controller].controllertype; @@ -300,24 +295,17 @@ void ConfigBox::DoGetButtons(int GetId) 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 - /* Open a new joystick. Joysticks[controller].GetId is the system GetId of the physical joystick - that is mapped to controller, for example 0, 1, 2, 3 for the first four PadMapping */ - SDL_Joystick *joy = SDL_JoystickOpen(PadMapping[Controller].ID); - - // Get the number of axes, hats and buttons - int buttons = SDL_JoystickNumButtons(joy); - int axes = SDL_JoystickNumAxes(joy); - int hats = SDL_JoystickNumHats(joy); - - // Declare values + // Values used in this function char format[128]; - int value; // Axis value - int type; // Button type - bool Succeed = false; - bool Stop = false; // Stop the timer - int pressed = 0; 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 // ======================= //Console::Print("Before (%i) Id:%i %i IsRunning:%i\n", @@ -358,90 +346,10 @@ void ConfigBox::DoGetButtons(int GetId) // If there is a timer but we should not create a new one else { - // Update the internal status - SDL_JoystickUpdate(); - - // For the triggers we accept both a digital or an analog button - if(Axis) - { - for(int i = 0; i < axes; i++) - { - value = SDL_JoystickGetAxis(joy, i); - - if(AvoidValues(value)) continue; // Avoid values - - pressed = i + (LeftRight ? 1000 : 0); // Identify the analog triggers - type = InputCommon::CTL_AXIS; - Succeed = true; - } - } - - // Check for a hat - if(Hat) - { - for(int i = 0; i < hats; i++) - { - if(SDL_JoystickGetHat(joy, i)) - { - pressed = i; - type = InputCommon::CTL_HAT; - Succeed = true; - } - } - } - - // Check for a button - if(Button) - { - for(int i = 0; i < buttons; i++) - { - // Some kind of bug in SDL 1.3 would give button 9 and 10 (nonexistent) the value 48 on the 360 pad - if (SDL_JoystickGetButton(joy, i) > 1) continue; - - if(SDL_JoystickGetButton(joy, i)) - { - pressed = i; - type = InputCommon::CTL_BUTTON; - Succeed = true; - } - } - } - - // Check for a XInput trigger - #ifdef _WIN32 - if(XInput) - { - for(int i = 0; i <= InputCommon::XI_TRIGGER_R; i++) - { - if(XInput::GetXI(0, i)) - { - pressed = i + 1000; - type = InputCommon::CTL_AXIS; - Succeed = true; - } - } - } - #endif - - // Check for keyboard action - if (g_Pressed && Button) - { - // Todo: Add a separate keyboard vector to remove this restriction - if(g_Pressed >= buttons) - { - pressed = g_Pressed; - type = InputCommon::CTL_BUTTON; - Succeed = true; - g_Pressed = 0; - if(pressed == WXK_ESCAPE) pressed = -1; // Check for the exape key - } - else - { - pressed = g_Pressed; - g_Pressed = -1; - Stop = true; - } - } + InputCommon::GetButton( + joyinfo[PadID].joy, PadID, joyinfo[PadID].NumButtons, joyinfo[PadID].NumAxes, joyinfo[PadID].NumHats, + g_Pressed, value, type, pressed, Succeed, Stop, + LeftRight, Axis, XInput, Button, Hat); } // ========================= Check for keys @@ -508,9 +416,6 @@ void ConfigBox::DoGetButtons(int GetId) } // ======================== Process results - // We don't need this gamepad handle any more - if(SDL_JoystickOpened(PadMapping[Controller].ID)) SDL_JoystickClose(joy); - // Debugging /* Console::Print("Change: %i %i %i %i '%s' '%s' '%s' '%s'\n", @@ -518,5 +423,4 @@ void ConfigBox::DoGetButtons(int GetId) m_JoyButtonHalfpress[0]->GetValue().c_str(), m_JoyButtonHalfpress[1]->GetValue().c_str(), m_JoyButtonHalfpress[2]->GetValue().c_str(), m_JoyButtonHalfpress[3]->GetValue().c_str() );*/ } - /////////////////////////////////////////////////////////// Configure button mapping diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp index e21942bd54..7853dfafbb 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp @@ -308,17 +308,16 @@ void Shutdown() if(SDL_JoystickOpened(PadMapping[i].ID)) SDL_JoystickClose(PadState[i].joy); } - SDL_Quit(); + // Clear the physical device info + joyinfo.clear(); + + // Finally close SDL + if (SDL_WasInit(0)) SDL_Quit(); #ifdef _DEBUG DEBUG_QUIT(); #endif - // Clear the physical device info - //delete [] joyinfo; - //joyinfo = NULL; - joyinfo.clear(); - g_EmulatorRunning = false; #ifdef _WIN32 diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.h b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.h index 8377b5c003..669d7907e4 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.h +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.h @@ -35,6 +35,9 @@ // ŻŻŻŻŻŻŻŻŻŻ // Set this if you want to use the rumble 'hack' for controller one //#define USE_RUMBLE_DINPUT_HACK + +// Show a status window with the detected axes, buttons and so on +//#define SHOW_PAD_STATUS //////////////////////////