From 0bf3dfda036f1da0cb26e1f266ea500fbe74f872 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sat, 3 Jul 2010 08:04:10 +0000 Subject: [PATCH] New Wiimote Plugin: Added real wiimote support.(only tested on Windows, still a few probs: after refresh alt+F{5..8} x2 is needed) New Wiimote/GCPad: Re-merged Keyboard+Mouse for easier kb+mouse configuration, like before.(DirectInput doesn't support individual kb/mice anymore like I thought it did) Fixed some bugs and maybe leaks in GUI.(got rid of evil dynamic_cast) Renamed stuff from DirectInput to DInput, cause it's shorter and rhymes with XInput, I guess. (I remembered eol-style native, shuffle lost his job :P) git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5822 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/InputCommon/InputCommon.vcproj | 22 +- .../ControllerInterface.cpp | 13 +- .../ControllerInterface/ControllerInterface.h | 8 +- .../DirectInput.cpp => DInput/DInput.cpp} | 26 +- .../DirectInput.h => DInput/DInput.h} | 8 +- .../DInputJoystick.cpp} | 8 +- .../DInputJoystick.h} | 6 +- .../DInput/DInputKeyboardMouse.cpp | 272 ++++++++++++ .../DInput/DInputKeyboardMouse.h | 122 ++++++ .../{DirectInput => DInput}/NamedKeys.h | 0 .../DirectInput/DirectInputKeyboard.cpp | 187 --------- .../DirectInput/DirectInputKeyboard.h | 99 ----- .../DirectInput/DirectInputMouse.cpp | 175 -------- .../DirectInput/DirectInputMouse.h | 83 ---- Source/Core/InputCommon/Src/InputConfig.cpp | 1 + Source/Core/InputUICommon/Src/ConfigDiag.cpp | 203 +++++---- Source/Core/InputUICommon/Src/ConfigDiag.h | 25 +- .../Plugin_Wiimote/Plugin_Wiimote.vcproj | 8 +- .../Plugin_WiimoteNew.vcproj | 58 ++- .../Plugins/Plugin_WiimoteNew/Src/SConscript | 2 + .../Src/WiimoteConfigDiag.cpp | 114 +++++ .../Plugin_WiimoteNew/Src/WiimoteConfigDiag.h | 49 +++ .../Plugin_WiimoteNew/Src/WiimoteNew.cpp | 75 +++- .../Src/WiimoteReal/WiimoteReal.cpp | 392 ++++++++++++++++++ .../Src/WiimoteReal/WiimoteReal.h | 56 +++ 25 files changed, 1276 insertions(+), 736 deletions(-) rename Source/Core/InputCommon/Src/ControllerInterface/{DirectInput/DirectInput.cpp => DInput/DInput.cpp} (77%) rename Source/Core/InputCommon/Src/ControllerInterface/{DirectInput/DirectInput.h => DInput/DInput.h} (84%) rename Source/Core/InputCommon/Src/ControllerInterface/{DirectInput/DirectInputJoystick.cpp => DInput/DInputJoystick.cpp} (99%) rename Source/Core/InputCommon/Src/ControllerInterface/{DirectInput/DirectInputJoystick.h => DInput/DInputJoystick.h} (96%) create mode 100644 Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputKeyboardMouse.cpp create mode 100644 Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputKeyboardMouse.h rename Source/Core/InputCommon/Src/ControllerInterface/{DirectInput => DInput}/NamedKeys.h (100%) delete mode 100644 Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputKeyboard.cpp delete mode 100644 Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputKeyboard.h delete mode 100644 Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputMouse.cpp delete mode 100644 Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputMouse.h create mode 100644 Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.cpp create mode 100644 Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.h create mode 100644 Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp create mode 100644 Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.h diff --git a/Source/Core/InputCommon/InputCommon.vcproj b/Source/Core/InputCommon/InputCommon.vcproj index 1ed94a6700..5150ecb61f 100644 --- a/Source/Core/InputCommon/InputCommon.vcproj +++ b/Source/Core/InputCommon/InputCommon.vcproj @@ -420,38 +420,30 @@ > - - - - expression + '|'); - const std::string mode_chars("|&!#"); + const std::string mode_chars("|&!^"); ControlReference::DeviceControl devc; @@ -530,6 +530,7 @@ ControllerInterface::Device::Control* ControllerInterface::OutputReference::Dete // this loop is to make stuff like flashing keyboard LEDs work while (ms > (slept += 10)) { + // TODO: improve this to update more than just the default device's output device->UpdateOutput(); Common::SleepCurrentThread(10); } diff --git a/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.h b/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.h index 15e7ab6180..838fe9d03d 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.h +++ b/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.h @@ -11,11 +11,9 @@ // enable disable sources #ifdef _WIN32 #define CIFACE_USE_XINPUT - #define CIFACE_USE_DIRECTINPUT_JOYSTICK - #define CIFACE_USE_DIRECTINPUT_KEYBOARD - #define CIFACE_USE_DIRECTINPUT_MOUSE - #define CIFACE_USE_DIRECTINPUT - #define DINPUT_SOURCE_NAME "DInput" + #define CIFACE_USE_DINPUT_JOYSTICK + #define CIFACE_USE_DINPUT_KBM + #define CIFACE_USE_DINPUT #endif #if defined(HAVE_X11) && HAVE_X11 #define CIFACE_USE_XLIB diff --git a/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInput.cpp b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.cpp similarity index 77% rename from Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInput.cpp rename to Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.cpp index d36e76b3c1..a9098d6288 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInput.cpp +++ b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.cpp @@ -1,19 +1,16 @@ #include "../ControllerInterface.h" -#ifdef CIFACE_USE_DIRECTINPUT +#ifdef CIFACE_USE_DINPUT -#include "DirectInput.h" +#include "DInput.h" #include -#ifdef CIFACE_USE_DIRECTINPUT_JOYSTICK - #include "DirectInputJoystick.h" +#ifdef CIFACE_USE_DINPUT_JOYSTICK + #include "DInputJoystick.h" #endif -#ifdef CIFACE_USE_DIRECTINPUT_KEYBOARD - #include "DirectInputKeyboard.h" -#endif -#ifdef CIFACE_USE_DIRECTINPUT_MOUSE - #include "DirectInputMouse.h" +#ifdef CIFACE_USE_DINPUT_KBM + #include "DInputKeyboardMouse.h" #endif #pragma comment(lib, "Dinput8.lib") @@ -21,7 +18,7 @@ namespace ciface { -namespace DirectInput +namespace DInput { //BOOL CALLBACK DIEnumEffectsCallback(LPCDIEFFECTINFO pdei, LPVOID pvRef) @@ -70,13 +67,10 @@ void Init( std::vector& devices/*, HWND hwnd*/ ) if (FAILED(DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&idi8, NULL))) return; -#ifdef CIFACE_USE_DIRECTINPUT_KEYBOARD - InitKeyboard(idi8, devices); +#ifdef CIFACE_USE_DINPUT_KBM + InitKeyboardMouse(idi8, devices); #endif -#ifdef CIFACE_USE_DIRECTINPUT_MOUSE - InitMouse(idi8, devices); -#endif -#ifdef CIFACE_USE_DIRECTINPUT_JOYSTICK +#ifdef CIFACE_USE_DINPUT_JOYSTICK InitJoystick(idi8, devices/*, hwnd*/); #endif diff --git a/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInput.h b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.h similarity index 84% rename from Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInput.h rename to Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.h index 9f4a045a55..5f2cb6da47 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInput.h +++ b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInput.h @@ -1,8 +1,10 @@ -#ifndef _CIFACE_DIRECTINPUT_H_ -#define _CIFACE_DIRECTINPUT_H_ +#ifndef _CIFACE_DINPUT_H_ +#define _CIFACE_DINPUT_H_ #include "../ControllerInterface.h" +#define DINPUT_SOURCE_NAME "DInput" + #define DIRECTINPUT_VERSION 0x0800 #define WIN32_LEAN_AND_MEAN #define NOMINMAX @@ -13,7 +15,7 @@ namespace ciface { -namespace DirectInput +namespace DInput { //BOOL CALLBACK DIEnumEffectsCallback(LPCDIEFFECTINFO pdei, LPVOID pvRef); diff --git a/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputJoystick.cpp b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputJoystick.cpp similarity index 99% rename from Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputJoystick.cpp rename to Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputJoystick.cpp index 0cd7459187..2eac4be616 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputJoystick.cpp +++ b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputJoystick.cpp @@ -1,9 +1,9 @@ #include "../ControllerInterface.h" -#ifdef CIFACE_USE_DIRECTINPUT_JOYSTICK +#ifdef CIFACE_USE_DINPUT_JOYSTICK -#include "DirectInputJoystick.h" -#include "DirectInput.h" +#include "DInputJoystick.h" +#include "DInput.h" inline bool operator<(const GUID & lhs, const GUID & rhs) { @@ -12,7 +12,7 @@ inline bool operator<(const GUID & lhs, const GUID & rhs) namespace ciface { -namespace DirectInput +namespace DInput { #define DATA_BUFFER_SIZE 32 diff --git a/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputJoystick.h b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputJoystick.h similarity index 96% rename from Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputJoystick.h rename to Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputJoystick.h index bdee377f72..1572de20f6 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputJoystick.h +++ b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputJoystick.h @@ -1,5 +1,5 @@ -#ifndef _CIFACE_DIRECTINPUT_JOYSTICK_H_ -#define _CIFACE_DIRECTINPUT_JOYSTICK_H_ +#ifndef _CIFACE_DINPUT_JOYSTICK_H_ +#define _CIFACE_DINPUT_JOYSTICK_H_ #include "../ControllerInterface.h" @@ -18,7 +18,7 @@ namespace ciface { -namespace DirectInput +namespace DInput { void InitJoystick( IDirectInput8* const idi8, std::vector& devices/*, HWND hwnd*/ ); diff --git a/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputKeyboardMouse.cpp b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputKeyboardMouse.cpp new file mode 100644 index 0000000000..c3b7cd807d --- /dev/null +++ b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputKeyboardMouse.cpp @@ -0,0 +1,272 @@ +#include "../ControllerInterface.h" + +#ifdef CIFACE_USE_DINPUT_KBM + +#include "DInputKeyboardMouse.h" +#include "DInput.h" + + // (lower would be more sensitive) user can lower sensitivity by setting range + // seems decent here ( at 8 ), I dont think anyone would need more sensitive than this + // and user can lower it much farther than they would want to with the range +#define MOUSE_AXIS_SENSITIVITY 8 + + // if input hasn't been received for this many ms, mouse input will be skipped + // otherwise it is just some crazy value +#define DROP_INPUT_TIME 250 + +namespace ciface +{ +namespace DInput +{ + +struct +{ + const BYTE code; + const char* const name; +} named_keys[] = +{ +#include "NamedKeys.h" +}; + +struct +{ + const BYTE code; + const char* const name; +} named_lights[] = +{ + { VK_NUMLOCK, "NUM LOCK" }, + { VK_CAPITAL, "CAPS LOCK" }, + { VK_SCROLL, "SCROLL LOCK" } +}; + +void InitKeyboardMouse( IDirectInput8* const idi8, std::vector& devices ) +{ + // mouse and keyboard are a combined device, to allow shift+click and stuff + // if thats dumb, i will make a VirtualDevice class that just uses ranges of inputs/outputs from other devices + // so there can be a separated Keyboard and mouse, as well as combined KeyboardMouse + + LPDIRECTINPUTDEVICE8 kb_device = NULL; + LPDIRECTINPUTDEVICE8 mo_device = NULL; + + if (SUCCEEDED(idi8->CreateDevice( GUID_SysKeyboard, &kb_device, NULL))) + { + if (SUCCEEDED(kb_device->SetDataFormat(&c_dfDIKeyboard))) + if (SUCCEEDED(kb_device->SetCooperativeLevel(NULL, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE))) + { + if (SUCCEEDED(idi8->CreateDevice( GUID_SysMouse, &mo_device, NULL ))) + { + if (SUCCEEDED(mo_device->SetDataFormat(&c_dfDIMouse2))) + if (SUCCEEDED(mo_device->SetCooperativeLevel(NULL, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE))) + { + devices.push_back(new KeyboardMouse(kb_device, mo_device)); + return; + } + } + } + } + + if (kb_device) + kb_device->Release(); + if (mo_device) + mo_device->Release(); +} + +KeyboardMouse::~KeyboardMouse() +{ + // kb + m_kb_device->Unacquire(); + m_kb_device->Release(); + // mouse + m_mo_device->Unacquire(); + m_mo_device->Release(); +} + +KeyboardMouse::KeyboardMouse( const LPDIRECTINPUTDEVICE8 kb_device, const LPDIRECTINPUTDEVICE8 mo_device ) + : m_kb_device(kb_device) + , m_mo_device(mo_device) +{ + m_kb_device->Acquire(); + m_mo_device->Acquire(); + + m_last_update = GetTickCount(); + + ZeroMemory( &m_state_in, sizeof(m_state_in) ); + ZeroMemory( m_state_out, sizeof(m_state_out) ); + ZeroMemory( &m_current_state_out, sizeof(m_current_state_out) ); + + // KEYBOARD + // add keys + for ( unsigned int i = 0; i < sizeof(named_keys)/sizeof(*named_keys); ++i ) + AddInput(new Key(i)); + // add lights + for ( unsigned int i = 0; i < sizeof(named_lights)/sizeof(*named_lights); ++i ) + AddOutput(new Light(i)); + + // MOUSE + // get caps + DIDEVCAPS mouse_caps; + ZeroMemory( &mouse_caps, sizeof(mouse_caps) ); + mouse_caps.dwSize = sizeof(mouse_caps); + m_mo_device->GetCapabilities(&mouse_caps); + // mouse buttons + for ( unsigned int i = 0; i < mouse_caps.dwButtons; ++i ) + AddInput(new Button(i)); + // mouse axes + for ( unsigned int i = 0; i < mouse_caps.dwAxes; ++i ) + { + // each axis gets a negative and a positive input instance associated with it + AddInput(new Axis(i, (2==i) ? -1 : -MOUSE_AXIS_SENSITIVITY)); + AddInput(new Axis(i, -(2==i) ? 1 : MOUSE_AXIS_SENSITIVITY)); + } +} + +bool KeyboardMouse::UpdateInput() +{ + DIMOUSESTATE2 tmp_mouse; + + // if mouse position hasn't been updated in a short while, skip a dev state + DWORD cur_time = GetTickCount(); + if (cur_time - m_last_update > DROP_INPUT_TIME) + { + // set axes to zero + ZeroMemory(&m_state_in.mouse, sizeof(m_state_in.mouse)); + // skip this input state + m_mo_device->GetDeviceState(sizeof(tmp_mouse), &tmp_mouse); + } + + m_last_update = cur_time; + + HRESULT kb_hr = m_kb_device->GetDeviceState(sizeof(m_state_in.keyboard), &m_state_in.keyboard); + HRESULT mo_hr = m_mo_device->GetDeviceState(sizeof(tmp_mouse), &tmp_mouse); + + if (DIERR_INPUTLOST == kb_hr || DIERR_NOTACQUIRED == kb_hr) + m_kb_device->Acquire(); + + if (DIERR_INPUTLOST == mo_hr || DIERR_NOTACQUIRED == mo_hr) + m_mo_device->Acquire(); + + if (SUCCEEDED(kb_hr) && SUCCEEDED(mo_hr)) + { + // need to smooth out the axes, otherwise it doesnt work for shit + for ( unsigned int i = 0; i < 3; ++i ) + ((&m_state_in.mouse.lX)[i] += (&tmp_mouse.lX)[i]) /= 2; + + // copy over the buttons + memcpy( m_state_in.mouse.rgbButtons, tmp_mouse.rgbButtons, sizeof(m_state_in.mouse.rgbButtons) ); + return true; + } + + return false; +} + +bool KeyboardMouse::UpdateOutput() +{ + class KInput : public INPUT + { + public: + KInput( const unsigned char key, const bool up = false ) + { + memset( this, 0, sizeof(*this) ); + type = INPUT_KEYBOARD; + ki.wVk = key; + if (up) ki.dwFlags = KEYEVENTF_KEYUP; + } + }; + + std::vector< KInput > kbinputs; + for ( unsigned int i = 0; i < sizeof(m_state_out)/sizeof(*m_state_out); ++i ) + { + bool want_on = false; + if ( m_state_out[i] ) + want_on = m_state_out[i] > GetTickCount() % 255 ; // light should flash when output is 0.5 + + // lights are set to their original state when output is zero + if ( want_on ^ m_current_state_out[i] ) + { + kbinputs.push_back( KInput( named_lights[i].code ) ); // press + kbinputs.push_back( KInput( named_lights[i].code, true ) ); // release + + m_current_state_out[i] ^= 1; + } + } + + if (kbinputs.size()) + return ( kbinputs.size() == SendInput( (UINT)kbinputs.size(), &kbinputs[0], sizeof( kbinputs[0] ) ) ); + else + return true; +} + +std::string KeyboardMouse::GetName() const +{ + return "Keyboard Mouse"; +} + +int KeyboardMouse::GetId() const +{ + // should this be -1, idk + return 0; +} + +std::string KeyboardMouse::GetSource() const +{ + return DINPUT_SOURCE_NAME; +} + +ControlState KeyboardMouse::GetInputState(const ControllerInterface::Device::Input* const input) const +{ + return ( ((Input*)input)->GetState( &m_state_in ) ); +} + +void KeyboardMouse::SetOutputState(const ControllerInterface::Device::Output* const output, const ControlState state) +{ + ((Output*)output)->SetState( state, m_state_out ); +} + +// names +std::string KeyboardMouse::Key::GetName() const +{ + return named_keys[m_index].name; +} + +std::string KeyboardMouse::Button::GetName() const +{ + return std::string("Button ") + char('0'+m_index); +} + +std::string KeyboardMouse::Axis::GetName() const +{ + std::string tmpstr("Axis "); + tmpstr += "XYZ"[m_index]; tmpstr += ( m_range>0 ? '+' : '-' ); + return tmpstr; +} + +std::string KeyboardMouse::Light::GetName() const +{ + return named_lights[ m_index ].name; +} + +// get/set state +ControlState KeyboardMouse::Key::GetState(const State* const state) const +{ + return ( state->keyboard[named_keys[m_index].code] > 0 ); +} + +ControlState KeyboardMouse::Button::GetState(const State* const state) const +{ + return ( state->mouse.rgbButtons[m_index] > 0 ); +} + +ControlState KeyboardMouse::Axis::GetState(const State* const state) const +{ + return std::max( 0.0f, ControlState((&state->mouse.lX)[m_index]) / m_range ); +} + +void KeyboardMouse::Light::SetState(const ControlState state, unsigned char* const state_out) +{ + state_out[m_index] = (unsigned char)(state * 255); +} + +} +} + +#endif diff --git a/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputKeyboardMouse.h b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputKeyboardMouse.h new file mode 100644 index 0000000000..8e6c20beb6 --- /dev/null +++ b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputKeyboardMouse.h @@ -0,0 +1,122 @@ +#ifndef _CIFACE_DINPUT_KBM_H_ +#define _CIFACE_DINPUT_KBM_H_ + +#include "../ControllerInterface.h" + +#define DIRECTINPUT_VERSION 0x0800 +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include +#include + +namespace ciface +{ +namespace DInput +{ + +void InitKeyboardMouse( IDirectInput8* const idi8, std::vector& devices ); + +class KeyboardMouse : public ControllerInterface::Device +{ + friend class ControllerInterface; + friend class ControllerInterface::ControlReference; + +protected: + + struct State + { + BYTE keyboard[256]; + DIMOUSESTATE2 mouse; + }; + + class Input : public ControllerInterface::Device::Input + { + friend class KeyboardMouse; + protected: + virtual ControlState GetState(const State* const boardstate) const = 0; + }; + + class Output : public ControllerInterface::Device::Output + { + friend class KeyboardMouse; + protected: + virtual void SetState(const ControlState state, unsigned char* const state_out) = 0; + }; + + class Key : public Input + { + friend class KeyboardMouse; + public: + std::string GetName() const; + protected: + Key( const unsigned int index ) : m_index(index) {} + ControlState GetState(const State* const state) const; + private: + const unsigned int m_index; + }; + + class Button : public Input + { + friend class KeyboardMouse; + public: + std::string GetName() const; + protected: + Button( const unsigned int index ) : m_index(index) {} + ControlState GetState(const State* const state) const; + private: + const unsigned int m_index; + }; + + class Axis : public Input + { + friend class KeyboardMouse; + public: + std::string GetName() const; + protected: + Axis( const unsigned int index, const LONG range ) : m_index(index), m_range(range) {} + ControlState GetState(const State* const state) const; + private: + const unsigned int m_index; + const LONG m_range; + }; + + class Light : public Output + { + friend class KeyboardMouse; + public: + std::string GetName() const; + protected: + Light( const unsigned int index ) : m_index(index) {} + void SetState( const ControlState state, unsigned char* const state_out ); + private: + const unsigned int m_index; + }; + + bool UpdateInput(); + bool UpdateOutput(); + + ControlState GetInputState( const ControllerInterface::Device::Input* const input ) const; + void SetOutputState( const ControllerInterface::Device::Output* const input, const ControlState state ); + +public: + KeyboardMouse(const LPDIRECTINPUTDEVICE8 kb_device, const LPDIRECTINPUTDEVICE8 mo_device); + ~KeyboardMouse(); + + std::string GetName() const; + int GetId() const; + std::string GetSource() const; + +private: + const LPDIRECTINPUTDEVICE8 m_kb_device; + const LPDIRECTINPUTDEVICE8 m_mo_device; + + DWORD m_last_update; + State m_state_in; + unsigned char m_state_out[3]; // NUM CAPS SCROLL + bool m_current_state_out[3]; // NUM CAPS SCROLL +}; + +} +} + +#endif diff --git a/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/NamedKeys.h b/Source/Core/InputCommon/Src/ControllerInterface/DInput/NamedKeys.h similarity index 100% rename from Source/Core/InputCommon/Src/ControllerInterface/DirectInput/NamedKeys.h rename to Source/Core/InputCommon/Src/ControllerInterface/DInput/NamedKeys.h diff --git a/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputKeyboard.cpp b/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputKeyboard.cpp deleted file mode 100644 index 79ccde8028..0000000000 --- a/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputKeyboard.cpp +++ /dev/null @@ -1,187 +0,0 @@ -#include "../ControllerInterface.h" - -#ifdef CIFACE_USE_DIRECTINPUT_KEYBOARD - -#include "DirectInputKeyboard.h" -#include "DirectInput.h" - -// TODO: maybe add a ClearInputState function to this device - -namespace ciface -{ -namespace DirectInput -{ - -struct -{ - const BYTE code; - const char* const name; -} named_keys[] = -{ -#include "NamedKeys.h" -}; - -struct -{ - const BYTE code; - const char* const name; -} named_lights[] = -{ - { VK_NUMLOCK, "NUM LOCK" }, - { VK_CAPITAL, "CAPS LOCK" }, - { VK_SCROLL, "SCROLL LOCK" } -}; - -void InitKeyboard(IDirectInput8* const idi8, std::vector& devices) -{ - LPDIRECTINPUTDEVICE8 kb_device; - - unsigned int kb_count = 0; - - std::list keyboards; - idi8->EnumDevices(DI8DEVCLASS_KEYBOARD, DIEnumDevicesCallback, (LPVOID)&keyboards, DIEDFL_ATTACHEDONLY); - - // add other keyboard devices - std::list::iterator - i = keyboards.begin(), - e = keyboards.end(); - for (; i!=e; ++i) - { - if (SUCCEEDED(idi8->CreateDevice(i->guidInstance, &kb_device, NULL))) - { - if (SUCCEEDED(kb_device->SetDataFormat(&c_dfDIKeyboard))) - if (SUCCEEDED(kb_device->SetCooperativeLevel(NULL, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE))) - { - devices.push_back(new Keyboard(kb_device, kb_count++)); - return; - } - } - kb_device->Release(); - } -} - -Keyboard::~Keyboard() -{ - // kb - m_kb_device->Unacquire(); - m_kb_device->Release(); - -} - -Keyboard::Keyboard(const LPDIRECTINPUTDEVICE8 kb_device, const int index) - : m_kb_device(kb_device) - , m_index(index) -{ - m_kb_device->Acquire(); - - ZeroMemory(&m_state_in, sizeof(m_state_in)); - ZeroMemory(m_state_out, sizeof(m_state_out)); - ZeroMemory(&m_current_state_out, sizeof(m_current_state_out)); - - // KEYBOARD - // add keys - for (unsigned int i = 0; i < sizeof(named_keys)/sizeof(*named_keys); ++i) - AddInput(new Key(i)); - // add lights - for (unsigned int i = 0; i < sizeof(named_lights)/sizeof(*named_lights); ++i) - AddOutput(new Light(i)); -} - -bool Keyboard::UpdateInput() -{ - HRESULT hr = m_kb_device->GetDeviceState(sizeof(m_state_in), m_state_in); - - if (DIERR_INPUTLOST == hr || DIERR_NOTACQUIRED == hr) - m_kb_device->Acquire(); - - return SUCCEEDED(hr); -} - -bool Keyboard::UpdateOutput() -{ - class KInput : public INPUT - { - public: - KInput( const unsigned char key, const bool up = false ) - { - memset( this, 0, sizeof(*this) ); - type = INPUT_KEYBOARD; - ki.wVk = key; - if (up) ki.dwFlags = KEYEVENTF_KEYUP; - } - }; - - std::vector< KInput > kbinputs; - for ( unsigned int i = 0; i < sizeof(m_state_out)/sizeof(*m_state_out); ++i ) - { - bool want_on = false; - if ( m_state_out[i] ) - want_on = m_state_out[i] > wxGetLocalTimeMillis() % 255 ; // light should flash when output is 0.5 - - // lights are set to their original state when output is zero - if ( want_on ^ m_current_state_out[i] ) - { - kbinputs.push_back( KInput( named_lights[i].code ) ); // press - kbinputs.push_back( KInput( named_lights[i].code, true ) ); // release - - m_current_state_out[i] ^= 1; - } - } - - if (kbinputs.size()) - return ( kbinputs.size() == SendInput( (UINT)kbinputs.size(), &kbinputs[0], sizeof( kbinputs[0] ) ) ); - else - return true; -} - -std::string Keyboard::GetName() const -{ - return "Keyboard"; -} - -int Keyboard::GetId() const -{ - return m_index; -} - -std::string Keyboard::GetSource() const -{ - return DINPUT_SOURCE_NAME; -} - -ControlState Keyboard::GetInputState(const ControllerInterface::Device::Input* const input) const -{ - return (((Input*)input)->GetState(m_state_in)); -} - -void Keyboard::SetOutputState(const ControllerInterface::Device::Output* const output, const ControlState state) -{ - ((Output*)output)->SetState(state, m_state_out); -} - -// names -std::string Keyboard::Key::GetName() const -{ - return named_keys[m_index].name; -} - -std::string Keyboard::Light::GetName() const -{ - return named_lights[ m_index ].name; -} - -// get/set state -ControlState Keyboard::Key::GetState(const BYTE keys[]) const -{ - return (keys[named_keys[m_index].code] != 0); -} - -void Keyboard::Light::SetState( const ControlState state, unsigned char* const state_out ) -{ - state_out[m_index] = state * 255; -} - -} -} - -#endif diff --git a/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputKeyboard.h b/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputKeyboard.h deleted file mode 100644 index 55f539fca8..0000000000 --- a/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputKeyboard.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef _CIFACE_DIRECTINPUT_KEYBOARD_H_ -#define _CIFACE_DIRECTINPUT_KEYBOARD_H_ - -#include "../ControllerInterface.h" - -#define DIRECTINPUT_VERSION 0x0800 -#define WIN32_LEAN_AND_MEAN -#define NOMINMAX -#include -#include - -#include -#include - -namespace ciface -{ -namespace DirectInput -{ - -void InitKeyboard(IDirectInput8* const idi8, std::vector& devices); - -class Keyboard : public ControllerInterface::Device -{ - friend class ControllerInterface; - friend class ControllerInterface::ControlReference; - -protected: - - struct State - { - - }; - - class Input : public ControllerInterface::Device::Input - { - friend class Keyboard; - protected: - virtual ControlState GetState(const BYTE keys[]) const = 0; - }; - - class Output : public ControllerInterface::Device::Output - { - friend class Keyboard; - protected: - virtual void SetState(const ControlState state, unsigned char* const state_out) = 0; - }; - - class Key : public Input - { - friend class Keyboard; - public: - std::string GetName() const; - protected: - Key(const unsigned int index) : m_index(index) {} - ControlState GetState(const BYTE keys[]) const; - private: - const unsigned int m_index; - }; - - class Light : public Output - { - friend class Keyboard; - public: - std::string GetName() const; - protected: - Light(const unsigned int index) : m_index(index) {} - void SetState(const ControlState state, unsigned char* const state_out); - private: - const unsigned int m_index; - }; - - bool UpdateInput(); - bool UpdateOutput(); - - ControlState GetInputState( const ControllerInterface::Device::Input* const input ) const; - void SetOutputState( const ControllerInterface::Device::Output* const input, const ControlState state ); - -public: - Keyboard(const LPDIRECTINPUTDEVICE8 kb_device, const int index); - ~Keyboard(); - - std::string GetName() const; - int GetId() const; - std::string GetSource() const; - -private: - const LPDIRECTINPUTDEVICE8 m_kb_device; - const int m_index; - - wxLongLong m_last_update; - BYTE m_state_in[256]; - unsigned char m_state_out[3]; // NUM CAPS SCROLL - bool m_current_state_out[3]; // NUM CAPS SCROLL -}; - -} -} - -#endif diff --git a/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputMouse.cpp b/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputMouse.cpp deleted file mode 100644 index 3464200349..0000000000 --- a/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputMouse.cpp +++ /dev/null @@ -1,175 +0,0 @@ -#include "../ControllerInterface.h" - -#ifdef CIFACE_USE_DIRECTINPUT_MOUSE - -#include "DirectInputMouse.h" -#include "DirectInput.h" - -// TODO: maybe add a ClearInputState function to this device - - // (lower would be more sensitive) user can lower sensitivity by setting range - // seems decent here ( at 8 ), I dont think anyone would need more sensitive than this - // and user can lower it much farther than they would want to with the range -#define MOUSE_AXIS_SENSITIVITY 8 - - // if input hasn't been received for this many ms, mouse input will be skipped - // otherwise it is just some crazy value -#define DROP_INPUT_TIME 250 - -namespace ciface -{ -namespace DirectInput -{ - -void InitMouse( IDirectInput8* const idi8, std::vector& devices ) -{ - LPDIRECTINPUTDEVICE8 mo_device; - - unsigned int mo_count = 0; - - std::list mice; - idi8->EnumDevices(DI8DEVCLASS_POINTER, DIEnumDevicesCallback, (LPVOID)&mice, DIEDFL_ATTACHEDONLY); - - // add other keyboard devices - std::list::iterator - i = mice.begin(), - e = mice.end(); - for (; i!=e; ++i) - { - if (SUCCEEDED(idi8->CreateDevice(i->guidInstance, &mo_device, NULL))) - { - if (SUCCEEDED(mo_device->SetDataFormat(&c_dfDIMouse2))) - if (SUCCEEDED(mo_device->SetCooperativeLevel(NULL, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE))) - { - devices.push_back(new Mouse(mo_device, mo_count++)); - return; - } - } - mo_device->Release(); - } -} - -Mouse::~Mouse() -{ - // mouse - m_mo_device->Unacquire(); - m_mo_device->Release(); -} - -Mouse::Mouse(const LPDIRECTINPUTDEVICE8 mo_device, const int index) - : m_mo_device(mo_device) - , m_index(index) -{ - m_mo_device->Acquire(); - - m_last_update = GetTickCount(); - ZeroMemory(&m_state_in, sizeof(m_state_in)); - - // MOUSE - // get caps - DIDEVCAPS mouse_caps; - ZeroMemory( &mouse_caps, sizeof(mouse_caps) ); - mouse_caps.dwSize = sizeof(mouse_caps); - m_mo_device->GetCapabilities(&mouse_caps); - // mouse buttons - for (unsigned int i = 0; i < mouse_caps.dwButtons; ++i) - AddInput(new Button(i)); - // mouse axes - for (unsigned int i = 0; i < mouse_caps.dwAxes; ++i) - { - // each axis gets a negative and a positive input instance associated with it - AddInput(new Axis(i, (2==i) ? -1 : -MOUSE_AXIS_SENSITIVITY)); - AddInput(new Axis(i, -(2==i) ? 1 : MOUSE_AXIS_SENSITIVITY)); - } - -} - -bool Mouse::UpdateInput() -{ - DIMOUSESTATE2 tmp_mouse; - HRESULT hr = m_mo_device->GetDeviceState(sizeof(tmp_mouse), &tmp_mouse); - - // if mouse position hasn't been updated in a short while, skip a dev state - const DWORD cur_time = GetTickCount(); - if (cur_time - m_last_update > DROP_INPUT_TIME) - { - // set buttons/axes to zero - // skip this input state - ZeroMemory(&m_state_in, sizeof(m_state_in)); - } - else if (SUCCEEDED(hr)) - { - // need to smooth out the axes, otherwise it doesnt work for shit - for (unsigned int i = 0; i < 3; ++i) - ((&m_state_in.lX)[i] += (&tmp_mouse.lX)[i]) /= 2; - - // copy over the buttons - memcpy(m_state_in.rgbButtons, tmp_mouse.rgbButtons, sizeof(m_state_in.rgbButtons)); - } - - m_last_update = cur_time; - - if (DIERR_INPUTLOST == hr || DIERR_NOTACQUIRED == hr) - m_mo_device->Acquire(); - - return SUCCEEDED(hr); -} - -bool Mouse::UpdateOutput() -{ - return true; -} - -std::string Mouse::GetName() const -{ - return "Mouse"; -} - -int Mouse::GetId() const -{ - return m_index; -} - -std::string Mouse::GetSource() const -{ - return DINPUT_SOURCE_NAME; -} - -ControlState Mouse::GetInputState( const ControllerInterface::Device::Input* const input ) const -{ - return (((Input*)input)->GetState(&m_state_in)); -} - -void Mouse::SetOutputState(const ControllerInterface::Device::Output* const output, const ControlState state) -{ - return; -} - -// names -std::string Mouse::Button::GetName() const -{ - return std::string("Button ") + char('0'+m_index); -} - -std::string Mouse::Axis::GetName() const -{ - std::string tmpstr("Axis "); - tmpstr += "XYZ"[m_index]; tmpstr += ( m_range>0 ? '+' : '-' ); - return tmpstr; -} - -// get/set state -ControlState Mouse::Button::GetState(const DIMOUSESTATE2* const state) const -{ - return (state->rgbButtons[m_index] != 0); -} - -ControlState Mouse::Axis::GetState(const DIMOUSESTATE2* const state) const -{ - return std::max(0.0f, ControlState((&state->lX)[m_index]) / m_range); -} - -} -} - -#endif diff --git a/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputMouse.h b/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputMouse.h deleted file mode 100644 index 57cc15ff5a..0000000000 --- a/Source/Core/InputCommon/Src/ControllerInterface/DirectInput/DirectInputMouse.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef _CIFACE_DIRECTINPUT_MOUSE_H_ -#define _CIFACE_DIRECTINPUT_MOUSE_H_ - -#include "../ControllerInterface.h" - -#define DIRECTINPUT_VERSION 0x0800 -#define WIN32_LEAN_AND_MEAN -#define NOMINMAX -#include -#include - -namespace ciface -{ -namespace DirectInput -{ - -void InitMouse(IDirectInput8* const idi8, std::vector& devices); - -class Mouse : public ControllerInterface::Device -{ - friend class ControllerInterface; - friend class ControllerInterface::ControlReference; - -protected: - - class Input : public ControllerInterface::Device::Input - { - friend class Mouse; - protected: - virtual ControlState GetState(const DIMOUSESTATE2* const boardstate) const = 0; - }; - - class Button : public Input - { - friend class Mouse; - public: - std::string GetName() const; - protected: - Button(const unsigned int index) : m_index(index) {} - ControlState GetState(const DIMOUSESTATE2* const state) const; - private: - const unsigned int m_index; - }; - - class Axis : public Input - { - friend class Mouse; - public: - std::string GetName() const; - protected: - Axis(const unsigned int index, const LONG range) : m_index(index), m_range(range) {} - ControlState GetState(const DIMOUSESTATE2* const state) const; - private: - const unsigned int m_index; - const LONG m_range; - }; - - bool UpdateInput(); - bool UpdateOutput(); - - ControlState GetInputState( const ControllerInterface::Device::Input* const input ) const; - void SetOutputState( const ControllerInterface::Device::Output* const input, const ControlState state ); - -public: - Mouse(const LPDIRECTINPUTDEVICE8 mo_device, const int index); - ~Mouse(); - - std::string GetName() const; - int GetId() const; - std::string GetSource() const; - -private: - const LPDIRECTINPUTDEVICE8 m_mo_device; - const int m_index; - - DWORD m_last_update; - DIMOUSESTATE2 m_state_in; -}; - -} -} - -#endif diff --git a/Source/Core/InputCommon/Src/InputConfig.cpp b/Source/Core/InputCommon/Src/InputConfig.cpp index cfba6aaec9..b4d8a3b546 100644 --- a/Source/Core/InputCommon/Src/InputConfig.cpp +++ b/Source/Core/InputCommon/Src/InputConfig.cpp @@ -59,6 +59,7 @@ void InputPlugin::SaveConfig() std::string ini_filename = (std::string(File::GetUserPath(D_CONFIG_IDX)) + ini_name + ".ini" ); IniFile inifile; + inifile.Load(ini_filename); std::vector< ControllerEmu* >::const_iterator i = controllers.begin(), e = controllers.end(); diff --git a/Source/Core/InputUICommon/Src/ConfigDiag.cpp b/Source/Core/InputUICommon/Src/ConfigDiag.cpp index 53ad28f796..3ecdb8ed22 100644 --- a/Source/Core/InputUICommon/Src/ConfigDiag.cpp +++ b/Source/Core/InputUICommon/Src/ConfigDiag.cpp @@ -52,7 +52,7 @@ void GamepadPage::ConfigExtension( wxCommandEvent& event ) } PadSettingExtension::PadSettingExtension( wxWindow* const parent, ControllerEmu::Extension* const ext ) - : wxChoice( parent, -1 ) + : PadSetting(new wxChoice( parent, -1 )) , extension(ext) { @@ -61,23 +61,23 @@ PadSettingExtension::PadSettingExtension( wxWindow* const parent, ControllerEmu: e = extension->attachments.end(); for ( ; i!=e; ++i ) - Append( wxString::FromAscii( (*i)->GetName().c_str() ) ); + ((wxChoice*)wxcontrol)->Append(WXSTR_FROM_STR((*i)->GetName())); UpdateGUI(); } void PadSettingExtension::UpdateGUI() { - Select( extension->switch_extension ); + ((wxChoice*)wxcontrol)->Select(extension->switch_extension); } void PadSettingExtension::UpdateValue() { - extension->switch_extension = GetSelection(); + extension->switch_extension = ((wxChoice*)wxcontrol)->GetSelection(); } PadSettingCheckBox::PadSettingCheckBox( wxWindow* const parent, ControlState& _value, const char* const label ) - : wxCheckBox( parent, -1, wxString::FromAscii( label ), wxDefaultPosition ) + : PadSetting(new wxCheckBox( parent, -1, wxString::FromAscii( label ), wxDefaultPosition )) , value(_value) { UpdateGUI(); @@ -85,23 +85,23 @@ PadSettingCheckBox::PadSettingCheckBox( wxWindow* const parent, ControlState& _v void PadSettingCheckBox::UpdateGUI() { - SetValue( value > 0 ); + ((wxCheckBox*)wxcontrol)->SetValue( value > 0 ); } void PadSettingCheckBox::UpdateValue() { // 0.01 so its saved to the ini file as just 1. :( - value = 0.01 * GetValue(); + value = 0.01 * ((wxCheckBox*)wxcontrol)->GetValue(); } -void PadSettingChoice::UpdateGUI() +void PadSettingSpin::UpdateGUI() { - SetValue(value * 100); + ((wxSpinCtrl*)wxcontrol)->SetValue(value * 100); } -void PadSettingChoice::UpdateValue() +void PadSettingSpin::UpdateValue() { - value = float(GetValue()) / 100; + value = float(((wxSpinCtrl*)wxcontrol)->GetValue()) / 100; } ControlDialog::ControlDialog(GamepadPage* const parent, InputPlugin& plugin, ControllerInterface::ControlReference* const ref) @@ -162,7 +162,7 @@ void InputConfigDialog::UpdateProfileComboBox() for ( ; si!=se; ++si ) { std::string str( si->begin() + si->find_last_of('/') + 1 , si->end() - 4 ) ; - strs.push_back( wxString::FromAscii( str.c_str() ) ); + strs.push_back(WXSTR_FROM_STR(str)); } std::vector< GamepadPage* >::iterator i = m_padpages.begin(), @@ -235,7 +235,7 @@ void ControlDialog::UpdateGUI() std::ostringstream ss; ss << "Bound Controls: "; if ( bound ) ss << bound; else ss << "None"; - m_bound_label->SetLabel( wxString::FromAscii(ss.str().c_str()) ); + m_bound_label->SetLabel(WXSTR_FROM_STR(ss.str())); }; void GamepadPage::UpdateGUI() @@ -265,19 +265,18 @@ void GamepadPage::UpdateGUI() void GamepadPage::ClearAll( wxCommandEvent& event ) { - m_plugin.controls_crit.Enter(); // enter - // just load an empty ini section to clear everything :P IniFile::Section section; controller->LoadConfig(§ion); // no point in using the real ControllerInterface i guess ControllerInterface face; + + m_plugin.controls_crit.Enter(); // enter controller->UpdateReferences(face); + m_plugin.controls_crit.Leave(); // leave UpdateGUI(); - - m_plugin.controls_crit.Leave(); // leave } void ControlDialog::SetControl( wxCommandEvent& event ) @@ -322,7 +321,32 @@ void ControlDialog::ClearControl(wxCommandEvent& event) { control_reference->expression.clear(); - m_plugin.controls_crit.Leave(); // enter + m_plugin.controls_crit.Enter(); // enter + m_plugin.controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); + m_plugin.controls_crit.Leave(); // leave + + UpdateGUI(); +} + +void ControlDialog::SetSelectedControl(wxCommandEvent& event) +{ + const int num = control_lbox->GetSelection(); + + if (num < 0) + return; + + wxString expr; + + // non-default device + if (false == (m_devq == m_parent->controller->default_device)) + expr.append(wxT('`')).append(WXSTR_FROM_STR(m_devq.ToString())).append(wxT('`')); + + // append the control name + expr += control_lbox->GetString(num); + + control_reference->expression = STR_FROM_WXSTR(expr); + + m_plugin.controls_crit.Enter(); // enter m_plugin.controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); m_plugin.controls_crit.Leave(); // leave @@ -354,7 +378,7 @@ void ControlDialog::AppendControl(wxCommandEvent& event) control_reference->expression = STR_FROM_WXSTR(expr); - m_plugin.controls_crit.Leave(); // enter + m_plugin.controls_crit.Enter(); // enter m_plugin.controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); m_plugin.controls_crit.Leave(); // leave @@ -363,20 +387,15 @@ void ControlDialog::AppendControl(wxCommandEvent& event) void GamepadPage::AdjustSetting( wxCommandEvent& event ) { - m_plugin.controls_crit.Enter(); // enter - - // updates the setting value from the GUI control - (dynamic_cast(event.GetEventObject()))->UpdateValue(); - + m_plugin.controls_crit.Enter(); // enter / prolly fine not being here + ((PadSetting*)((wxControl*)event.GetEventObject())->GetClientData())->UpdateValue(); m_plugin.controls_crit.Leave(); // leave } void GamepadPage::AdjustControlOption( wxCommandEvent& event ) { m_plugin.controls_crit.Enter(); // enter / prolly fine not being here - m_control_dialog->control_reference->range = (ControlState)(m_control_dialog->range_slider->GetValue()) / SLIDER_TICK_COUNT; - m_plugin.controls_crit.Leave(); // leave } @@ -396,9 +415,9 @@ void GamepadPage::ClearControl( wxCommandEvent& event ) btn->control_reference->expression.clear(); //btn->control_reference->device_qualifier = controller->default_device; - m_plugin.controls_crit.Enter(); + m_plugin.controls_crit.Enter(); // enter controller->UpdateReferences( m_plugin.controller_interface ); - m_plugin.controls_crit.Leave(); + m_plugin.controls_crit.Leave(); // leave // update changes UpdateGUI(); @@ -416,13 +435,12 @@ void ControlDialog::DetectControl(wxCommandEvent& event) m_plugin.controls_crit.Enter(); // enter ControllerInterface::Device::Control* const ctrl = control_reference->Detect(DETECT_WAIT_TIME, dev); + m_plugin.controls_crit.Leave(); // leave // if we got input, select it in the list if (ctrl) SelectControl(ctrl->GetName()); - m_plugin.controls_crit.Leave(); // leave - btn->SetLabel(lbl); } } @@ -457,34 +475,41 @@ wxStaticBoxSizer* ControlDialog::CreateControlChooser( wxWindow* const parent, w { wxStaticBoxSizer* const main_szr = new wxStaticBoxSizer(wxVERTICAL, parent, control_reference->is_input ? wxT("Input") : wxT("Output")); - textctrl = new wxTextCtrl(parent, -1, wxEmptyString, wxDefaultPosition, wxSize(-1, 48), wxTE_PROCESS_ENTER | wxTE_MULTILINE); - _connect_macro_(textctrl, ControlDialog::SetControl, wxEVT_COMMAND_TEXT_ENTER, parent); + textctrl = new wxTextCtrl(parent, -1, wxEmptyString, wxDefaultPosition, wxSize(-1, 48), wxTE_MULTILINE); wxButton* const detect_button = new wxButton( parent, -1, control_reference->is_input ? wxT("Detect") : wxT("Test") ); - wxButton* const clear_button = new wxButton( parent, -1, wxT("Clear"), wxDefaultPosition ); - wxButton* const set_button = new wxButton( parent, -1, wxT("Set")/*, wxDefaultPosition, wxSize( 32, -1 )*/ ); + + wxButton* const clear_button = new wxButton( parent, -1, wxT("Clear")); + wxButton* const set_button = new wxButton( parent, -1, wxT("Set")); + + wxButton* const select_button = new wxButton( parent, -1, wxT("Select")); + _connect_macro_(select_button, ControlDialog::SetSelectedControl, wxEVT_COMMAND_BUTTON_CLICKED, parent); wxButton* const or_button = new wxButton( parent, -1, wxT("| OR"), wxDefaultPosition ); - // TODO: check if && is good on other OS - wxButton* const and_button = new wxButton( parent, -1, wxT("&& AND"), wxDefaultPosition ); - wxButton* const not_button = new wxButton( parent, -1, wxT("! NOT"), wxDefaultPosition ); - wxButton* const add_button = new wxButton( parent, -1, wxT("# ADD"), wxDefaultPosition ); - _connect_macro_(or_button, ControlDialog::AppendControl, wxEVT_COMMAND_BUTTON_CLICKED, parent); - _connect_macro_(and_button, ControlDialog::AppendControl, wxEVT_COMMAND_BUTTON_CLICKED, parent); - _connect_macro_(not_button, ControlDialog::AppendControl, wxEVT_COMMAND_BUTTON_CLICKED, parent); - _connect_macro_(add_button, ControlDialog::AppendControl, wxEVT_COMMAND_BUTTON_CLICKED, parent); - control_lbox = new wxListBox(parent, -1, wxDefaultPosition, wxSize(128, 128)); + control_lbox = new wxListBox(parent, -1, wxDefaultPosition, wxSize(-1, 64)); wxBoxSizer* const button_sizer = new wxBoxSizer(wxVERTICAL); button_sizer->Add(detect_button, 1, 0, 5); - button_sizer->Add(clear_button, 1, 0, 5); + button_sizer->Add(select_button, 1, 0, 5); button_sizer->Add(or_button, 1, 0, 5); - button_sizer->Add(and_button, 1, 0, 5); - button_sizer->Add(not_button, 1, 0, 5); - button_sizer->Add(add_button, 1, 0, 5); - button_sizer->Add(set_button, 1, 0, 5); + + if (control_reference->is_input) + { + // TODO: check if && is good on other OS + wxButton* const and_button = new wxButton( parent, -1, wxT("&& AND"), wxDefaultPosition ); + wxButton* const not_button = new wxButton( parent, -1, wxT("! NOT"), wxDefaultPosition ); + wxButton* const add_button = new wxButton( parent, -1, wxT("^ ADD"), wxDefaultPosition ); + + _connect_macro_(and_button, ControlDialog::AppendControl, wxEVT_COMMAND_BUTTON_CLICKED, parent); + _connect_macro_(not_button, ControlDialog::AppendControl, wxEVT_COMMAND_BUTTON_CLICKED, parent); + _connect_macro_(add_button, ControlDialog::AppendControl, wxEVT_COMMAND_BUTTON_CLICKED, parent); + + button_sizer->Add(and_button, 1, 0, 5); + button_sizer->Add(not_button, 1, 0, 5); + button_sizer->Add(add_button, 1, 0, 5); + } range_slider = new wxSlider( parent, -1, SLIDER_TICK_COUNT, 0, SLIDER_TICK_COUNT * 2, wxDefaultPosition, wxDefaultSize, wxSL_TOP | wxSL_LABELS /*| wxSL_AUTOTICKS*/ ); @@ -506,9 +531,15 @@ wxStaticBoxSizer* ControlDialog::CreateControlChooser( wxWindow* const parent, w ctrls_sizer->Add(control_lbox, 1, wxEXPAND, 0); ctrls_sizer->Add(button_sizer, 0, wxEXPAND, 0); + wxBoxSizer* const bottom_btns_sizer = new wxBoxSizer(wxHORIZONTAL); + bottom_btns_sizer->Add(clear_button, 0, wxLEFT, 5); + bottom_btns_sizer->AddStretchSpacer(1); + bottom_btns_sizer->Add(set_button, 0, wxRIGHT, 5); + main_szr->Add(range_sizer, 0, wxEXPAND|wxLEFT|wxRIGHT, 5); main_szr->Add(ctrls_sizer, 0, wxEXPAND|wxLEFT|wxRIGHT|wxBOTTOM, 5); main_szr->Add(textctrl, 1, wxEXPAND|wxLEFT|wxRIGHT|wxBOTTOM, 5); + main_szr->Add(bottom_btns_sizer, 0, wxEXPAND|wxBOTTOM, 5); main_szr->Add(m_bound_label, 0, wxCENTER, 0); UpdateListContents(); @@ -618,7 +649,7 @@ void GamepadPage::RefreshDevices( wxCommandEvent& event ) } ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWindow* const parent, wxWindow* const eventsink ) - : wxStaticBoxSizer( wxVERTICAL, parent, wxString::FromAscii( group->name ) ) + : wxStaticBoxSizer(wxVERTICAL, parent, wxString::FromAscii(group->name)) { control_group = group; @@ -674,7 +705,7 @@ ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWi wxBitmap bitmap(64, 64); dc.SelectObject(bitmap); dc.Clear(); - static_bitmap = new wxStaticBitmap( parent, -1, bitmap, wxDefaultPosition, wxDefaultSize, wxBITMAP_TYPE_BMP ); + static_bitmap = new wxStaticBitmap(parent, -1, bitmap, wxDefaultPosition, wxDefaultSize, wxBITMAP_TYPE_BMP); std::vector< ControllerEmu::ControlGroup::Setting* >::const_iterator i = group->settings.begin(), @@ -683,11 +714,11 @@ ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWi wxBoxSizer* const szr = new wxBoxSizer( wxVERTICAL ); for ( ; i!=e; ++i ) { - PadSettingChoice* cbox = new PadSettingChoice( parent, *i ); - _connect_macro_( cbox, GamepadPage::AdjustSetting, wxEVT_COMMAND_SPINCTRL_UPDATED, eventsink ); - options.push_back( cbox ); - szr->Add( new wxStaticText( parent, -1, wxString::FromAscii( (*i)->name ) ) ); - szr->Add( cbox, 0, wxLEFT, 0 ); + PadSettingSpin* setting = new PadSettingSpin(parent, *i); + _connect_macro_(setting->wxcontrol, GamepadPage::AdjustSetting, wxEVT_COMMAND_SPINCTRL_UPDATED, eventsink); + options.push_back(setting); + szr->Add(new wxStaticText(parent, -1, wxString::FromAscii((*i)->name))); + szr->Add(setting->wxcontrol, 0, wxLEFT, 0 ); } wxBoxSizer* const h_szr = new wxBoxSizer( wxHORIZONTAL ); @@ -702,21 +733,21 @@ ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWi wxBitmap bitmap(int(12*group->controls.size()+1), 12); dc.SelectObject(bitmap); dc.Clear(); - static_bitmap = new wxStaticBitmap( parent, -1, bitmap, wxDefaultPosition, wxDefaultSize, wxBITMAP_TYPE_BMP ); + static_bitmap = new wxStaticBitmap(parent, -1, bitmap, wxDefaultPosition, wxDefaultSize, wxBITMAP_TYPE_BMP); - PadSettingChoice* const threshold_cbox = new PadSettingChoice( parent, group->settings[0] ); - _connect_macro_( threshold_cbox, GamepadPage::AdjustSetting, wxEVT_COMMAND_SPINCTRL_UPDATED, eventsink ); + PadSettingSpin* const threshold_cbox = new PadSettingSpin(parent, group->settings[0]); + _connect_macro_(threshold_cbox->wxcontrol, GamepadPage::AdjustSetting, wxEVT_COMMAND_SPINCTRL_UPDATED, eventsink); - threshold_cbox->SetToolTip(wxT("Adjust the analog control pressure required to activate buttons.")); + threshold_cbox->wxcontrol->SetToolTip(wxT("Adjust the analog control pressure required to activate buttons.")); - options.push_back( threshold_cbox ); + options.push_back(threshold_cbox); wxBoxSizer* const szr = new wxBoxSizer( wxHORIZONTAL ); - szr->Add( new wxStaticText( parent, -1, wxString::FromAscii( group->settings[0]->name ) ), 0, wxCENTER|wxRIGHT, 3 ); - szr->Add( threshold_cbox, 0, wxRIGHT, 3 ); + szr->Add(new wxStaticText(parent, -1, wxString::FromAscii(group->settings[0]->name)), 0, wxCENTER|wxRIGHT, 3); + szr->Add(threshold_cbox->wxcontrol, 0, wxRIGHT, 3); - Add( szr, 0, wxALL|wxCENTER, 3 ); - Add( static_bitmap, 0, wxALL|wxCENTER, 3 ); + Add(szr, 0, wxALL|wxCENTER, 3); + Add(static_bitmap, 0, wxALL|wxCENTER, 3); } break; case GROUP_TYPE_MIXED_TRIGGERS : @@ -732,20 +763,20 @@ ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWi wxBitmap bitmap(width, height+1); dc.SelectObject(bitmap); dc.Clear(); - static_bitmap = new wxStaticBitmap( parent, -1, bitmap, wxDefaultPosition, wxDefaultSize, wxBITMAP_TYPE_BMP ); + static_bitmap = new wxStaticBitmap(parent, -1, bitmap, wxDefaultPosition, wxDefaultSize, wxBITMAP_TYPE_BMP); std::vector::const_iterator i = group->settings.begin(), e = group->settings.end(); for ( ; i!=e; ++i ) { - PadSettingChoice* cbox = new PadSettingChoice( parent, *i ); - _connect_macro_( cbox, GamepadPage::AdjustSetting, wxEVT_COMMAND_SPINCTRL_UPDATED, eventsink ); - options.push_back( cbox ); + PadSettingSpin* setting = new PadSettingSpin(parent, *i); + _connect_macro_(setting->wxcontrol, GamepadPage::AdjustSetting, wxEVT_COMMAND_SPINCTRL_UPDATED, eventsink); + options.push_back(setting); wxBoxSizer* const szr = new wxBoxSizer( wxHORIZONTAL ); - szr->Add( new wxStaticText( parent, -1, wxString::FromAscii( (*i)->name ) ), 0, wxCENTER|wxRIGHT, 3 ); - szr->Add( cbox, 0, wxRIGHT, 3 ); - Add( szr, 0, wxALL|wxCENTER, 3 ); + szr->Add(new wxStaticText(parent, -1, wxString::FromAscii((*i)->name)), 0, wxCENTER|wxRIGHT, 3); + szr->Add(setting->wxcontrol, 0, wxRIGHT, 3); + Add(szr, 0, wxALL|wxCENTER, 3); } Add( static_bitmap, 0, wxALL|wxCENTER, 3 ); @@ -754,15 +785,15 @@ ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWi case GROUP_TYPE_EXTENSION : { PadSettingExtension* const attachments = new PadSettingExtension( parent, (ControllerEmu::Extension*)group ); - wxButton* const configure = new ExtensionButton( parent, (ControllerEmu::Extension*)group ); + wxButton* const configure_btn = new ExtensionButton( parent, (ControllerEmu::Extension*)group ); - options.push_back( attachments ); + options.push_back(attachments); - _connect_macro_( attachments, GamepadPage::AdjustSetting, wxEVT_COMMAND_CHOICE_SELECTED, eventsink ); - _connect_macro_( configure, GamepadPage::ConfigExtension, wxEVT_COMMAND_BUTTON_CLICKED, eventsink ); + _connect_macro_(attachments->wxcontrol, GamepadPage::AdjustSetting, wxEVT_COMMAND_CHOICE_SELECTED, eventsink); + _connect_macro_(configure_btn, GamepadPage::ConfigExtension, wxEVT_COMMAND_BUTTON_CLICKED, eventsink); - Add( attachments, 0, wxTOP|wxLEFT|wxRIGHT|wxEXPAND, 3 ); - Add( configure, 0, wxALL|wxEXPAND, 3 ); + Add(attachments->wxcontrol, 0, wxTOP|wxLEFT|wxRIGHT|wxEXPAND, 3); + Add(configure_btn, 0, wxALL|wxEXPAND, 3 ); } break; default : @@ -774,11 +805,11 @@ ControlGroupBox::ControlGroupBox( ControllerEmu::ControlGroup* const group, wxWi e = group->settings.end(); for ( ; i!=e; ++i ) { - PadSettingCheckBox* setting_cbox = new PadSettingCheckBox( parent, (*i)->value, (*i)->name ); - _connect_macro_( setting_cbox, GamepadPage::AdjustSetting, wxEVT_COMMAND_CHECKBOX_CLICKED, eventsink ); - options.push_back( setting_cbox ); + PadSettingCheckBox* setting_cbox = new PadSettingCheckBox(parent, (*i)->value, (*i)->name); + _connect_macro_(setting_cbox->wxcontrol, GamepadPage::AdjustSetting, wxEVT_COMMAND_CHECKBOX_CLICKED, eventsink); + options.push_back(setting_cbox); - Add( setting_cbox, 0, wxALL|wxLEFT, 5 ); + Add(setting_cbox->wxcontrol, 0, wxALL|wxLEFT, 5); } } @@ -822,8 +853,8 @@ ControlGroupsSizer::ControlGroupsSizer( ControllerEmu* const controller, wxWindo GamepadPage::GamepadPage( wxWindow* parent, InputPlugin& plugin, const unsigned int pad_num, InputConfigDialog* const config_dialog ) : wxNotebookPage( parent, -1 , wxDefaultPosition, wxDefaultSize ) ,controller(plugin.controllers[pad_num]) - ,m_config_dialog(config_dialog) - ,m_plugin(plugin) + , m_config_dialog(config_dialog) + , m_plugin(plugin) { wxBoxSizer* control_group_sizer = new ControlGroupsSizer( m_plugin.controllers[pad_num], this, this, &control_groups ); @@ -883,7 +914,7 @@ GamepadPage::GamepadPage( wxWindow* parent, InputPlugin& plugin, const unsigned }; -InputConfigDialog::InputConfigDialog(wxWindow* const parent, InputPlugin& plugin, const std::string& name) +InputConfigDialog::InputConfigDialog(wxWindow* const parent, InputPlugin& plugin, const std::string& name, const int tab_num) : wxDialog( parent, wxID_ANY, wxString::FromAscii(name.c_str()), wxPoint(128,-1), wxDefaultSize ) , m_plugin(plugin) { @@ -892,9 +923,11 @@ InputConfigDialog::InputConfigDialog(wxWindow* const parent, InputPlugin& plugin { GamepadPage* gp = new GamepadPage( m_pad_notebook, m_plugin, i, this ); m_padpages.push_back( gp ); - m_pad_notebook->AddPage( gp, wxString::FromAscii( m_plugin.gui_name ) + wxT(' ') + wxChar('1'+i) ); + m_pad_notebook->AddPage( gp, wxString::FromAscii(m_plugin.gui_name) + wxT(' ') + wxChar('1'+i) ); } + m_pad_notebook->SetSelection(tab_num); + UpdateDeviceComboBox(); UpdateProfileComboBox(); diff --git a/Source/Core/InputUICommon/Src/ConfigDiag.h b/Source/Core/InputUICommon/Src/ConfigDiag.h index 0f1c2e7dcd..a5d4de3db6 100644 --- a/Source/Core/InputUICommon/Src/ConfigDiag.h +++ b/Source/Core/InputUICommon/Src/ConfigDiag.h @@ -47,29 +47,33 @@ class PadSetting { protected: - PadSetting() {} + PadSetting(wxControl* const _control) : wxcontrol(_control) { wxcontrol->SetClientData(this); } public: virtual void UpdateGUI() = 0; virtual void UpdateValue() = 0; + + virtual ~PadSetting() {} + + wxControl* const wxcontrol; }; -class PadSettingExtension : public wxChoice, public PadSetting +class PadSettingExtension : public PadSetting { public: - PadSettingExtension( wxWindow* const parent, ControllerEmu::Extension* const ext ); + PadSettingExtension(wxWindow* const parent, ControllerEmu::Extension* const ext); void UpdateGUI(); void UpdateValue(); ControllerEmu::Extension* const extension; }; -class PadSettingChoice : public wxSpinCtrl, public PadSetting +class PadSettingSpin : public PadSetting { public: - PadSettingChoice( wxWindow* const parent, ControllerEmu::ControlGroup::Setting* const setting ) - : wxSpinCtrl(parent, -1, wxEmptyString, wxDefaultPosition - , wxSize( 54, -1 ), 0, setting->low, setting->high, setting->value * 100) + PadSettingSpin(wxWindow* const parent, ControllerEmu::ControlGroup::Setting* const setting) + : PadSetting(new wxSpinCtrl(parent, -1, wxEmptyString, wxDefaultPosition + , wxSize( 54, -1 ), 0, setting->low, setting->high, setting->value * 100)) , value(setting->value) {} void UpdateGUI(); @@ -78,10 +82,10 @@ public: ControlState& value; }; -class PadSettingCheckBox : public wxCheckBox, public PadSetting +class PadSettingCheckBox : public PadSetting { public: - PadSettingCheckBox( wxWindow* const parent, ControlState& _value, const char* const label ); + PadSettingCheckBox(wxWindow* const parent, ControlState& _value, const char* const label); void UpdateGUI(); void UpdateValue(); @@ -106,6 +110,7 @@ public: void UpdateListContents(); void SelectControl(const std::string& name); + void SetSelectedControl(wxCommandEvent& event); void AppendControl(wxCommandEvent& event); ControllerInterface::ControlReference* const control_reference; @@ -212,7 +217,7 @@ private: class InputConfigDialog : public wxDialog { public: - InputConfigDialog( wxWindow* const parent, InputPlugin& plugin, const std::string& name); + InputConfigDialog( wxWindow* const parent, InputPlugin& plugin, const std::string& name, const int tab_num = 0); //~InputConfigDialog(); bool Destroy(); diff --git a/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj b/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj index a88d0e24aa..417f14edf7 100644 --- a/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj +++ b/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/SConscript b/Source/Plugins/Plugin_WiimoteNew/Src/SConscript index 325e90f82f..0149a40d6a 100644 --- a/Source/Plugins/Plugin_WiimoteNew/Src/SConscript +++ b/Source/Plugins/Plugin_WiimoteNew/Src/SConscript @@ -16,7 +16,9 @@ files = [ 'WiimoteEmu/EmuSubroutines.cpp', 'WiimoteEmu/Encryption.cpp', 'WiimoteEmu/Speaker.cpp', + 'WiimoteReal/WiimoteReal.cpp', 'WiimoteNew.cpp', + 'WiimoteConfigDiag.cpp', ] wiinewenv.Append( diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.cpp new file mode 100644 index 0000000000..848fec8b84 --- /dev/null +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.cpp @@ -0,0 +1,114 @@ + +#include "WiimoteConfigDiag.h" +#include "WiimoteReal/WiimoteReal.h" + +#define _connect_macro_(b, f, c, s) (b)->Connect(wxID_ANY, (c), wxCommandEventHandler( f ), (wxObject*)0, (wxEvtHandler*)s) + +WiimoteConfigPage::WiimoteConfigPage(wxWindow* const parent, const int index) + : wxNotebookPage(parent, -1, wxDefaultPosition, wxDefaultSize) + , m_index(index) +{ + // input source + m_input_src_choice = new wxChoice(this, -1, wxDefaultPosition); + m_input_src_choice->Append(wxT("None")); + m_input_src_choice->Append(wxT("Emulated Wiimote")); + m_input_src_choice->Append(wxT("Real Wiimote")); + m_input_src_choice->Select(g_wiimote_sources[m_index]); + _connect_macro_(m_input_src_choice, WiimoteConfigPage::SelectSource, wxEVT_COMMAND_CHOICE_SELECTED, this); + + wxStaticBoxSizer* const input_src_sizer = new wxStaticBoxSizer(wxHORIZONTAL, this, wxT("Input Source")); + input_src_sizer->Add(m_input_src_choice, 1, wxEXPAND | wxALL, 5); + + // emulated wiimote + wxButton* const configure_wiimote_emu_btn = new wxButton(this, -1, wxT("Configure")); + wxStaticBoxSizer* const wiimote_emu_sizer = new wxStaticBoxSizer(wxHORIZONTAL, this, wxT("Emulated Wiimote")); + wiimote_emu_sizer->Add(configure_wiimote_emu_btn, 1, wxEXPAND | wxALL, 5); + _connect_macro_(configure_wiimote_emu_btn, WiimoteConfigDiag::ConfigEmulatedWiimote, wxEVT_COMMAND_BUTTON_CLICKED, parent->GetParent()); + + // real wiimote + m_connected_wiimotes_txt = new wxStaticText(this, -1, wxEmptyString); + wxStaticBoxSizer* const wiimote_real_sizer = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Real Wiimote")); + wxButton* const refresh_btn = new wxButton(this, -1, wxT("Refresh"), wxDefaultPosition); + _connect_macro_(refresh_btn, WiimoteConfigPage::RefreshRealWiimotes, wxEVT_COMMAND_BUTTON_CLICKED, this); + + wiimote_real_sizer->Add(m_connected_wiimotes_txt, 1, wxALIGN_CENTER | wxALL, 5); + wiimote_real_sizer->Add(refresh_btn, 1, wxALIGN_CENTER | wxALL, 5); + + m_connected_wiimotes_txt->SetLabel(wxString(wxT("Connected to ")) + wxChar(wxT('0') + WiimoteReal::Initialize()) + wxT(" Real Wiimotes")); + + // sizers + wxBoxSizer* const left_sizer = new wxBoxSizer(wxVERTICAL); + left_sizer->Add(input_src_sizer, 1, wxEXPAND | wxBOTTOM, 5); + left_sizer->Add(wiimote_emu_sizer, 1, wxEXPAND, 0); + + wxBoxSizer* const main_sizer = new wxBoxSizer(wxHORIZONTAL); + main_sizer->Add(left_sizer, 1, wxLEFT | wxTOP | wxBOTTOM | wxEXPAND, 5); + main_sizer->Add(wiimote_real_sizer, 1, wxALL | wxEXPAND, 5); + + SetSizerAndFit(main_sizer); + Layout(); +} + +WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin) + : wxDialog(parent, -1, wxT("Dolphin Wiimote Configuration"), wxDefaultPosition, wxDefaultSize) + , m_plugin(plugin) +{ + m_pad_notebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize, wxNB_DEFAULT); + for (unsigned int i = 0; i < 4; ++i) + { + WiimoteConfigPage* const wpage = new WiimoteConfigPage(m_pad_notebook, i); + //m_padpages.push_back(wpage); + m_pad_notebook->AddPage(wpage, wxString(wxT("Wiimote ")) + wxChar('1'+i)); + } + + wxButton* const ok_button = new wxButton(this, -1, wxT("OK"), wxDefaultPosition); + _connect_macro_(ok_button, WiimoteConfigDiag::Save, wxEVT_COMMAND_BUTTON_CLICKED, this); + + wxBoxSizer* const main_sizer = new wxBoxSizer(wxVERTICAL); + main_sizer->Add(m_pad_notebook, 1, wxEXPAND | wxALL, 5); + main_sizer->Add(ok_button, 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 5); + + SetSizerAndFit(main_sizer); + + Center(); +} + +void WiimoteConfigDiag::ConfigEmulatedWiimote(wxCommandEvent& event) +{ + InputConfigDialog* const m_emu_config_diag = new InputConfigDialog(this, m_plugin, "Dolphin Emulated Wiimote Configuration", m_pad_notebook->GetSelection()); + m_emu_config_diag->ShowModal(); + m_emu_config_diag->Destroy(); +} + +void WiimoteConfigPage::RefreshRealWiimotes(wxCommandEvent& event) +{ + WiimoteReal::Refresh(); + m_connected_wiimotes_txt->SetLabel(wxString(wxT("Connected to ")) + wxChar(wxT('0') + WiimoteReal::Initialize()) + wxT(" Real Wiimotes")); +} + +void WiimoteConfigPage::SelectSource(wxCommandEvent& event) +{ + // should be kinda fine, maybe should just set when user clicks OK, w/e change it later + g_wiimote_sources[m_index] = m_input_src_choice->GetSelection(); +} + +void WiimoteConfigDiag::Save(wxCommandEvent& event) +{ + std::string ini_filename = (std::string(File::GetUserPath(D_CONFIG_IDX)) + g_plugin.ini_name + ".ini" ); + + IniFile inifile; + inifile.Load(ini_filename); + + for (unsigned int i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ConfigDiag.h" + +class WiimoteConfigPage : public wxNotebookPage +{ +public: + WiimoteConfigPage(wxWindow* const parent, const int index); + + void RefreshRealWiimotes(wxCommandEvent& event); + void SelectSource(wxCommandEvent& event); + +private: + const int m_index; + + wxStaticText* m_connected_wiimotes_txt; + wxChoice* m_input_src_choice; +}; + +class WiimoteConfigDiag : public wxDialog +{ +public: + WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin); + + void ConfigEmulatedWiimote(wxCommandEvent& event); + void Save(wxCommandEvent& event); + +private: + InputPlugin& m_plugin; + + wxNotebook* m_pad_notebook; + +}; + + +#endif \ No newline at end of file diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteNew.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteNew.cpp index 308fb92d98..2314d1f9df 100644 --- a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteNew.cpp +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteNew.cpp @@ -2,6 +2,9 @@ #include "Common.h" #include "pluginspecs_wiimote.h" +#include "WiimoteConfigDiag.h" +#include "WiimoteReal/WiimoteReal.h" + #include "ControllerInterface/ControllerInterface.h" #include "WiimoteEmu/WiimoteEmu.h" @@ -32,7 +35,7 @@ #endif // plugin globals -static InputPlugin g_plugin( "WiimoteNew", "Wiimote", "Wiimote" ); +InputPlugin g_plugin( "WiimoteNew", "Wiimote", "Wiimote" ); SWiimoteInitialize g_WiimoteInitialize; #ifdef _WIN32 @@ -90,7 +93,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) void DeInitPlugin() { - if ( g_plugin.controller_interface.IsInit() ) + if (g_plugin.controller_interface.IsInit()) { std::vector::const_iterator i = g_plugin.controllers.begin(), @@ -102,13 +105,16 @@ void DeInitPlugin() // true parameter to make SDL not quit in the wiimote plugin, // the old wiimote plugin uses this hack as well, to prevent crash on stop g_plugin.controller_interface.DeInit(true); + + // real wiimotes + WiimoteReal::Shutdown(); } } // if plugin isn't initialized, init and load config void InitPlugin( void* const hwnd ) { - if ( false == g_plugin.controller_interface.IsInit() ) + if (false == g_plugin.controller_interface.IsInit()) { // add 4 wiimotes for ( unsigned int i = 0; i<4; ++i ) @@ -118,15 +124,18 @@ void InitPlugin( void* const hwnd ) g_plugin.LoadConfig(); // needed for Xlib and exclusive dinput - g_plugin.controller_interface.SetHwnd( hwnd ); + g_plugin.controller_interface.SetHwnd(hwnd); g_plugin.controller_interface.Init(); // update control refs - std::vector::const_iterator i = g_plugin.controllers.begin(), + std::vector::const_iterator + i = g_plugin.controllers.begin(), e = g_plugin.controllers.end(); for ( ; i!=e; ++i ) (*i)->UpdateReferences( g_plugin.controller_interface ); + // real wiimotes + WiimoteReal::Initialize(); } } @@ -141,8 +150,15 @@ void InitPlugin( void* const hwnd ) // void Wiimote_ControlChannel(int _number, u16 _channelID, const void* _pData, u32 _Size) { - //PanicAlert( "Wiimote_ControlChannel" ); - ((WiimoteEmu::Wiimote*)g_plugin.controllers[ _number ])->ControlChannel( _channelID, _pData, _Size ); + switch (g_wiimote_sources[_number]) + { + case WIIMOTE_SRC_REAL : + WiimoteReal::ControlChannel(_number, _channelID, _pData, _Size); + break; + case WIIMOTE_SRC_EMU : + ((WiimoteEmu::Wiimote*)g_plugin.controllers[ _number ])->ControlChannel( _channelID, _pData, _Size ); + break; + } } // __________________________________________________________________________________________________ @@ -176,8 +192,15 @@ unsigned int Wiimote_UnPairWiimotes(void) // void Wiimote_InterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size) { - //PanicAlert( "Wiimote_InterruptChannel" ); - ((WiimoteEmu::Wiimote*)g_plugin.controllers[ _number ])->InterruptChannel( _channelID, _pData, _Size ); + switch (g_wiimote_sources[_number]) + { + case WIIMOTE_SRC_REAL : + WiimoteReal::InterruptChannel(_number, _channelID, _pData, _Size); + break; + case WIIMOTE_SRC_EMU : + ((WiimoteEmu::Wiimote*)g_plugin.controllers[ _number ])->InterruptChannel( _channelID, _pData, _Size ); + break; + } } // __________________________________________________________________________________________________ @@ -202,7 +225,15 @@ void Wiimote_Update(int _number) } _last_number = _number; - ((WiimoteEmu::Wiimote*)g_plugin.controllers[ _number ])->Update(); + switch (g_wiimote_sources[_number]) + { + case WIIMOTE_SRC_REAL : + WiimoteReal::Update(_number); + break; + case WIIMOTE_SRC_EMU : + ((WiimoteEmu::Wiimote*)g_plugin.controllers[ _number ])->Update(); + break; + } g_plugin.controls_crit.Leave(); } @@ -250,11 +281,9 @@ void GetDllInfo(PLUGIN_INFO* _pPluginInfo) void DllConfig(HWND _hParent) { #if defined(HAVE_WX) && HAVE_WX - bool was_init = false; + const bool was_init = g_plugin.controller_interface.IsInit(); - if ( g_plugin.controller_interface.IsInit() ) // hack for showing dialog when game isnt running - was_init = true; - else + if (false == was_init) { #if defined(HAVE_X11) && HAVE_X11 Window win = GDK_WINDOW_XID(GTK_WIDGET(_hParent)->window); @@ -266,9 +295,9 @@ void DllConfig(HWND _hParent) #endif } - // copied from GCPad wxWindow *frame = GetParentedWxWindow(_hParent); - InputConfigDialog* m_ConfigFrame = new InputConfigDialog(frame, g_plugin, PLUGIN_FULL_NAME); + WiimoteConfigDiag* const m_ConfigFrame = new WiimoteConfigDiag(frame, g_plugin); + //InputConfigDialog* const m_ConfigFrame = new InputConfigDialog(frame, g_plugin, PLUGIN_FULL_NAME); #ifdef _WIN32 frame->Disable(); @@ -279,17 +308,16 @@ void DllConfig(HWND _hParent) #endif #ifdef _WIN32 - wxMilliSleep( 50 ); // hooray for hacks + wxMilliSleep(50); // hooray for hacks frame->SetFocus(); frame->SetHWND(NULL); #endif m_ConfigFrame->Destroy(); - m_ConfigFrame = NULL; frame->Destroy(); // / - if ( false == was_init ) + if (false == was_init) DeInitPlugin(); #endif } @@ -350,9 +378,11 @@ void Shutdown(void) // void DoState(unsigned char **ptr, int mode) { - PointerWrap p(ptr, mode); - for (unsigned int i=0; i<4; ++i) - ((WiimoteEmu::Wiimote*)g_plugin.controllers[i])->DoState(p); + // TODO: this + + //PointerWrap p(ptr, mode); + //for (unsigned int i=0; i<4; ++i) + // ((WiimoteEmu::Wiimote*)g_plugin.controllers[i])->DoState(p); } // ___________________________________________________________________________ @@ -364,4 +394,5 @@ void DoState(unsigned char **ptr, int mode) void EmuStateChange(PLUGIN_EMUSTATE newState) { // maybe use this later + WiimoteReal::StateChange(newState); } diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp new file mode 100644 index 0000000000..393f660e88 --- /dev/null +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp @@ -0,0 +1,392 @@ +// 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 "Common.h" +#include "IniFile.h" +#include "Thread.h" +#include "StringUtil.h" +#include "Timer.h" +#include "pluginspecs_wiimote.h" + +#include "wiiuse.h" +#include "WiimoteReal.h" + +#include "../WiimoteEmu/WiimoteHid.h" + +unsigned int g_wiimote_sources[MAX_WIIMOTES]; + +namespace WiimoteReal +{ + +bool g_real_wiimotes_initialized = false; +wiimote_t** g_wiimotes_from_wiiuse = NULL; +unsigned int g_wiimotes_found = 0; + +volatile bool g_run_wiimote_thread = false; +Common::Thread *g_wiimote_thread = NULL; +Common::CriticalSection g_wiimote_critsec; + +THREAD_RETURN WiimoteThreadFunc(void* arg); + +// silly, copying data n stuff, o well, don't use this too often +void SendPacket(wiimote_t* const wm, const u8 rpt_id, const void* const data, const unsigned int size) +{ + u8* const rpt = new u8[size + 2]; + rpt[0] = 0xA1; + rpt[1] = rpt_id; + memcpy(rpt + 2, data, size); + wiiuse_io_write(wm, (byte*)rpt, size + 2); + delete[] rpt; +} + +class Wiimote +{ +public: + Wiimote(wiimote_t* const wm, const unsigned int index); + ~Wiimote(); + + void ControlChannel(const u16 channel, const void* const data, const u32 size); + void InterruptChannel(const u16 channel, const void* const data, const u32 size); + void Update(); + + void Read(); + + void Disconnect(); + +private: + void ClearReports(); + + wiimote_t* const m_wiimote; + const unsigned int m_index; + + u16 m_channel; + u8 m_last_data_report[MAX_PAYLOAD]; + bool m_last_data_report_valid; + + std::queue m_reports; +}; + +Wiimote::Wiimote(wiimote_t* const wm, const unsigned int index) + : m_wiimote(wm) + , m_index(index) + , m_channel(0) + , m_last_data_report_valid(false) +{ + { + // disable reporting + wm_report_mode rpt = wm_report_mode(); + rpt.mode = WM_REPORT_CORE; + SendPacket(m_wiimote, WM_REPORT_MODE, &rpt, sizeof(rpt)); + } + + // clear all msgs, silly maybe + while (wiiuse_io_read(m_wiimote)); + + { + // request status, will be sent to game on start + wm_request_status rpt = wm_request_status(); + SendPacket(m_wiimote, WM_REQUEST_STATUS, &rpt, sizeof(rpt)); + } + + //{ + // LEDs test + //wm_leds rpt = wm_leds(); + //rpt.leds = 1 << i; + //SendPacket(g_wiimotes_from_wiiuse[i], WM_LEDS, &rpt, sizeof(rpt)); + //} + + // set LEDs + wiiuse_set_leds(m_wiimote, WIIMOTE_LED_1 << m_index); +} + +Wiimote::~Wiimote() +{ + ClearReports(); + + // send disconnect message to wii, maybe, i hope, naw shit messes up on emu-stop + //if (g_WiimoteInitialize.pWiimoteInterruptChannel) + //{ + // //u8* const rpt = new u8[2]; + // //rpt[0] = 0XA1; rpt[1] = 0x15; + // //m_reports.push(rpt); + // //Update(); + + // const u8 rpt[] = { 0xA1, 0x15 }; + // g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_channel, rpt, sizeof(rpt)); + //} +} + +void Wiimote::ClearReports() +{ + while (m_reports.size()) + { + delete[] m_reports.front(); + m_reports.pop(); + } +} + +void Wiimote::ControlChannel(const u16 channel, const void* const data, const u32 size) +{ + // Check for custom communication + if (99 == channel) + Disconnect(); + else + InterruptChannel(channel, data, size); +} + +void Wiimote::InterruptChannel(const u16 channel, const void* const data, const u32 size) +{ + m_channel = channel; + wiiuse_io_write(m_wiimote, (byte*)data, size); +} + +void Wiimote::Read() +{ + if (wiiuse_io_read(m_wiimote)) + { + // a data report, save it + if (m_wiimote->event_buf[1] >= 0x30) + { + memcpy(m_last_data_report, m_wiimote->event_buf, MAX_PAYLOAD - 1); + m_last_data_report_valid = true; + } + else + { + // some other report, add it to queue + u8* const rpt = new u8[MAX_PAYLOAD - 1]; + memcpy(rpt, m_wiimote->event_buf, MAX_PAYLOAD - 1); + m_reports.push(rpt); + } + } +} + +void Wiimote::Update() +{ + // do we have some queued reports + if (m_reports.size()) + { + u8* const rpt = m_reports.front(); + m_reports.pop(); + g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_channel, rpt, MAX_PAYLOAD - 1); + delete[] rpt; + } + else if (m_last_data_report_valid) + { + // otherwise send the last data report, if there is one + g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_channel, m_last_data_report, MAX_PAYLOAD - 1); + } +} + +void Wiimote::Disconnect() +{ + { + // disable reporting + wm_report_mode rpt = wm_report_mode(); + rpt.mode = WM_REPORT_CORE; + SendPacket(m_wiimote, WM_REPORT_MODE, &rpt, sizeof(rpt)); + } + + // clear queue + m_last_data_report_valid = false; + ClearReports(); + + // clear out wiiuse queue, or maybe not, silly? idk + while (wiiuse_io_read(m_wiimote)); +} + +Wiimote* g_wiimotes[4]; + +unsigned int Initialize() +{ + // return if already initialized + if (g_real_wiimotes_initialized) + return g_wiimotes_found; + + + // load realwiimote settings from inifile + { + std::string ini_filename = (std::string(File::GetUserPath(D_CONFIG_IDX)) + g_plugin.ini_name + ".ini" ); + + IniFile inifile; + inifile.Load(ini_filename); + + for (unsigned int i=0; iWaitForDeath(); + delete g_wiimote_thread; + g_wiimote_thread = NULL; + } + + g_wiimote_critsec.Enter(); // enter + + // delete wiimotes + for (unsigned int i=0; iInterruptChannel(_channelID, _pData, _Size); + + g_wiimote_critsec.Leave(); // leave +} + +void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) +{ + g_wiimote_critsec.Enter(); // enter + + if (g_wiimotes[_WiimoteNumber]) + g_wiimotes[_WiimoteNumber]->ControlChannel(_channelID, _pData, _Size); + + g_wiimote_critsec.Leave(); // leave +} + + +// Read the Wiimote once +void Update(int _WiimoteNumber) +{ + g_wiimote_critsec.Enter(); // enter + + if (g_wiimotes[_WiimoteNumber]) + g_wiimotes[_WiimoteNumber]->Update(); + + g_wiimote_critsec.Leave(); // leave +} + +void StateChange(PLUGIN_EMUSTATE newState) +{ + g_wiimote_critsec.Enter(); // enter + + // TODO: disable/enable auto reporting, maybe + + g_wiimote_critsec.Leave(); // leave +} + +THREAD_RETURN WiimoteThreadFunc(void* arg) +{ + while (g_run_wiimote_thread) + { + g_wiimote_critsec.Enter(); // enter + + for (unsigned int i=0; iRead(); + + g_wiimote_critsec.Leave(); // leave + + // hmmm, i get occasional lockups without this :/ + Common::SleepCurrentThread(1); + } + + return 0; +} + +}; // end of namespace diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.h b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.h new file mode 100644 index 0000000000..7c60ae3e68 --- /dev/null +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.h @@ -0,0 +1,56 @@ +// 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 WIIMOTE_REAL_H +#define WIIMOTE_REAL_H + +#include "wiiuse.h" +#include "ChunkFile.h" + +#include "../../InputCommon/Src/InputConfig.h" + +#define MAX_WIIMOTES 4 + +extern unsigned int g_wiimote_sources[MAX_WIIMOTES]; +extern InputPlugin g_plugin; +extern SWiimoteInitialize g_WiimoteInitialize; + +enum +{ + WIIMOTE_SRC_NONE = 0, + WIIMOTE_SRC_EMU, + WIIMOTE_SRC_REAL, +}; + +namespace WiimoteReal +{ + +unsigned int Initialize(); +void Shutdown(); +void Refresh(); + +void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size); +void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size); +void Update(int _WiimoteNumber); + +void DoState(PointerWrap &p); +void StateChange(PLUGIN_EMUSTATE newState); + +}; // WiiMoteReal + +#endif