-
Notifications
You must be signed in to change notification settings - Fork 68
/
input.go
145 lines (126 loc) · 3.7 KB
/
input.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Package input exposes the two input callbacks Poll and State needed by the
// libretro implementation. It uses GLFW to access keyboard and joypad, and
// takes care of binding and auto configuring joypads.
package input
import (
"github.com/go-gl/glfw/v3.2/glfw"
"github.com/libretro/ludo/libretro"
"github.com/libretro/ludo/notifications"
"github.com/libretro/ludo/video"
)
const numPlayers = 5
type joybinds map[bind]uint32
const btn = 0
const axis = 1
type bind struct {
kind uint32
index uint32
direction float32
threshold float32
}
type inputstate [numPlayers][ActionLast]bool
// Input state for all the players
var (
NewState inputstate // input state for the current frame
OldState inputstate // input state for the previous frame
Released inputstate // keys just released during this frame
Pressed inputstate // keys just pressed during this frame
)
// joystickCallback is triggered when a joypad is plugged.
func joystickCallback(joy int, event int) {
switch glfw.MonitorEvent(event) {
case glfw.Connected:
notifications.DisplayAndLog("Input", "Joystick #%d plugged: %s.", joy, glfw.GetJoystickName(glfw.Joystick(joy)))
case glfw.Disconnected:
notifications.DisplayAndLog("Input", "Joystick #%d unplugged.", joy)
default:
notifications.DisplayAndLog("Input", "Joystick #%d unhandled event: %d.", joy, event)
}
}
// ContextReseter is an interface to to allow reloading icons after the
// window is recreated when switching fullscreen
type ContextReseter interface {
ContextReset()
}
var vid *video.Video
var menu ContextReseter
// Init initializes the input package
func Init(v *video.Video, m ContextReseter) {
vid = v
menu = m
glfw.SetJoystickCallback(joystickCallback)
}
// Resets all retropad buttons to false
func reset(state inputstate) inputstate {
for p := range state {
for k := range state[p] {
state[p][k] = false
}
}
return state
}
// pollJoypads process joypads of all players
func pollJoypads(state inputstate) inputstate {
for p := range state {
buttonState := glfw.GetJoystickButtons(glfw.Joystick(p))
axisState := glfw.GetJoystickAxes(glfw.Joystick(p))
name := glfw.GetJoystickName(glfw.Joystick(p))
jb := joyBinds[name]
if len(buttonState) > 0 {
for k, v := range jb {
switch k.kind {
case btn:
if int(k.index) < len(buttonState) &&
glfw.Action(buttonState[k.index]) == glfw.Press {
state[p][v] = true
}
case axis:
if int(k.index) < len(axisState) &&
k.direction*axisState[k.index] > k.threshold*k.direction {
state[p][v] = true
}
}
}
}
}
return state
}
// pollKeyboard processes keyboard keys
func pollKeyboard(state inputstate) inputstate {
for k, v := range keyBinds {
if vid.Window.GetKey(k) == glfw.Press {
state[0][v] = true
}
}
return state
}
// Compute the keys pressed or released during this frame
func getPressedReleased(new inputstate, old inputstate) (inputstate, inputstate) {
for p := range new {
for k := range new[p] {
Pressed[p][k] = new[p][k] && !old[p][k]
Released[p][k] = !new[p][k] && old[p][k]
}
}
return Pressed, Released
}
// Poll calculates the input state. It is meant to be called for each frame.
func Poll() {
NewState = reset(NewState)
NewState = pollJoypads(NewState)
NewState = pollKeyboard(NewState)
Pressed, Released = getPressedReleased(NewState, OldState)
// Store the old input state for comparisions
OldState = NewState
}
// State is a callback passed to core.SetInputState
// It returns 1 if the button corresponding to the parameters is pressed
func State(port uint, device uint32, index uint, id uint) int16 {
if id >= 255 || index > 0 || device != libretro.DeviceJoypad {
return 0
}
if NewState[port][id] {
return 1
}
return 0
}