예제 #1
0
bool Joystick::openGamepad(int deviceindex)
{
	if (!SDL_IsGameController(deviceindex))
		return false;

	if (isGamepad())
	{
		SDL_GameControllerClose(controller);
		controller = nullptr;
	}

	controller = SDL_GameControllerOpen(deviceindex);
	return isGamepad();
}
예제 #2
0
Joystick::JoystickInput Joystick::getGamepadMapping(const GamepadInput &input) const
{
	Joystick::JoystickInput jinput;
	jinput.type = INPUT_TYPE_MAX_ENUM;

	if (!isGamepad())
		return jinput;

	SDL_GameControllerButtonBind sdlbind = {};
	sdlbind.bindType = SDL_CONTROLLER_BINDTYPE_NONE;

	SDL_GameControllerButton sdlbutton;
	SDL_GameControllerAxis sdlaxis;

	switch (input.type)
	{
	case INPUT_TYPE_BUTTON:
		if (getConstant(input.button, sdlbutton))
			sdlbind = SDL_GameControllerGetBindForButton(controller, sdlbutton);
		break;
	case INPUT_TYPE_AXIS:
		if (getConstant(input.axis, sdlaxis))
			sdlbind = SDL_GameControllerGetBindForAxis(controller, sdlaxis);
		break;
	default:
		break;
	}

	switch (sdlbind.bindType)
	{
	case SDL_CONTROLLER_BINDTYPE_BUTTON:
		jinput.type = INPUT_TYPE_BUTTON;
		jinput.button = sdlbind.value.button;
		break;
	case SDL_CONTROLLER_BINDTYPE_AXIS:
		jinput.type = INPUT_TYPE_AXIS;
		jinput.axis = sdlbind.value.axis;
		break;
	case SDL_CONTROLLER_BINDTYPE_HAT:
		if (getConstant(sdlbind.value.hat.hat_mask, jinput.hat.value))
		{
			jinput.type = INPUT_TYPE_HAT;
			jinput.hat.index = sdlbind.value.hat.hat;
		}
		break;
	case SDL_CONTROLLER_BINDTYPE_NONE:
	default:
		break;
	}

	return jinput;
}
예제 #3
0
float Joystick::getGamepadAxis(love::joystick::Joystick::GamepadAxis axis) const
{
	if (!isConnected() || !isGamepad())
		return 0.f;

	SDL_GameControllerAxis sdlaxis;
	if (!getConstant(axis, sdlaxis))
		return 0.f;

	Sint16 value = SDL_GameControllerGetAxis(controller, sdlaxis);

	return clampval((float) value / 32768.0f);
}
예제 #4
0
bool Joystick::isGamepadDown(const std::vector<GamepadButton> &blist) const
{
	if (!isConnected() || !isGamepad())
		return false;

	SDL_GameControllerButton sdlbutton;

	for (GamepadButton button : blist)
	{
		if (!getConstant(button, sdlbutton))
			continue;

		if (SDL_GameControllerGetButton(controller, sdlbutton) == 1)
			return true;
	}

	return false;
}
예제 #5
0
bool Joystick::isVibrationSupported()
{
	if (!checkCreateHaptic())
		return false;

	unsigned int features = SDL_HapticQuery(haptic);

	if ((features & SDL_HAPTIC_LEFTRIGHT) != 0)
		return true;

	// Some gamepad drivers only support left/right motors via a custom effect.
	if (isGamepad() && (features & SDL_HAPTIC_CUSTOM) != 0)
		return true;

	// Test for simple sine wave support as a last resort.
	if ((features & SDL_HAPTIC_SINE) != 0)
		return true;

	return false;
}
예제 #6
0
bool Joystick::setVibration(float left, float right, float duration)
{
	left = std::min(std::max(left, 0.0f), 1.0f);
	right = std::min(std::max(right, 0.0f), 1.0f);

	if (left == 0.0f && right == 0.0f)
		return setVibration();

	if (!checkCreateHaptic())
		return false;

	Uint32 length = SDL_HAPTIC_INFINITY;
	if (duration >= 0.0f)
	{
		float maxduration = std::numeric_limits<Uint32>::max() / 1000.0f;
		length = Uint32(std::min(duration, maxduration) * 1000);
	}

	bool success = false;
	unsigned int features = SDL_HapticQuery(haptic);
	int axes = SDL_HapticNumAxes(haptic);

	if ((features & SDL_HAPTIC_LEFTRIGHT) != 0)
	{
		memset(&vibration.effect, 0, sizeof(SDL_HapticEffect));
		vibration.effect.type = SDL_HAPTIC_LEFTRIGHT;

		vibration.effect.leftright.length = length;
		vibration.effect.leftright.large_magnitude = Uint16(left * LOVE_UINT16_MAX);
		vibration.effect.leftright.small_magnitude = Uint16(right * LOVE_UINT16_MAX);

		success = runVibrationEffect();
	}

	// Some gamepad drivers only give support for controlling individual motors
	// through a custom FF effect.
	if (!success && isGamepad() && (features & SDL_HAPTIC_CUSTOM) && axes == 2)
	{
		// NOTE: this may cause issues with drivers which support custom effects
		// but aren't similar to https://github.com/d235j/360Controller .

		// Custom effect data is clamped to 0x7FFF in SDL.
		vibration.data[0] = vibration.data[2] = Uint16(left * 0x7FFF);
		vibration.data[1] = vibration.data[3] = Uint16(right * 0x7FFF);

		memset(&vibration.effect, 0, sizeof(SDL_HapticEffect));
		vibration.effect.type = SDL_HAPTIC_CUSTOM;

		vibration.effect.custom.length = length;
		vibration.effect.custom.channels = 2;
		vibration.effect.custom.period = 10;
		vibration.effect.custom.samples = 2;
		vibration.effect.custom.data = vibration.data;

		success = runVibrationEffect();
	}

	// Fall back to a simple sine wave if all else fails. This only supports a
	// single strength value.
	if (!success && (features & SDL_HAPTIC_SINE) != 0)
	{
		memset(&vibration.effect, 0, sizeof(SDL_HapticEffect));
		vibration.effect.type = SDL_HAPTIC_SINE;

		vibration.effect.periodic.length = length;
		vibration.effect.periodic.period = 10;

		float strength = std::max(left, right);
		vibration.effect.periodic.magnitude = Sint16(strength * 0x7FFF);

		success = runVibrationEffect();
	}

	if (success)
	{
		vibration.left = left;
		vibration.right = right;

		if (length == SDL_HAPTIC_INFINITY)
			vibration.endtime = SDL_HAPTIC_INFINITY;
		else
			vibration.endtime = SDL_GetTicks() + length;
	}
	else
	{
		vibration.left = vibration.right = 0.0f;
		vibration.endtime = SDL_HAPTIC_INFINITY;
	}

	return success;
}