diff --git a/Source/Core/InputCommon/Src/Configuration.cpp b/Source/Core/InputCommon/Src/Configuration.cpp index 4756692974..ded3168bba 100644 --- a/Source/Core/InputCommon/Src/Configuration.cpp +++ b/Source/Core/InputCommon/Src/Configuration.cpp @@ -41,6 +41,20 @@ namespace InputCommon { +////////////////////////////////////////////////////////////////////////////////////////// +// Degree to radian and back +// ŻŻŻŻŻŻŻŻŻŻŻŻŻ +float Deg2Rad(float Deg) +{ + return Deg * (M_PI / 180.0); +} +float Rad2Deg(float Rad) +{ + return (Rad * 180.0) / M_PI; +} +///////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////////////////////// // Convert stick values // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ @@ -71,7 +85,7 @@ int Pad_Convert(int _val) return _val; } - +////////////////////////////////////////////////////////////////////////////////////////// /* Convert the stick raidus from a circular to a square. I don't know what input values the actual GC controller produce for the GC, it may be a square, a circle or something in between. But one thing that is certain is that PC pads differ in their output (as @@ -88,23 +102,24 @@ int Pad_Convert(int _val) GameCube Controller (Third Party) with EMS TrioLinker Plus II: 60% */ // ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ + +/* Calculate the distance from the center of the current stick coordinates. The distance is defined + as at most sqrt(2) in the corners */ float SquareDistance(float deg) { // See if we have to adjust the angle deg = abs(deg); if( (deg > 45 && deg < 135) ) deg = deg - 90; - // Calculate radians from degrees - float rad = deg * M_PI / 180; - - float val = abs(cos(rad)); + float val = abs(cos(Deg2Rad(deg))); float dist = 1 / val; // Calculate distance from center //m_frame->m_pStatusBar2->SetLabel(wxString::Format("Deg:%f Val:%f Dist:%f", deg, val, dist)); return dist; } -std::vector Pad_Square_to_Circle(int _x, int _y, int _pad, CONTROLLER_MAPPING _PadMapping) +// Produce the circle from the original +std::vector Square2Circle(int _x, int _y, int _pad, std::string SDiagonal, bool Circle2Square) { /* Do we need this? */ if(_x > 32767) _x = 32767; if(_y > 32767) _y = 32767; // upper limit @@ -113,41 +128,51 @@ std::vector Pad_Square_to_Circle(int _x, int _y, int _pad, CONTROLLER_MAPPI // ==================================== // Convert to circle // ----------- - int Tmp = atoi (_PadMapping.SDiagonal.substr(0, _PadMapping.SDiagonal.length() - 1).c_str()); + // Get the manually configured diagonal distance + int Tmp = atoi (SDiagonal.substr(0, SDiagonal.length() - 1).c_str()); float Diagonal = Tmp / 100.0; // First make a perfect square in case we don't have one already float OrigDist = sqrt( pow((float)_y, 2) + pow((float)_x, 2) ); // Get current distance - float rad = atan2((float)_y, (float)_x); // Get current angle - float deg = rad * 180 / M_PI; + float deg = Rad2Deg(atan2((float)_y, (float)_x)); // Get current angle - // A diagonal of 85% means a distance of 1.20 - float corner_circle_dist = ( Diagonal / sin(45 * M_PI / 180) ); + // A diagonal of 85% means a maximum distance of 0.85 * sqrt(2) ~1.2 in the diagonals + float corner_circle_dist = ( Diagonal / sin(Deg2Rad(45)) ); float SquareDist = SquareDistance(deg); - float adj_ratio1; // The original-to-square distance adjustment - float adj_ratio2 = SquareDist; // The circle-to-square distance adjustment - // float final_ratio; // The final adjustment to the current distance //TODO: This is not used - float result_dist; // The resulting distance + // The original-to-square distance adjustment + float adj_ratio1; + // The circle-to-square distance adjustment + float adj_ratio2 = SquareDist; + // The resulting distance + float result_dist; // Calculate the corner-to-square adjustment ratio if(corner_circle_dist < SquareDist) adj_ratio1 = SquareDist / corner_circle_dist; else adj_ratio1 = 1; // Calculate the resulting distance - result_dist = OrigDist * adj_ratio1 / adj_ratio2; - - float x = result_dist * cos(rad); // calculate x - float y = result_dist * sin(rad); // calculate y - + if(Circle2Square) + result_dist = OrigDist * adj_ratio1; + else + result_dist = OrigDist * adj_ratio1 / adj_ratio2; + + // Calculate x and y and return it + float x = result_dist * cos(Deg2Rad(deg)); + float y = result_dist * sin(Deg2Rad(deg)); + // Make integers int int_x = (int)floor(x); int int_y = (int)floor(y); + // Boundaries + if (int_x < -32767) int_x = -32767; if (int_x > 32767) int_x = 32767; + if (int_y < -32767) int_y = -32767; if (int_y > 32767) int_y = 32767; + // Return it + std::vector vec; + vec.push_back(int_x); + vec.push_back(int_y); // Debugging //m_frame->m_pStatusBar2->SetLabel(wxString::Format("%f %f %i", corner_circle_dist, Diagonal, Tmp)); - std::vector vec; - vec.push_back(int_x); - vec.push_back(int_y); return vec; } ///////////////////////////////////////////////////////////////////// diff --git a/Source/Core/InputCommon/Src/SDL.h b/Source/Core/InputCommon/Src/SDL.h index b6da81d6cb..e6e3a0d683 100644 --- a/Source/Core/InputCommon/Src/SDL.h +++ b/Source/Core/InputCommon/Src/SDL.h @@ -187,6 +187,7 @@ struct CONTROLLER_MAPPING_NEW // GC PAD MAPPING int triggertype; // SDL or XInput trigger std::string SDiagonal; bool bSquareToCircle; + bool bCircle2Square; }; //////////////////////////// @@ -201,8 +202,10 @@ void GetJoyState(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, in void GetButton(SDL_Joystick*, int,int,int,int, int&,int&,int&,int&,bool&,bool&, bool,bool,bool,bool,bool,bool); // Value conversion +float Deg2Rad(float Deg); +float Rad2Deg(float Rad); int Pad_Convert(int _val); -std::vector Pad_Square_to_Circle(int _x, int _y, int _pad, CONTROLLER_MAPPING _PadMapping); +std::vector Square2Circle(int _x, int _y, int _pad, std::string SDiagonal, bool Circle2Square = false); #ifndef _SDL_MAIN_ extern int g_LastPad; diff --git a/Source/Plugins/Plugin_Wiimote/Src/Config.cpp b/Source/Plugins/Plugin_Wiimote/Src/Config.cpp index e7231db045..efe508c932 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/Config.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/Config.cpp @@ -62,9 +62,8 @@ void Config::Load(bool ChangePad) std::string SectionName = StringFromFormat("Wiimote%i", i + 1); iniFile.Get(SectionName.c_str(), "NoTriggerFilter", &bNoTriggerFilter, false); iniFile.Get(SectionName.c_str(), "TriggerType", &Trigger.Type, TRIGGER_OFF); - iniFile.Get(SectionName.c_str(), "TriggerRange", &Trigger.Range, 50); - iniFile.Get(SectionName.c_str(), "TriggerRoll", &Trigger.Roll, false); - iniFile.Get(SectionName.c_str(), "TriggerPitch", &Trigger.Pitch, false); + iniFile.Get(SectionName.c_str(), "TriggerRollRange", &Trigger.Range.Roll, 50); + iniFile.Get(SectionName.c_str(), "TriggerPitchRange", &Trigger.Range.Pitch, false); // Don't update this when we are loading settings from the ConfigBox if(!ChangePad) @@ -99,7 +98,7 @@ void Config::Load(bool ChangePad) 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); + iniFile.Get(SectionName.c_str(), "Circle2Square", &WiiMoteEmu::PadMapping[i].bCircle2Square, false); } // ============================= Console::Print("Load()\n"); @@ -134,9 +133,8 @@ void Config::Save(int Slot) iniFile.Set(SectionName.c_str(), "Enabled", WiiMoteEmu::PadMapping[i].enabled); iniFile.Set(SectionName.c_str(), "NoTriggerFilter", bNoTriggerFilter); iniFile.Set(SectionName.c_str(), "TriggerType", Trigger.Type); - iniFile.Set(SectionName.c_str(), "TriggerRange", Trigger.Range); - iniFile.Set(SectionName.c_str(), "TriggerRoll", Trigger.Roll); - iniFile.Set(SectionName.c_str(), "TriggerPitch", Trigger.Pitch); + iniFile.Set(SectionName.c_str(), "TriggerRollRange", Trigger.Range.Roll); + iniFile.Set(SectionName.c_str(), "TriggerPitchRange", Trigger.Range.Pitch); // Save the physical device ID number iniFile.Set(SectionName.c_str(), "DeviceID", WiiMoteEmu::PadMapping[i].ID); @@ -165,8 +163,8 @@ void Config::Save(int Slot) //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.Set(SectionName.c_str(), "Diagonal", WiiMoteEmu::PadMapping[i].SDiagonal); + iniFile.Set(SectionName.c_str(), "Circle2Square", WiiMoteEmu::PadMapping[i].bCircle2Square); // ====================================== } diff --git a/Source/Plugins/Plugin_Wiimote/Src/Config.h b/Source/Plugins/Plugin_Wiimote/Src/Config.h index cee8967188..cabfb50135 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/Config.h +++ b/Source/Plugins/Plugin_Wiimote/Src/Config.h @@ -24,12 +24,16 @@ struct Config void Load(bool ChangePad = false); void Save(int Slot = -1); + struct PadRange + { + int Roll; + int Pitch; + }; + struct PadTrigger { int Type; - int Range; - int Roll; - int Pitch; + PadRange Range; }; enum ETriggerType diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp index 3deec285ab..7111c3c474 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp @@ -102,9 +102,10 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog) // Gamepad EVT_COMBOBOX(ID_TRIGGER_TYPE, ConfigDialog::GeneralSettingsChanged) EVT_COMBOBOX(ID_TILT_INPUT, ConfigDialog::GeneralSettingsChanged) - EVT_COMBOBOX(ID_TILT_RANGE, ConfigDialog::GeneralSettingsChanged) - EVT_COMBOBOX(IDC_JOYNAME, ConfigDialog::GeneralSettingsChanged) - + EVT_COMBOBOX(ID_TILT_RANGE_ROLL, ConfigDialog::GeneralSettingsChanged) + EVT_COMBOBOX(ID_TILT_RANGE_PITCH, ConfigDialog::GeneralSettingsChanged) + EVT_COMBOBOX(IDCB_LEFT_DIAGONAL, ConfigDialog::GeneralSettingsChanged) + EVT_CHECKBOX(IDC_LEFT_C2S, ConfigDialog::GeneralSettingsChanged) EVT_BUTTON(IDB_ANALOG_LEFT_X, ConfigDialog::GetButtons) EVT_BUTTON(IDB_ANALOG_LEFT_Y, ConfigDialog::GetButtons) @@ -387,8 +388,9 @@ void ConfigDialog::CreateGUIControls() StrTilt.Add(wxString::FromAscii("Analog stick")); StrTilt.Add(wxString::FromAscii("Triggers")); // The range is in degrees and are set at even 5 degrees values - wxArrayString StrTiltRange; - for (int i = 2; i < 19; i++) StrTiltRange.Add(wxString::Format(wxT("%i"), i*5)); + wxArrayString StrTiltRangeRoll, StrTiltRangePitch; + for (int i = 0; i < 37; i++) StrTiltRangeRoll.Add(wxString::Format(wxT("%i"), i*5)); + for (int i = 0; i < 37; i++) StrTiltRangePitch.Add(wxString::Format(wxT("%i"), i*5)); // The Trigger type list wxArrayString StrTriggerType; @@ -409,7 +411,7 @@ void ConfigDialog::CreateGUIControls() 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(ChW, -1)); + m_WiimoteOnline[i] = new wxCheckBox(m_Controller[i], IDC_WIMOTE_ON, 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(ChW, -1)); m_WideScreen[i] = new wxCheckBox(m_Controller[i], ID_WIDESCREEN, wxT("WideScreen Mode (for correct aiming)")); @@ -494,15 +496,45 @@ void ConfigDialog::CreateGUIControls() // Controller // ----------------------------- /**/ - // Controls - m_Joyname[i] = new wxComboBox(m_Controller[i], IDC_JOYNAME, StrJoyname[0], wxDefaultPosition, wxSize(225, -1), StrJoyname, wxCB_READONLY); + // Controller + m_Joyname[i] = new wxComboBox(m_Controller[i], IDC_JOYNAME, StrJoyname[0], wxDefaultPosition, wxSize(205, -1), StrJoyname, wxCB_READONLY); + + // Circle to square + m_CheckC2S[i] = new wxCheckBox(m_Controller[i], IDC_LEFT_C2S, wxT("Circle to square")); - 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); + // The label + m_CheckC2SLabel[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Diagonal")); + + // The drop down menu for the circle to square adjustment + wxArrayString asStatusInSet; + asStatusInSet.Add(wxT("100%")); + asStatusInSet.Add(wxT("95%")); + asStatusInSet.Add(wxT("90%")); + asStatusInSet.Add(wxT("85%")); + asStatusInSet.Add(wxT("80%")); + m_ComboDiagonal[i] = new wxComboBox(m_Controller[i], IDCB_LEFT_DIAGONAL, asStatusInSet[0], wxDefaultPosition, wxDefaultSize, asStatusInSet, wxCB_READONLY); // Tooltips m_Joyname[i]->SetToolTip(wxT("Save your settings and configure another joypad")); - + m_CheckC2S[i]->SetToolTip(wxT( + "This will convert a circular stick radius to a square stick radius." + " This can be useful for the pitch and roll emulation." + )); + m_CheckC2SLabel[i]->SetToolTip(wxT( + "To produce a perfect square circle in the 'Out' window you have to manually set" + "\nyour diagonal values here from what is shown in the 'In' window." + )); + + // Sizers + m_gCircle2Square[i] = new wxBoxSizer(wxHORIZONTAL); + m_gCircle2Square[i]->Add(m_CheckC2SLabel[i], 0, (wxUP), 4); + m_gCircle2Square[i]->Add(m_ComboDiagonal[i], 0, (wxLEFT), 2); + + m_gJoyname[i] = new wxStaticBoxSizer (wxVERTICAL, m_Controller[i], wxT("Gamepad")); + m_gJoyname[i]->Add(m_Joyname[i], 0, wxALIGN_CENTER | (wxLEFT | wxRIGHT | wxDOWN), 5); + m_gJoyname[i]->Add(m_CheckC2S[i], 0, wxALIGN_CENTER | (wxLEFT | wxRIGHT | wxDOWN), 5); + m_gJoyname[i]->Add(m_gCircle2Square[i], 0, wxALIGN_CENTER | (wxLEFT | wxRIGHT | wxDOWN), 5); + // -------------------------------------------------------------------- // Tilt Wiimote @@ -510,26 +542,35 @@ void ConfigDialog::CreateGUIControls() /**/ // Controls m_TiltComboInput[i] = new wxComboBox(m_Controller[i], ID_TILT_INPUT, StrTilt[0], wxDefaultPosition, wxDefaultSize, StrTilt, wxCB_READONLY); - m_TiltComboRange[i] = new wxComboBox(m_Controller[i], ID_TILT_RANGE, StrTiltRange[0], wxDefaultPosition, wxDefaultSize, StrTiltRange, wxCB_READONLY); - m_TiltText[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Range")); + m_TiltComboRangeRoll[i] = new wxComboBox(m_Controller[i], ID_TILT_RANGE_ROLL, StrTiltRangeRoll[0], wxDefaultPosition, wxDefaultSize, StrTiltRangeRoll, wxCB_READONLY); + m_TiltComboRangePitch[i] = new wxComboBox(m_Controller[i], ID_TILT_RANGE_PITCH, StrTiltRangePitch[0], wxDefaultPosition, wxDefaultSize, StrTiltRangePitch, wxCB_READONLY); + m_TiltTextRoll[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Roll Range")); + m_TiltTextPitch[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Pitch Range")); - m_TiltHoriz[i] = new wxBoxSizer(wxHORIZONTAL); - m_TiltHoriz[i]->Add(m_TiltText[i], 0, (wxLEFT | wxTOP), 4); - m_TiltHoriz[i]->Add(m_TiltComboRange[i], 0, (wxLEFT | wxRIGHT), 5); - - m_gTilt[i] = new wxStaticBoxSizer (wxVERTICAL, m_Controller[i], wxT("Tilt Wiimote")); + m_TiltGrid[i] = new wxGridBagSizer(0, 0); + m_TiltGrid[i]->Add(m_TiltTextRoll[i], wxGBPosition(0, 0), wxGBSpan(1, 1), (wxTOP), 4); + m_TiltGrid[i]->Add(m_TiltComboRangeRoll[i], wxGBPosition(0, 1), wxGBSpan(1, 1), (wxLEFT), 2); + m_TiltGrid[i]->Add(m_TiltTextPitch[i], wxGBPosition(1, 0), wxGBSpan(1, 1), (wxTOP), 4); + m_TiltGrid[i]->Add(m_TiltComboRangePitch[i], wxGBPosition(1, 1), wxGBSpan(1, 1), (wxLEFT | wxTOP | wxDOWN), 2); + + // For additional padding options if needed + //m_TiltHoriz[i] = new wxBoxSizer(wxHORIZONTAL); + + m_gTilt[i] = new wxStaticBoxSizer (wxVERTICAL, m_Controller[i], wxT("Roll and pitch")); m_gTilt[i]->AddStretchSpacer(); m_gTilt[i]->Add(m_TiltComboInput[i], 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5); - m_gTilt[i]->Add(m_TiltHoriz[i], 0, wxEXPAND | (wxLEFT | wxRIGHT), 5); + m_gTilt[i]->Add(m_TiltGrid[i], 0, wxEXPAND | (wxLEFT | wxRIGHT), 5); m_gTilt[i]->AddStretchSpacer(); //Set values m_TiltComboInput[i]->SetSelection(g_Config.Trigger.Type); - m_TiltComboRange[i]->SetValue(wxString::Format(wxT("%i"), g_Config.Trigger.Range)); + m_TiltComboRangeRoll[i]->SetValue(wxString::Format(wxT("%i"), g_Config.Trigger.Range.Roll)); + m_TiltComboRangePitch[i]->SetValue(wxString::Format(wxT("%i"), g_Config.Trigger.Range.Pitch)); // Tooltips m_TiltComboInput[i]->SetToolTip(wxT("Control tilting by an analog gamepad stick, an analog trigger or the keyboard.")); - m_TiltComboRange[i]->SetToolTip(wxT("The maximum tilt in degrees")); + m_TiltComboRangeRoll[i]->SetToolTip(wxT("The maximum roll in degrees. Set to 0 to turn off.")); + m_TiltComboRangePitch[i]->SetToolTip(wxT("The maximum pitch in degrees. Set to 0 to turn off.")); // -------------------------------------------------------------------- // Analog triggers @@ -557,7 +598,7 @@ void ConfigDialog::CreateGUIControls() 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_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); @@ -586,11 +627,11 @@ void ConfigDialog::CreateGUIControls() 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_SizeAnalogTriggerHorizConfig[i], 0, (wxUP), 2); 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); + m_gTrigger[i]->Add(m_SizeAnalogTriggerVertRight[i], 0, wxEXPAND | (wxLEFT | wxRIGHT), 5); // -------------------------------------------------------------------- @@ -599,7 +640,7 @@ void ConfigDialog::CreateGUIControls() 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, wxEXPAND | (wxLEFT), 5); - m_HorizControllerTilt[i]->Add(m_gTrigger[i], 0, (wxLEFT), 5); + m_HorizControllerTilt[i]->Add(m_gTrigger[i], 0, wxEXPAND | (wxLEFT), 5); m_HorizControllerTiltParent[i] = new wxBoxSizer(wxBOTH); m_HorizControllerTiltParent[i]->Add(m_HorizControllerTilt[i]); @@ -1061,11 +1102,17 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event) case ID_TILT_INPUT: g_Config.Trigger.Type = m_TiltComboInput[Page]->GetSelection(); break; - case ID_TILT_RANGE: - m_TiltComboRange[Page]->GetValue().ToLong(&TmpValue); g_Config.Trigger.Range = TmpValue; + case ID_TILT_RANGE_ROLL: + m_TiltComboRangeRoll[Page]->GetValue().ToLong(&TmpValue); g_Config.Trigger.Range.Roll = TmpValue; + break; + case ID_TILT_RANGE_PITCH: + m_TiltComboRangePitch[Page]->GetValue().ToLong(&TmpValue); g_Config.Trigger.Range.Pitch = TmpValue; break; case IDC_JOYNAME: DoChangeJoystick(); + case IDCB_LEFT_DIAGONAL: + case IDC_LEFT_C2S: + SaveButtonMappingAll(Page); break; ////////////////////////// diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h index 8d4f245fb8..63425e0e81 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h @@ -84,26 +84,26 @@ class ConfigDialog : public wxDialog // Emulated Wiimote key settings wxBoxSizer *m_SizeBasicPadding[4], *m_SizeEmuPadding[4], *m_SizeRealPadding[4], *m_SizeExtensionsPadding[4], *m_SizeBasicGeneral[4], *m_SizeBasicGeneralLeft[4], *m_SizeBasicGeneralRight[4], - *m_HorizControllers[4], *m_HorizControllerTiltParent[4], *m_HorizControllerTilt[4], *m_TiltHoriz[4], + *m_HorizControllers[4], *m_gCircle2Square[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_TiltGrid[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], + wxStaticText *m_tAnalogX[8], *m_tAnalogY[8], *m_TiltTextRoll[4], *m_TiltTextPitch[4], + *m_CheckC2SLabel[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]; // Emulated Wiimote settings - wxCheckBox *m_SidewaysDPad[4], *m_WiimoteOnline[4]; - wxCheckBox *m_WideScreen[4]; + wxCheckBox *m_SidewaysDPad[4], *m_WiimoteOnline[4], *m_WideScreen[4]; + wxCheckBox *m_CheckC2S[4]; wxCheckBox *m_WiiMotionPlusConnected[4], *m_NunchuckConnected[4], *m_ClassicControllerConnected[4], *m_BalanceBoardConnected[4], *m_GuitarHeroGuitarConnected[4], *m_GuitarHeroWorldTourDrumsConnected[4]; - wxComboBox *m_TiltComboInput[4], *m_TiltComboRange[4], *m_Joyname[4], *m_TriggerType[4]; + wxComboBox *m_TiltComboInput[4], *m_TiltComboRangeRoll[4], *m_TiltComboRangePitch[4], *m_Joyname[4], *m_ComboDiagonal[4], *m_TriggerType[4]; // Real Wiimote settings wxCheckBox *m_ConnectRealWiimote[4], *m_UseRealWiimote[4], *m_UpdateMeters; @@ -147,7 +147,7 @@ class ConfigDialog : public wxDialog ID_SIDEWAYSDPAD, // Emulated ID_WIDESCREEN, ID_NUNCHUCKCONNECTED, ID_CLASSICCONTROLLERCONNECTED, - IDC_JOYNAME, IDC_JOYATTACH, + IDC_WIMOTE_ON, IDC_JOYNAME, IDC_LEFT_C2S, IDCB_LEFT_DIAGONAL, // Gamepad IDB_ANALOG_LEFT_X, IDB_ANALOG_LEFT_Y, @@ -159,7 +159,7 @@ class ConfigDialog : public wxDialog ID_TRIGGER_L, ID_TRIGGER_R, // Gamepad settings - ID_TRIGGER_TYPE, ID_TILT_INPUT, ID_TILT_RANGE, + ID_TRIGGER_TYPE, ID_TILT_INPUT, ID_TILT_RANGE_ROLL, ID_TILT_RANGE_PITCH, // Real ID_CONNECT_REAL, ID_USE_REAL, ID_UPDATE_REAL, IDT_STATUS, ID_NEUTRAL_CHOICE, diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigGamepad.cpp b/Source/Plugins/Plugin_Wiimote/Src/ConfigGamepad.cpp index eed8bbca5b..374bf37b28 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigGamepad.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigGamepad.cpp @@ -94,6 +94,8 @@ void ConfigDialog::SetButtonTextAll(int id, char text[128]) void ConfigDialog::SaveButtonMappingAll(int Slot) { + //Console::Print("SaveButtonMappingAll()\n"); + for (int i = 0; i < 4; i++) { // This can occur when no gamepad is detected @@ -127,8 +129,8 @@ void ConfigDialog::UpdateGUIButtonMapping(int controller) // 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); + m_ComboDiagonal[controller]->SetValue(wxString::FromAscii(WiiMoteEmu::PadMapping[controller].SDiagonal.c_str())); + m_CheckC2S[controller]->SetValue(WiiMoteEmu::PadMapping[controller].bCircle2Square); //LogMsg("m_TriggerType[%i] = %i\n", controller, PadMapping[controller].triggertype); } @@ -154,8 +156,8 @@ void ConfigDialog::SaveButtonMapping(int controller, bool DontChangeId, int From //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(); + WiiMoteEmu::PadMapping[controller].SDiagonal = m_ComboDiagonal[FromSlot]->GetLabel().mb_str(); + WiiMoteEmu::PadMapping[controller].bCircle2Square = m_CheckC2S[FromSlot]->IsChecked(); // The analog buttons m_AnalogLeftX[FromSlot]->GetValue().ToLong(&value); WiiMoteEmu::PadMapping[controller].Axis.Lx = value; tmp.clear(); @@ -167,8 +169,8 @@ void ConfigDialog::SaveButtonMapping(int controller, bool DontChangeId, int From 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()); + //Console::Print("WiiMoteEmu::PadMapping[%i].bSquareToCircle = %i, m_CheckC2S[%i]->GetValue() = %i\n", + // controller, WiiMoteEmu::PadMapping[controller].bSquareToCircle, FromSlot, m_CheckC2S[FromSlot]->GetValue()); // Replace "-1" with "" ToBlank(); @@ -496,14 +498,13 @@ void ConfigDialog::PadGetStatus() // 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) + // Produce square + if(WiiMoteEmu::PadMapping[Page].bCircle2Square) { - std::vector main_xy = InputCommon::Pad_Square_to_Circle(main_x, main_y, notebookpage, PadMapping[notebookpage]); + std::vector main_xy = InputCommon::Square2Circle(main_x, main_y, Page, WiiMoteEmu::PadMapping[Page].SDiagonal, true); main_x_after = main_xy.at(0); main_y_after = main_xy.at(1); - } - */ + } // float f_x = main_x / 32767.0; diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDynamics.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuDynamics.cpp index 4f0981f3e7..97609b1d86 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuDynamics.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDynamics.cpp @@ -44,84 +44,133 @@ namespace WiiMoteEmu { -void PitchDegreeToAccelerometer(float _Roll, float _Pitch, u8 &_x, u8 &_y, u8 &_z, bool RollOn, bool PitchOn) + +////////////////////////////////////////////////////////////////////////////////////////// +// Test the calculations +// ŻŻŻŻŻŻŻŻŻŻŻŻŻ +void TiltTest(u8 x, u8 y, u8 z) { - // Then don't update z either - if (!RollOn && ! PitchOn) return; + int Roll, Pitch, RollAdj, PitchAdj; + PitchAccelerometerToDegree(x, y, z, Roll, Pitch, RollAdj, PitchAdj); + std::string From = StringFromFormat("From: X:%i Y:%i Z:%i Roll:%s Pitch:%s", x, y, z, + (Roll >= 0) ? StringFromFormat(" %03i", Roll).c_str() : StringFromFormat("%04i", Roll).c_str(), + (Pitch >= 0) ? StringFromFormat(" %03i", Pitch).c_str() : StringFromFormat("%04i", Pitch).c_str()); - // Calculate the radian - float _RollRad = _Roll * M_PI / 180.0; - float _PitchRad = _Pitch * M_PI / 180.0; + float _Roll = (float)Roll, _Pitch = (float)Pitch; + PitchDegreeToAccelerometer(_Roll, _Pitch, x, y, z); + std::string To = StringFromFormat("%s\nTo: X:%i Y:%i Z:%i Roll:%s Pitch:%s", From.c_str(), x, y, z, + (_Roll >= 0) ? StringFromFormat(" %03i", (int)_Roll).c_str() : StringFromFormat("%04i", (int)_Roll).c_str(), + (_Pitch >= 0) ? StringFromFormat(" %03i", (int)_Pitch).c_str() : StringFromFormat("%04i", (int)_Pitch).c_str()); + Console::Print("%s\n", To.c_str()); +} +//////////////////////////////////// - // Calculate a good set of y and z values for the degree - float r = 1.0; - float fx = r * sin(_RollRad); // y - float fy = r * sin(_PitchRad); // y - float fz = r * cos(_PitchRad); // x - // Multiple with the neutral of z and its g + +////////////////////////////////////////////////////////////////////////////////////////// +// Angles to accelerometer values +// ŻŻŻŻŻŻŻŻŻŻŻŻŻ +void PitchDegreeToAccelerometer(float _Roll, float _Pitch, u8 &_x, u8 &_y, u8 &_z) +{ + // We need radiands for the math functions + _Roll = InputCommon::Deg2Rad(_Roll); + _Pitch = InputCommon::Deg2Rad(_Pitch); + // We need decimal values + float x = (float)_x, y = (float)_y, z = (float)_z; + + // In these cases we can use the simple and accurate formula + if(g_Config.Trigger.Range.Pitch == 0) + { + x = sin(_Roll); + z = cos(_Roll); + } + else if (g_Config.Trigger.Range.Roll == 0) + { + + y = sin(_Pitch); + z = cos(_Pitch); + } + else + { + // ==================================================== + /* This seems to always produce the exact same combination of x, y, z and Roll and Pitch that the + real Wiimote produce. There is an unlimited amount of x, y, z combinations for any combination of + Roll and Pitch. But if we select a Z from the smallest of the absolute value of cos(Roll) and + cos (Pitch) we get the right values. */ + // --------- + if (abs(cos(_Roll)) < abs(cos(_Pitch))) z = cos(_Roll); else z = cos(_Pitch); + /* I got these from reversing the calculation in PitchAccelerometerToDegree() in a math program + I don't know if we can derive these from some kind of matrix or something */ + float x_num = 2 * tan(0.5 * _Roll) * z; + float x_den = pow(tan(0.5 * _Roll),2) - 1; + x = - (x_num / x_den); + float y_num = 2 * tan(0.5 * _Pitch) * z; + float y_den = pow(tan(0.5 * _Pitch), 2) - 1; + y = - (y_num / y_den); + // ========================= + } + + // Multiply with the neutral of z and its g float xg = g_accel.cal_g.x; float yg = g_accel.cal_g.y; float zg = g_accel.cal_g.z; float x_zero = g_accel.cal_zero.x; float y_zero = g_accel.cal_zero.y; float z_zero = g_accel.cal_zero.z; - fx = (int) (x_zero + xg * fx); - fy = (int) (y_zero + yg * fy); - fz = (int) (z_zero + zg * fz); + int ix = (int) (x_zero + xg * x); + int iy = (int) (y_zero + yg * y); + int iz = (int) (z_zero + zg * z); // Boundaries - int ix = (int)fx; - int iy = (int)fy; - int iz = (int)fz; if (ix < 0) ix = 0; if (ix > 255) ix = 255; if (iy < 0) iy = 0; if (iy > 255) iy = 255; if (iz < 0) iz = 0; if (iz > 255) iz = 255; - if (RollOn) _x = ix; - if (PitchOn) _y = iy; + if(g_Config.Trigger.Range.Roll != 0) _x = ix; + if(g_Config.Trigger.Range.Pitch != 0) _y = iy; _z = iz; } -// The pitch and roll in 360° -void PitchAccelerometerToDegree(u8 _x, u8 _y, u8 _z, int &_Roll, int &_Pitch) +////////////////////////////////////////////////////////////////////////////////////////// +// Accelerometer to roll and pitch angles +// ŻŻŻŻŻŻŻŻŻŻŻŻŻ +void PitchAccelerometerToDegree(u8 _x, u8 _y, u8 _z, int &_Roll, int &_Pitch, int &_RollAdj, int &_PitchAdj) { /* find out how much it has to move to be 1g */ float xg = (float)g_accel.cal_g.x; float yg = (float)g_accel.cal_g.y; float zg = (float)g_accel.cal_g.z; - float Pitch = 0, Roll = 0; + float Roll = 0, Pitch = 0; - /* find out how much it actually moved and normalize to +/- 1g */ - float x = ((float)_x - (float)g_accel.cal_zero.x) / xg; - float y = ((float)_y - (float)g_accel.cal_zero.y) / yg; + // Calculate how many g we are from the neutral + float x = ((float)_x - (float)g_accel.cal_zero.x) / xg; + float y = ((float)_y - (float)g_accel.cal_zero.y) / yg; float z = ((float)_z - (float)g_accel.cal_zero.z) / zg; - /* make sure x,y,z are between -1 and 1 for the tan function */ - if (x < -1.0) x = -1.0; - else if (x > 1.0) x = 1.0; - if (y < -1.0) y = -1.0; - else if (y > 1.0) y = 1.0; - if (z < -1.0) z = -1.0; - else if (z > 1.0) z = 1.0; - // If it is over 1g then it is probably accelerating and may not reliable //if (abs(accel->x - ac->cal_zero.x) <= ac->cal_g.x) { - // Calculate the radian - Roll = atan2(x, z); - // Calculate the degree - Roll = (Roll * 180.0) / M_PI; + // Calculate the degree + Roll = InputCommon::Rad2Deg(atan2(x, z)); } //if (abs(_y - g_accel.cal_zero.y) <= g_accel.cal_g.y) { - // Calculate the radian - Pitch = atan2(y, z); - // Calculate the degree - Pitch = (Pitch * 180.0) / M_PI; + // Calculate the degree + Pitch = InputCommon::Rad2Deg(atan2(y, z)); } - _Roll = Roll; - _Pitch = Pitch; + + _Roll = (int)Roll; + _Pitch = (int)Pitch; + + /* Don't allow forces bigger than 1g */ + if (x < -1.0) x = -1.0; else if (x > 1.0) x = 1.0; + if (y < -1.0) y = -1.0; else if (y > 1.0) y = 1.0; + if (z < -1.0) z = -1.0; else if (z > 1.0) z = 1.0; + Roll = InputCommon::Rad2Deg(atan2(x, z)); + Pitch = InputCommon::Rad2Deg(atan2(y, z)); + + _RollAdj = (int)Roll; + _PitchAdj = (int)Pitch; } } // WiiMoteEmu \ No newline at end of file diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h index da9a89c980..2652f23932 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h @@ -51,9 +51,10 @@ 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); -void PitchDegreeToAccelerometer(float _Roll, float _Pitch, u8 &_x, u8 &_y, u8 &_z, bool RollOn, bool PitchOn); -void PitchAccelerometerToDegree(u8 _x, u8 _y, u8 _z, int &_Roll, int &_Pitch); - +void PitchDegreeToAccelerometer(float _Roll, float _Pitch, u8 &_x, u8 &_y, u8 &_z); +void PitchAccelerometerToDegree(u8 _x, u8 _y, u8 _z, int &_Roll, int &_Pitch, int&, int&); +void TiltTest(u8 x, u8 y, u8 z); +void Tilt(u8 &_x, u8 &_y, u8 &_z); }; // WiiMoteEmu diff --git a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp index 598c7e42e0..86a03e07a7 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp @@ -322,7 +322,7 @@ void FillReportInfo(wm_core& _core) //int consoleDisplay = 0; // For all functions -u8 x, y, z, X, Y, Z; +u8 g_x, g_y, g_z, g_X, g_Y, g_Z; // For the shake function int shake = -1; @@ -351,23 +351,24 @@ void SingleShake(u8 &_z, u8 &_y) } else if(shake == 1) { - _z = Z; - _y = Y; + _z = g_Z; + _y = g_Y; shake = -1; } else // the default Z if nothing is pressed { - _z = Z; + _z = g_Z; } #endif } + // ------------------------------------------ /* Tilting Wiimote with gamepad. We can guess that the game will calculate a Wiimote pitch and use it as a measure of the tilting of the Wiimote. We are interested in this tilting range 90° to -90° */ // --------------- -void TiltWiimoteGamepad(u8 &_x, u8 &_y, u8 &_z) +void TiltWiimoteGamepad(float &Roll, float &Pitch) { // Return if we have no pads if (NumGoodPads == 0) return; @@ -376,6 +377,15 @@ void TiltWiimoteGamepad(u8 &_x, u8 &_y, u8 &_z) const int Page = 0; WiiMoteEmu::GetJoyState(PadState[Page], PadMapping[Page], Page, joyinfo[PadMapping[Page].ID].NumButtons); + // Check if we should make adjustments + if(PadMapping[Page].bCircle2Square) + { + std::vector main_xy = InputCommon::Square2Circle(PadState[Page].Axis.Lx, PadState[Page].Axis.Ly, Page, PadMapping[Page].SDiagonal, true); + + PadState[Page].Axis.Lx = main_xy.at(0); + PadState[Page].Axis.Ly = main_xy.at(1); + } + // Convert the big values float Lx = (float)InputCommon::Pad_Convert(PadState[Page].Axis.Lx); float Ly = (float)InputCommon::Pad_Convert(PadState[Page].Axis.Ly); @@ -394,11 +404,9 @@ void TiltWiimoteGamepad(u8 &_x, u8 &_y, u8 &_z) Tr = (float)PadState[Page].Axis.Tr; } - // It's easier to use a float here - float Roll = 0; - float Pitch = 0; // Save the Range in degrees, 45° and 90° are good values in some games - float Range = (float)g_Config.Trigger.Range; + float RollRange = (float)g_Config.Trigger.Range.Roll; + float PitchRange = (float)g_Config.Trigger.Range.Pitch; // Trigger if (g_Config.Trigger.Type == g_Config.TRIGGER) @@ -407,59 +415,49 @@ void TiltWiimoteGamepad(u8 &_x, u8 &_y, u8 &_z) Tl = Tl / 2; Tr = Tr / 2; - Pitch = Tl * (Range / 128) - - Tr * (Range / 128); + Pitch = Tl * (PitchRange / 128) + - Tr * (PitchRange / 128); } // Analog stick else { // Adjust the trigger to go between negative and positive values - Lx = Lx - 128; Ly = Ly - 128; + Lx = Lx - 128; // Produce the final value - Pitch = -Lx * (Range / 128); - Roll = -Ly * (Range / 128); + Roll = -Ly * (RollRange / 128); + Pitch = -Lx * (PitchRange / 128); } // Adjustment to prevent a slightly to high angle - if (Pitch >= Range) Pitch = Range - 0.1; - - // Calculate the accelerometer value from this tilt angle - //PitchDegreeToAccelerometer(Roll, Pitch, _x, _y, _z, g_Config.Trigger.Roll, g_Config.Trigger.Pitch); - PitchDegreeToAccelerometer(Roll, Pitch, _x, _y, _z, false, true); - - //Console::ClearScreen(); - /*Console::Print("L:%2.1f R:%2.1f Lx:%2.1f Range:%2.1f Degree:%2.1f L:%i R:%i\n", - Tl, Tr, Lx, Range, Degree, PadState[Page].Axis.Tl, PadState[Page].Axis.Tr);*/ - /**/Console::Print("Pitch:%2.1f\n", Pitch); + if (Pitch >= PitchRange) Pitch = PitchRange - 0.1; + if (Roll >= RollRange) Roll = RollRange - 0.1; } // ------------------------------------------ -// Tilting Wiimote (Wario Land aiming, Mario Kart steering) : For some reason 150 and 40 -// seemed like decent starting values. +// Tilting Wiimote with keyboard // --------------- -void TiltWiimoteKeyboard(u8 &_y, u8 &_z) +void TiltWiimoteKeyboard(float &Roll, float &Pitch) { #ifdef _WIN32 if(GetAsyncKeyState('3')) { // Stop at the upper end of the range - if(KbDegree < g_Config.Trigger.Range) + if(KbDegree < g_Config.Trigger.Range.Roll) KbDegree += 3; // aim left } else if(GetAsyncKeyState('4')) { // Stop at the lower end of the range - if(KbDegree > -g_Config.Trigger.Range) + if(KbDegree > -g_Config.Trigger.Range.Roll) KbDegree -= 3; // aim right } // ----------------------------------- // Check for inactivity in the tilting, the Y value will be reset after ten inactive updates // ---------- - yhist[yhist.size() - 1] = ( GetAsyncKeyState('3') || GetAsyncKeyState('4') @@ -473,21 +471,57 @@ void TiltWiimoteKeyboard(u8 &_y, u8 &_z) yhist[i-1] = yhist[i]; if(yhist[i]) ypressed = true; } - // Tilting was not used a single time, reset y to its neutral value + // Tilting was not used a single time, reset the angle to zero if(!ypressed) { - _y = Y; + KbDegree = 0; } else { - u8 x; - PitchDegreeToAccelerometer(KbDegree, 0, x, _y, _z, false, true); + Pitch = KbDegree; //Console::Print("Degree: %2.1f\n", KbDegree); } // -------------------- #endif } +// ------------------------------------------ +// Tilting Wiimote (Wario Land aiming, Mario Kart steering and other things) +// --------------- +void Tilt(u8 &_x, u8 &_y, u8 &_z) +{ + // Set to zero + float Roll = 0, Pitch = 0; + + // Select input method and return the x, y, x values + if (g_Config.Trigger.Type == g_Config.KEYBOARD) + TiltWiimoteKeyboard(Roll, Pitch); + else if (g_Config.Trigger.Type == g_Config.TRIGGER || g_Config.Trigger.Type == g_Config.ANALOG) + TiltWiimoteGamepad(Roll, Pitch); + + // Calculate the accelerometer value from this tilt angle + //PitchDegreeToAccelerometer(Roll, Pitch, _x, _y, _z, g_Config.Trigger.Roll, g_Config.Trigger.Pitch); + PitchDegreeToAccelerometer(Roll, Pitch, _x, _y, _z); + + /* + if (Roll > 90) + { + if (Pitch >= 0) + Pitch = 180 - Pitch; + else if (Pitch < 0) + Pitch = 180 + Pitch; + } + */ + + if (g_DebugData) + { + //Console::ClearScreen(); + /*Console::Print("L:%2.1f R:%2.1f Lx:%2.1f Range:%2.1f Degree:%2.1f L:%i R:%i\n", + Tl, Tr, Lx, Range, Degree, PadState[Page].Axis.Tl, PadState[Page].Axis.Tr);*/ + /**/Console::Print("Roll:%2.1f Pitch:%2.1f\n", Roll, Pitch); + } +} + void FillReportAcc(wm_accel& _acc) { // ------------------------------------ @@ -507,17 +541,17 @@ void FillReportAcc(wm_accel& _acc) // --------------------- // The default values can change so we need to update them all the time - X = g_accel.cal_zero.x; - Y = g_accel.cal_zero.y; - Z = g_accel.cal_zero.z + g_accel.cal_g.z; + g_X = g_accel.cal_zero.x; + g_Y = g_accel.cal_zero.y; + g_Z = g_accel.cal_zero.z + g_accel.cal_g.z; // Check that Dolphin is in focus if (!IsFocus()) { - _acc.x = X; - _acc.y = y; - _acc.z = z; + _acc.x = g_X; + _acc.y = g_y; + _acc.z = g_z; return; } @@ -526,23 +560,20 @@ void FillReportAcc(wm_accel& _acc) // ------------ // The following functions may or may not update these values - x = X; - y = Y; - z = Z; + g_x = g_X; + g_y = g_Y; + g_z = g_Z; // Shake the Wiimote - SingleShake(z, y); + SingleShake(g_z, g_y); // Tilt Wiimote - if (g_Config.Trigger.Type == g_Config.KEYBOARD) - TiltWiimoteKeyboard(y, z); - else if (g_Config.Trigger.Type == g_Config.TRIGGER || g_Config.Trigger.Type == g_Config.ANALOG) - TiltWiimoteGamepad(x, y, z); + // Write final values - _acc.x = x; - _acc.y = y; - _acc.z = z; + _acc.x = g_x; + _acc.y = g_y; + _acc.z = g_z; // ---------------------------- diff --git a/Source/Plugins/Plugin_Wiimote/Src/main.cpp b/Source/Plugins/Plugin_Wiimote/Src/main.cpp index 6226ac2165..f7bf5d4d37 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/main.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/main.cpp @@ -627,12 +627,28 @@ void ReadDebugging(bool Emu, const void* _pData, int Size) TmpData = Tmp1 + StringFromFormat("%03i %03i %03i", data[19], data[20], data[21]) + Tmp2; } // Calculate the Wiimote roll and pitch in degrees - int Roll, Pitch; - WiiMoteEmu::PitchAccelerometerToDegree(data[4], data[5], data[6], Roll, Pitch); - std::string RollPitch = StringFromFormat("%i %i", Roll, Pitch); + int Roll, Pitch, RollAdj, PitchAdj; + WiiMoteEmu::PitchAccelerometerToDegree(data[4], data[5], data[6], Roll, Pitch, RollAdj, PitchAdj); + std::string RollPitch = StringFromFormat("%s %s %s %s", + (Roll >= 0) ? StringFromFormat(" %03i", Roll).c_str() : StringFromFormat("%04i", Roll).c_str(), + (Pitch >= 0) ? StringFromFormat(" %03i", Pitch).c_str() : StringFromFormat("%04i", Pitch).c_str(), + (RollAdj == Roll) ? "" : StringFromFormat("%i*", RollAdj).c_str(), + (PitchAdj == Pitch) ? "" : StringFromFormat("%i*", PitchAdj).c_str()); + // --------------------------------------------- + // Test values + // ----------- + Console::ClearScreen(); + // Show a test of our calculations + WiiMoteEmu::TiltTest(data[4], data[5], data[6]); + u8 x, y, z; + WiiMoteEmu::Tilt(x, y, z); + WiiMoteEmu::TiltTest(x, y, z); + // ------------------------- + Console::Print("Read[%s]: %s| %s\n", (Emu ? "Emu" : "Real"), TmpData.c_str(), RollPitch.c_str()); // No timestamp //Console::Print(" (%s): %s\n", Tm(true).c_str(), Temp.c_str()); // Timestamp + } if(g_DebugAccelerometer) { diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigAdvanced.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigAdvanced.cpp index e5c29e4482..093ce67f72 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigAdvanced.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigAdvanced.cpp @@ -87,7 +87,7 @@ void ConfigBox::PadGetStatus() int main_x_after = main_x, main_y_after = main_y; if(PadMapping[notebookpage].bSquareToCircle) { - std::vector main_xy = InputCommon::Pad_Square_to_Circle(main_x, main_y, notebookpage, PadMapping[notebookpage]); + std::vector main_xy = InputCommon::Square2Circle(main_x, main_y, notebookpage, PadMapping[notebookpage].SDiagonal); main_x_after = main_xy.at(0); main_y_after = main_xy.at(1); } diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp index 6b8c3991a0..0066324a69 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/nJoy.cpp @@ -432,7 +432,7 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) // Check if we should make adjustments if(PadMapping[_numPAD].bSquareToCircle) { - std::vector main_xy = InputCommon::Pad_Square_to_Circle(i_main_stick_x, i_main_stick_y, _numPAD, PadMapping[_numPAD]); + std::vector main_xy = InputCommon::Square2Circle(i_main_stick_x, i_main_stick_y, _numPAD, PadMapping[_numPAD].SDiagonal); i_main_stick_x = main_xy.at(0); i_main_stick_y = main_xy.at(1); }