InputCommon and nJoy: Moved more functions to InputCommon

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2150 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson 2009-02-08 15:05:03 +00:00
parent c225e83913
commit 94d8eb5d4e
7 changed files with 172 additions and 124 deletions

View File

@ -415,10 +415,6 @@
RelativePath=".\Src\Configuration.cpp"
>
</File>
<File
RelativePath=".\Src\Configuration.h"
>
</File>
<File
RelativePath=".\Src\Event.hpp"
>

View File

@ -0,0 +1,155 @@
//////////////////////////////////////////////////////////////////////////////////////////
// Project description
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Name: Input Configuration and Calibration
// Description: Common SDL Input Functions
//
// Author: Falcon4ever (nJoy@falcon4ever.com, www.multigesture.net), JPeterson etc
// Copyright (C) 2003-2008 Dolphin Project.
//
//////////////////////////////////////////////////////////////////////////////////////////
//
// Licensetype: GNU General Public License (GPL)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
//
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
//
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Include
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
#include "SDL.h" // Local
////////////////////////////////////
namespace InputCommon
{
//////////////////////////////////////////////////////////////////////////////////////////
// Convert stick values
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
/* Convert stick values.
The value returned by SDL_JoystickGetAxis is a signed integer s16
(-32768 to 32767). The value used for the gamecube controller is an unsigned
char u8 (0 to 255) with neutral at 0x80 (128), so that it's equivalent to a signed
-128 to 127.
*/
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
int Pad_Convert(int _val)
{
/* If the limits on PadState[].axis[] actually is a u16 then we don't need this
but if it's not actually limited to that we need to apply these limits */
if(_val > 32767) _val = 32767; // upper limit
if(_val < -32768) _val = -32768; // lower limit
// Convert the range (-0x8000 to 0x7fff) to (0 to 0xffff)
_val = 0x8000 +_val;
// Convert the range (-32768 to 32767) to (-128 to 127)
_val = _val >> 8;
//Console::Print("0x%04x %06i\n\n", _val, _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
shown in the list below), so it may be beneficiary to convert whatever radius they
produce to the radius the GC games expect. This is the first implementation of this
that convert a square radius to a circual radius. Use the advanced settings to enable
and calibrate it.
Observed diagonals:
Perfect circle: 71% = sin(45)
Logitech Dual Action: 100%
Dual Shock 2 (Original) with Super Dual Box Pro: 90%
XBox 360 Wireless: 85%
GameCube Controller (Third Party) with EMS TrioLinker Plus II: 60%
*/
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
float SquareDistance(float deg)
{
// See if we have to adjust the angle
deg = abs(deg);
if( (deg > 45 && deg < 135) ) deg = deg - 90;
float rad = deg * M_PI / 180;
float val = abs(cos(rad));
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)
{
/* Do we need this? */
if(_x > 32767) _x = 32767; if(_y > 32767) _y = 32767; // upper limit
if(_x < -32768) _x = -32768; if(_y > 32767) _y = 32767; // lower limit
// ====================================
// Convert to circle
// -----------
int Tmp = atoi (_PadMapping.SDiagonal.substr(0, _PadMapping.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;
// A diagonal of 85% means a distance of 1.20
float corner_circle_dist = ( Diagonal / sin(45 * M_PI / 180) );
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
// 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
int int_x = (int)floor(x);
int int_y = (int)floor(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;
}
/////////////////////////////////////////////////////////////////////
}

View File

@ -36,6 +36,7 @@
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
#include <iostream> // System
#include <vector>
#include <cmath>
#include <SDL.h> // Externals
@ -153,9 +154,15 @@ enum
//////////////////////////////////////////////////////////////////////////////////////////
// Declarations
// ¯¯¯¯¯¯¯¯¯
// General functions
bool SearchDevices(std::vector<CONTROLLER_INFO> &_joyinfo, int &NumPads, int &NumGoodPads);
void GetJoyState(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, int controller, int NumButtons);
// Value conversion
int Pad_Convert(int _val);
std::vector<int> Pad_Square_to_Circle(int _x, int _y, int _pad, CONTROLLER_MAPPING _PadMapping);
#ifndef _SDL_MAIN_
#endif

View File

@ -92,7 +92,7 @@ void ConfigBox::PadGetStatus()
int main_x_after = main_x, main_y_after = main_y;
if(PadMapping[notebookpage].bSquareToCircle)
{
std::vector<int> main_xy = Pad_Square_to_Circle(main_x, main_y, notebookpage);
std::vector<int> main_xy = InputCommon::Pad_Square_to_Circle(main_x, main_y, notebookpage, PadMapping[notebookpage]);
main_x_after = main_xy.at(0);
main_y_after = main_xy.at(1);
}
@ -146,8 +146,8 @@ void ConfigBox::PadGetStatus()
// Convert the triggers values
if (PadMapping[notebookpage].triggertype == InputCommon::CTL_TRIGGER_SDL)
{
TriggerLeft = Pad_Convert(TriggerLeft);
TriggerRight = Pad_Convert(TriggerRight);
TriggerLeft = InputCommon::Pad_Convert(TriggerLeft);
TriggerRight = InputCommon::Pad_Convert(TriggerRight);
}
// If we don't have any axis selected for the shoulder buttons

View File

@ -419,22 +419,22 @@ void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
// Check if we should make adjustments
if(PadMapping[_numPAD].bSquareToCircle)
{
std::vector<int> main_xy = Pad_Square_to_Circle(i_main_stick_x, i_main_stick_y, _numPAD);
std::vector<int> main_xy = InputCommon::Pad_Square_to_Circle(i_main_stick_x, i_main_stick_y, _numPAD, PadMapping[_numPAD]);
i_main_stick_x = main_xy.at(0);
i_main_stick_y = main_xy.at(1);
}
// Convert axis values
u8 main_stick_x = Pad_Convert(i_main_stick_x);
u8 main_stick_y = Pad_Convert(i_main_stick_y);
u8 sub_stick_x = Pad_Convert(i_sub_stick_x);
u8 sub_stick_y = Pad_Convert(i_sub_stick_y);
u8 main_stick_x = InputCommon::Pad_Convert(i_main_stick_x);
u8 main_stick_y = InputCommon::Pad_Convert(i_main_stick_y);
u8 sub_stick_x = InputCommon::Pad_Convert(i_sub_stick_x);
u8 sub_stick_y = InputCommon::Pad_Convert(i_sub_stick_y);
// Convert the triggers values, if we are using analog triggers at all
if(PadMapping[_numPAD].triggertype == InputCommon::CTL_TRIGGER_SDL)
{
if(PadMapping[_numPAD].buttons[InputCommon::CTL_L_SHOULDER] >= 1000) TriggerLeft = Pad_Convert(TriggerLeft);
if(PadMapping[_numPAD].buttons[InputCommon::CTL_R_SHOULDER] >= 1000) TriggerRight = Pad_Convert(TriggerRight);
if(PadMapping[_numPAD].buttons[InputCommon::CTL_L_SHOULDER] >= 1000) TriggerLeft = InputCommon::Pad_Convert(TriggerLeft);
if(PadMapping[_numPAD].buttons[InputCommon::CTL_R_SHOULDER] >= 1000) TriggerRight = InputCommon::Pad_Convert(TriggerRight);
}
// Set Deadzones (perhaps out of function?)
@ -582,115 +582,7 @@ bool IsFocus()
}
//////////////////////////////////////////////////////////////////////////////////////////
// Convert stick values
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
/* Convert stick values.
The value returned by SDL_JoystickGetAxis is a signed integer s16
(-32768 to 32767). The value used for the gamecube controller is an unsigned
char u8 (0 to 255) with neutral at 0x80 (128), so that it's equivalent to a signed
-128 to 127.
*/
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
int Pad_Convert(int _val)
{
/* If the limits on PadState[].axis[] actually is a u16 then we don't need this
but if it's not actually limited to that we need to apply these limits */
if(_val > 32767) _val = 32767; // upper limit
if(_val < -32768) _val = -32768; // lower limit
// Convert the range (-0x8000 to 0x7fff) to (0 to 0xffff)
_val = 0x8000 +_val;
// Convert the range (-32768 to 32767) to (-128 to 127)
_val = _val >> 8;
//Console::Print("0x%04x %06i\n\n", _val, _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
shown in the list below), so it may be beneficiary to convert whatever radius they
produce to the radius the GC games expect. This is the first implementation of this
that convert a square radius to a circual radius. Use the advanced settings to enable
and calibrate it.
Observed diagonals:
Perfect circle: 71% = sin(45)
Logitech Dual Action: 100%
Dual Shock 2 (Original) with Super Dual Box Pro: 90%
XBox 360 Wireless: 85%
GameCube Controller (Third Party) with EMS TrioLinker Plus II: 60%
*/
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
float SquareDistance(float deg)
{
// See if we have to adjust the angle
deg = abs(deg);
if( (deg > 45 && deg < 135) ) deg = deg - 90;
float rad = deg * M_PI / 180;
float val = abs(cos(rad));
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)
{
/* Do we need this? */
if(_x > 32767) _x = 32767; if(_y > 32767) _y = 32767; // upper limit
if(_x < -32768) _x = -32768; if(_y > 32767) _y = 32767; // lower limit
// ====================================
// Convert to circle
// -----------
int Tmp = atoi (PadMapping[_pad].SDiagonal.substr(0, PadMapping[_pad].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;
// A diagonal of 85% means a distance of 1.20
float corner_circle_dist = ( Diagonal / sin(45 * M_PI / 180) );
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
// 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
int int_x = (int)floor(x);
int int_y = (int)floor(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;
}
///////////////////////////////////////////////////////////////////// Convert stick values

View File

@ -136,8 +136,6 @@ void DEBUG_QUIT();
bool IsFocus();
void Pad_Use_Rumble(u8 _numPAD, SPADStatus* _pPADStatus); // Rumble
int Pad_Convert(int _val); // Value conversion
std::vector<int> Pad_Square_to_Circle(int _x, int _y, int _pad); // Value conversion
//void SaveConfig();
//void LoadConfig();