retro-gamepad.vala 2.99 KB
Newer Older
1
// This file is part of GNOME Games. License: GPL-3.0+.
Megh Parikh's avatar
Megh Parikh committed
2

3
private class Games.RetroGamepad : Object, Retro.Controller {
4
	public Manette.Device device { get; construct; }
5
	public bool present_analog_sticks { get; construct; }
Megh Parikh's avatar
Megh Parikh committed
6 7 8

	private bool[] buttons;
	private int16[] axes;
9
	private uint16 rumble_effect[2];
Megh Parikh's avatar
Megh Parikh committed
10

11 12
	public RetroGamepad (Manette.Device device, bool present_analog_sticks) {
		Object (device: device, present_analog_sticks: present_analog_sticks);
Megh Parikh's avatar
Megh Parikh committed
13 14 15
	}

	construct {
16 17
		buttons = new bool[EventCode.KEY_MAX + 1];
		axes = new int16[EventCode.ABS_MAX + 1];
Megh Parikh's avatar
Megh Parikh committed
18

19 20 21
		device.button_press_event.connect (on_button_press_event);
		device.button_release_event.connect (on_button_release_event);
		device.absolute_axis_event.connect (on_absolute_axis_event);
Megh Parikh's avatar
Megh Parikh committed
22 23 24 25
	}

	public void poll () {}

26 27
	public int16 get_input_state (Retro.Input input) {
		switch (input.get_controller_type ()) {
28
		case Retro.ControllerType.JOYPAD:
29 30 31 32 33
			Retro.JoypadId id;
			if (!input.get_joypad (out id))
				return 0;

			return get_button_pressed (id) ? int16.MAX : 0;
34
		case Retro.ControllerType.ANALOG:
35 36 37 38 39 40
			Retro.AnalogId id;
			Retro.AnalogIndex index;
			if (!input.get_analog (out id, out index))
				return 0;

			return get_analog_value (index, id);
Megh Parikh's avatar
Megh Parikh committed
41 42 43 44 45
		default:
			return 0;
		}
	}

46
	public Retro.ControllerType get_controller_type () {
47
		if (present_analog_sticks)
48
			return Retro.ControllerType.ANALOG;
49

50
		return Retro.ControllerType.JOYPAD;
Megh Parikh's avatar
Megh Parikh committed
51 52
	}

53 54
	public uint64 get_capabilities () {
		return (1 << Retro.ControllerType.JOYPAD) | (1 << Retro.ControllerType.ANALOG);
Megh Parikh's avatar
Megh Parikh committed
55 56
	}

57
	public bool set_rumble_state (Retro.RumbleEffect effect, uint16 strength) {
58 59 60 61 62 63 64 65 66 67
		rumble_effect[effect] = strength;

		if (!device.has_rumble ())
			return false;

		device.rumble (rumble_effect[Retro.RumbleEffect.STRONG],
		               rumble_effect[Retro.RumbleEffect.WEAK],
		               uint16.MAX);

		return true;
68 69
	}

70
	private bool get_button_pressed (Retro.JoypadId button) {
71 72 73
		var button_code = button.to_button_code ();

		return button_code != EventCode.EV_MAX && buttons[button_code];
Megh Parikh's avatar
Megh Parikh committed
74 75
	}

76
	private int16 get_analog_value (Retro.AnalogIndex index, Retro.AnalogId id) {
Megh Parikh's avatar
Megh Parikh committed
77 78 79 80
		switch (index) {
		case Retro.AnalogIndex.LEFT:
			switch (id) {
			case Retro.AnalogId.X:
81
				return axes[EventCode.ABS_X];
Megh Parikh's avatar
Megh Parikh committed
82
			case Retro.AnalogId.Y:
83
				return axes[EventCode.ABS_Y];
Megh Parikh's avatar
Megh Parikh committed
84 85 86 87 88 89
			default:
				return 0;
			}
		case Retro.AnalogIndex.RIGHT:
			switch (id) {
			case Retro.AnalogId.X:
90
				return axes[EventCode.ABS_RX];
Megh Parikh's avatar
Megh Parikh committed
91
			case Retro.AnalogId.Y:
92
				return axes[EventCode.ABS_RY];
Megh Parikh's avatar
Megh Parikh committed
93 94 95 96 97 98 99
			default:
				return 0;
			}
		default:
			return 0;
		}
	}
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121

	private void on_button_press_event (Manette.Event event) {
		uint16 button;

		if (event.get_button (out button))
			buttons[button] = true;
	}

	private void on_button_release_event (Manette.Event event) {
		uint16 button;

		if (event.get_button (out button))
			buttons[button] = false;
	}

	private void on_absolute_axis_event (Manette.Event event) {
		uint16 axis;
		double value;

		if (event.get_absolute (out axis, out value))
			axes[axis] = (int16) (value * int16.MAX);
	}
Megh Parikh's avatar
Megh Parikh committed
122
}