XInput + x360ceの使用

#XInputの特徴とか
+ 基本XBox 360のコントローラ用のライブラリ
+ キーボードやマウスを取る場合はDirectInputやWin32APIを用いる
+ デバイスが限定されている分、DirectInputと比べてかなり簡単に扱える
+ XInputに対応してないコントローラもx360ceを用いることで使えるようになる

#x360ce
[x360ce - XBOX 360 Controller emulator](https://code.google.com/p/x360ce/)
XInput対応コントローラを持っていないため確認できないが、パススルーの設定もできるためDirectInput対応コントローラとXInput対応コントローラの共存は可能な模様

##使用方法
+ x360ce Librariesと書かれたものダウンロードして中のxinput1_3.dllを実行ファイルから見えるディレクトリに配置
+ XBOX 360 Controller emulatorと書かれたものをダウンロードして中のx360ce.exeを適当な場所に配置・起動してコントローラの設定を行い、作成されたx360ce.iniをxinput1_3.dllと同じディレクトリに配置

##注意点
+ x360ce.exeから自動作成されるxinput1_3.dllをx360ce Librariesの代わりに用いると、デバッグ時にエラーを吐く
+ x360ce.ini中のInstanceGuidはPC毎にも変わるため、環境ごとに編集する必要あり
+ バイブレーションは対応してなさそう

#ラッパークラス
作ったものの正直必要ない気はする

```cpp:Joypad.h
#pragma once
#include <complex>

#ifndef STRICT
#define STRICT
#endif

#include <windows.h>
#include <XInput.h>

inline void JoypadEnable(bool enable) { XInputEnable(enable); }

class Joypad{
public:
	enum class Button{
		A = XINPUT_GAMEPAD_A,
		B = XINPUT_GAMEPAD_B,
		X = XINPUT_GAMEPAD_X,
		Y = XINPUT_GAMEPAD_Y,
		Up = XINPUT_GAMEPAD_DPAD_UP,
		Down = XINPUT_GAMEPAD_DPAD_DOWN,
		Left = XINPUT_GAMEPAD_DPAD_LEFT,
		Right = XINPUT_GAMEPAD_DPAD_RIGHT,
		Start = XINPUT_GAMEPAD_START,
		Back = XINPUT_GAMEPAD_BACK,
		LThumb = XINPUT_GAMEPAD_LEFT_THUMB,
		RThumb = XINPUT_GAMEPAD_RIGHT_THUMB,
		LShoulder = XINPUT_GAMEPAD_LEFT_SHOULDER,
		RShoulder = XINPUT_GAMEPAD_RIGHT_SHOULDER
	};

	Joypad(int userIndex) : m_UserIndex(userIndex) {}

	bool update();
	bool isPushed(Button button);
	bool vibrate(double leftMotorSpeedByPercent, double rightMotorSpeedByPercent);
	bool isConnected();
	double getLTrigger(double thresholdByPercent = XINPUT_GAMEPAD_TRIGGER_THRESHOLD / (double)TriggerMax);
	double getRTrigger(double thresholdByPercent = XINPUT_GAMEPAD_TRIGGER_THRESHOLD / (double)TriggerMax);
	std::complex<double> getLStick(double thresholdByPercent = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE / (double)StickMax);
	std::complex<double> getRStick(double thresholdByPercent = XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE / (double)StickMax);
	int getUserIndex();
private:
	static const long TriggerMax = 255;
	static const long MotorSpeedMax = 65535;
	static const long StickMax = 32767;

	int m_UserIndex;
	XINPUT_STATE m_State;
	bool m_Connected;
};
```

```cpp:Joypad.cpp
#include "Joypad.h"

#include <algorithm>
#pragma comment(lib, "Xinput.lib")



bool Joypad::isPushed(Button button) {
	return isConnected() && (m_State.Gamepad.wButtons & static_cast<int>(button));
}

bool Joypad::isConnected() {
	return m_Connected;
}

bool Joypad::update() {
	m_Connected = (XInputGetState(m_UserIndex, &m_State) == ERROR_SUCCESS);
	return m_Connected;
}

int Joypad::getUserIndex() {
	return m_UserIndex;
}

std::complex<double> Joypad::getLStick(double thresholdByPercent) {
	if (!isConnected()) return std::complex<double>(0, 0);
	auto y_abs = std::abs(m_State.Gamepad.sThumbLY) / (double)StickMax; // 負の割り算は処理系定義な為
	auto y_sign = (m_State.Gamepad.sThumbLY < 0) ? -1 : 1;
	auto x_abs = std::abs(m_State.Gamepad.sThumbLX) / (double)StickMax;
	auto x_sign = (m_State.Gamepad.sThumbLX < 0) ? -1 : 1;

	return std::complex<double>(
		(x_abs < thresholdByPercent) ? 0 : x_abs * x_sign,
		(y_abs < thresholdByPercent) ? 0 : y_abs * y_sign
		);
}

std::complex<double> Joypad::getRStick(double thresholdByPercent) {
	if (!isConnected()) return std::complex<double>(0, 0);
	auto y_abs = std::abs(m_State.Gamepad.sThumbRY) / (double)StickMax;
	auto y_sign = (m_State.Gamepad.sThumbRY < 0) ? -1 : 1;
	auto x_abs = std::abs(m_State.Gamepad.sThumbRX) / (double)StickMax;
	auto x_sign = (m_State.Gamepad.sThumbRX < 0) ? -1 : 1;

	return std::complex<double>(
		(x_abs < thresholdByPercent) ? 0 : x_abs * x_sign,
		(y_abs < thresholdByPercent) ? 0 : y_abs * y_sign
	);
}

double Joypad::getLTrigger(double thresholdByPercent) {
	if (!isConnected()) return 0;
	auto t = m_State.Gamepad.bLeftTrigger / (double)TriggerMax;
	return (t < thresholdByPercent) ? 0 : t;
}

double Joypad::getRTrigger(double thresholdByPercent) {
	if (!isConnected()) return 0;
	auto t = m_State.Gamepad.bLeftTrigger / (double)TriggerMax;
	return (t < thresholdByPercent) ? 0 : t;
}

bool Joypad::vibrate(double leftMotorSpeedByPercent, double rightMotorSpeedByPercent) {
	XINPUT_VIBRATION vib;
	vib.wLeftMotorSpeed = leftMotorSpeedByPercent * MotorSpeedMax;
	vib.wRightMotorSpeed = rightMotorSpeedByPercent * MotorSpeedMax;
	return XInputSetState(m_UserIndex, &vib) == ERROR_SUCCESS;
}
```