mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-25 07:21:14 +01:00
Emulated Wiimote: Fixed the angles to x, y, z values conversion. There's just one thing left to fix before the combined roll and pitch works, when roll is more than 90 pitch has to be changed from for example 15 to -165 or something like that. Until I figure that out you can use the emulated roll and pitch separately by setting the range of either one of them to zero.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2219 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
7958eae6da
commit
b932a53b68
@ -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<int> Pad_Square_to_Circle(int _x, int _y, int _pad, CONTROLLER_MAPPING _PadMapping)
|
||||
// Produce the circle from the original
|
||||
std::vector<int> 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<int> 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<int> 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<int> vec;
|
||||
vec.push_back(int_x);
|
||||
vec.push_back(int_y);
|
||||
return vec;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
@ -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<int> Pad_Square_to_Circle(int _x, int _y, int _pad, CONTROLLER_MAPPING _PadMapping);
|
||||
std::vector<int> Square2Circle(int _x, int _y, int _pad, std::string SDiagonal, bool Circle2Square = false);
|
||||
|
||||
#ifndef _SDL_MAIN_
|
||||
extern int g_LastPad;
|
||||
|
@ -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);
|
||||
// ======================================
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
//////////////////////////
|
||||
|
@ -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 <It's important that the internal ordering of these are unchanged>
|
||||
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,
|
||||
|
@ -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<int> main_xy = InputCommon::Pad_Square_to_Circle(main_x, main_y, notebookpage, PadMapping[notebookpage]);
|
||||
std::vector<int> 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;
|
||||
|
@ -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
|
@ -51,9 +51,10 @@ void SetDefaultExtensionRegistry();
|
||||
// Gamepad
|
||||
bool Search_Devices(std::vector<InputCommon::CONTROLLER_INFO> &_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
|
||||
|
||||
|
@ -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<int> 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;
|
||||
|
||||
|
||||
// ----------------------------
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -87,7 +87,7 @@ void ConfigBox::PadGetStatus()
|
||||
int main_x_after = main_x, main_y_after = main_y;
|
||||
if(PadMapping[notebookpage].bSquareToCircle)
|
||||
{
|
||||
std::vector<int> main_xy = InputCommon::Pad_Square_to_Circle(main_x, main_y, notebookpage, PadMapping[notebookpage]);
|
||||
std::vector<int> 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);
|
||||
}
|
||||
|
@ -432,7 +432,7 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
|
||||
// Check if we should make adjustments
|
||||
if(PadMapping[_numPAD].bSquareToCircle)
|
||||
{
|
||||
std::vector<int> main_xy = InputCommon::Pad_Square_to_Circle(i_main_stick_x, i_main_stick_y, _numPAD, PadMapping[_numPAD]);
|
||||
std::vector<int> 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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user