wx: input configuration
This commit is contained in:
parent
2abb85a05d
commit
2aa985baec
|
@ -0,0 +1,278 @@
|
|||
|
||||
// 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 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
|
||||
// -------------------
|
||||
#if defined HAVE_WX && HAVE_WX
|
||||
#include <wx/wx.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#include "SDL.h" // Local
|
||||
|
||||
|
||||
|
||||
namespace InputCommon
|
||||
{
|
||||
|
||||
|
||||
|
||||
// Degree to radian and back
|
||||
// -------------
|
||||
float Deg2Rad(float Deg)
|
||||
{
|
||||
return Deg * (float)M_PI / 180.0f;
|
||||
}
|
||||
float Rad2Deg(float Rad)
|
||||
{
|
||||
return Rad * 180.0f / (float)M_PI;
|
||||
}
|
||||
|
||||
// Check if the pad is within the dead zone, we assume the range is 0x8000
|
||||
// ----------------
|
||||
float CoordinatesToRadius(int x, int y)
|
||||
{
|
||||
return sqrt(pow((float)x, 2) + pow((float)y, 2));
|
||||
}
|
||||
|
||||
bool IsDeadZone(float DeadZone, int x, int y)
|
||||
{
|
||||
// Get the distance from the center
|
||||
float Distance = CoordinatesToRadius(x, y) / 32767.0f;
|
||||
|
||||
//Console::Print("%f\n", Distance);
|
||||
|
||||
// Check if it's within the dead zone
|
||||
if (Distance <= DeadZone)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Scale down stick values from 0x8000 to 0x80
|
||||
/* ----------------
|
||||
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 (0 to 0xffff) to (0 to 0xff)
|
||||
_val = _val >> 8;
|
||||
|
||||
//Console::Print("0x%04x %06i\n\n", _val, _val);
|
||||
|
||||
return _val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Adjust the radius
|
||||
// ----------------
|
||||
void RadiusAdjustment(int &_x, int &_y, int _pad, std::string SRadius)
|
||||
{
|
||||
// Get the radius setting
|
||||
int Tmp = atoi (SRadius.substr(0, SRadius.length() - 1).c_str());
|
||||
float RadiusSetting = Tmp / 100.0f;
|
||||
|
||||
// Get current angle
|
||||
float Deg = Rad2Deg(atan2((float)_y, (float)_x));
|
||||
// Get the current radius
|
||||
float Radius = sqrt((float)(_x*_x + _y*_y));
|
||||
// Adjust radius
|
||||
Radius = Radius * RadiusSetting;
|
||||
// Produce new coordinates
|
||||
float x = Radius * cos(Deg2Rad(Deg));
|
||||
float y = Radius * sin(Deg2Rad(Deg));
|
||||
// Update values
|
||||
_x = (int)x, _y = (int)y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Convert the stick raidus from a square or rounded box to a circular radius. 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%
|
||||
PS2 Dual Shock 2 (Original) with Super Dual Box Pro: 90%
|
||||
XBox 360 Wireless: 85%
|
||||
GameCube Controller (Third Party) with EMS Trio Linker Plus II: 60%
|
||||
*/
|
||||
// ---------------------
|
||||
|
||||
/* Calculate the distance from the outer edges of the box to the outer edges of the circle inside the box
|
||||
at any angle from 0 to 360. The returned value is 1 + Distance, for example at most sqrt(2) in the
|
||||
corners and at least 1.0 at the horizontal and vertical angles. */
|
||||
float Square2CircleDistance(float deg)
|
||||
{
|
||||
// See if we have to adjust the angle
|
||||
deg = abs(deg);
|
||||
if( (deg > 45 && deg < 135) ) deg = deg - 90;
|
||||
|
||||
// Calculate distance from center
|
||||
float val = abs(cos(Deg2Rad(deg)));
|
||||
float Distance = 1 / val;
|
||||
|
||||
//m_frame->m_pStatusBar2->SetLabel(wxString::Format("Deg:%f Val:%f Dist:%f", deg, val, dist));
|
||||
|
||||
return Distance;
|
||||
}
|
||||
// Produce a perfect circle from an original square or rounded box
|
||||
void Square2Circle(int &_x, int &_y, int _pad, std::string SDiagonal, bool Circle2Square)
|
||||
{
|
||||
// Do we need to do this check?
|
||||
if(_x > 32767) _x = 32767; if(_y > 32767) _y = 32767; // upper limit
|
||||
if(_x < -32768) _x = -32768; if(_y < -32768) _y = -32768; // lower limit
|
||||
|
||||
// ====================================
|
||||
// Convert to circle
|
||||
// -----------
|
||||
// Get the manually configured diagonal distance
|
||||
int Tmp = atoi (SDiagonal.substr(0, SDiagonal.length() - 1).c_str());
|
||||
float Diagonal = Tmp / 100.0f;
|
||||
|
||||
// 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 deg = Rad2Deg(atan2((float)_y, (float)_x)); // Get current angle
|
||||
|
||||
/* Calculate the actual distance between the maxium diagonal values, and the outer edges of the
|
||||
square. 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.0f)) );
|
||||
float SquareDist = Square2CircleDistance(deg);
|
||||
// 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
|
||||
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));
|
||||
// Update coordinates
|
||||
_x = (int)floor(x);
|
||||
_y = (int)floor(y);
|
||||
// Boundaries
|
||||
if (_x < -32768) _x = -32768; if (_x > 32767) _x = 32767;
|
||||
if (_y < -32768) _y = -32768; if (_y > 32767) _y = 32767;
|
||||
|
||||
// Debugging
|
||||
//Console::Print("%f %f %i", corner_circle_dist, Diagonal, Tmp));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Windows Virtual Key Codes Names
|
||||
// ---------------------
|
||||
#ifdef _WIN32
|
||||
std::string VKToString(int keycode)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Default value
|
||||
char KeyStr[64] = {0};
|
||||
std::string KeyString;
|
||||
|
||||
// TODO: Switch to unicode GetKeyNameText?
|
||||
if (keycode < 256) // Keyboard
|
||||
GetKeyNameTextA(MapVirtualKey(keycode, MAPVK_VK_TO_VSC) << 16, KeyStr, 64);
|
||||
else // Pad
|
||||
sprintf(KeyStr, "PAD: %d", keycode - 0x1000);
|
||||
|
||||
switch(keycode)
|
||||
{
|
||||
// Give it some help with a few keys
|
||||
case VK_END: return "END";
|
||||
case VK_INSERT: return "INS";
|
||||
case VK_DELETE: return "DEL";
|
||||
case VK_PRIOR: return "PGUP";
|
||||
case VK_NEXT: return "PGDN";
|
||||
|
||||
case VK_UP: return "UP";
|
||||
case VK_DOWN: return "DOWN";
|
||||
case VK_LEFT: return "LEFT";
|
||||
case VK_RIGHT: return "RIGHT";
|
||||
|
||||
case VK_LSHIFT: return "LEFT SHIFT";
|
||||
case VK_LCONTROL: return "LEFT CTRL";
|
||||
case VK_RCONTROL: return "RIGHT CTRL";
|
||||
case VK_LMENU: return "LEFT ALT";
|
||||
|
||||
default: return KeyString = KeyStr;
|
||||
}
|
||||
#else
|
||||
// An equivalent name translation can probably be used on other systems to?
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
|
||||
// Include
|
||||
// -------------------
|
||||
#include "DirectInputBase.h"
|
||||
|
||||
|
||||
|
||||
DInput::DInput()
|
||||
: g_pDI(NULL),
|
||||
g_pKeyboard(NULL)
|
||||
{}
|
||||
|
||||
|
||||
DInput::~DInput()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
void DInput::DIKToString(unsigned int keycode, char *keyStr)
|
||||
{
|
||||
switch(keycode) {
|
||||
case DIK_RETURN:
|
||||
sprintf(keyStr, "Enter");
|
||||
break;
|
||||
case DIK_UP:
|
||||
sprintf(keyStr, "Up");
|
||||
break;
|
||||
case DIK_DOWN:
|
||||
sprintf(keyStr, "Down");
|
||||
break;
|
||||
case DIK_LEFT:
|
||||
sprintf(keyStr, "Left");
|
||||
break;
|
||||
case DIK_RIGHT:
|
||||
sprintf(keyStr, "Right");
|
||||
break;
|
||||
case DIK_HOME:
|
||||
strcpy(keyStr, "Home");
|
||||
break;
|
||||
case DIK_END:
|
||||
strcpy(keyStr, "End");
|
||||
break;
|
||||
case DIK_INSERT:
|
||||
strcpy(keyStr, "Ins");
|
||||
break;
|
||||
case DIK_DELETE:
|
||||
strcpy(keyStr, "Del");
|
||||
break;
|
||||
case DIK_PGUP:
|
||||
strcpy(keyStr, "PgUp");
|
||||
break;
|
||||
case DIK_PGDN:
|
||||
strcpy(keyStr, "PgDn");
|
||||
break;
|
||||
case DIK_NUMPAD0:
|
||||
strcpy(keyStr, "Num 0");
|
||||
break;
|
||||
case DIK_NUMPAD1:
|
||||
strcpy(keyStr, "Num 1");
|
||||
break;
|
||||
case DIK_NUMPAD2:
|
||||
strcpy(keyStr, "Num 2");
|
||||
break;
|
||||
case DIK_NUMPAD3:
|
||||
strcpy(keyStr, "Num 3");
|
||||
break;
|
||||
case DIK_NUMPAD4:
|
||||
strcpy(keyStr, "Num 4");
|
||||
break;
|
||||
case DIK_NUMPAD5:
|
||||
strcpy(keyStr, "Num 5");
|
||||
break;
|
||||
case DIK_NUMPAD6:
|
||||
strcpy(keyStr, "Num 6");
|
||||
break;
|
||||
case DIK_NUMPAD7:
|
||||
strcpy(keyStr, "Num 7");
|
||||
break;
|
||||
case DIK_NUMPAD8:
|
||||
strcpy(keyStr, "Num 8");
|
||||
break;
|
||||
case DIK_NUMPAD9:
|
||||
strcpy(keyStr, "Num 9");
|
||||
break;
|
||||
case DIK_NUMPADSLASH:
|
||||
strcpy(keyStr, "Num /");
|
||||
break;
|
||||
default:
|
||||
// TODO: Switch to unicode GetKeyNameText?
|
||||
GetKeyNameTextA(keycode << 16, keyStr, 64);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT DInput::Init(HWND hWnd)
|
||||
{
|
||||
HRESULT hr;
|
||||
DWORD dwCoopFlags;
|
||||
dwCoopFlags = DISCL_FOREGROUND | DISCL_NOWINKEY;
|
||||
|
||||
// Create a DInput object
|
||||
if (FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
|
||||
IID_IDirectInput8, (VOID* *)&g_pDI, NULL)))
|
||||
{
|
||||
MessageBox(0, "Direct Input Create Failed", 0, MB_ICONERROR);
|
||||
return(hr);
|
||||
}
|
||||
|
||||
if (FAILED(hr = g_pDI->CreateDevice(GUID_SysKeyboard, &g_pKeyboard, NULL)))
|
||||
{
|
||||
MessageBox(0, "Couldn't access keyboard", 0, MB_ICONERROR);
|
||||
Free();
|
||||
return(hr);
|
||||
}
|
||||
|
||||
g_pKeyboard->SetDataFormat(&c_dfDIKeyboard);
|
||||
g_pKeyboard->SetCooperativeLevel(hWnd, dwCoopFlags);
|
||||
g_pKeyboard->Acquire();
|
||||
|
||||
return(S_OK);
|
||||
}
|
||||
|
||||
void DInput::Free()
|
||||
{
|
||||
if (g_pKeyboard)
|
||||
{
|
||||
g_pKeyboard->Unacquire();
|
||||
g_pKeyboard->Release();
|
||||
g_pKeyboard = 0;
|
||||
}
|
||||
|
||||
if (g_pDI)
|
||||
{
|
||||
g_pDI->Release();
|
||||
g_pDI = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Desc: Read the input device's state when in immediate mode and display it.
|
||||
HRESULT DInput::Read()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL == g_pKeyboard)
|
||||
{
|
||||
return(S_OK);
|
||||
}
|
||||
|
||||
// Get the input's device state, and put the state in dims
|
||||
ZeroMemory(diks, sizeof(diks));
|
||||
hr = g_pKeyboard->GetDeviceState(sizeof(diks), diks);
|
||||
|
||||
// for (int i=0; i<256; i++)
|
||||
// if (diks[i]) MessageBox(0,"DSFJDKSF|",0,0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// DirectInput may be telling us that the input stream has been
|
||||
// interrupted. We aren't tracking any state between polls, so
|
||||
// we don't have any special reset that needs to be done.
|
||||
// We just re-acquire and try again.
|
||||
|
||||
// If input is lost then acquire and keep trying
|
||||
hr = g_pKeyboard->Acquire();
|
||||
|
||||
while (hr == DIERR_INPUTLOST)
|
||||
{
|
||||
hr = g_pKeyboard->Acquire();
|
||||
}
|
||||
|
||||
// hr may be DIERR_OTHERAPPHASPRIO or other errors. This
|
||||
// may occur when the app is minimized or in the process of
|
||||
// switching, so just try again later
|
||||
return(S_OK);
|
||||
}
|
||||
|
||||
return(S_OK);
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _DIRECTINPUTBASE_H
|
||||
#define _DIRECTINPUTBASE_H
|
||||
|
||||
|
||||
|
||||
// Include
|
||||
// -------------------
|
||||
#include <windows.h> // System
|
||||
#include <stdio.h>
|
||||
|
||||
#define DIRECTINPUT_VERSION 0x0800 // DirectInput
|
||||
#include <dinput.h>
|
||||
|
||||
//#include "ConsoleWindow.h" // Common
|
||||
|
||||
|
||||
|
||||
class DInput
|
||||
{
|
||||
public:
|
||||
|
||||
DInput();
|
||||
~DInput();
|
||||
|
||||
static void DInput::DIKToString(unsigned int keycode, char *keyStr);
|
||||
|
||||
HRESULT Init(HWND hWnd);
|
||||
void Free();
|
||||
HRESULT Read();
|
||||
|
||||
|
||||
BYTE diks[256]; // DirectInput keyboard state buffer
|
||||
|
||||
private:
|
||||
|
||||
LPDIRECTINPUT8 g_pDI; // The DirectInput object
|
||||
LPDIRECTINPUTDEVICE8 g_pKeyboard; // The keyboard device
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,264 @@
|
|||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it freely,
|
||||
// subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented;
|
||||
// you must not claim that you wrote the original software.
|
||||
// If you use this software in a product, an acknowledgment
|
||||
// in the product documentation would be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such,
|
||||
// and must not be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef SFML_EVENT_HPP
|
||||
#define SFML_EVENT_HPP
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace Key
|
||||
{
|
||||
enum Code
|
||||
{
|
||||
A = 'a',
|
||||
B = 'b',
|
||||
C = 'c',
|
||||
D = 'd',
|
||||
E = 'e',
|
||||
F = 'f',
|
||||
G = 'g',
|
||||
H = 'h',
|
||||
I = 'i',
|
||||
J = 'j',
|
||||
K = 'k',
|
||||
L = 'l',
|
||||
M = 'm',
|
||||
N = 'n',
|
||||
O = 'o',
|
||||
P = 'p',
|
||||
Q = 'q',
|
||||
R = 'r',
|
||||
S = 's',
|
||||
T = 't',
|
||||
U = 'u',
|
||||
V = 'v',
|
||||
W = 'w',
|
||||
X = 'x',
|
||||
Y = 'y',
|
||||
Z = 'z',
|
||||
Num0 = '0',
|
||||
Num1 = '1',
|
||||
Num2 = '2',
|
||||
Num3 = '3',
|
||||
Num4 = '4',
|
||||
Num5 = '5',
|
||||
Num6 = '6',
|
||||
Num7 = '7',
|
||||
Num8 = '8',
|
||||
Num9 = '9',
|
||||
Escape = 256,
|
||||
LControl,
|
||||
LShift,
|
||||
LAlt,
|
||||
LSystem,
|
||||
RControl,
|
||||
RShift,
|
||||
RAlt,
|
||||
RSystem,
|
||||
Menu,
|
||||
LBracket,
|
||||
RBracket,
|
||||
SemiColon,
|
||||
Comma,
|
||||
Period,
|
||||
Quote,
|
||||
Slash,
|
||||
BackSlash,
|
||||
Tilde,
|
||||
Equal,
|
||||
Dash,
|
||||
Space,
|
||||
Return,
|
||||
Back,
|
||||
Tab,
|
||||
PageUp,
|
||||
PageDown,
|
||||
End,
|
||||
Home,
|
||||
Insert,
|
||||
Delete,
|
||||
Add,
|
||||
Subtract,
|
||||
Multiply,
|
||||
Divide,
|
||||
Left,
|
||||
Right,
|
||||
Up,
|
||||
Down,
|
||||
Numpad0,
|
||||
Numpad1,
|
||||
Numpad2,
|
||||
Numpad3,
|
||||
Numpad4,
|
||||
Numpad5,
|
||||
Numpad6,
|
||||
Numpad7,
|
||||
Numpad8,
|
||||
Numpad9,
|
||||
F1,
|
||||
F2,
|
||||
F3,
|
||||
F4,
|
||||
F5,
|
||||
F6,
|
||||
F7,
|
||||
F8,
|
||||
F9,
|
||||
F10,
|
||||
F11,
|
||||
F12,
|
||||
F13,
|
||||
F14,
|
||||
F15,
|
||||
Pause,
|
||||
|
||||
Count // For internal use
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
namespace Mouse
|
||||
{
|
||||
enum Button
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
Middle,
|
||||
XButton1,
|
||||
XButton2,
|
||||
|
||||
Count // For internal use
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
namespace Joy
|
||||
{
|
||||
enum Axis
|
||||
{
|
||||
AxisX,
|
||||
AxisY,
|
||||
AxisZ,
|
||||
AxisR,
|
||||
AxisU,
|
||||
AxisV,
|
||||
AxisPOV,
|
||||
|
||||
Count // For internal use
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
class Event
|
||||
{
|
||||
public :
|
||||
|
||||
struct KeyEvent
|
||||
{
|
||||
Key::Code Code;
|
||||
bool Alt;
|
||||
bool Control;
|
||||
bool Shift;
|
||||
};
|
||||
|
||||
struct TextEvent
|
||||
{
|
||||
// I'm not sure we need this...
|
||||
unsigned short Unicode;
|
||||
};
|
||||
|
||||
struct MouseMoveEvent
|
||||
{
|
||||
int X;
|
||||
int Y;
|
||||
};
|
||||
|
||||
struct MouseButtonEvent
|
||||
{
|
||||
Mouse::Button Button;
|
||||
int X;
|
||||
int Y;
|
||||
};
|
||||
|
||||
struct MouseWheelEvent
|
||||
{
|
||||
int Delta;
|
||||
};
|
||||
|
||||
struct JoyMoveEvent
|
||||
{
|
||||
unsigned int JoystickId;
|
||||
Joy::Axis Axis;
|
||||
float Position;
|
||||
};
|
||||
|
||||
struct JoyButtonEvent
|
||||
{
|
||||
unsigned int JoystickId;
|
||||
unsigned int Button;
|
||||
};
|
||||
|
||||
struct SizeEvent
|
||||
{
|
||||
unsigned int Width;
|
||||
unsigned int Height;
|
||||
};
|
||||
|
||||
enum EventType
|
||||
{
|
||||
Closed,
|
||||
Resized,
|
||||
LostFocus,
|
||||
GainedFocus,
|
||||
TextEntered,
|
||||
KeyPressed,
|
||||
KeyReleased,
|
||||
MouseWheelMoved,
|
||||
MouseButtonPressed,
|
||||
MouseButtonReleased,
|
||||
MouseMoved,
|
||||
MouseEntered,
|
||||
MouseLeft,
|
||||
JoyButtonPressed,
|
||||
JoyButtonReleased,
|
||||
JoyMoved
|
||||
};
|
||||
|
||||
// Member data
|
||||
EventType Type;
|
||||
|
||||
union
|
||||
{
|
||||
KeyEvent Key;
|
||||
TextEvent Text;
|
||||
MouseMoveEvent MouseMove;
|
||||
MouseButtonEvent MouseButton;
|
||||
MouseWheelEvent MouseWheel;
|
||||
JoyMoveEvent JoyMove;
|
||||
JoyButtonEvent JoyButton;
|
||||
SizeEvent Size;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_EVENT_HPP
|
|
@ -0,0 +1,316 @@
|
|||
#include "EventHandler.h"
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if defined HAVE_WX && HAVE_WX
|
||||
#include <wx/wx.h>
|
||||
#endif
|
||||
|
||||
EventHandler *EventHandler::m_Instance = 0;
|
||||
|
||||
EventHandler::EventHandler() {
|
||||
memset(keys, 0, sizeof(keys));
|
||||
memset(mouse, 0, sizeof(mouse));
|
||||
memset(joys, 0, sizeof(joys));
|
||||
}
|
||||
|
||||
EventHandler::~EventHandler() {
|
||||
}
|
||||
|
||||
EventHandler *EventHandler::GetInstance() {
|
||||
// fprintf(stderr, "handler instance %p\n", m_Instance);
|
||||
|
||||
if (! m_Instance)
|
||||
m_Instance = new EventHandler();
|
||||
return m_Instance;
|
||||
}
|
||||
|
||||
void EventHandler::Destroy() {
|
||||
if (m_Instance)
|
||||
delete m_Instance;
|
||||
// fprintf(stderr, "deleting instance %p\n", m_Instance);
|
||||
m_Instance = 0;
|
||||
}
|
||||
|
||||
bool EventHandler::RegisterEventListener(listenFuncPtr func, Keys key) {
|
||||
if (key.inputType == KeyboardInput) {
|
||||
// fprintf(stderr, "Registering %d:%d %p %p \n", key.keyCode, key.mods, func, this);
|
||||
if (key.keyCode == sf::Key::Count || key.mods >= NUMMODS ||
|
||||
key.keyCode >= NUMKEYS)
|
||||
return false;
|
||||
if (keys[key.keyCode][key.mods] && keys[key.keyCode][key.mods] != func)
|
||||
return false
|
||||
;
|
||||
keys[key.keyCode][key.mods] = func;
|
||||
} else if (key.inputType == MouseInput) {
|
||||
if (mouse[key.mouseButton])
|
||||
return false;
|
||||
mouse[key.mouseButton] = func;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EventHandler::RemoveEventListener(Keys key) {
|
||||
if (key.inputType == KeyboardInput) {
|
||||
if ((key.keyCode == sf::Key::Count || key.keyCode >= NUMKEYS
|
||||
|| key.mods >= NUMMODS) && ! keys[key.keyCode][key.mods])
|
||||
return false;
|
||||
keys[key.keyCode][key.mods] = NULL;
|
||||
} else if (key.inputType == MouseInput) {
|
||||
if (! mouse[key.mouseButton])
|
||||
return false;
|
||||
mouse[key.mouseButton] = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EventHandler::Update() {
|
||||
for (unsigned int i = 0; i < eventQueue.size();i++) {
|
||||
sf::Event ev = eventQueue.front();
|
||||
eventQueue.pop();
|
||||
fprintf(stderr, "Updating event type %d code %d mod %d func %p %p\n", ev.Type, ev.Key.Code, ev.Key.Alt+2*ev.Key.Shift+4*ev.Key.Control, keys[ev.Key.Code][ev.Key.Alt+2*ev.Key.Shift+4*ev.Key.Control], this);
|
||||
if(keys[ev.Key.Code][ev.Key.Alt+2*ev.Key.Shift+4*ev.Key.Control])
|
||||
keys[ev.Key.Code][ev.Key.Alt+2*ev.Key.Shift+4*ev.Key.Control](ev);
|
||||
}
|
||||
}
|
||||
|
||||
bool EventHandler::addEvent(sf::Event *ev) {
|
||||
eventQueue.push(*ev);
|
||||
fprintf(stderr, "Got event type %d code %d %p\n", ev->Type, ev->Key.Code, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool EventHandler::TestEvent (Keys k, sf::Event e)
|
||||
{
|
||||
//Mouse event
|
||||
if (k.inputType==MouseInput && k.eventType==e.Type && k.mouseButton==e.MouseButton.Button)
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
//Keyboard event
|
||||
if (k.inputType==KeyboardInput && k.eventType==e.Type && k.keyCode==e.Key.Code)
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
#if defined HAVE_WX && HAVE_WX
|
||||
// Taken from wxw source code
|
||||
sf::Key::Code EventHandler::wxCharCodeToSF(int id)
|
||||
{
|
||||
sf::Key::Code sfKey;
|
||||
|
||||
switch (id) {
|
||||
// case WXK_CANCEL: sfKey = sf::Key::Cancel; break;
|
||||
// case WXK_BACK: sfKey = sf::Key::BackSpace; break;
|
||||
case WXK_TAB: sfKey = sf::Key::Tab; break;
|
||||
// case WXK_CLEAR: sfKey = sf::Key::Clear; break;
|
||||
case WXK_RETURN: sfKey = sf::Key::Return; break;
|
||||
case WXK_SHIFT: sfKey = sf::Key::LShift; break;
|
||||
case WXK_CONTROL: sfKey = sf::Key::LControl; break;
|
||||
case WXK_ALT: sfKey = sf::Key::LAlt; break;
|
||||
// case WXK_CAPITAL: sfKey = sf::Key::Caps_Lock; break;
|
||||
case WXK_MENU : sfKey = sf::Key::Menu; break;
|
||||
case WXK_PAUSE: sfKey = sf::Key::Pause; break;
|
||||
case WXK_ESCAPE: sfKey = sf::Key::Escape; break;
|
||||
case WXK_SPACE: sfKey = sf::Key::Space; break;
|
||||
case WXK_PAGEUP: sfKey = sf::Key::PageUp; break;
|
||||
case WXK_PAGEDOWN: sfKey = sf::Key::PageDown; break;
|
||||
case WXK_END: sfKey = sf::Key::End; break;
|
||||
case WXK_HOME : sfKey = sf::Key::Home; break;
|
||||
case WXK_LEFT : sfKey = sf::Key::Left; break;
|
||||
case WXK_UP: sfKey = sf::Key::Up; break;
|
||||
case WXK_RIGHT: sfKey = sf::Key::Right; break;
|
||||
case WXK_DOWN : sfKey = sf::Key::Down; break;
|
||||
// case WXK_SELECT: sfKey = sf::Key::Select; break;
|
||||
// case WXK_PRINT: sfKey = sf::Key::Print; break;
|
||||
// case WXK_EXECUTE: sfKey = sf::Key::Execute; break;
|
||||
case WXK_INSERT: sfKey = sf::Key::Insert; break;
|
||||
case WXK_DELETE: sfKey = sf::Key::Delete; break;
|
||||
// case WXK_HELP : sfKey = sf::Key::Help; break;
|
||||
case WXK_NUMPAD0: sfKey = sf::Key::Numpad0; break;
|
||||
case WXK_NUMPAD_INSERT: sfKey = sf::Key::Insert; break;
|
||||
case WXK_NUMPAD1: sfKey = sf::Key::Numpad1; break;
|
||||
case WXK_NUMPAD_END: sfKey = sf::Key::End; break;
|
||||
case WXK_NUMPAD2: sfKey = sf::Key::Numpad2; break;
|
||||
case WXK_NUMPAD_DOWN: sfKey = sf::Key::Down; break;
|
||||
case WXK_NUMPAD3: sfKey = sf::Key::Numpad3; break;
|
||||
case WXK_NUMPAD_PAGEDOWN: sfKey = sf::Key::PageDown; break;
|
||||
case WXK_NUMPAD4: sfKey = sf::Key::Numpad4; break;
|
||||
case WXK_NUMPAD_LEFT: sfKey = sf::Key::Left; break;
|
||||
case WXK_NUMPAD5: sfKey = sf::Key::Numpad5; break;
|
||||
case WXK_NUMPAD6: sfKey = sf::Key::Numpad6; break;
|
||||
case WXK_NUMPAD_RIGHT: sfKey = sf::Key::Right; break;
|
||||
case WXK_NUMPAD7: sfKey = sf::Key::Numpad7; break;
|
||||
case WXK_NUMPAD_HOME: sfKey = sf::Key::Home; break;
|
||||
case WXK_NUMPAD8: sfKey = sf::Key::Numpad8; break;
|
||||
case WXK_NUMPAD_UP: sfKey = sf::Key::Up; break;
|
||||
case WXK_NUMPAD9: sfKey = sf::Key::Numpad9; break;
|
||||
case WXK_NUMPAD_PAGEUP: sfKey = sf::Key::PageUp; break;
|
||||
// case WXK_NUMPAD_DECIMAL: sfKey = sf::Key::Decimal; break;
|
||||
case WXK_NUMPAD_DELETE: sfKey = sf::Key::Delete; break;
|
||||
case WXK_NUMPAD_MULTIPLY: sfKey = sf::Key::Multiply; break;
|
||||
case WXK_NUMPAD_ADD: sfKey = sf::Key::Add; break;
|
||||
case WXK_NUMPAD_SUBTRACT: sfKey = sf::Key::Subtract; break;
|
||||
case WXK_NUMPAD_DIVIDE: sfKey = sf::Key::Divide; break;
|
||||
case WXK_NUMPAD_ENTER: sfKey = sf::Key::Return; break;
|
||||
// case WXK_NUMPAD_SEPARATOR:sfKey = sf::Key::Separator; break;
|
||||
case WXK_F1: sfKey = sf::Key::F1; break;
|
||||
case WXK_F2: sfKey = sf::Key::F2; break;
|
||||
case WXK_F3: sfKey = sf::Key::F3; break;
|
||||
case WXK_F4: sfKey = sf::Key::F4; break;
|
||||
case WXK_F5: sfKey = sf::Key::F5; break;
|
||||
case WXK_F6: sfKey = sf::Key::F6; break;
|
||||
case WXK_F7: sfKey = sf::Key::F7; break;
|
||||
case WXK_F8: sfKey = sf::Key::F8; break;
|
||||
case WXK_F9: sfKey = sf::Key::F9; break;
|
||||
case WXK_F10: sfKey = sf::Key::F10; break;
|
||||
case WXK_F11: sfKey = sf::Key::F11; break;
|
||||
case WXK_F12: sfKey = sf::Key::F12; break;
|
||||
case WXK_F13: sfKey = sf::Key::F13; break;
|
||||
case WXK_F14: sfKey = sf::Key::F14; break;
|
||||
case WXK_F15: sfKey = sf::Key::F15; break;
|
||||
// case WXK_NUMLOCK: sfKey = sf::Key::Num_Lock; break;
|
||||
// case WXK_SCROLL: sfKey = sf::Key::Scroll_Lock; break;
|
||||
default:
|
||||
|
||||
// To lower (will tolower work on windows?)
|
||||
if (id >= 'A' && id <= 'Z')
|
||||
id = id - 'A' + 'a';
|
||||
|
||||
if ((id >= 'a' && id <= 'z') ||
|
||||
(id >= '0' && id <= '9'))
|
||||
sfKey = (sf::Key::Code)id;
|
||||
else
|
||||
sfKey = sf::Key::Count; // Invalid key
|
||||
|
||||
}
|
||||
|
||||
return sfKey;
|
||||
}
|
||||
#endif
|
||||
|
||||
void EventHandler::SFKeyToString(sf::Key::Code keycode, char *keyStr) {
|
||||
switch (keycode) {
|
||||
/* case sf::Key::A = 'a': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::B = 'b': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::C = 'c': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::D = 'd': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::E = 'e': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::F = 'f': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::G = 'g': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::H = 'h': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::I = 'i': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::J = 'j': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::K = 'k': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::L = 'l': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::M = 'm': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::N = 'n': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::O = 'o': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::P = 'p': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::Q = 'q': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::R = 'r': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::S = 's': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::T = 't': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::U = 'u': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::V = 'v': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::W = 'w': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::X = 'x': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::Y = 'y': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::Z = 'z': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::Num0 = '0': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::Num1 = '1': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::Num2 = '2': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::Num3 = '3': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::Num4 = '4': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::Num5 = '5': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::Num6 = '6': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::Num7 = '7': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::Num8 = '8': sprintf(keyStr, "UP"); break;
|
||||
case sf::Key::Num9 = '9': sprintf(keyStr, "UP"); break;*/
|
||||
case sf::Key::Escape: sprintf(keyStr, "Escape"); break;
|
||||
case sf::Key::LControl: sprintf(keyStr, "LControl"); break;
|
||||
case sf::Key::LShift: sprintf(keyStr, "LShift"); break;
|
||||
case sf::Key::LAlt: sprintf(keyStr, "LAlt"); break;
|
||||
case sf::Key::LSystem: sprintf(keyStr, "LSystem"); break;
|
||||
case sf::Key::RControl: sprintf(keyStr, "RControl"); break;
|
||||
case sf::Key::RShift: sprintf(keyStr, "RShift"); break;
|
||||
case sf::Key::RAlt: sprintf(keyStr, "RAlt"); break;
|
||||
case sf::Key::RSystem: sprintf(keyStr, "RSystem"); break;
|
||||
case sf::Key::Menu: sprintf(keyStr, "Menu"); break;
|
||||
case sf::Key::LBracket: sprintf(keyStr, "LBracket"); break;
|
||||
case sf::Key::RBracket: sprintf(keyStr, "RBracket"); break;
|
||||
case sf::Key::SemiColon: sprintf(keyStr, ";"); break;
|
||||
case sf::Key::Comma: sprintf(keyStr, ","); break;
|
||||
case sf::Key::Period: sprintf(keyStr, "."); break;
|
||||
case sf::Key::Quote: sprintf(keyStr, "\'"); break;
|
||||
case sf::Key::Slash: sprintf(keyStr, "/"); break;
|
||||
case sf::Key::BackSlash: sprintf(keyStr, "\\"); break;
|
||||
case sf::Key::Tilde: sprintf(keyStr, "~"); break;
|
||||
case sf::Key::Equal: sprintf(keyStr, "="); break;
|
||||
case sf::Key::Dash: sprintf(keyStr, "-"); break;
|
||||
case sf::Key::Space: sprintf(keyStr, "Space"); break;
|
||||
case sf::Key::Return: sprintf(keyStr, "Return"); break;
|
||||
case sf::Key::Back: sprintf(keyStr, "Back"); break;
|
||||
case sf::Key::Tab: sprintf(keyStr, "Tab"); break;
|
||||
case sf::Key::PageUp: sprintf(keyStr, "Page Up"); break;
|
||||
case sf::Key::PageDown: sprintf(keyStr, "Page Down"); break;
|
||||
case sf::Key::End: sprintf(keyStr, "End"); break;
|
||||
case sf::Key::Home: sprintf(keyStr, "Home"); break;
|
||||
case sf::Key::Insert: sprintf(keyStr, "Insert"); break;
|
||||
case sf::Key::Delete: sprintf(keyStr, "Delete"); break;
|
||||
case sf::Key::Add: sprintf(keyStr, "+"); break;
|
||||
case sf::Key::Subtract: sprintf(keyStr, "-"); break;
|
||||
case sf::Key::Multiply: sprintf(keyStr, "*"); break;
|
||||
case sf::Key::Divide: sprintf(keyStr, "/"); break;
|
||||
case sf::Key::Left: sprintf(keyStr, "Left"); break;
|
||||
case sf::Key::Right: sprintf(keyStr, "Right"); break;
|
||||
case sf::Key::Up: sprintf(keyStr, "Up"); break;
|
||||
case sf::Key::Down: sprintf(keyStr, "Down"); break;
|
||||
case sf::Key::Numpad0: sprintf(keyStr, "NP 0"); break;
|
||||
case sf::Key::Numpad1: sprintf(keyStr, "NP 1"); break;
|
||||
case sf::Key::Numpad2: sprintf(keyStr, "NP 2"); break;
|
||||
case sf::Key::Numpad3: sprintf(keyStr, "NP 3"); break;
|
||||
case sf::Key::Numpad4: sprintf(keyStr, "NP 4"); break;
|
||||
case sf::Key::Numpad5: sprintf(keyStr, "NP 5"); break;
|
||||
case sf::Key::Numpad6: sprintf(keyStr, "NP 6"); break;
|
||||
case sf::Key::Numpad7: sprintf(keyStr, "NP 7"); break;
|
||||
case sf::Key::Numpad8: sprintf(keyStr, "NP 8"); break;
|
||||
case sf::Key::Numpad9: sprintf(keyStr, "NP 9"); break;
|
||||
case sf::Key::F1: sprintf(keyStr, "F1"); break;
|
||||
case sf::Key::F2: sprintf(keyStr, "F2"); break;
|
||||
case sf::Key::F3: sprintf(keyStr, "F3"); break;
|
||||
case sf::Key::F4: sprintf(keyStr, "F4"); break;
|
||||
case sf::Key::F5: sprintf(keyStr, "F5"); break;
|
||||
case sf::Key::F6: sprintf(keyStr, "F6"); break;
|
||||
case sf::Key::F7: sprintf(keyStr, "F7"); break;
|
||||
case sf::Key::F8: sprintf(keyStr, "F8"); break;
|
||||
case sf::Key::F9: sprintf(keyStr, "F9"); break;
|
||||
case sf::Key::F10: sprintf(keyStr, "F10"); break;
|
||||
case sf::Key::F11: sprintf(keyStr, "F11"); break;
|
||||
case sf::Key::F12: sprintf(keyStr, "F12"); break;
|
||||
case sf::Key::F13: sprintf(keyStr, "F13"); break;
|
||||
case sf::Key::F14: sprintf(keyStr, "F14"); break;
|
||||
case sf::Key::F15: sprintf(keyStr, "F15"); break;
|
||||
case sf::Key::Pause: sprintf(keyStr, "Pause"); break;
|
||||
default:
|
||||
if (keycode > sf::Key::Escape)
|
||||
sprintf(keyStr, "Invalid Key");
|
||||
else
|
||||
sprintf(keyStr, "%c", toupper(keycode));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
class EventHandlerCleaner
|
||||
{
|
||||
public:
|
||||
~EventHandlerCleaner()
|
||||
{
|
||||
//EventHandler::Destroy();
|
||||
}
|
||||
} EventHandlerCleanerInst;
|
|
@ -0,0 +1,63 @@
|
|||
#ifndef EVENTHANDER_H
|
||||
#define EVENTHANDER_H 1
|
||||
#include "Common.h"
|
||||
#include <queue>
|
||||
#include "Event.hpp"
|
||||
|
||||
#define NUMKEYS 300
|
||||
#define NUMMODS 8
|
||||
|
||||
typedef bool (*listenFuncPtr) (sf::Event);
|
||||
enum InputType
|
||||
{
|
||||
KeyboardInput,
|
||||
MouseInput,
|
||||
JoystickInput
|
||||
};
|
||||
|
||||
enum Modifiers {
|
||||
UseAlt = 1,
|
||||
UseShift = 2,
|
||||
UseCtrl = 4
|
||||
};
|
||||
|
||||
struct Keys {
|
||||
InputType inputType;
|
||||
sf::Event::EventType eventType;
|
||||
sf::Key::Code keyCode;
|
||||
int mods;
|
||||
sf::Mouse::Button mouseButton;
|
||||
};
|
||||
|
||||
class EventHandler {
|
||||
|
||||
private:
|
||||
listenFuncPtr keys[NUMKEYS][NUMMODS];
|
||||
listenFuncPtr mouse[sf::Mouse::Count+1];
|
||||
listenFuncPtr joys[sf::Joy::Count+1];
|
||||
std::queue<sf::Event> eventQueue;
|
||||
static EventHandler *m_Instance;
|
||||
|
||||
protected:
|
||||
EventHandler(const EventHandler&);
|
||||
EventHandler& operator= (const EventHandler&);
|
||||
|
||||
EventHandler();
|
||||
~EventHandler();
|
||||
|
||||
public:
|
||||
|
||||
bool RegisterEventListener(listenFuncPtr func, Keys key);
|
||||
bool RemoveEventListener(Keys key);
|
||||
void Update();
|
||||
static EventHandler *GetInstance();
|
||||
static void Destroy();
|
||||
bool addEvent(sf::Event *e);
|
||||
static bool TestEvent (Keys k, sf::Event e);
|
||||
#if defined HAVE_WX && HAVE_WX
|
||||
static sf::Key::Code wxCharCodeToSF(int id);
|
||||
#endif
|
||||
static void SFKeyToString(sf::Key::Code keycode, char *keyStr);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,16 @@
|
|||
#include "EventHandler.h"
|
||||
|
||||
//EventHandler *eventHandler = NULL;
|
||||
|
||||
namespace InputCommon
|
||||
{
|
||||
void Init() {
|
||||
// init the event handler
|
||||
//EventHandler::GetInstance();
|
||||
}
|
||||
|
||||
void Shutdown() {
|
||||
//if (eventHandler)
|
||||
// delete eventHandler;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#include "EventHandler.h"
|
||||
|
||||
//extern EventHandler *eventHandler;
|
||||
|
||||
namespace InputCommon
|
||||
{
|
||||
void Init();
|
||||
void Shutdown();
|
||||
}
|
|
@ -0,0 +1,375 @@
|
|||
|
||||
// Project description
|
||||
// -------------------
|
||||
// Name: SDL Input
|
||||
// Description: Common SDL Input Functions
|
||||
//
|
||||
// Author: Falcon4ever (nJoy@falcon4ever.com, www.multigesture.net), JPeterson etc
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
//
|
||||
|
||||
//
|
||||
// Licensetype: GNU General Public License (GPL)
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
//
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
// Include
|
||||
// -------------------
|
||||
#define _SDL_MAIN_ // Avoid certain declarations in SDL.h
|
||||
#include "SDL.h" // Local
|
||||
#include "XInput.h"
|
||||
|
||||
|
||||
|
||||
|
||||
// Definitions
|
||||
// -------------------
|
||||
int g_LastPad = 0;
|
||||
|
||||
|
||||
|
||||
namespace InputCommon
|
||||
{
|
||||
|
||||
|
||||
// Definitions
|
||||
// -------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Search attached devices. Populate joyinfo for all attached physical devices.
|
||||
// -----------------------
|
||||
bool SearchDevices(std::vector<CONTROLLER_INFO> &_joyinfo, int &_NumPads, int &_NumGoodPads)
|
||||
{
|
||||
if (!SDL_WasInit(0))
|
||||
#if SDL_VERSION_ATLEAST(1, 3, 0)
|
||||
if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC) < 0)
|
||||
#else
|
||||
if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
|
||||
#endif
|
||||
{
|
||||
PanicAlert("Could not initialize SDL: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get device status
|
||||
int numjoy = SDL_NumJoysticks();
|
||||
for (int i = 0; i < numjoy; i++ )
|
||||
{
|
||||
CONTROLLER_INFO Tmp;
|
||||
|
||||
Tmp.joy = SDL_JoystickOpen(i);
|
||||
Tmp.ID = i;
|
||||
Tmp.NumAxes = SDL_JoystickNumAxes(Tmp.joy);
|
||||
Tmp.NumButtons = SDL_JoystickNumButtons(Tmp.joy);
|
||||
Tmp.NumBalls = SDL_JoystickNumBalls(Tmp.joy);
|
||||
Tmp.NumHats = SDL_JoystickNumHats(Tmp.joy);
|
||||
Tmp.Name = SDL_JoystickName(i);
|
||||
|
||||
// Check if the device is okay
|
||||
if ( Tmp.NumAxes == 0
|
||||
&& Tmp.NumBalls == 0
|
||||
&& Tmp.NumButtons == 0
|
||||
&& Tmp.NumHats == 0
|
||||
)
|
||||
{
|
||||
Tmp.Good = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_NumGoodPads++;
|
||||
Tmp.Good = true;
|
||||
}
|
||||
|
||||
_joyinfo.push_back(Tmp);
|
||||
|
||||
// We have now read the values we need so we close the device
|
||||
if (SDL_JoystickOpened(i)) SDL_JoystickClose(_joyinfo[i].joy);
|
||||
}
|
||||
|
||||
_NumPads = (int)_joyinfo.size();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Supporting functions
|
||||
// ----------------
|
||||
|
||||
// Read current joystick status
|
||||
/* ----------------
|
||||
The value PadMapping[].buttons[] is the number of the assigned joypad button,
|
||||
PadState[].buttons[] is the status of the button, it becomes 0 (no pressed) or 1 (pressed) */
|
||||
|
||||
|
||||
// Read buttons status. Called from GetJoyState().
|
||||
// ----------------------
|
||||
void ReadButton(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, int button, int NumButtons)
|
||||
{
|
||||
int ctl_button = _PadMapping.buttons[button];
|
||||
if (ctl_button < NumButtons)
|
||||
{
|
||||
_PadState.buttons[button] = SDL_JoystickGetButton(_PadState.joy, ctl_button);
|
||||
}
|
||||
}
|
||||
|
||||
// Request joystick state.
|
||||
// ----------------------
|
||||
/* Called from: PAD_GetStatus()
|
||||
Input: The virtual device 0, 1, 2 or 3
|
||||
Function: Updates the PadState struct with the current pad status. The input value "controller" is
|
||||
for a virtual controller 0 to 3. */
|
||||
void GetJoyState(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, int Controller, int NumButtons)
|
||||
{
|
||||
// Update the gamepad status
|
||||
SDL_JoystickUpdate();
|
||||
|
||||
// Update axis states. It doesn't hurt much if we happen to ask for nonexisting axises here.
|
||||
_PadState.axis[CTL_MAIN_X] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.axis[CTL_MAIN_X]);
|
||||
_PadState.axis[CTL_MAIN_Y] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.axis[CTL_MAIN_Y]);
|
||||
_PadState.axis[CTL_SUB_X] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.axis[CTL_SUB_X]);
|
||||
_PadState.axis[CTL_SUB_Y] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.axis[CTL_SUB_Y]);
|
||||
|
||||
// Update the analog trigger axis values
|
||||
#ifdef _WIN32
|
||||
if (_PadMapping.triggertype == CTL_TRIGGER_SDL)
|
||||
{
|
||||
#endif
|
||||
// If we are using SDL analog triggers the buttons have to be mapped as 1000 or up, otherwise they are not used
|
||||
if(_PadMapping.buttons[CTL_L_SHOULDER] >= 1000) _PadState.axis[CTL_L_SHOULDER] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.buttons[CTL_L_SHOULDER] - 1000); else _PadState.axis[CTL_L_SHOULDER] = 0;
|
||||
if(_PadMapping.buttons[CTL_R_SHOULDER] >= 1000) _PadState.axis[CTL_R_SHOULDER] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.buttons[CTL_R_SHOULDER] - 1000); else _PadState.axis[CTL_R_SHOULDER] = 0;
|
||||
#ifdef _WIN32
|
||||
}
|
||||
else
|
||||
{
|
||||
// XInput triggers for Xbox360 pads
|
||||
_PadState.axis[CTL_L_SHOULDER] = XInput::GetXI(0, _PadMapping.buttons[CTL_L_SHOULDER] - 1000);
|
||||
_PadState.axis[CTL_R_SHOULDER] = XInput::GetXI(0, _PadMapping.buttons[CTL_R_SHOULDER] - 1000);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Update button states to on or off
|
||||
ReadButton(_PadState, _PadMapping, CTL_L_SHOULDER, NumButtons);
|
||||
ReadButton(_PadState, _PadMapping, CTL_R_SHOULDER, NumButtons);
|
||||
ReadButton(_PadState, _PadMapping, CTL_A_BUTTON, NumButtons);
|
||||
ReadButton(_PadState, _PadMapping, CTL_B_BUTTON, NumButtons);
|
||||
ReadButton(_PadState, _PadMapping, CTL_X_BUTTON, NumButtons);
|
||||
ReadButton(_PadState, _PadMapping, CTL_Y_BUTTON, NumButtons);
|
||||
ReadButton(_PadState, _PadMapping, CTL_Z_TRIGGER, NumButtons);
|
||||
ReadButton(_PadState, _PadMapping, CTL_START, NumButtons);
|
||||
|
||||
// Update Halfpress state, this one is not in the standard _PadState.buttons array
|
||||
if (_PadMapping.halfpress < NumButtons && _PadMapping.halfpress >= 0)
|
||||
_PadState.halfpress = SDL_JoystickGetButton(_PadState.joy, _PadMapping.halfpress);
|
||||
else
|
||||
_PadState.halfpress = 0;
|
||||
|
||||
|
||||
// Check if we have an analog or digital joypad
|
||||
if (_PadMapping.controllertype == CTL_DPAD_HAT)
|
||||
{
|
||||
_PadState.dpad = SDL_JoystickGetHat(_PadState.joy, _PadMapping.dpad);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only do this if the assigned button is in range (to allow for the current way of saving keyboard
|
||||
// keys in the same array)
|
||||
if(_PadMapping.dpad2[CTL_D_PAD_UP] <= NumButtons)
|
||||
_PadState.dpad2[CTL_D_PAD_UP] = SDL_JoystickGetButton(_PadState.joy, _PadMapping.dpad2[CTL_D_PAD_UP]);
|
||||
if(_PadMapping.dpad2[CTL_D_PAD_DOWN] <= NumButtons)
|
||||
_PadState.dpad2[CTL_D_PAD_DOWN] = SDL_JoystickGetButton(_PadState.joy, _PadMapping.dpad2[CTL_D_PAD_DOWN]);
|
||||
if(_PadMapping.dpad2[CTL_D_PAD_LEFT] <= NumButtons)
|
||||
_PadState.dpad2[CTL_D_PAD_LEFT] = SDL_JoystickGetButton(_PadState.joy, _PadMapping.dpad2[CTL_D_PAD_LEFT]);
|
||||
if(_PadMapping.dpad2[CTL_D_PAD_RIGHT] <= NumButtons)
|
||||
_PadState.dpad2[CTL_D_PAD_RIGHT] = SDL_JoystickGetButton(_PadState.joy, _PadMapping.dpad2[CTL_D_PAD_RIGHT]);
|
||||
}
|
||||
|
||||
#ifdef SHOW_PAD_STATUS
|
||||
// Show the status of all connected pads
|
||||
//ConsoleListener* Console = LogManager::GetInstance()->getConsoleListener();
|
||||
//if ((g_LastPad == 0 && Controller == 0) || Controller < g_LastPad) Console->ClearScreen();
|
||||
g_LastPad = Controller;
|
||||
NOTICE_LOG(CONSOLE,
|
||||
"Pad | Number:%i Enabled:%i Handle:%i\n"
|
||||
"Main Stick | X:%03i Y:%03i\n"
|
||||
"C Stick | X:%03i Y:%03i\n"
|
||||
"Trigger | Type:%s DigitalL:%i DigitalR:%i AnalogL:%03i AnalogR:%03i HalfPress:%i\n"
|
||||
"Buttons | A:%i X:%i\n"
|
||||
"D-Pad | Type:%s Hat:%i U:%i D:%i\n"
|
||||
"======================================================\n",
|
||||
|
||||
Controller, _PadMapping.enabled, _PadState.joy,
|
||||
|
||||
_PadState.axis[InputCommon::CTL_MAIN_X], _PadState.axis[InputCommon::CTL_MAIN_Y],
|
||||
_PadState.axis[InputCommon::CTL_SUB_X], _PadState.axis[InputCommon::CTL_SUB_Y],
|
||||
|
||||
(_PadMapping.triggertype ? "CTL_TRIGGER_XINPUT" : "CTL_TRIGGER_SDL"),
|
||||
_PadState.buttons[InputCommon::CTL_L_SHOULDER], _PadState.buttons[InputCommon::CTL_R_SHOULDER],
|
||||
_PadState.axis[InputCommon::CTL_L_SHOULDER], _PadState.axis[InputCommon::CTL_R_SHOULDER],
|
||||
_PadState.halfpress,
|
||||
|
||||
_PadState.buttons[InputCommon::CTL_A_BUTTON], _PadState.buttons[InputCommon::CTL_X_BUTTON],
|
||||
|
||||
(_PadMapping.controllertype ? "CTL_DPAD_CUSTOM" : "CTL_DPAD_HAT"),
|
||||
_PadState.dpad,
|
||||
_PadState.dpad2[InputCommon::CTL_D_PAD_UP], _PadState.dpad2[InputCommon::CTL_D_PAD_DOWN]
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Configure button mapping
|
||||
// ----------
|
||||
|
||||
// Avoid extreme axis values
|
||||
// ---------------------
|
||||
/* Function: We have to avoid very big values to becuse some triggers are -0x8000 in the
|
||||
unpressed state (and then go from -0x8000 to 0x8000 as they are fully pressed) */
|
||||
bool AvoidValues(int value, bool NoTriggerFilter)
|
||||
{
|
||||
// Avoid detecting very small or very big (for triggers) values
|
||||
if( (value > -0x2000 && value < 0x2000) // Small values
|
||||
|| ((value < -0x6000 || value > 0x6000) && !NoTriggerFilter)) // Big values
|
||||
return true; // Avoid
|
||||
else
|
||||
return false; // Keep
|
||||
}
|
||||
|
||||
|
||||
// Detect a pressed button
|
||||
// ---------------------
|
||||
void GetButton(SDL_Joystick *joy, int ControllerID, int buttons, int axes, int hats,
|
||||
int &KeyboardKey, int &value, int &type, int &pressed, bool &Succeed, bool &Stop,
|
||||
bool LeftRight, bool Axis, bool XInput, bool Button, bool Hat, bool NoTriggerFilter)
|
||||
{
|
||||
// It needs the wxWidgets excape keycode
|
||||
static const int WXK_ESCAPE = 27;
|
||||
|
||||
// Update the internal status
|
||||
SDL_JoystickUpdate();
|
||||
|
||||
// For the triggers we accept both a digital or an analog button
|
||||
if(Axis)
|
||||
{
|
||||
for(int i = 0; i < axes; i++)
|
||||
{
|
||||
value = SDL_JoystickGetAxis(joy, i);
|
||||
|
||||
if(AvoidValues(value, NoTriggerFilter)) continue; // Avoid values
|
||||
|
||||
pressed = i + (LeftRight ? 1000 : 0); // Identify the analog triggers
|
||||
type = InputCommon::CTL_AXIS;
|
||||
Succeed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for a hat
|
||||
if(Hat)
|
||||
{
|
||||
for(int i = 0; i < hats; i++)
|
||||
{
|
||||
value = SDL_JoystickGetHat(joy, i);
|
||||
if(value)
|
||||
{
|
||||
pressed = i;
|
||||
type = InputCommon::CTL_HAT;
|
||||
Succeed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for a button
|
||||
if(Button)
|
||||
{
|
||||
for(int i = 0; i < buttons; i++)
|
||||
{
|
||||
// Some kind of bug in SDL 1.3 would give button 9 and 10 (nonexistent) the value 48 on the 360 pad
|
||||
if (SDL_JoystickGetButton(joy, i) > 1) continue;
|
||||
|
||||
if(SDL_JoystickGetButton(joy, i))
|
||||
{
|
||||
pressed = i;
|
||||
type = InputCommon::CTL_BUTTON;
|
||||
Succeed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for a XInput trigger
|
||||
#ifdef _WIN32
|
||||
if(XInput)
|
||||
{
|
||||
for(int i = 0; i <= InputCommon::XI_TRIGGER_R; i++)
|
||||
{
|
||||
if(XInput::GetXI(0, i))
|
||||
{
|
||||
pressed = i + 1000;
|
||||
type = InputCommon::CTL_AXIS;
|
||||
Succeed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check for keyboard action
|
||||
if (KeyboardKey)
|
||||
{
|
||||
if(Button)
|
||||
{
|
||||
// Todo: Add a separate keyboard vector to remove this restriction
|
||||
if(KeyboardKey >= buttons)
|
||||
{
|
||||
pressed = KeyboardKey;
|
||||
type = InputCommon::CTL_BUTTON;
|
||||
Succeed = true;
|
||||
KeyboardKey = 0;
|
||||
if(pressed == WXK_ESCAPE) pressed = -1; // Check for the escape key
|
||||
}
|
||||
// Else show the error message
|
||||
else
|
||||
{
|
||||
pressed = KeyboardKey;
|
||||
KeyboardKey = -1;
|
||||
Stop = true;
|
||||
}
|
||||
}
|
||||
// Only accept the escape key
|
||||
else if (KeyboardKey == WXK_ESCAPE)
|
||||
{
|
||||
Succeed = true;
|
||||
KeyboardKey = 0;
|
||||
pressed = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////// Configure button mapping
|
||||
|
||||
|
||||
|
||||
} // InputCommon
|
||||
|
|
@ -0,0 +1,269 @@
|
|||
|
||||
// Project description
|
||||
// -------------------
|
||||
// Name: SDL Input
|
||||
// Description: Common SDL Input Functions
|
||||
//
|
||||
// Author: Falcon4ever (nJoy@falcon4ever.com, www.multigesture.net), JPeterson etc
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
//
|
||||
|
||||
//
|
||||
// Licensetype: GNU General Public License (GPL)
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
//
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
//
|
||||
|
||||
|
||||
#ifndef _SDL_h
|
||||
#define _SDL_h
|
||||
|
||||
|
||||
// Include
|
||||
// -------------------
|
||||
#include <iostream> // System
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <SDL.h> // Externals
|
||||
#include <SDL_version.h>
|
||||
#if SDL_VERSION_ATLEAST(1, 3, 0)
|
||||
#include <SDL_haptic.h>
|
||||
#endif
|
||||
#else
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_version.h>
|
||||
#if SDL_VERSION_ATLEAST(1, 3, 0)
|
||||
#include <SDL/SDL_haptic.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "Common.h" // Common
|
||||
|
||||
|
||||
|
||||
namespace InputCommon
|
||||
{
|
||||
|
||||
|
||||
// Settings
|
||||
// ----------
|
||||
// Show a status window with the detected axes, buttons and so on
|
||||
//#define SHOW_PAD_STATUS
|
||||
|
||||
|
||||
|
||||
// Structures
|
||||
/* -------------------
|
||||
CONTROLLER_STATE buttons (PadState) = 0 or 1
|
||||
CONTROLLER_MAPPING buttons (joystick) = 0 or 1, 2, 3, 4, a certain joypad button
|
||||
|
||||
Please remember: The axis limit is hardcoded here, if you allow more axises (for
|
||||
example for analog A and B buttons) you must first incrase the size of the axis array
|
||||
size here
|
||||
*/
|
||||
struct CONTROLLER_STATE // GC PAD INFO/STATE
|
||||
{
|
||||
int buttons[8]; // Amount of buttons (A B X Y Z, L-Trigger R-Trigger Start) might need to change the triggers buttons
|
||||
int dpad; // Automatic SDL D-Pad (8 directions + neutral)
|
||||
int dpad2[4]; // D-pad using buttons
|
||||
int axis[6]; // 2 x 2 Axes (Main & Sub)
|
||||
int halfpress; // Halfpress... you know, like not fully pressed ;)...
|
||||
SDL_Joystick *joy; // SDL joystick device
|
||||
};
|
||||
|
||||
struct CONTROLLER_MAPPING // GC PAD MAPPING
|
||||
{
|
||||
int buttons[8]; // (See above)
|
||||
int dpad; // (See above)
|
||||
int dpad2[4]; // (See above)
|
||||
int axis[6]; // (See above)
|
||||
int halfpress; // (See above)
|
||||
int deadzone; // Deadzone... what else?
|
||||
int ID; // SDL joystick device ID
|
||||
int controllertype; // Hat: Hat or custom buttons
|
||||
int triggertype; // Triggers range
|
||||
std::string SRadius, SDiagonal, SRadiusC, SDiagonalC;
|
||||
bool bRadiusOnOff, bSquareToCircle, bRadiusOnOffC, bSquareToCircleC;
|
||||
bool rumble;
|
||||
bool enable;
|
||||
int eventnum; // Linux Event Number, Can't be found dynamically yet
|
||||
};
|
||||
|
||||
struct CONTROLLER_INFO // CONNECTED WINDOWS DEVICES INFO
|
||||
{
|
||||
int NumAxes; // Amount of Axes
|
||||
int NumButtons; // Amount of Buttons
|
||||
int NumBalls; // Amount of Balls
|
||||
int NumHats; // Amount of Hats (POV)
|
||||
std::string Name; // Joypad/stickname
|
||||
int ID; // SDL joystick device ID
|
||||
bool Good; // Pad is good (it has at least one button or axis)
|
||||
SDL_Joystick *joy; // SDL joystick device
|
||||
};
|
||||
enum
|
||||
{
|
||||
// CTL_L_SHOULDER and CTL_R_SHOULDER = 0 and 1
|
||||
CTL_MAIN_X = 2,
|
||||
CTL_MAIN_Y,
|
||||
CTL_SUB_X,
|
||||
CTL_SUB_Y
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CTL_L_SHOULDER = 0,
|
||||
CTL_R_SHOULDER,
|
||||
CTL_A_BUTTON,
|
||||
CTL_B_BUTTON,
|
||||
CTL_X_BUTTON,
|
||||
CTL_Y_BUTTON,
|
||||
CTL_Z_TRIGGER,
|
||||
CTL_START
|
||||
};
|
||||
// DPad Type
|
||||
enum
|
||||
{
|
||||
CTL_DPAD_HAT = 0, // Automatically use the first hat that SDL finds
|
||||
CTL_DPAD_CUSTOM // Custom directional pad settings
|
||||
};
|
||||
// Trigger Type
|
||||
enum
|
||||
{
|
||||
CTL_TRIGGER_SDL = 0, //
|
||||
CTL_TRIGGER_XINPUT // The XBox 360 pad
|
||||
};
|
||||
enum
|
||||
{
|
||||
CTL_D_PAD_UP = 0,
|
||||
CTL_D_PAD_DOWN,
|
||||
CTL_D_PAD_LEFT,
|
||||
CTL_D_PAD_RIGHT
|
||||
};
|
||||
// Button type for the configuration
|
||||
enum
|
||||
{
|
||||
CTL_AXIS = 0,
|
||||
CTL_HAT,
|
||||
CTL_BUTTON,
|
||||
CTL_KEY
|
||||
};
|
||||
// XInput buttons
|
||||
enum
|
||||
{
|
||||
XI_TRIGGER_L = 0,
|
||||
XI_TRIGGER_R
|
||||
};
|
||||
|
||||
|
||||
union PadAxis
|
||||
{
|
||||
int keyForControls[6];
|
||||
struct
|
||||
{
|
||||
int Lx;
|
||||
int Ly;
|
||||
int Rx;
|
||||
int Ry;
|
||||
int Tl; // Trigger
|
||||
int Tr; // Trigger
|
||||
};
|
||||
};
|
||||
struct PadWiimote
|
||||
{
|
||||
int keyForControls[16];
|
||||
// Order is A, B, 1, 2, +, -, Home
|
||||
// L, R, U, D, RollL, RollR, PitchU, PitchD, Shake
|
||||
};
|
||||
struct PadNunchuck
|
||||
{
|
||||
int keyForControls[7];
|
||||
// Order is Z, C, L, R, U, D, Shake
|
||||
};
|
||||
struct PadClassicController
|
||||
{
|
||||
int keyForControls[23];
|
||||
// Order is A, B, X, Y, +, -, Home
|
||||
// Tl, Zl, Zr, Tr, Dl, Dr, Du, Dd
|
||||
// Ll, Lr, Lu, Ld, Rl, Rr, Ru, Rd
|
||||
};
|
||||
struct PadGH3Controller
|
||||
{
|
||||
int keyForControls[14];
|
||||
// Order is Green, Red, Yellow, Blue, Orange,
|
||||
// +, -, Whammy,
|
||||
// Al, Ar, Au, Ad,
|
||||
// StrumUp, StrumDown
|
||||
};
|
||||
struct CONTROLLER_STATE_NEW // GC PAD INFO/STATE
|
||||
{
|
||||
PadAxis Axis; // 6 Axes (Main, Sub, Triggers)
|
||||
SDL_Joystick *joy; // SDL joystick device
|
||||
};
|
||||
struct CONTROLLER_MAPPING_NEW // GC PAD MAPPING
|
||||
{
|
||||
PadAxis Axis; // (See above)
|
||||
PadWiimote Wm;
|
||||
PadNunchuck Nc;
|
||||
PadClassicController Cc;
|
||||
PadGH3Controller GH3c;
|
||||
bool enabled; // Pad attached?
|
||||
bool Rumble;
|
||||
int RumbleStrength;
|
||||
int DeadZoneL; // Analog 1 Deadzone
|
||||
int DeadZoneR; // Analog 2 Deadzone
|
||||
int ID; // SDL joystick device ID
|
||||
int controllertype; // D-Pad type: Hat or custom buttons
|
||||
int triggertype; // SDL or XInput trigger
|
||||
std::string SDiagonal;
|
||||
bool bSquareToCircle;
|
||||
bool bCircle2Square;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// 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);
|
||||
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);
|
||||
float SquareDistance(float deg);
|
||||
bool IsDeadZone(float DeadZone, int x, int y);
|
||||
void Square2Circle(int &_x, int &_y, int _pad, std::string SDiagonal, bool Circle2Square = false);
|
||||
void RadiusAdjustment(int &_x, int &_y, int _pad, std::string SRadius);
|
||||
|
||||
// Input configuration
|
||||
std::string VKToString(int keycode);
|
||||
|
||||
#ifndef _SDL_MAIN_
|
||||
extern int g_LastPad;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
} // InputCommon
|
||||
|
||||
|
||||
#endif // _SDL_h
|
|
@ -0,0 +1,156 @@
|
|||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "X11InputBase.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
namespace InputCommon
|
||||
{
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
// Taken from wxw source code
|
||||
KeySym wxCharCodeWXToX(int id)
|
||||
{
|
||||
KeySym keySym;
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case WXK_CANCEL: keySym = XK_Cancel; break;
|
||||
case WXK_BACK: keySym = XK_BackSpace; break;
|
||||
case WXK_TAB: keySym = XK_Tab; break;
|
||||
case WXK_CLEAR: keySym = XK_Clear; break;
|
||||
case WXK_RETURN: keySym = XK_Return; break;
|
||||
case WXK_SHIFT: keySym = XK_Shift_L; break;
|
||||
case WXK_CONTROL: keySym = XK_Control_L; break;
|
||||
case WXK_ALT: keySym = XK_Meta_L; break;
|
||||
case WXK_CAPITAL: keySym = XK_Caps_Lock; break;
|
||||
case WXK_MENU : keySym = XK_Menu; break;
|
||||
case WXK_PAUSE: keySym = XK_Pause; break;
|
||||
case WXK_ESCAPE: keySym = XK_Escape; break;
|
||||
case WXK_SPACE: keySym = ' '; break;
|
||||
case WXK_PAGEUP: keySym = XK_Prior; break;
|
||||
case WXK_PAGEDOWN: keySym = XK_Next; break;
|
||||
case WXK_END: keySym = XK_End; break;
|
||||
case WXK_HOME : keySym = XK_Home; break;
|
||||
case WXK_LEFT : keySym = XK_Left; break;
|
||||
case WXK_UP: keySym = XK_Up; break;
|
||||
case WXK_RIGHT: keySym = XK_Right; break;
|
||||
case WXK_DOWN : keySym = XK_Down; break;
|
||||
case WXK_SELECT: keySym = XK_Select; break;
|
||||
case WXK_PRINT: keySym = XK_Print; break;
|
||||
case WXK_EXECUTE: keySym = XK_Execute; break;
|
||||
case WXK_INSERT: keySym = XK_Insert; break;
|
||||
case WXK_DELETE: keySym = XK_Delete; break;
|
||||
case WXK_HELP : keySym = XK_Help; break;
|
||||
case WXK_NUMPAD0: keySym = XK_KP_0; break; case WXK_NUMPAD_INSERT: keySym = XK_KP_Insert; break;
|
||||
case WXK_NUMPAD1: keySym = XK_KP_1; break; case WXK_NUMPAD_END: keySym = XK_KP_End; break;
|
||||
case WXK_NUMPAD2: keySym = XK_KP_2; break; case WXK_NUMPAD_DOWN: keySym = XK_KP_Down; break;
|
||||
case WXK_NUMPAD3: keySym = XK_KP_3; break; case WXK_NUMPAD_PAGEDOWN: keySym = XK_KP_Page_Down; break;
|
||||
case WXK_NUMPAD4: keySym = XK_KP_4; break; case WXK_NUMPAD_LEFT: keySym = XK_KP_Left; break;
|
||||
case WXK_NUMPAD5: keySym = XK_KP_5; break;
|
||||
case WXK_NUMPAD6: keySym = XK_KP_6; break; case WXK_NUMPAD_RIGHT: keySym = XK_KP_Right; break;
|
||||
case WXK_NUMPAD7: keySym = XK_KP_7; break; case WXK_NUMPAD_HOME: keySym = XK_KP_Home; break;
|
||||
case WXK_NUMPAD8: keySym = XK_KP_8; break; case WXK_NUMPAD_UP: keySym = XK_KP_Up; break;
|
||||
case WXK_NUMPAD9: keySym = XK_KP_9; break; case WXK_NUMPAD_PAGEUP: keySym = XK_KP_Page_Up; break;
|
||||
case WXK_NUMPAD_DECIMAL: keySym = XK_KP_Decimal; break; case WXK_NUMPAD_DELETE: keySym = XK_KP_Delete; break;
|
||||
case WXK_NUMPAD_MULTIPLY: keySym = XK_KP_Multiply; break;
|
||||
case WXK_NUMPAD_ADD: keySym = XK_KP_Add; break;
|
||||
case WXK_NUMPAD_SUBTRACT: keySym = XK_KP_Subtract; break;
|
||||
case WXK_NUMPAD_DIVIDE: keySym = XK_KP_Divide; break;
|
||||
case WXK_NUMPAD_ENTER: keySym = XK_KP_Enter; break;
|
||||
case WXK_NUMPAD_SEPARATOR: keySym = XK_KP_Separator; break;
|
||||
case WXK_F1: keySym = XK_F1; break;
|
||||
case WXK_F2: keySym = XK_F2; break;
|
||||
case WXK_F3: keySym = XK_F3; break;
|
||||
case WXK_F4: keySym = XK_F4; break;
|
||||
case WXK_F5: keySym = XK_F5; break;
|
||||
case WXK_F6: keySym = XK_F6; break;
|
||||
case WXK_F7: keySym = XK_F7; break;
|
||||
case WXK_F8: keySym = XK_F8; break;
|
||||
case WXK_F9: keySym = XK_F9; break;
|
||||
case WXK_F10: keySym = XK_F10; break;
|
||||
case WXK_F11: keySym = XK_F11; break;
|
||||
case WXK_F12: keySym = XK_F12; break;
|
||||
case WXK_F13: keySym = XK_F13; break;
|
||||
case WXK_F14: keySym = XK_F14; break;
|
||||
case WXK_F15: keySym = XK_F15; break;
|
||||
case WXK_F16: keySym = XK_F16; break;
|
||||
case WXK_F17: keySym = XK_F17; break;
|
||||
case WXK_F18: keySym = XK_F18; break;
|
||||
case WXK_F19: keySym = XK_F19; break;
|
||||
case WXK_F20: keySym = XK_F20; break;
|
||||
case WXK_F21: keySym = XK_F21; break;
|
||||
case WXK_F22: keySym = XK_F22; break;
|
||||
case WXK_F23: keySym = XK_F23; break;
|
||||
case WXK_F24: keySym = XK_F24; break;
|
||||
case WXK_NUMLOCK: keySym = XK_Num_Lock; break;
|
||||
case WXK_SCROLL: keySym = XK_Scroll_Lock; break;
|
||||
default: keySym = id <= 255 ? (KeySym)id : 0;
|
||||
}
|
||||
|
||||
return keySym;
|
||||
}
|
||||
#else
|
||||
KeySym wxCharCodeWXToX(int id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
void XKeyToString(unsigned int keycode, char *keyStr) {
|
||||
switch (keycode) {
|
||||
|
||||
case XK_Left:
|
||||
sprintf(keyStr, "LEFT");
|
||||
break;
|
||||
case XK_Up:
|
||||
sprintf(keyStr, "UP");
|
||||
break;
|
||||
case XK_Right:
|
||||
sprintf(keyStr, "RIGHT");
|
||||
break;
|
||||
case XK_Down:
|
||||
sprintf(keyStr, "DOWN");
|
||||
break;
|
||||
case XK_Return:
|
||||
sprintf(keyStr, "RETURN");
|
||||
break;
|
||||
case XK_KP_Enter:
|
||||
sprintf(keyStr, "KP ENTER");
|
||||
break;
|
||||
case XK_KP_Left:
|
||||
sprintf(keyStr, "KP LEFT");
|
||||
break;
|
||||
case XK_KP_Up:
|
||||
sprintf(keyStr, "KP UP");
|
||||
break;
|
||||
case XK_KP_Right:
|
||||
sprintf(keyStr, "KP RIGHT");
|
||||
break;
|
||||
case XK_KP_Down:
|
||||
sprintf(keyStr, "KP DOWN");
|
||||
break;
|
||||
case XK_Shift_L:
|
||||
sprintf(keyStr, "LShift");
|
||||
break;
|
||||
case XK_Control_L:
|
||||
sprintf(keyStr, "LControl");
|
||||
break;
|
||||
default:
|
||||
sprintf(keyStr, "%c", toupper(keycode));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef XINPUTBASE_H
|
||||
#define XINPUTBASE_H
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/keysym.h>
|
||||
#include "Config.h"
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
#include <wx/wx.h>
|
||||
#endif
|
||||
namespace InputCommon
|
||||
{
|
||||
KeySym wxCharCodeWXToX(int id);
|
||||
void XKeyToString(unsigned int keycode, char *keyStr);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,136 @@
|
|||
|
||||
//
|
||||
// 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/
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
// File description
|
||||
/* -------------------
|
||||
Function: This file will get the status of the analog triggers of any connected XInput device.
|
||||
This code was made with the help of SimpleController.cpp in the June 2008 Microsoft DirectX SDK
|
||||
Samples.
|
||||
|
||||
///////////////////////////////////////////////////// */
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
// Includes
|
||||
// -------------------
|
||||
#include <windows.h>
|
||||
#include <XInput.h> // XInput API
|
||||
|
||||
#include "SDL.h" // Local
|
||||
|
||||
|
||||
|
||||
namespace XInput
|
||||
{
|
||||
|
||||
|
||||
|
||||
// Declarations
|
||||
// -------------------
|
||||
|
||||
#define MAX_CONTROLLERS 4 // XInput handles up to 4 controllers
|
||||
|
||||
struct CONTROLER_STATE
|
||||
{
|
||||
XINPUT_STATE state;
|
||||
bool bConnected;
|
||||
};
|
||||
CONTROLER_STATE g_Controllers[MAX_CONTROLLERS];
|
||||
|
||||
|
||||
|
||||
|
||||
// Init
|
||||
// -------------------
|
||||
/* Function: Calculate the number of connected XInput devices
|
||||
Todo: Implement this to figure out if there are multiple XInput controllers connected,
|
||||
we currently only try to connect to XInput device 0 */
|
||||
void Init()
|
||||
{
|
||||
// Init state
|
||||
//ZeroMemory( g_Controllers, sizeof( CONTROLER_STATE ) * MAX_CONTROLLERS );
|
||||
|
||||
// Declaration
|
||||
DWORD dwResult;
|
||||
|
||||
// Calculate the number of connected XInput devices
|
||||
for( DWORD i = 0; i < MAX_CONTROLLERS; i++ )
|
||||
{
|
||||
// Simply get the state of the controller from XInput.
|
||||
dwResult = XInputGetState( i, &g_Controllers[i].state );
|
||||
|
||||
if( dwResult == ERROR_SUCCESS )
|
||||
g_Controllers[i].bConnected = true;
|
||||
else
|
||||
g_Controllers[i].bConnected = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Get the trigger status
|
||||
// -------------------
|
||||
int GetXI(int Controller, int Button)
|
||||
{
|
||||
// Update the internal status
|
||||
DWORD dwResult;
|
||||
dwResult = XInputGetState( Controller, &g_Controllers[Controller].state );
|
||||
|
||||
if( dwResult != ERROR_SUCCESS ) return -1;
|
||||
|
||||
switch(Button)
|
||||
{
|
||||
case InputCommon::XI_TRIGGER_L:
|
||||
return g_Controllers[0].state.Gamepad.bLeftTrigger;
|
||||
|
||||
case InputCommon::XI_TRIGGER_R:
|
||||
return g_Controllers[0].state.Gamepad.bRightTrigger;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Check if a certain controller is connected
|
||||
// -------------------
|
||||
bool IsConnected(int Controller)
|
||||
{
|
||||
DWORD dwResult = XInputGetState( Controller, &g_Controllers[Controller].state );
|
||||
|
||||
// Update the connected status
|
||||
if( dwResult == ERROR_SUCCESS )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // XInput
|
||||
|
||||
#endif
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
//
|
||||
// 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/
|
||||
//
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
||||
// Includes
|
||||
// ----------
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
||||
|
||||
namespace XInput
|
||||
{
|
||||
|
||||
|
||||
// Declarations
|
||||
// ----------
|
||||
void Init();
|
||||
int GetXI(int Controller, int Button);
|
||||
bool IsConnected(int Controller);
|
||||
|
||||
|
||||
} // XInput
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,557 @@
|
|||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "Common.h"
|
||||
#include "ConfigDlg.h"
|
||||
#include "../PadSimple.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "XInput.h"
|
||||
#include "../../InputCommon/DirectInputBase.h" // Core
|
||||
|
||||
DInput m_dinput;
|
||||
#endif
|
||||
|
||||
BEGIN_EVENT_TABLE(PADConfigDialogSimple,wxDialog)
|
||||
EVT_SHOW(PADConfigDialogSimple::OnShow)
|
||||
EVT_CLOSE(PADConfigDialogSimple::OnClose)
|
||||
EVT_BUTTON(ID_CLOSE,PADConfigDialogSimple::OnCloseClick)
|
||||
EVT_BUTTON(ID_PAD_ABOUT,PADConfigDialogSimple::DllAbout)
|
||||
|
||||
EVT_CHECKBOX(ID_X360PAD,PADConfigDialogSimple::ControllerSettingsChanged)
|
||||
EVT_CHOICE(ID_X360PAD_CHOICE,PADConfigDialogSimple::ControllerSettingsChanged)
|
||||
EVT_CHECKBOX(ID_RUMBLE,PADConfigDialogSimple::ControllerSettingsChanged)
|
||||
EVT_CHECKBOX(ID_DISABLE,PADConfigDialogSimple::ControllerSettingsChanged)
|
||||
|
||||
// Input recording
|
||||
#ifdef RERECORDING
|
||||
EVT_CHECKBOX(ID_RECORDING,PADConfigDialogSimple::ControllerSettingsChanged)
|
||||
EVT_CHECKBOX(ID_PLAYBACK,PADConfigDialogSimple::ControllerSettingsChanged)
|
||||
EVT_BUTTON(ID_SAVE_RECORDING,PADConfigDialogSimple::ControllerSettingsChanged)
|
||||
#endif
|
||||
|
||||
EVT_BUTTON(CTL_A, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_B, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_X, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_Y, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_Z, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_START, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_L, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_R, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_L_SEMI, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_R_SEMI, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_SLIDER(ID_TRIGGER_SEMIVALUE, PADConfigDialogSimple::ControllerSettingsChanged)
|
||||
EVT_BUTTON(CTL_MAINUP, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_MAINDOWN, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_MAINLEFT, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_MAINRIGHT, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_MAIN_SEMI, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_SLIDER(ID_MAIN_SEMIVALUE, PADConfigDialogSimple::ControllerSettingsChanged)
|
||||
EVT_BUTTON(CTL_SUBUP, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_SUBDOWN, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_SUBLEFT, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_SLIDER(ID_SUB_SEMIVALUE, PADConfigDialogSimple::ControllerSettingsChanged)
|
||||
EVT_BUTTON(CTL_SUBRIGHT, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_SUB_SEMI, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_DPADUP, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_DPADDOWN, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_DPADLEFT, PADConfigDialogSimple::OnButtonClick)
|
||||
EVT_BUTTON(CTL_DPADRIGHT, PADConfigDialogSimple::OnButtonClick)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
PADConfigDialogSimple::PADConfigDialogSimple(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
|
||||
: wxDialog(parent, id, title, position, size, style)
|
||||
{
|
||||
ClickedButton = NULL;
|
||||
CreateGUIControls();
|
||||
Fit();
|
||||
|
||||
// Connect keydown to the window
|
||||
wxTheApp->Connect(wxID_ANY, wxEVT_KEY_DOWN,
|
||||
wxKeyEventHandler(PADConfigDialogSimple::OnKeyDown),
|
||||
(wxObject*)NULL, this);
|
||||
|
||||
Show();
|
||||
}
|
||||
|
||||
PADConfigDialogSimple::~PADConfigDialogSimple()
|
||||
{
|
||||
}
|
||||
|
||||
// Create input button controls
|
||||
// -------------------
|
||||
inline void AddControl(wxPanel *pan, wxButton **button,
|
||||
wxStaticBoxSizer *sizer, const char *name, int ctl, int controller)
|
||||
{
|
||||
wxBoxSizer *hButton = new wxBoxSizer(wxHORIZONTAL);
|
||||
char keyStr[10] = {0};
|
||||
|
||||
// Add the label
|
||||
hButton->Add(new wxStaticText(pan, 0, wxString::FromAscii(name),
|
||||
wxDefaultPosition, wxDefaultSize), 0,
|
||||
wxALIGN_CENTER_VERTICAL|wxALL);
|
||||
|
||||
// Give it the mapped key name
|
||||
#ifdef _WIN32
|
||||
DInput::DIKToString(pad[controller].keyForControl[ctl], keyStr);
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
InputCommon::XKeyToString(pad[controller].keyForControl[ctl], keyStr);
|
||||
#endif
|
||||
|
||||
// Add the button to its sizer
|
||||
*button = new wxButton(pan, ctl, wxString::FromAscii(keyStr),
|
||||
wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS);
|
||||
hButton->Add(*button, 0, wxALIGN_RIGHT|wxALL);
|
||||
sizer->Add(hButton, 0, wxALIGN_RIGHT|wxALL);
|
||||
}
|
||||
|
||||
// Create input slider controls
|
||||
// -------------------
|
||||
inline void PADConfigDialogSimple::AddSlider(wxPanel *pan, wxSlider **slider,
|
||||
wxStaticBoxSizer *sizer, const char *name, int ctl, int controller)
|
||||
{
|
||||
wxBoxSizer *hSlider = new wxBoxSizer(wxHORIZONTAL);
|
||||
int semivalue, maxvalue;
|
||||
std::stringstream ss;
|
||||
|
||||
// Add the label
|
||||
hSlider->Add(new wxStaticText(pan, 0, wxString::FromAscii(name),
|
||||
wxDefaultPosition, wxDefaultSize), 0,
|
||||
wxALIGN_CENTER_VERTICAL|wxALL);
|
||||
|
||||
// Do everything else
|
||||
switch (ctl)
|
||||
{
|
||||
case ID_TRIGGER_SEMIVALUE:
|
||||
semivalue = pad[controller].Trigger_semivalue;
|
||||
maxvalue = TRIGGER_FULL;
|
||||
// Add the slider to its sizer
|
||||
*slider = new wxSlider(pan, ctl, semivalue, 0, maxvalue, wxDefaultPosition, wxSize(100,-1));
|
||||
(**slider).SetPageSize(32);
|
||||
hSlider->Add(*slider, 0, wxALIGN_RIGHT|wxALL);
|
||||
sizer->Add(hSlider, 0, wxALIGN_RIGHT|wxALL);
|
||||
// Add numeric value label to sizer
|
||||
ss << pad[controller].Trigger_semivalue;
|
||||
m_Trigger_SemiValue_Label[controller] = new wxStaticText(pan, 0,
|
||||
wxString::FromAscii( ss.str().c_str() ), wxDefaultPosition, wxSize(25, -1));
|
||||
hSlider->Add(m_Trigger_SemiValue_Label[controller],
|
||||
0, wxALIGN_CENTER_VERTICAL|wxALL);
|
||||
break;
|
||||
case ID_MAIN_SEMIVALUE:
|
||||
semivalue = pad[controller].Main_stick_semivalue;
|
||||
maxvalue = STICK_FULL;
|
||||
// Add the slider to its sizer
|
||||
*slider = new wxSlider(pan, ctl, semivalue, 0, maxvalue, wxDefaultPosition, wxSize(100, -1));
|
||||
(**slider).SetPageSize(10);
|
||||
hSlider->Add(*slider, 0, wxALIGN_RIGHT|wxALL);
|
||||
sizer->Add(hSlider, 0, wxALIGN_RIGHT|wxALL);
|
||||
// Add numeric value label to sizer
|
||||
ss << pad[controller].Main_stick_semivalue;
|
||||
m_Stick_SemiValue_Label[controller] = new wxStaticText(pan, 0,
|
||||
wxString::FromAscii( ss.str().c_str() ), wxDefaultPosition, wxSize(25, -1));
|
||||
hSlider->Add(m_Stick_SemiValue_Label[controller],
|
||||
0, wxALIGN_CENTER_VERTICAL|wxALL);
|
||||
break;
|
||||
case ID_SUB_SEMIVALUE:
|
||||
semivalue = pad[controller].Sub_stick_semivalue;
|
||||
maxvalue = STICK_FULL;
|
||||
// Add the slider to its sizer
|
||||
*slider = new wxSlider(pan, ctl, semivalue, 0, maxvalue, wxDefaultPosition, wxSize(100,-1));
|
||||
(**slider).SetPageSize(10);
|
||||
hSlider->Add(*slider, 0, wxALIGN_RIGHT|wxALL);
|
||||
sizer->Add(hSlider, 0, wxALIGN_RIGHT|wxALL);
|
||||
// Add numeric value label to sizer
|
||||
ss << pad[controller].Sub_stick_semivalue;
|
||||
m_CStick_SemiValue_Label[controller] = new wxStaticText(pan, 0,
|
||||
wxString::FromAscii( ss.str().c_str() ), wxDefaultPosition, wxSize(25, -1));
|
||||
hSlider->Add(m_CStick_SemiValue_Label[controller],
|
||||
0, wxALIGN_CENTER_VERTICAL|wxALL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PADConfigDialogSimple::CreateGUIControls()
|
||||
{
|
||||
// Notebook
|
||||
m_Notebook = new wxNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize);
|
||||
|
||||
// Controller pages
|
||||
m_Controller[0] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE1, wxDefaultPosition, wxDefaultSize);
|
||||
m_Notebook->AddPage(m_Controller[0], wxT("Controller 1"));
|
||||
m_Controller[1] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE2, wxDefaultPosition, wxDefaultSize);
|
||||
m_Notebook->AddPage(m_Controller[1], wxT("Controller 2"));
|
||||
m_Controller[2] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE3, wxDefaultPosition, wxDefaultSize);
|
||||
m_Notebook->AddPage(m_Controller[2], wxT("Controller 3"));
|
||||
m_Controller[3] = new wxPanel(m_Notebook, ID_CONTROLLERPAGE4, wxDefaultPosition, wxDefaultSize);
|
||||
m_Notebook->AddPage(m_Controller[3], wxT("Controller 4"));
|
||||
|
||||
// Standard buttons
|
||||
m_Close = new wxButton(this, ID_CLOSE, wxT("Close"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
m_About = new wxButton(this, ID_PAD_ABOUT, wxT("About"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
|
||||
// Put notebook and standard buttons in sizers
|
||||
wxBoxSizer* sSButtons;
|
||||
sSButtons = new wxBoxSizer(wxHORIZONTAL);
|
||||
sSButtons->Add(m_About,0,wxALL, 5);
|
||||
sSButtons->Add(0, 0, 1, wxEXPAND, 5);
|
||||
sSButtons->Add(m_Close, 0, wxALL, 5);
|
||||
|
||||
wxBoxSizer* sMain;
|
||||
sMain = new wxBoxSizer(wxVERTICAL);
|
||||
sMain->Add(m_Notebook, 1, wxEXPAND|wxALL, 5);
|
||||
sMain->Add(sSButtons, 0, wxEXPAND, 5);
|
||||
|
||||
this->SetSizer(sMain);
|
||||
this->Layout();
|
||||
|
||||
#ifdef _WIN32
|
||||
// Add connected XPads
|
||||
for (int x = 0; x < 4; x++)
|
||||
{
|
||||
XINPUT_STATE xstate;
|
||||
DWORD xresult = XInputGetState(x, &xstate);
|
||||
|
||||
if (xresult == ERROR_SUCCESS)
|
||||
{
|
||||
arrayStringFor_X360Pad.Add(wxString::Format(wxT("%i"), x+1));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
// --------------------------------------------------------------------
|
||||
// Settings
|
||||
// -----------------------------
|
||||
// Main horizontal container
|
||||
sDevice[i] = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
sbDevice[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Controller Settings"));
|
||||
m_Disable[i] = new wxCheckBox(m_Controller[i], ID_DISABLE, wxT("Disable when Dolphin is not in focus"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
sbDevice[i]->Add(m_Disable[i], 0, wxEXPAND|wxALL, 1);
|
||||
|
||||
#ifdef _WIN32
|
||||
m_SizeXInput[i] = new wxStaticBoxSizer(wxHORIZONTAL, m_Controller[i], wxT("XInput Pad"));
|
||||
m_X360Pad[i] = new wxCheckBox(m_Controller[i], ID_X360PAD, wxT("Enable X360Pad"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
m_X360PadC[i] = new wxChoice(m_Controller[i], ID_X360PAD_CHOICE, wxDefaultPosition, wxDefaultSize, arrayStringFor_X360Pad, 0, wxDefaultValidator);
|
||||
m_Rumble[i] = new wxCheckBox(m_Controller[i], ID_RUMBLE, wxT("Enable rumble"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
|
||||
m_SizeXInput[i]->Add(m_X360Pad[i], 0, wxEXPAND | wxALL, 1);
|
||||
m_SizeXInput[i]->Add(m_X360PadC[i], 0, wxEXPAND | wxALL, 1);
|
||||
m_SizeXInput[i]->Add(m_Rumble[i], 0, wxEXPAND | wxALL, 1);
|
||||
#endif
|
||||
// Set values
|
||||
m_Disable[i]->SetValue(pad[i].bDisable);
|
||||
|
||||
#ifdef _WIN32
|
||||
// Check if any XInput pad was found
|
||||
if (arrayStringFor_X360Pad.IsEmpty())
|
||||
{
|
||||
m_X360Pad[i]->SetLabel(wxT("Enable X360Pad - No pad connected"));
|
||||
m_X360Pad[i]->SetValue(false);
|
||||
m_X360Pad[i]->Enable(false);
|
||||
pad[i].bEnableXPad = false;
|
||||
m_X360PadC[i]->Hide();
|
||||
m_Rumble[i]->Hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_X360Pad[i]->SetValue(pad[i].bEnableXPad);
|
||||
m_X360PadC[i]->SetSelection(pad[i].XPadPlayer);
|
||||
m_X360PadC[i]->Enable(m_X360Pad[i]->IsChecked());
|
||||
m_Rumble[i]->SetValue(pad[i].bRumble);
|
||||
m_Rumble[i]->Enable(m_X360Pad[i]->IsChecked());
|
||||
}
|
||||
#endif
|
||||
|
||||
// Sizers
|
||||
sDevice[i]->Add(sbDevice[i], 0, wxEXPAND | wxALL, 1);
|
||||
//sDevice[i]->AddStretchSpacer();
|
||||
#ifdef _WIN32
|
||||
sDevice[i]->Add(m_SizeXInput[i], 0, wxEXPAND | wxALL, 1);
|
||||
#endif
|
||||
// -----------------------------------
|
||||
|
||||
|
||||
|
||||
// Rerecording
|
||||
// ---------
|
||||
#ifdef RERECORDING
|
||||
// Create controls
|
||||
m_SizeRecording[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Input Recording"));
|
||||
m_CheckRecording[i] = new wxCheckBox(m_Controller[i], ID_RECORDING, wxT("Record input"));
|
||||
m_CheckPlayback[i] = new wxCheckBox(m_Controller[i], ID_PLAYBACK, wxT("Play back input"));
|
||||
m_BtnSaveRecording[i] = new wxButton(m_Controller[i], ID_SAVE_RECORDING, wxT("Save recording"), wxDefaultPosition, wxDefaultSize);
|
||||
|
||||
// Tool tips
|
||||
m_CheckRecording[i]->SetToolTip(wxT("Your recording will be saved to pad-record.bin in the Dolphin dir when you stop the game"));
|
||||
m_CheckPlayback[i]->SetToolTip(wxT("Play back the pad-record.bin file from the Dolphin dir"));
|
||||
m_BtnSaveRecording[i]->SetToolTip(wxT(
|
||||
"This will save the current recording to pad-record.bin. Your recording will\n"
|
||||
"also be automatically saved every 60 * 10 frames. And when you shut down the\n"
|
||||
"game."));
|
||||
|
||||
// Sizers
|
||||
m_SizeRecording[i]->Add(m_CheckRecording[i], 0, wxEXPAND | wxALL, 1);
|
||||
m_SizeRecording[i]->Add(m_CheckPlayback[i], 0, wxEXPAND | wxALL, 1);
|
||||
m_SizeRecording[i]->Add(m_BtnSaveRecording[i], 0, wxEXPAND | wxALL, 1);
|
||||
|
||||
// Only enable these options for pad 0
|
||||
m_CheckRecording[i]->Enable(false); m_CheckRecording[0]->Enable(true);
|
||||
m_CheckPlayback[i]->Enable(false); m_CheckPlayback[0]->Enable(true);
|
||||
m_BtnSaveRecording[i]->Enable(false); m_BtnSaveRecording[0]->Enable(true);
|
||||
// Don't allow saving when we are not recording
|
||||
m_BtnSaveRecording[i]->Enable(g_EmulatorRunning && pad[0].bRecording);
|
||||
sDevice[i]->Add(m_SizeRecording[i], 0, wxEXPAND | wxALL, 1);
|
||||
|
||||
// Set values
|
||||
m_CheckRecording[0]->SetValue(pad[0].bRecording);
|
||||
m_CheckPlayback[0]->SetValue(pad[0].bPlayback);
|
||||
|
||||
//DEBUG_LOG(CONSOLE, "m_CheckRecording: %i\n", pad[0].bRecording, pad[0].bPlayback);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Buttons
|
||||
// -----------------------------
|
||||
sButtons[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Buttons"));
|
||||
|
||||
AddControl(m_Controller[i], &(m_ButtonA[i]), sButtons[i], "A: ", CTL_A, i);
|
||||
AddControl(m_Controller[i], &(m_ButtonB[i]), sButtons[i], "B: ", CTL_B, i);
|
||||
AddControl(m_Controller[i], &(m_ButtonX[i]), sButtons[i], "X: ", CTL_X, i);
|
||||
AddControl(m_Controller[i], &(m_ButtonY[i]), sButtons[i], "Y: ", CTL_Y, i);
|
||||
AddControl(m_Controller[i], &(m_ButtonZ[i]), sButtons[i], "Z: ", CTL_Z, i);
|
||||
AddControl(m_Controller[i], &(m_ButtonStart[i]), sButtons[i], "Start: ", CTL_START, i);
|
||||
|
||||
sTriggers[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Triggers"));
|
||||
|
||||
AddControl(m_Controller[i], &(m_ButtonL[i]), sTriggers[i], "L: ", CTL_L, i);
|
||||
AddControl(m_Controller[i], &(m_ButtonR[i]), sTriggers[i], "R: ", CTL_R, i);
|
||||
AddControl(m_Controller[i], &(m_ButtonL_Semi[i]), sTriggers[i], "Semi-L: ", CTL_L_SEMI, i);
|
||||
AddControl(m_Controller[i], &(m_ButtonR_Semi[i]), sTriggers[i], "Semi-R: ", CTL_R_SEMI, i);
|
||||
AddSlider(m_Controller[i], &(m_Trigger_SemiValue[i]), sTriggers[i], "Semi: ", ID_TRIGGER_SEMIVALUE, i);
|
||||
|
||||
sStick[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("Main Stick"));
|
||||
|
||||
AddControl(m_Controller[i], &(m_StickUp[i]), sStick[i], "Up: ", CTL_MAINUP, i);
|
||||
AddControl(m_Controller[i], &(m_StickDown[i]), sStick[i], "Down: ", CTL_MAINDOWN, i);
|
||||
AddControl(m_Controller[i], &(m_StickLeft[i]), sStick[i], "Left: ", CTL_MAINLEFT, i);
|
||||
AddControl(m_Controller[i], &(m_StickRight[i]), sStick[i], "Right: ", CTL_MAINRIGHT, i);
|
||||
AddControl(m_Controller[i], &(m_Stick_Semi[i]), sStick[i], "Semi-press: ", CTL_MAIN_SEMI, i);
|
||||
AddSlider(m_Controller[i], &(m_Stick_SemiValue[i]), sStick[i], "Semi: ", ID_MAIN_SEMIVALUE, i);
|
||||
|
||||
sDPad[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("D-Pad"));
|
||||
|
||||
AddControl(m_Controller[i], &(m_DPadUp[i]), sDPad[i], "Up: ", CTL_DPADUP, i);
|
||||
AddControl(m_Controller[i], &(m_DPadDown[i]), sDPad[i], "Down: ", CTL_DPADDOWN, i);
|
||||
AddControl(m_Controller[i], &(m_DPadLeft[i]), sDPad[i], "Left: ", CTL_DPADLEFT, i);
|
||||
AddControl(m_Controller[i], &(m_DPadRight[i]), sDPad[i], "Right: ", CTL_DPADRIGHT, i);
|
||||
|
||||
sCStick[i] = new wxStaticBoxSizer(wxVERTICAL, m_Controller[i], wxT("C-Stick"));
|
||||
|
||||
AddControl(m_Controller[i], &(m_CStickUp[i]), sCStick[i], "Up: ", CTL_SUBUP, i);
|
||||
AddControl(m_Controller[i], &(m_CStickDown[i]), sCStick[i], "Down: ", CTL_SUBDOWN, i);
|
||||
AddControl(m_Controller[i], &(m_CStickLeft[i]), sCStick[i], "Left: ", CTL_SUBLEFT, i);
|
||||
AddControl(m_Controller[i], &(m_CStickRight[i]), sCStick[i], "Right: ", CTL_SUBRIGHT, i);
|
||||
AddControl(m_Controller[i], &(m_CStick_Semi[i]), sCStick[i], "Semi-press: ", CTL_SUB_SEMI, i);
|
||||
AddSlider(m_Controller[i], &(m_CStick_SemiValue[i]), sCStick[i], "Semi: ", ID_SUB_SEMIVALUE, i);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Sizers
|
||||
// -----------------------------
|
||||
sPage[i] = new wxGridBagSizer(0, 0);
|
||||
sPage[i]->SetFlexibleDirection(wxBOTH);
|
||||
sPage[i]->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
|
||||
sPage[i]->Add(sDevice[i], wxGBPosition(0, 0), wxGBSpan(1, 5), wxEXPAND|wxALL, 1);
|
||||
sPage[i]->Add(sButtons[i], wxGBPosition(1, 0), wxGBSpan(2, 1), wxALL, 1);
|
||||
sPage[i]->Add(sTriggers[i], wxGBPosition(1, 1), wxGBSpan(1, 1), wxEXPAND|wxALL, 1);
|
||||
sPage[i]->Add(sStick[i], wxGBPosition(1, 2), wxGBSpan(2, 1), wxALL, 1);
|
||||
sPage[i]->Add(sDPad[i], wxGBPosition(1, 3), wxGBSpan(2, 1), wxALL, 1);
|
||||
sPage[i]->Add(sCStick[i], wxGBPosition(1, 4), wxGBSpan(2, 1), wxALL, 1);
|
||||
m_Controller[i]->SetSizer(sPage[i]);
|
||||
sPage[i]->Layout();
|
||||
}
|
||||
}
|
||||
|
||||
void PADConfigDialogSimple::OnClose(wxCloseEvent& event)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
m_dinput.Free();
|
||||
#endif
|
||||
EndModal(0);
|
||||
}
|
||||
|
||||
void PADConfigDialogSimple::OnCloseClick(wxCommandEvent& event)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void PADConfigDialogSimple::OnShow(wxShowEvent& event)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
m_dinput.Init((HWND)this->GetParent());
|
||||
#endif
|
||||
}
|
||||
|
||||
void PADConfigDialogSimple::OnKeyDown(wxKeyEvent& event)
|
||||
{
|
||||
char keyStr[10] = {0};
|
||||
if(ClickedButton)
|
||||
{
|
||||
// Get the selected notebook page
|
||||
int page = m_Notebook->GetSelection();
|
||||
|
||||
#ifdef _WIN32
|
||||
m_dinput.Read();
|
||||
if (m_dinput.diks[DIK_ESCAPE])
|
||||
{
|
||||
pad[page].keyForControl[ClickedButton->GetId()] = 0x00;
|
||||
ClickedButton->SetLabel(wxString::FromAscii(""));
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 0; i < 255; i++)
|
||||
{
|
||||
if(m_dinput.diks[i])
|
||||
{
|
||||
// Save the mapped key
|
||||
pad[page].keyForControl[ClickedButton->GetId()] = i;
|
||||
// Get the key name
|
||||
DInput::DIKToString(i, keyStr);
|
||||
ClickedButton->SetLabel(wxString::FromAscii(keyStr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
if (event.GetKeyCode() == (XK_Escape & 0xFF))
|
||||
{
|
||||
pad[page].keyForControl[ClickedButton->GetId()] = InputCommon::wxCharCodeWXToX(0x00);
|
||||
ClickedButton->SetLabel(wxString::FromAscii(""));
|
||||
}
|
||||
else
|
||||
{
|
||||
pad[page].keyForControl[ClickedButton->GetId()] = InputCommon::wxCharCodeWXToX(event.GetKeyCode());
|
||||
InputCommon::XKeyToString(pad[page].keyForControl[ClickedButton->GetId()], keyStr);
|
||||
ClickedButton->SetLabel(wxString::FromAscii(keyStr));
|
||||
}
|
||||
#endif
|
||||
ClickedButton->Disconnect();
|
||||
}
|
||||
// Reset
|
||||
ClickedButton = NULL;
|
||||
//event.Skip();
|
||||
}
|
||||
|
||||
// We have clicked a button
|
||||
void PADConfigDialogSimple::OnButtonClick(wxCommandEvent& event)
|
||||
{
|
||||
// Check if the Space key was set, to solve the problem that the Space key calls this function
|
||||
#ifdef _WIN32
|
||||
if (m_dinput.diks[DIK_SPACE]) { m_dinput.diks[DIK_SPACE] = 0; return; }
|
||||
#endif
|
||||
|
||||
// If we come here again before any key was set
|
||||
if(ClickedButton) ClickedButton->SetLabel(oldLabel);
|
||||
|
||||
// Save the old button label so we can reapply it if necessary
|
||||
ClickedButton = (wxButton *)event.GetEventObject();
|
||||
oldLabel = ClickedButton->GetLabel();
|
||||
ClickedButton->SetLabel(_("Press Key/Esc"));
|
||||
|
||||
ClickedButton->SetWindowStyle(wxWANTS_CHARS);
|
||||
}
|
||||
|
||||
void PADConfigDialogSimple::ControllerSettingsChanged(wxCommandEvent& event)
|
||||
{
|
||||
int page = m_Notebook->GetSelection();
|
||||
std::stringstream ss;
|
||||
|
||||
switch (event.GetId())
|
||||
{
|
||||
// General settings
|
||||
case ID_DISABLE:
|
||||
pad[page].bDisable = m_Disable[page]->GetValue();
|
||||
break;
|
||||
|
||||
// XInput
|
||||
case ID_X360PAD:
|
||||
pad[page].bEnableXPad = event.IsChecked();
|
||||
m_Rumble[page]->Enable(event.IsChecked());
|
||||
m_X360PadC[page]->Enable(event.IsChecked());
|
||||
break;
|
||||
case ID_X360PAD_CHOICE:
|
||||
pad[page].XPadPlayer = event.GetSelection();
|
||||
break;
|
||||
case ID_RUMBLE:
|
||||
pad[page].bRumble = m_Rumble[page]->GetValue();
|
||||
break;
|
||||
|
||||
// Semi-press adjustment
|
||||
case ID_TRIGGER_SEMIVALUE:
|
||||
pad[page].Trigger_semivalue = m_Trigger_SemiValue[page]->GetValue();
|
||||
ss << pad[page].Trigger_semivalue;
|
||||
(*m_Trigger_SemiValue_Label[page]).SetLabel(wxString::FromAscii( ss.str().c_str() ));
|
||||
break;
|
||||
case ID_MAIN_SEMIVALUE:
|
||||
pad[page].Main_stick_semivalue = m_Stick_SemiValue[page]->GetValue();
|
||||
ss << pad[page].Main_stick_semivalue;
|
||||
(*m_Stick_SemiValue_Label[page]).SetLabel(wxString::FromAscii( ss.str().c_str() ));
|
||||
break;
|
||||
case ID_SUB_SEMIVALUE:
|
||||
pad[page].Sub_stick_semivalue = m_CStick_SemiValue[page]->GetValue();
|
||||
ss << pad[page].Sub_stick_semivalue;
|
||||
(*m_CStick_SemiValue_Label[page]).SetLabel(wxString::FromAscii( ss.str().c_str() ));
|
||||
break;
|
||||
|
||||
// Input recording
|
||||
#ifdef RERECORDING
|
||||
case ID_RECORDING:
|
||||
pad[page].bRecording = m_CheckRecording[page]->GetValue();
|
||||
// Turn off the other option
|
||||
pad[page].bPlayback = false; m_CheckPlayback[page]->SetValue(false);
|
||||
break;
|
||||
case ID_PLAYBACK:
|
||||
pad[page].bPlayback = m_CheckPlayback[page]->GetValue();
|
||||
// Turn off the other option
|
||||
pad[page].bRecording = false; m_CheckRecording[page]->SetValue(false);
|
||||
break;
|
||||
case ID_SAVE_RECORDING:
|
||||
// Double check again that we are still running a game
|
||||
if (g_EmulatorRunning) SaveRecord();
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void PADConfigDialogSimple::DllAbout(wxCommandEvent& event)
|
||||
{
|
||||
wxString message;
|
||||
#ifdef _WIN32
|
||||
message = _("A simple keyboard and XInput plugin for dolphin.");
|
||||
#else
|
||||
message = _("A simple keyboard plugin for dolphin.");
|
||||
#endif
|
||||
|
||||
wxMessageBox(_T("Dolphin PadSimple Plugin\nBy ector and F|RES\n\n" + message),
|
||||
_T("Dolphin PadSimple"), wxOK, this);
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef __CONFIGDLG_H__
|
||||
#define __CONFIGDLG_H__
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/gbsizer.h>
|
||||
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
#include "X11InputBase.h"
|
||||
#endif
|
||||
|
||||
class PADConfigDialogSimple : public wxDialog
|
||||
{
|
||||
|
||||
|
||||
public:
|
||||
PADConfigDialogSimple(wxWindow *parent, wxWindowID id = 1, const wxString &title = wxT("Pad Configuration"),
|
||||
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE);
|
||||
|
||||
virtual ~PADConfigDialogSimple();
|
||||
|
||||
private:
|
||||
DECLARE_EVENT_TABLE();
|
||||
wxNotebook *m_Notebook;
|
||||
wxPanel *m_Controller[4];
|
||||
wxButton *m_About;
|
||||
wxButton *m_Close;
|
||||
|
||||
wxStaticBoxSizer *sbDevice[4], *m_SizeXInput[4], *m_SizeRecording[4];
|
||||
wxBoxSizer *sDevice[4];
|
||||
wxGridBagSizer *sPage[4];
|
||||
wxStaticBoxSizer *sButtons[4];
|
||||
wxStaticBoxSizer *sTriggers[4];
|
||||
wxStaticBoxSizer *sStick[4];
|
||||
wxStaticBoxSizer *sCStick[4];
|
||||
wxStaticBoxSizer *sDPad[4];
|
||||
|
||||
wxArrayString arrayStringFor_X360Pad;
|
||||
wxCheckBox *m_X360Pad[4];
|
||||
wxChoice *m_X360PadC[4];
|
||||
wxCheckBox *m_Disable[4];
|
||||
wxCheckBox *m_Rumble[4];
|
||||
|
||||
// Recording
|
||||
wxCheckBox *m_CheckRecording[4];
|
||||
wxCheckBox *m_CheckPlayback[4];
|
||||
wxButton *m_BtnSaveRecording[4];
|
||||
|
||||
wxButton *m_ButtonA[4];
|
||||
wxButton *m_ButtonB[4];
|
||||
wxButton *m_ButtonX[4];
|
||||
wxButton *m_ButtonY[4];
|
||||
wxButton *m_ButtonZ[4];
|
||||
wxButton *m_ButtonStart[4];
|
||||
wxButton *m_ButtonL[4];
|
||||
wxButton *m_ButtonR[4];
|
||||
wxButton *m_ButtonL_Semi[4];
|
||||
wxButton *m_ButtonR_Semi[4];
|
||||
wxSlider *m_Trigger_SemiValue[4];
|
||||
wxStaticText *m_Trigger_SemiValue_Label[4];
|
||||
wxButton *m_StickUp[4];
|
||||
wxButton *m_StickDown[4];
|
||||
wxButton *m_StickLeft[4];
|
||||
wxButton *m_StickRight[4];
|
||||
wxButton *m_Stick_Semi[4];
|
||||
wxSlider *m_Stick_SemiValue[4];
|
||||
wxStaticText *m_Stick_SemiValue_Label[4];
|
||||
wxButton *m_CStickUp[4];
|
||||
wxButton *m_CStickDown[4];
|
||||
wxButton *m_CStickLeft[4];
|
||||
wxButton *m_CStickRight[4];
|
||||
wxButton *m_CStick_Semi[4];
|
||||
wxSlider *m_CStick_SemiValue[4];
|
||||
wxStaticText *m_CStick_SemiValue_Label[4];
|
||||
wxButton *m_DPadUp[4];
|
||||
wxButton *m_DPadDown[4];
|
||||
wxButton *m_DPadLeft[4];
|
||||
wxButton *m_DPadRight[4];
|
||||
|
||||
enum
|
||||
{
|
||||
////GUI Enum Control ID Start
|
||||
ID_CLOSE = 1000,
|
||||
ID_NOTEBOOK,
|
||||
ID_CONTROLLERPAGE1,
|
||||
ID_CONTROLLERPAGE2,
|
||||
ID_CONTROLLERPAGE3,
|
||||
ID_CONTROLLERPAGE4,
|
||||
|
||||
// XInput pad
|
||||
ID_X360PAD_CHOICE,
|
||||
ID_X360PAD,
|
||||
ID_RUMBLE,
|
||||
|
||||
// Semi-press values
|
||||
ID_TRIGGER_SEMIVALUE,
|
||||
ID_MAIN_SEMIVALUE,
|
||||
ID_SUB_SEMIVALUE,
|
||||
|
||||
// Input recording
|
||||
ID_RECORDING,
|
||||
ID_PLAYBACK,
|
||||
ID_SAVE_RECORDING,
|
||||
|
||||
// General settings
|
||||
ID_DISABLE,
|
||||
ID_PAD_ABOUT,
|
||||
};
|
||||
|
||||
void OnClose(wxCloseEvent& event);
|
||||
void CreateGUIControls();
|
||||
void OnCloseClick(wxCommandEvent& event);
|
||||
void OnKeyDown(wxKeyEvent& event);
|
||||
void ControllerSettingsChanged(wxCommandEvent& event);
|
||||
void OnButtonClick(wxCommandEvent& event);
|
||||
void DllAbout(wxCommandEvent& event);
|
||||
void OnShow(wxShowEvent& event);
|
||||
void AddSlider(wxPanel *pan, wxSlider **slider,
|
||||
wxStaticBoxSizer *sizer, const char *name, int ctl, int controller);
|
||||
|
||||
wxButton *ClickedButton;
|
||||
wxString oldLabel;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,994 @@
|
|||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
|
||||
// Include
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "Common.h"
|
||||
//#include "LogManager.h"
|
||||
#include "pluginspecs_pad.h"
|
||||
#include "PadSimple.h"
|
||||
//#include "IniFile.h"
|
||||
//#include "StringUtil.h"
|
||||
//#include "FileUtil.h"
|
||||
//#include "ChunkFile.h"
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
#include "GUI/ConfigDlg.h"
|
||||
PADConfigDialogSimple* m_ConfigFrame = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "XInput.h"
|
||||
#include "../InputCommon/DirectInputBase.h" // Core
|
||||
|
||||
DInput dinput;
|
||||
//#elif defined(USE_SDL) && USE_SDL
|
||||
//#include <SDL.h>
|
||||
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/XKBlib.h>
|
||||
|
||||
Display* GXdsp;
|
||||
bool KeyStatus[NUMCONTROLS];
|
||||
#elif defined(HAVE_COCOA) && HAVE_COCOA
|
||||
#include <Cocoa/Cocoa.h>
|
||||
bool KeyStatus[NUMCONTROLS];
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Declarations
|
||||
SPads pad[4];
|
||||
SPADInitialize g_PADInitialize;
|
||||
|
||||
|
||||
// Standard crap to make wxWidgets happy
|
||||
#ifdef _WIN32
|
||||
//HINSTANCE g_hInstance;
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
class wxDLLApp : public wxApp
|
||||
{
|
||||
bool OnInit()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
|
||||
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
|
||||
#endif
|
||||
|
||||
BOOL APIENTRY aMain(HINSTANCE hinstDLL, // DLL module handle
|
||||
DWORD dwReason, // reason called
|
||||
LPVOID lpvReserved) // reserved
|
||||
{
|
||||
switch (dwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
{
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
wxSetInstance((HINSTANCE)hinstDLL);
|
||||
int argc = 0;
|
||||
char **argv = NULL;
|
||||
wxEntryStart(argc, argv);
|
||||
if (!wxTheApp || !wxTheApp->CallOnInit())
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
wxEntryCleanup();
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//g_hInstance = hinstDLL;
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
wxWindow* GetParentedWxWindow(HWND Parent)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// wxSetInstance((HINSTANCE)g_hInstance);
|
||||
#endif
|
||||
wxWindow *win = new wxWindow();
|
||||
#ifdef _WIN32
|
||||
win->SetHWND((WXHWND)Parent);
|
||||
win->AdoptAttributesFromHWND();
|
||||
#endif
|
||||
return win;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Input Recording
|
||||
|
||||
// Enable these to record or play back
|
||||
//#define RECORD_REPLAY
|
||||
//#define RECORD_STORE
|
||||
#if 0
|
||||
// Pre defined maxium storage limit
|
||||
#define RECORD_SIZE (1024 * 128)
|
||||
PLUGIN_GLOBALS* globals = NULL;
|
||||
SPADStatus recordBuffer[RECORD_SIZE];
|
||||
int count = 0;
|
||||
bool g_EmulatorRunning = false;
|
||||
|
||||
//******************************************************************************
|
||||
// Supporting functions
|
||||
//******************************************************************************
|
||||
|
||||
void RecordInput(const SPADStatus& _rPADStatus)
|
||||
{
|
||||
if (count >= RECORD_SIZE) return;
|
||||
recordBuffer[count++] = _rPADStatus;
|
||||
|
||||
// Logging
|
||||
//u8 TmpData[sizeof(SPADStatus)];
|
||||
//memcpy(TmpData, &recordBuffer[count - 1], sizeof(SPADStatus));
|
||||
//Console::Print("RecordInput(%i): %s\n", count, ArrayToString(TmpData, sizeof(SPADStatus), 0, 30).c_str());
|
||||
|
||||
// Auto save every ten seconds
|
||||
if (count % (60 * 10) == 0) SaveRecord();
|
||||
}
|
||||
|
||||
const SPADStatus& PlayRecord()
|
||||
{
|
||||
// Logging
|
||||
//Console::Print("PlayRecord(%i)\n", count);
|
||||
|
||||
if (count >= RECORD_SIZE)
|
||||
{
|
||||
// Todo: Make the recording size unlimited?
|
||||
//PanicAlert("The recording reached its end");
|
||||
return(recordBuffer[0]);
|
||||
}
|
||||
return(recordBuffer[count++]);
|
||||
}
|
||||
|
||||
void LoadRecord()
|
||||
{
|
||||
FILE* pStream = fopen("pad-record.bin", "rb");
|
||||
|
||||
if (pStream != NULL)
|
||||
{
|
||||
fread(recordBuffer, 1, RECORD_SIZE * sizeof(SPADStatus), pStream);
|
||||
fclose(pStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
PanicAlert("SimplePad: Could not open pad-record.bin");
|
||||
}
|
||||
|
||||
//Console::Print("LoadRecord()");
|
||||
}
|
||||
|
||||
void SaveRecord()
|
||||
{
|
||||
// Open the file in a way that clears all old data
|
||||
FILE* pStream = fopen("pad-record.bin", "wb");
|
||||
|
||||
if (pStream != NULL)
|
||||
{
|
||||
fwrite(recordBuffer, 1, RECORD_SIZE * sizeof(SPADStatus), pStream);
|
||||
fclose(pStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
PanicAlert("SimplePad: Could not save pad-record.bin");
|
||||
}
|
||||
//PanicAlert("SaveRecord()");
|
||||
//Console::Print("SaveRecord()");
|
||||
}
|
||||
|
||||
#endif
|
||||
// Check if Dolphin is in focus
|
||||
bool IsFocus()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HWND Parent = GetParent(g_PADInitialize.hWnd);
|
||||
HWND TopLevel = GetParent(Parent);
|
||||
// Support both rendering to main window and not
|
||||
if (GetForegroundWindow() == TopLevel || GetForegroundWindow() == g_PADInitialize.hWnd)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Implement circular deadzone
|
||||
const float kDeadZone = 0.1f;
|
||||
void ScaleStickValues(unsigned char* outx,
|
||||
unsigned char* outy,
|
||||
short inx, short iny)
|
||||
{
|
||||
float x = ((float)inx + 0.5f) / 32767.5f;
|
||||
float y = ((float)iny + 0.5f) / 32767.5f;
|
||||
|
||||
if ((x == 0.0f) && (y == 0.0f)) // to be safe
|
||||
{
|
||||
*outx = 0;
|
||||
*outy = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
float magnitude = sqrtf(x * x + y * y);
|
||||
float nx = x / magnitude;
|
||||
float ny = y / magnitude;
|
||||
|
||||
if (magnitude < kDeadZone){magnitude = kDeadZone;}
|
||||
|
||||
magnitude = (magnitude - kDeadZone) / (1.0f - kDeadZone);
|
||||
magnitude *= magnitude; // another power may be more appropriate
|
||||
nx *= magnitude;
|
||||
ny *= magnitude;
|
||||
int ix = (int)(nx * 100);
|
||||
int iy = (int)(ny * 100);
|
||||
*outx = 0x80 + ix;
|
||||
*outy = 0x80 + iy;
|
||||
}
|
||||
|
||||
// for same displacement should be sqrt(2)/2 (in theory)
|
||||
// 3/4 = 0.75 is a little faster than sqrt(2)/2 = 0.7071...
|
||||
// In SMS, 17/20 = 0.85 is perfect; in WW, 7/10 = 0.70 is closer.
|
||||
#define DIAGONAL_SCALE 0.70710678
|
||||
void EmulateAnalogStick(unsigned char *stickX, unsigned char *stickY, bool buttonUp, bool buttonDown, bool buttonLeft, bool buttonRight, int magnitude) {
|
||||
int mainY = 0;
|
||||
int mainX = 0;
|
||||
if (buttonUp)
|
||||
mainY = magnitude;
|
||||
else if (buttonDown)
|
||||
mainY = -magnitude;
|
||||
if (buttonLeft)
|
||||
mainX = -magnitude;
|
||||
else if (buttonRight)
|
||||
mainX = magnitude;
|
||||
// only update if there is some action
|
||||
// this allows analog stick to still work
|
||||
// disable for now, enable later if any platform supports both methods of input
|
||||
//if ((mainX != 0) && (mainY != 0)) {
|
||||
if (true) {
|
||||
if ((mainX == 0) || (mainY == 0))
|
||||
{
|
||||
*stickX += mainX;
|
||||
*stickY += mainY;
|
||||
}
|
||||
else
|
||||
{
|
||||
*stickX += mainX*DIAGONAL_SCALE;
|
||||
*stickY += mainY*DIAGONAL_SCALE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// Input
|
||||
//******************************************************************************
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
void DInput_Read(int _numPAD, SPADStatus* _pPADStatus)
|
||||
{
|
||||
dinput.Read();
|
||||
|
||||
// for (int i = 0; i < 200; i++)
|
||||
// if(dinput.diks[i])
|
||||
// printf("DInput_Read");
|
||||
|
||||
// Analog stick values based on semi-press keys
|
||||
int mainstickvalue = (dinput.diks[pad[_numPAD].keyForControl[CTL_MAIN_SEMI]] & 0xFF) ? pad[_numPAD].Main_stick_semivalue : STICK_FULL;
|
||||
int substickvalue = (dinput.diks[pad[_numPAD].keyForControl[CTL_SUB_SEMI]] & 0xFF) ? pad[_numPAD].Sub_stick_semivalue : STICK_FULL;
|
||||
// Buttons (A/B/X/Y/Z/Start)
|
||||
if (dinput.diks[pad[_numPAD].keyForControl[CTL_A]] & 0xFF)
|
||||
{
|
||||
_pPADStatus->button |= PAD_BUTTON_A;
|
||||
_pPADStatus->analogA = BUTTON_FULL;
|
||||
}
|
||||
if (dinput.diks[pad[_numPAD].keyForControl[CTL_B]] & 0xFF)
|
||||
{
|
||||
_pPADStatus->button |= PAD_BUTTON_B;
|
||||
_pPADStatus->analogB = BUTTON_FULL;
|
||||
}
|
||||
if (dinput.diks[pad[_numPAD].keyForControl[CTL_X]] & 0xFF){_pPADStatus->button |= PAD_BUTTON_X;}
|
||||
if (dinput.diks[pad[_numPAD].keyForControl[CTL_Y]] & 0xFF){_pPADStatus->button |= PAD_BUTTON_Y;}
|
||||
if (dinput.diks[pad[_numPAD].keyForControl[CTL_Z]] & 0xFF){_pPADStatus->button |= PAD_TRIGGER_Z;}
|
||||
if (dinput.diks[pad[_numPAD].keyForControl[CTL_START]] & 0xFF){_pPADStatus->button |= PAD_BUTTON_START;}
|
||||
// Triggers (L/R)
|
||||
if (dinput.diks[pad[_numPAD].keyForControl[CTL_L]] & 0xFF)
|
||||
{
|
||||
_pPADStatus->button |= PAD_TRIGGER_L;
|
||||
_pPADStatus->triggerLeft = TRIGGER_FULL;
|
||||
}
|
||||
if (dinput.diks[pad[_numPAD].keyForControl[CTL_R]] & 0xFF)
|
||||
{
|
||||
_pPADStatus->button |= PAD_TRIGGER_R;
|
||||
_pPADStatus->triggerRight = TRIGGER_FULL;
|
||||
}
|
||||
if (dinput.diks[pad[_numPAD].keyForControl[CTL_L_SEMI]] & 0xFF)
|
||||
{
|
||||
_pPADStatus->triggerLeft = pad[_numPAD].Trigger_semivalue;
|
||||
if (pad[_numPAD].Trigger_semivalue > TRIGGER_THRESHOLD)
|
||||
_pPADStatus->button |= PAD_TRIGGER_L;
|
||||
}
|
||||
if (dinput.diks[pad[_numPAD].keyForControl[CTL_R_SEMI]] & 0xFF)
|
||||
{
|
||||
_pPADStatus->triggerRight = pad[_numPAD].Trigger_semivalue;
|
||||
if (pad[_numPAD].Trigger_semivalue > TRIGGER_THRESHOLD)
|
||||
_pPADStatus->button |= PAD_TRIGGER_R;
|
||||
}
|
||||
// Main stick
|
||||
EmulateAnalogStick(
|
||||
&_pPADStatus->stickX,
|
||||
&_pPADStatus->stickY,
|
||||
!!dinput.diks[pad[_numPAD].keyForControl[CTL_MAINUP]],
|
||||
!!dinput.diks[pad[_numPAD].keyForControl[CTL_MAINDOWN]],
|
||||
!!dinput.diks[pad[_numPAD].keyForControl[CTL_MAINLEFT]],
|
||||
!!dinput.diks[pad[_numPAD].keyForControl[CTL_MAINRIGHT]],
|
||||
mainstickvalue );
|
||||
|
||||
// Sub-stick (C-stick)
|
||||
EmulateAnalogStick(
|
||||
&_pPADStatus->substickX,
|
||||
&_pPADStatus->substickY,
|
||||
!!dinput.diks[pad[_numPAD].keyForControl[CTL_SUBUP]],
|
||||
!!dinput.diks[pad[_numPAD].keyForControl[CTL_SUBDOWN]],
|
||||
!!dinput.diks[pad[_numPAD].keyForControl[CTL_SUBLEFT]],
|
||||
!!dinput.diks[pad[_numPAD].keyForControl[CTL_SUBRIGHT]],
|
||||
substickvalue );
|
||||
// D-pad
|
||||
if (dinput.diks[pad[_numPAD].keyForControl[CTL_DPADUP]] & 0xFF){_pPADStatus->button |= PAD_BUTTON_UP;}
|
||||
if (dinput.diks[pad[_numPAD].keyForControl[CTL_DPADDOWN]] & 0xFF){_pPADStatus->button |= PAD_BUTTON_DOWN;}
|
||||
if (dinput.diks[pad[_numPAD].keyForControl[CTL_DPADLEFT]] & 0xFF){_pPADStatus->button |= PAD_BUTTON_LEFT;}
|
||||
if (dinput.diks[pad[_numPAD].keyForControl[CTL_DPADRIGHT]] & 0xFF){_pPADStatus->button |= PAD_BUTTON_RIGHT;}
|
||||
// Mic key
|
||||
_pPADStatus->MicButton = (dinput.diks[pad[_numPAD].keyForControl[CTL_MIC]] & 0xFF) ? true : false;
|
||||
}
|
||||
|
||||
bool XInput_Read(int XPadPlayer, SPADStatus* _pPADStatus)
|
||||
{
|
||||
const int base = 0x80;
|
||||
XINPUT_STATE xstate;
|
||||
DWORD xresult = XInputGetState(XPadPlayer, &xstate);
|
||||
|
||||
// Let's .. yes, let's use XINPUT!
|
||||
if (xresult == ERROR_SUCCESS)
|
||||
{
|
||||
const XINPUT_GAMEPAD& xpad = xstate.Gamepad;
|
||||
|
||||
if ((_pPADStatus->stickX == base) && (_pPADStatus->stickY == base))
|
||||
{
|
||||
ScaleStickValues(
|
||||
&_pPADStatus->stickX,
|
||||
&_pPADStatus->stickY,
|
||||
xpad.sThumbLX,
|
||||
xpad.sThumbLY);
|
||||
}
|
||||
|
||||
if ((_pPADStatus->substickX == base) && (_pPADStatus->substickY == base))
|
||||
{
|
||||
ScaleStickValues(
|
||||
&_pPADStatus->substickX,
|
||||
&_pPADStatus->substickY,
|
||||
xpad.sThumbRX,
|
||||
xpad.sThumbRY);
|
||||
}
|
||||
|
||||
if (xpad.wButtons & XINPUT_GAMEPAD_DPAD_UP) {_pPADStatus->button |= PAD_BUTTON_UP;}
|
||||
if (xpad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) {_pPADStatus->button |= PAD_BUTTON_DOWN;}
|
||||
if (xpad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) {_pPADStatus->button |= PAD_BUTTON_LEFT;}
|
||||
if (xpad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) {_pPADStatus->button |= PAD_BUTTON_RIGHT;}
|
||||
|
||||
_pPADStatus->triggerLeft = xpad.bLeftTrigger;
|
||||
_pPADStatus->triggerRight = xpad.bRightTrigger;
|
||||
if (xpad.bLeftTrigger > TRIGGER_THRESHOLD) {_pPADStatus->button |= PAD_TRIGGER_L;}
|
||||
if (xpad.bRightTrigger > TRIGGER_THRESHOLD) {_pPADStatus->button |= PAD_TRIGGER_R;}
|
||||
if (xpad.wButtons & XINPUT_GAMEPAD_START) {_pPADStatus->button |= PAD_BUTTON_START;}
|
||||
if (xpad.wButtons & XINPUT_GAMEPAD_A) {_pPADStatus->button |= PAD_BUTTON_A;}
|
||||
if (xpad.wButtons & XINPUT_GAMEPAD_B) {_pPADStatus->button |= PAD_BUTTON_X;}
|
||||
if (xpad.wButtons & XINPUT_GAMEPAD_X) {_pPADStatus->button |= PAD_BUTTON_B;}
|
||||
if (xpad.wButtons & XINPUT_GAMEPAD_Y) {_pPADStatus->button |= PAD_BUTTON_Y;}
|
||||
if (xpad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER){_pPADStatus->button |= PAD_TRIGGER_Z;}
|
||||
|
||||
//_pPADStatus->MicButton = (xpad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) ? true : false;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(HAVE_X11) && HAVE_X11) || (defined(HAVE_COCOA) && HAVE_COCOA)
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
// The graphics plugin in the PCSX2 design leaves a lot of the window processing to the pad plugin, weirdly enough.
|
||||
void X11_Read(int _numPAD, SPADStatus* _pPADStatus)
|
||||
{
|
||||
// Do all the stuff we need to do once per frame here
|
||||
if (_numPAD != 0)
|
||||
return;
|
||||
// This code is from Zerofrog's pcsx2 pad plugin
|
||||
XEvent E;
|
||||
//int keyPress=0, keyRelease=0;
|
||||
KeySym key;
|
||||
|
||||
// keyboard input
|
||||
int num_events;
|
||||
for (num_events = XPending(GXdsp);num_events > 0;num_events--)
|
||||
{
|
||||
XNextEvent(GXdsp, &E);
|
||||
switch (E.type)
|
||||
{
|
||||
case KeyPress:
|
||||
//_KeyPress(pad, XLookupKeysym((XKeyEvent *)&E, 0));
|
||||
//break;
|
||||
key = XLookupKeysym((XKeyEvent*)&E, 0);
|
||||
|
||||
if((key >= XK_F1 && key <= XK_F9) ||
|
||||
key == XK_Shift_L || key == XK_Shift_R ||
|
||||
key == XK_Control_L || key == XK_Control_R)
|
||||
{
|
||||
XPutBackEvent(GXdsp, &E);
|
||||
break;
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < NUMCONTROLS; i++) {
|
||||
if (key == pad[_numPAD].keyForControl[i]) {
|
||||
KeyStatus[i] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KeyRelease:
|
||||
key = XLookupKeysym((XKeyEvent*)&E, 0);
|
||||
if((key >= XK_F1 && key <= XK_F9) ||
|
||||
key == XK_Shift_L || key == XK_Shift_R ||
|
||||
key == XK_Control_L || key == XK_Control_R)
|
||||
{
|
||||
XPutBackEvent(GXdsp, &E);
|
||||
break;
|
||||
}
|
||||
//_KeyRelease(pad, XLookupKeysym((XKeyEvent *)&E, 0));
|
||||
for (i = 0; i < NUMCONTROLS; i++)
|
||||
{
|
||||
if (key == pad[_numPAD].keyForControl[i])
|
||||
{
|
||||
KeyStatus[i] = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#elif defined(HAVE_COCOA) && HAVE_COCOA
|
||||
void cocoa_Read(int _numPAD, SPADStatus* _pPADStatus)
|
||||
{
|
||||
// Do all the stuff we need to do once per frame here
|
||||
if (_numPAD != 0)
|
||||
return;
|
||||
//get event from main thread
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSConnection *conn;
|
||||
NSDistantObject *proxy;
|
||||
|
||||
conn = [NSConnection connectionWithRegisteredName:@"DolphinCocoaEvent" host:nil];
|
||||
//if (!conn) {
|
||||
//printf("error creating cnx event client\n");
|
||||
//}
|
||||
proxy = [conn rootProxy];
|
||||
//if (!proxy) {
|
||||
// printf("error prox client\n");
|
||||
//}
|
||||
|
||||
long cocoaKey = (long)[proxy keyCode];
|
||||
|
||||
int i;
|
||||
if ((long)[proxy type] == 10)
|
||||
{
|
||||
for (i = 0; i < NUMCONTROLS; i++)
|
||||
{
|
||||
if (cocoaKey == pad[_numPAD].keyForControl[i])
|
||||
{
|
||||
KeyStatus[i] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < NUMCONTROLS; i++)
|
||||
{
|
||||
if (cocoaKey == pad[_numPAD].keyForControl[i])
|
||||
{
|
||||
KeyStatus[i] = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Analog stick values based on semi-press keys
|
||||
int mainstickvalue = (KeyStatus[CTL_MAIN_SEMI]) ? pad[_numPAD].Main_stick_semivalue : STICK_FULL;
|
||||
int substickvalue = (KeyStatus[CTL_SUB_SEMI]) ? pad[_numPAD].Sub_stick_semivalue : STICK_FULL;
|
||||
// Buttons (A/B/X/Y/Z/Start)
|
||||
if (KeyStatus[CTL_A])
|
||||
{
|
||||
_pPADStatus->button |= PAD_BUTTON_A;
|
||||
_pPADStatus->analogA = BUTTON_FULL;
|
||||
}
|
||||
if (KeyStatus[CTL_B])
|
||||
{
|
||||
_pPADStatus->button |= PAD_BUTTON_B;
|
||||
_pPADStatus->analogB = BUTTON_FULL;
|
||||
}
|
||||
if (KeyStatus[CTL_X]){_pPADStatus->button |= PAD_BUTTON_X;}
|
||||
if (KeyStatus[CTL_Y]){_pPADStatus->button |= PAD_BUTTON_Y;}
|
||||
if (KeyStatus[CTL_Z]){_pPADStatus->button |= PAD_TRIGGER_Z;}
|
||||
if (KeyStatus[CTL_START]){_pPADStatus->button |= PAD_BUTTON_START;}
|
||||
// Triggers (L/R)
|
||||
if (KeyStatus[CTL_L]){_pPADStatus->triggerLeft = TRIGGER_FULL;}
|
||||
if (KeyStatus[CTL_R]){_pPADStatus->triggerRight = TRIGGER_FULL;}
|
||||
if (KeyStatus[CTL_L_SEMI]){_pPADStatus->triggerLeft = pad[_numPAD].Trigger_semivalue;}
|
||||
if (KeyStatus[CTL_R_SEMI]){_pPADStatus->triggerRight = pad[_numPAD].Trigger_semivalue;}
|
||||
// Main stick
|
||||
EmulateAnalogStick(
|
||||
&_pPADStatus->stickX,
|
||||
&_pPADStatus->stickY,
|
||||
KeyStatus[CTL_MAINUP],
|
||||
KeyStatus[CTL_MAINDOWN],
|
||||
KeyStatus[CTL_MAINLEFT],
|
||||
KeyStatus[CTL_MAINRIGHT],
|
||||
mainstickvalue );
|
||||
EmulateAnalogStick(
|
||||
&_pPADStatus->substickX,
|
||||
&_pPADStatus->substickY,
|
||||
KeyStatus[CTL_SUBUP],
|
||||
KeyStatus[CTL_SUBDOWN],
|
||||
KeyStatus[CTL_SUBLEFT],
|
||||
KeyStatus[CTL_SUBRIGHT],
|
||||
substickvalue );
|
||||
// D-pad
|
||||
if (KeyStatus[CTL_DPADUP]) {_pPADStatus->button |= PAD_BUTTON_UP;}
|
||||
if (KeyStatus[CTL_DPADDOWN]) {_pPADStatus->button |= PAD_BUTTON_DOWN;}
|
||||
if (KeyStatus[CTL_DPADLEFT]) {_pPADStatus->button |= PAD_BUTTON_LEFT;}
|
||||
if (KeyStatus[CTL_DPADRIGHT]){_pPADStatus->button |= PAD_BUTTON_RIGHT;}
|
||||
// Mic key
|
||||
_pPADStatus->MicButton = KeyStatus[CTL_MIC];
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
}
|
||||
#elif defined(HAVE_COCOA) && HAVE_COCOA
|
||||
[pool release];
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//******************************************************************************
|
||||
// Plugin specification functions
|
||||
//******************************************************************************
|
||||
#if 0
|
||||
void GetDllInfo(PLUGIN_INFO* _PluginInfo)
|
||||
{
|
||||
_PluginInfo->Version = 0x0100;
|
||||
_PluginInfo->Type = PLUGIN_TYPE_PAD;
|
||||
|
||||
#ifdef DEBUGFAST
|
||||
sprintf(_PluginInfo->Name, "Dolphin KB/X360pad (DebugFast)");
|
||||
#else
|
||||
#ifndef _DEBUG
|
||||
sprintf(_PluginInfo->Name, "Dolphin KB/X360pad");
|
||||
#else
|
||||
sprintf(_PluginInfo->Name, "Dolphin KB/X360pad (Debug)");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals)
|
||||
{
|
||||
globals = _pPluginGlobals;
|
||||
LogManager::SetInstance((LogManager *)globals->logManager);
|
||||
}
|
||||
|
||||
void DllConfig(HWND _hParent)
|
||||
{
|
||||
// Load configuration
|
||||
LoadConfig();
|
||||
|
||||
// Show wxDialog
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
if (!m_ConfigFrame)
|
||||
m_ConfigFrame = new PADConfigDialogSimple(GetParentedWxWindow(_hParent));
|
||||
else if (!m_ConfigFrame->GetParent()->IsShown())
|
||||
m_ConfigFrame->Close(true);
|
||||
|
||||
// Only allow one open at a time
|
||||
if (!m_ConfigFrame->IsShown())
|
||||
m_ConfigFrame->ShowModal();
|
||||
else
|
||||
m_ConfigFrame->Hide();
|
||||
#endif
|
||||
|
||||
// Save configuration
|
||||
SaveConfig();
|
||||
}
|
||||
|
||||
void DllDebugger(HWND _hParent, bool Show) {}
|
||||
#endif
|
||||
void Initialize(void *init)
|
||||
{
|
||||
// We are now running a game
|
||||
// g_EmulatorRunning = true;
|
||||
|
||||
// Load configuration
|
||||
LoadConfig();
|
||||
|
||||
#ifdef RERECORDING
|
||||
/* Check if we are starting the pad to record the input, and an old file exists. In that case ask
|
||||
if we really want to start the recording and eventually overwrite the file */
|
||||
if (pad[0].bRecording && File::Exists("pad-record.bin"))
|
||||
{
|
||||
if (!AskYesNo("An old version of '%s' aleady exists in your Dolphin directory. You can"
|
||||
" now make a copy of it before you start a new recording and overwrite the file."
|
||||
" Select Yes to continue and overwrite the file. Select No to turn off the input"
|
||||
" recording and continue without recording anything.",
|
||||
"pad-record.bin"))
|
||||
{
|
||||
// Turn off recording and continue
|
||||
pad[0].bRecording = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Load recorded input if we are to play it back, otherwise begin with a blank recording
|
||||
if (pad[0].bPlayback) LoadRecord();
|
||||
#endif
|
||||
|
||||
g_PADInitialize = *(SPADInitialize*)init;
|
||||
|
||||
#ifdef _WIN32
|
||||
dinput.Init((HWND)g_PADInitialize.hWnd);
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
GXdsp = (Display*)g_PADInitialize.hWnd;
|
||||
#elif defined(HAVE_COCOA) && HAVE_COCOA
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void DoState(unsigned char **ptr, int mode)
|
||||
{
|
||||
#ifdef RERECORDING
|
||||
// Load or save the counter
|
||||
PointerWrap p(ptr, mode);
|
||||
p.Do(count);
|
||||
|
||||
//Console::Print("count: %i\n", count);
|
||||
|
||||
// Update the frame counter for the sake of the status bar
|
||||
if (mode == PointerWrap::MODE_READ)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// This only works when rendering to the main window, I think
|
||||
PostMessage(GetParent(g_PADInitialize.hWnd), WM_USER, INPUT_FRAME_COUNTER, count);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
// Save the recording and reset the counter
|
||||
#ifdef RERECORDING
|
||||
// Save recording
|
||||
if (pad[0].bRecording) SaveRecord();
|
||||
// Reset the counter
|
||||
count = 0;
|
||||
#endif
|
||||
|
||||
// We have stopped the game
|
||||
//g_EmulatorRunning = false;
|
||||
|
||||
#ifdef _WIN32
|
||||
dinput.Free();
|
||||
// Kill xpad rumble
|
||||
XINPUT_VIBRATION vib;
|
||||
vib.wLeftMotorSpeed = 0;
|
||||
vib.wRightMotorSpeed = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
if (pad[i].bRumble)
|
||||
XInputSetState(pad[i].XPadPlayer, &vib);
|
||||
#endif
|
||||
SaveConfig();
|
||||
}
|
||||
|
||||
|
||||
// Set buttons status from wxWidgets in the main application
|
||||
void PAD_Input(u16 _Key, u8 _UpDown) {}
|
||||
|
||||
|
||||
void PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
|
||||
{
|
||||
// Check if all is okay
|
||||
if (_pPADStatus == NULL) return;
|
||||
|
||||
// Play back input instead of accepting any user input
|
||||
#ifdef RERECORDING
|
||||
if (pad[0].bPlayback)
|
||||
{
|
||||
*_pPADStatus = PlayRecord();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
const int base = 0x80;
|
||||
// Clear pad
|
||||
memset(_pPADStatus, 0, sizeof(SPADStatus));
|
||||
|
||||
_pPADStatus->stickY = base;
|
||||
_pPADStatus->stickX = base;
|
||||
_pPADStatus->substickX = base;
|
||||
_pPADStatus->substickY = base;
|
||||
_pPADStatus->button |= PAD_USE_ORIGIN;
|
||||
#ifdef _WIN32
|
||||
// Only update pad on focus, don't do this when recording
|
||||
if (pad[_numPAD].bDisable && !pad[0].bRecording && !IsFocus()) return;
|
||||
|
||||
// Dolphin doesn't really care about the pad error codes anyways...
|
||||
_pPADStatus->err = PAD_ERR_NONE;
|
||||
|
||||
// Read XInput
|
||||
if (pad[_numPAD].bEnableXPad)
|
||||
XInput_Read(pad[_numPAD].XPadPlayer, _pPADStatus);
|
||||
|
||||
// Read Direct Input
|
||||
DInput_Read(_numPAD, _pPADStatus);
|
||||
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
_pPADStatus->err = PAD_ERR_NONE;
|
||||
X11_Read(_numPAD, _pPADStatus);
|
||||
#elif defined(HAVE_COCOA) && HAVE_COCOA
|
||||
_pPADStatus->err = PAD_ERR_NONE;
|
||||
cocoa_Read(_numPAD, _pPADStatus);
|
||||
#endif
|
||||
|
||||
#ifdef RERECORDING
|
||||
// Record input
|
||||
if (pad[0].bRecording) RecordInput(*_pPADStatus);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Rough approximation of GC behaviour - needs improvement.
|
||||
void PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (pad[_numPAD].bEnableXPad)
|
||||
{
|
||||
static int a = 0;
|
||||
|
||||
if ((_uType == 0) || (_uType == 2))
|
||||
{
|
||||
a = 0;
|
||||
}
|
||||
else if (_uType == 1)
|
||||
{
|
||||
a = _uStrength > 2 ? pad[_numPAD].RumbleStrength : 0;
|
||||
}
|
||||
|
||||
a = int ((float)a * 0.96f);
|
||||
|
||||
if (!pad[_numPAD].bRumble)
|
||||
{
|
||||
a = 0;
|
||||
}
|
||||
|
||||
XINPUT_VIBRATION vib;
|
||||
vib.wLeftMotorSpeed = a; //_uStrength*100;
|
||||
vib.wRightMotorSpeed = a; //_uStrength*100;
|
||||
XInputSetState(pad[_numPAD].XPadPlayer, &vib);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// Load and save the configuration
|
||||
//******************************************************************************
|
||||
|
||||
void LoadConfig()
|
||||
{
|
||||
// Initialize first pad to standard controls
|
||||
#ifdef _WIN32
|
||||
const int defaultKeyForControl[NUMCONTROLS] =
|
||||
{
|
||||
DIK_X, // A
|
||||
DIK_Z, // B
|
||||
DIK_C, // X
|
||||
DIK_S, // Y
|
||||
DIK_D, // Z
|
||||
DIK_RETURN, // Start
|
||||
DIK_Q, // L
|
||||
DIK_W, // R
|
||||
0x00, // L semi-press
|
||||
0x00, // R semi-press
|
||||
DIK_UP, // Main stick up
|
||||
DIK_DOWN, // Main stick down
|
||||
DIK_LEFT, // Main stick left
|
||||
DIK_RIGHT, // Main stick right
|
||||
DIK_LSHIFT, // Main stick semi-press
|
||||
DIK_I, // C-stick up
|
||||
DIK_K, // C-stick down
|
||||
DIK_J, // C-stick left
|
||||
DIK_L, // C-stick right
|
||||
DIK_LCONTROL, // C-stick semi-press
|
||||
DIK_T, // D-pad up
|
||||
DIK_G, // D-pad down
|
||||
DIK_F, // D-pad left
|
||||
DIK_H, // D-pad right
|
||||
DIK_M, // Mic
|
||||
};
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
const int defaultKeyForControl[NUMCONTROLS] =
|
||||
{
|
||||
XK_x, // A
|
||||
XK_z, // B
|
||||
XK_c, // X
|
||||
XK_s, // Y
|
||||
XK_d, // Z
|
||||
XK_Return, // Start
|
||||
XK_q, // L
|
||||
XK_w, // R
|
||||
0x00, // L semi-press
|
||||
0x00, // R semi-press
|
||||
XK_Up, // Main stick up
|
||||
XK_Down, // Main stick down
|
||||
XK_Left, // Main stick left
|
||||
XK_Right, // Main stick right
|
||||
XK_Shift_L, // Main stick semi-press
|
||||
XK_i, // C-stick up
|
||||
XK_k, // C-stick down
|
||||
XK_j, // C-stick left
|
||||
XK_l, // C-stick right
|
||||
XK_Control_L, // C-stick semi-press
|
||||
XK_t, // D-pad up
|
||||
XK_g, // D-pad down
|
||||
XK_f, // D-pad left
|
||||
XK_h, // D-pad right
|
||||
XK_m, // Mic
|
||||
};
|
||||
#elif defined(HAVE_COCOA) && HAVE_COCOA
|
||||
// Reference for Cocoa key codes:
|
||||
// http://boredzo.org/blog/archives/2007-05-22/virtual-key-codes
|
||||
const int defaultKeyForControl[NUMCONTROLS] =
|
||||
{
|
||||
7, // A (x)
|
||||
6, // B (z)
|
||||
8, // X (c)
|
||||
1, // Y (s)
|
||||
2, // Z (d)
|
||||
36, // Start (return)
|
||||
12, // L (q)
|
||||
13, // R (w)
|
||||
-1, // L semi-press (none)
|
||||
-1, // R semi-press (none)
|
||||
126, // Main stick up (up)
|
||||
125, // Main stick down (down)
|
||||
123, // Main stick left (left)
|
||||
124, // Main stick right (right)
|
||||
56, // Main stick semi-press (left shift)
|
||||
34, // C-stick up (i)
|
||||
40, // C-stick down (k)
|
||||
38, // C-stick left (j)
|
||||
37, // C-stick right (l)
|
||||
59, // C-stick semi-press (left control)
|
||||
17, // D-pad up (t)
|
||||
5, // D-pad down (g)
|
||||
3, // D-pad left (f)
|
||||
4, // D-pad right (h)
|
||||
46, // Mic (m)
|
||||
};
|
||||
#endif
|
||||
//TODO
|
||||
#if 0
|
||||
IniFile file;
|
||||
file.Load(FULL_CONFIG_DIR "pad.ini");
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
char SectionName[32];
|
||||
sprintf(SectionName, "PAD%i", i+1);
|
||||
|
||||
file.Get(SectionName, "UseXPad", &pad[i].bEnableXPad, i==0);
|
||||
file.Get(SectionName, "DisableOnBackground", &pad[i].bDisable, false);
|
||||
file.Get(SectionName, "Rumble", &pad[i].bRumble, true);
|
||||
file.Get(SectionName, "RumbleStrength", &pad[i].RumbleStrength, 8000);
|
||||
file.Get(SectionName, "XPad#", &pad[i].XPadPlayer);
|
||||
|
||||
file.Get(SectionName, "Trigger_semivalue", &pad[i].Trigger_semivalue, TRIGGER_HALF_DEFAULT);
|
||||
file.Get(SectionName, "Main_stick_semivalue", &pad[i].Main_stick_semivalue, STICK_HALF_DEFAULT);
|
||||
file.Get(SectionName, "Sub_stick_semivalue", &pad[i].Sub_stick_semivalue, STICK_HALF_DEFAULT);
|
||||
|
||||
#ifdef RERECORDING
|
||||
file.Get(SectionName, "Recording", &pad[0].bRecording, false);
|
||||
file.Get(SectionName, "Playback", &pad[0].bPlayback, false);
|
||||
#endif
|
||||
|
||||
for (int x = 0; x < NUMCONTROLS; x++)
|
||||
{
|
||||
file.Get(SectionName, controlNames[x],
|
||||
&pad[i].keyForControl[x],
|
||||
(i==0) ? defaultKeyForControl[x] : 0);
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
// In linux we have a problem assigning the upper case of the
|
||||
// keys because they're not being recognized
|
||||
pad[i].keyForControl[x] = tolower(pad[i].keyForControl[x]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void SaveConfig()
|
||||
{
|
||||
//TODO
|
||||
#if 0
|
||||
IniFile file;
|
||||
file.Load(FULL_CONFIG_DIR "pad.ini");
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
char SectionName[32];
|
||||
sprintf(SectionName, "PAD%i", i+1);
|
||||
|
||||
file.Set(SectionName, "UseXPad", pad[i].bEnableXPad);
|
||||
file.Set(SectionName, "DisableOnBackground", pad[i].bDisable);
|
||||
file.Set(SectionName, "Rumble", pad[i].bRumble);
|
||||
file.Set(SectionName, "RumbleStrength", pad[i].RumbleStrength);
|
||||
file.Set(SectionName, "XPad#", pad[i].XPadPlayer);
|
||||
|
||||
file.Set(SectionName, "Trigger_semivalue", pad[i].Trigger_semivalue);
|
||||
file.Set(SectionName, "Main_stick_semivalue", pad[i].Main_stick_semivalue);
|
||||
file.Set(SectionName, "Sub_stick_semivalue", pad[i].Sub_stick_semivalue);
|
||||
|
||||
#ifdef RERECORDING
|
||||
file.Set(SectionName, "Recording", pad[0].bRecording);
|
||||
file.Set(SectionName, "Playback", pad[0].bPlayback);
|
||||
#endif
|
||||
|
||||
for (int x = 0; x < NUMCONTROLS; x++)
|
||||
{
|
||||
file.Set(SectionName, controlNames[x], pad[i].keyForControl[x]);
|
||||
}
|
||||
}
|
||||
file.Save(FULL_CONFIG_DIR "pad.ini");
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef __PADSIMPLE_H__
|
||||
#define __PADSIMPLE_H__
|
||||
|
||||
//#include "Setup.h" // Common
|
||||
|
||||
// Constants for full-press sticks and triggers
|
||||
const int BUTTON_FULL = 255;
|
||||
const int STICK_FULL = 100;
|
||||
const int STICK_HALF_DEFAULT = 50;
|
||||
const int TRIGGER_FULL = 255;
|
||||
const int TRIGGER_HALF_DEFAULT = 128;
|
||||
const int TRIGGER_THRESHOLD = 230;
|
||||
|
||||
// Controls
|
||||
enum
|
||||
{
|
||||
CTL_A = 0,
|
||||
CTL_B,
|
||||
CTL_X,
|
||||
CTL_Y,
|
||||
CTL_Z,
|
||||
CTL_START,
|
||||
CTL_L,
|
||||
CTL_R,
|
||||
CTL_L_SEMI,
|
||||
CTL_R_SEMI,
|
||||
CTL_MAINUP,
|
||||
CTL_MAINDOWN,
|
||||
CTL_MAINLEFT,
|
||||
CTL_MAINRIGHT,
|
||||
CTL_MAIN_SEMI,
|
||||
CTL_SUBUP,
|
||||
CTL_SUBDOWN,
|
||||
CTL_SUBLEFT,
|
||||
CTL_SUBRIGHT,
|
||||
CTL_SUB_SEMI,
|
||||
CTL_DPADUP,
|
||||
CTL_DPADDOWN,
|
||||
CTL_DPADLEFT,
|
||||
CTL_DPADRIGHT,
|
||||
CTL_MIC,
|
||||
NUMCONTROLS,
|
||||
};
|
||||
|
||||
// Control names
|
||||
static const char* controlNames[] =
|
||||
{
|
||||
"A_button",
|
||||
"B_button",
|
||||
"X_button",
|
||||
"Y_button",
|
||||
"Z_trigger",
|
||||
"Start",
|
||||
"L_button",
|
||||
"R_button",
|
||||
"L_button_semi",
|
||||
"R_button_semi",
|
||||
"Main_stick_up",
|
||||
"Main_stick_down",
|
||||
"Main_stick_left",
|
||||
"Main_stick_right",
|
||||
"Main_stick_semi",
|
||||
"Sub_stick_up",
|
||||
"Sub_stick_down",
|
||||
"Sub_stick_left",
|
||||
"Sub_stick_right",
|
||||
"Sub_stick_semi",
|
||||
"D-Pad_up",
|
||||
"D-Pad_down",
|
||||
"D-Pad_left",
|
||||
"D-Pad_right",
|
||||
"Mic-button",
|
||||
};
|
||||
|
||||
struct SPads
|
||||
{
|
||||
bool bEnableXPad; // Use an XPad in addition to the keyboard?
|
||||
bool bDisable; // Disabled when dolphin isn't in focus
|
||||
bool bRumble; // Rumble for xpad
|
||||
u32 RumbleStrength; // Rumble strength
|
||||
bool bRecording; // Record input?
|
||||
bool bPlayback; // Playback input?
|
||||
s32 XPadPlayer; // Player# of the xpad
|
||||
u32 keyForControl[NUMCONTROLS]; // Keyboard mapping
|
||||
u32 Trigger_semivalue; // Semi-press value for triggers
|
||||
u32 Main_stick_semivalue; // Semi-press value for main stick
|
||||
u32 Sub_stick_semivalue; // Semi-press value for sub-stick
|
||||
};
|
||||
|
||||
extern SPads pad[];
|
||||
//extern bool g_EmulatorRunning;
|
||||
|
||||
void LoadConfig();
|
||||
void SaveConfig();
|
||||
bool IsFocus();
|
||||
|
||||
// Input Recording
|
||||
void SaveRecord();
|
||||
|
||||
#endif
|
|
@ -0,0 +1,86 @@
|
|||
//__________________________________________________________________________________________________
|
||||
// Common pad plugin spec, version #1.0 maintained by F|RES
|
||||
//
|
||||
|
||||
#ifndef _PAD_H_INCLUDED__
|
||||
#define _PAD_H_INCLUDED__
|
||||
|
||||
//#include "PluginSpecs.h"
|
||||
|
||||
//#include "ExportProlog.h"
|
||||
|
||||
#define PAD_ERR_NONE 0
|
||||
#define PAD_ERR_NO_CONTROLLER -1
|
||||
#define PAD_ERR_NOT_READY -2
|
||||
#define PAD_ERR_TRANSFER -3
|
||||
|
||||
#define PAD_USE_ORIGIN 0x0080
|
||||
|
||||
#define PAD_BUTTON_LEFT 0x0001
|
||||
#define PAD_BUTTON_RIGHT 0x0002
|
||||
#define PAD_BUTTON_DOWN 0x0004
|
||||
#define PAD_BUTTON_UP 0x0008
|
||||
#define PAD_TRIGGER_Z 0x0010
|
||||
#define PAD_TRIGGER_R 0x0020
|
||||
#define PAD_TRIGGER_L 0x0040
|
||||
#define PAD_BUTTON_A 0x0100
|
||||
#define PAD_BUTTON_B 0x0200
|
||||
#define PAD_BUTTON_X 0x0400
|
||||
#define PAD_BUTTON_Y 0x0800
|
||||
#define PAD_BUTTON_START 0x1000
|
||||
|
||||
typedef void (*TLog)(const char* _pMessage);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HWND hWnd;
|
||||
TLog pLog;
|
||||
int padNumber;
|
||||
} SPADInitialize;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short button; // Or-ed PAD_BUTTON_* and PAD_TRIGGER_* bits
|
||||
unsigned char stickX; // 0 <= stickX <= 255
|
||||
unsigned char stickY; // 0 <= stickY <= 255
|
||||
unsigned char substickX; // 0 <= substickX <= 255
|
||||
unsigned char substickY; // 0 <= substickY <= 255
|
||||
unsigned char triggerLeft; // 0 <= triggerLeft <= 255
|
||||
unsigned char triggerRight; // 0 <= triggerRight <= 255
|
||||
unsigned char analogA; // 0 <= analogA <= 255
|
||||
unsigned char analogB; // 0 <= analogB <= 255
|
||||
bool MicButton; // HAX
|
||||
signed char err; // one of PAD_ERR_* number
|
||||
} SPADStatus;
|
||||
|
||||
#define EXPORT
|
||||
#define CALL
|
||||
|
||||
// I N T E R F A C E
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Function:
|
||||
// Purpose:
|
||||
// input:
|
||||
// output:
|
||||
//
|
||||
EXPORT void CALL PAD_GetStatus(u8 _numPAD, SPADStatus* _pPADStatus);
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Function: Send keyboard input to the plugin
|
||||
// Purpose:
|
||||
// input: The key and if it's pressed or released
|
||||
// output: None
|
||||
//
|
||||
EXPORT void CALL PAD_Input(u16 _Key, u8 _UpDown);
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Function: PAD_Rumble
|
||||
// Purpose: Pad rumble!
|
||||
// input: PAD number, Command type (Stop=0, Rumble=1, Stop Hard=2) and strength of Rumble
|
||||
// output: none
|
||||
//
|
||||
EXPORT void CALL PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength);
|
||||
|
||||
//#include "ExportEpilog.h"
|
||||
#endif
|
|
@ -16,6 +16,8 @@
|
|||
#include "wx/stdpaths.h"
|
||||
|
||||
#include "LuaWindow.h"
|
||||
#include "PadSimple/GUI/ConfigDlg.h"
|
||||
#include "PadSimple/pluginspecs_pad.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
|
@ -45,13 +47,40 @@ public:
|
|||
this);
|
||||
}
|
||||
|
||||
bool up,down,left,right,x,y,a,b,l,r,start,select;
|
||||
|
||||
void applyInput(){
|
||||
//TODO
|
||||
return;
|
||||
|
||||
u16 pad = (0 |
|
||||
bool up,down,left,right,x,y,a,b,l,r,start,select;
|
||||
|
||||
up = down = left = right = x = y = a = b = l = r = start = select = false;
|
||||
|
||||
SPADStatus s;
|
||||
memset(&s,0,sizeof(s));
|
||||
PAD_GetStatus(0, &s);
|
||||
|
||||
if(s.button & PAD_BUTTON_LEFT)
|
||||
left = true;
|
||||
if(s.button & PAD_BUTTON_RIGHT)
|
||||
right = true;
|
||||
if(s.button & PAD_BUTTON_UP)
|
||||
up = true;
|
||||
if(s.button & PAD_BUTTON_DOWN)
|
||||
down = true;
|
||||
if(s.button & PAD_BUTTON_A)
|
||||
a = true;
|
||||
if(s.button & PAD_BUTTON_B)
|
||||
b = true;
|
||||
if(s.button & PAD_BUTTON_X)
|
||||
x = true;
|
||||
if(s.button & PAD_BUTTON_Y)
|
||||
y = true;
|
||||
if(s.button & PAD_TRIGGER_L)
|
||||
l = true;
|
||||
if(s.button & PAD_TRIGGER_R)
|
||||
r = true;
|
||||
if(s.button & PAD_BUTTON_START)
|
||||
start = true;
|
||||
|
||||
u16 pad1 = (0 |
|
||||
((a ? 0 : 0x80) >> 7) |
|
||||
((b ? 0 : 0x80) >> 6) |
|
||||
((select? 0 : 0x80) >> 5) |
|
||||
|
@ -63,8 +92,8 @@ public:
|
|||
((r ? 0 : 0x80) << 1) |
|
||||
((l ? 0 : 0x80) << 2)) ;
|
||||
|
||||
((u16 *)MMU.ARM9_REG)[0x130>>1] = (u16)pad;
|
||||
((u16 *)MMU.ARM7_REG)[0x130>>1] = (u16)pad;
|
||||
((u16 *)MMU.ARM9_REG)[0x130>>1] = (u16)pad1;
|
||||
((u16 *)MMU.ARM7_REG)[0x130>>1] = (u16)pad1;
|
||||
|
||||
bool debug = false;
|
||||
bool lidClosed = false;
|
||||
|
@ -79,79 +108,6 @@ public:
|
|||
((u16 *)MMU.ARM7_REG)[0x136>>1] = (u16)padExt;
|
||||
}
|
||||
|
||||
void OnKeyDown(wxKeyEvent &event){
|
||||
|
||||
switch(event.m_keyCode) {
|
||||
case WXK_UP:
|
||||
up = true;
|
||||
break;
|
||||
case WXK_DOWN:
|
||||
down = true;
|
||||
break;
|
||||
case WXK_LEFT:
|
||||
left = true;
|
||||
break;
|
||||
case WXK_RIGHT:
|
||||
right = true;
|
||||
break;
|
||||
case WXK_RETURN:
|
||||
start = true;
|
||||
break;
|
||||
case WXK_SHIFT:
|
||||
select = true;
|
||||
break;
|
||||
case 65://a
|
||||
y = true;
|
||||
break;
|
||||
case 83://s
|
||||
x = true;
|
||||
break;
|
||||
case 90://z
|
||||
b = true;
|
||||
break;
|
||||
case 88://x
|
||||
a = true;
|
||||
break;
|
||||
}
|
||||
// printf("%d",event.m_keyCode);
|
||||
}
|
||||
|
||||
void OnKeyUp(wxKeyEvent &event){
|
||||
|
||||
switch(event.m_keyCode) {
|
||||
case WXK_UP:
|
||||
up = false;
|
||||
break;
|
||||
case WXK_DOWN:
|
||||
down = false;
|
||||
break;
|
||||
case WXK_LEFT:
|
||||
left = false;
|
||||
break;
|
||||
case WXK_RIGHT:
|
||||
right = false;
|
||||
break;
|
||||
case WXK_RETURN:
|
||||
start = false;
|
||||
break;
|
||||
case WXK_SHIFT:
|
||||
select = false;
|
||||
break;
|
||||
case 65://a
|
||||
y = false;
|
||||
break;
|
||||
case 83://s
|
||||
x = false;
|
||||
break;
|
||||
case 90://z
|
||||
b = false;
|
||||
break;
|
||||
case 88://x
|
||||
a = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO integrate paths system?
|
||||
void LoadRom(wxCommandEvent& event){
|
||||
wxFileDialog dialog(this,"Load Rom",wxGetHomeDir(),"","*.nds",wxFD_OPEN, wxDefaultPosition, wxDefaultSize);
|
||||
|
@ -313,6 +269,11 @@ case 88://x
|
|||
new wxLuaWindow(this, wxDefaultPosition, wxSize(600, 390));
|
||||
}
|
||||
|
||||
void OnOpenControllerConfiguration(wxCommandEvent& WXUNUSED (event))
|
||||
{
|
||||
new PADConfigDialogSimple(this);
|
||||
}
|
||||
|
||||
wxMenu* MakeStatesSubMenu( int baseid ) const
|
||||
{
|
||||
wxMenu* mnuSubstates = new wxMenu();
|
||||
|
@ -369,7 +330,8 @@ enum
|
|||
wQuickScreenshot,
|
||||
wLuaWindow,
|
||||
wLoadState01,
|
||||
wSaveState01 = wLoadState01+20
|
||||
wSaveState01 = wLoadState01+20,
|
||||
wConfigureControls
|
||||
};
|
||||
|
||||
void DesmumeFrame::Menu_SaveStates(wxCommandEvent &event){savestate_slot(event.GetId() - wSaveState01 - 1);}
|
||||
|
@ -389,8 +351,6 @@ EVT_MENU(wDisplayInput,DesmumeFrame::displayInput)
|
|||
EVT_MENU(wDisplayGraphicalInput,DesmumeFrame::displayGraphicalInput)
|
||||
EVT_MENU(wDisplayLagCounter,DesmumeFrame::displayLagCounter)
|
||||
EVT_MENU(wDisplayMicrophone,DesmumeFrame::displayMicrophone)
|
||||
EVT_KEY_DOWN(DesmumeFrame::OnKeyDown)
|
||||
EVT_KEY_UP(DesmumeFrame::OnKeyUp)
|
||||
|
||||
EVT_MENU(wMainGPU,DesmumeFrame::mainGPU)
|
||||
EVT_MENU(wMainBG0,DesmumeFrame::mainBG0)
|
||||
|
@ -425,6 +385,8 @@ EVT_MENU(w3dView,DesmumeFrame::_3dView)
|
|||
|
||||
EVT_MENU(wLuaWindow,DesmumeFrame::OnOpenLuaWindow)
|
||||
|
||||
EVT_MENU(wConfigureControls,DesmumeFrame::OnOpenControllerConfiguration)
|
||||
|
||||
END_EVENT_TABLE()
|
||||
|
||||
IMPLEMENT_APP(Desmume)
|
||||
|
@ -447,9 +409,15 @@ bool Desmume::OnInit()
|
|||
DesmumeFrame *frame = new DesmumeFrame((char*)EMU_DESMUME_NAME_AND_VERSION());
|
||||
frame->Show(true);
|
||||
|
||||
SPADInitialize PADInitialize;
|
||||
PADInitialize.padNumber = 1;
|
||||
extern void Initialize(void *init);
|
||||
Initialize(&PADInitialize);
|
||||
|
||||
//TODO
|
||||
addon_type = NDS_ADDON_NONE;
|
||||
addonsChangePak(addon_type);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -478,8 +446,9 @@ DesmumeFrame::DesmumeFrame(const wxString& title)
|
|||
fileMenu->AppendSubMenu(loads,"Load State");
|
||||
#define ConnectMenuRange( id_start, inc, handler ) \
|
||||
Connect( id_start, id_start + inc, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DesmumeFrame::handler) )
|
||||
ConnectMenuRange(wLoadState01+1, 10, Menu_LoadStates);
|
||||
ConnectMenuRange(wSaveState01+1, 10, Menu_SaveStates);
|
||||
//TODO something is wrong here
|
||||
// ConnectMenuRange(wLoadState01+1, 10, Menu_LoadStates);
|
||||
// ConnectMenuRange(wSaveState01+1, 10, Menu_SaveStates);
|
||||
}
|
||||
fileMenu->AppendSeparator();
|
||||
fileMenu->Append(wImportBackupMemory, "Import Backup Memory...");
|
||||
|
@ -522,6 +491,9 @@ DesmumeFrame::DesmumeFrame(const wxString& title)
|
|||
layersMenu->Append(wSubBG2,"Sub BG 2");
|
||||
layersMenu->Append(wSubBG3,"Sub BG 3");
|
||||
}
|
||||
|
||||
configMenu->Append(wConfigureControls,"Controls");
|
||||
|
||||
toolsMenu->AppendSeparator();
|
||||
toolsMenu->AppendSubMenu(layersMenu,"View Layers");
|
||||
|
||||
|
|
Loading…
Reference in New Issue