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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
package ui
import (
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/inpututil"
"muhq.space/muhqs-game/go/log"
)
// InputType distinguishes the different supported kinds of input.
type InputType int
const (
// Click represents a mouse click.
Click InputType = iota + 1
// Scroll represents a mouse wheel event.
Scroll
// Text represents any keyboard input.
Text
// Tap represents a short touch input.
Tap
// Pan represents a longer moving touch input.
Pan
// Pinch represents a moving multi touch input.
Pinch
// HoverStart represents the start of a hover input.
HoverStart
// HoverEnd represents the end of a hover input.
HoverEnd
// Longtap represents a longer touch input.
Longtap
)
func (it InputType) String() string {
switch it {
case Click:
return "Click"
case Scroll:
return "Scroll"
case Text:
return "Text"
case Tap:
return "Tap"
case Pan:
return "Pan"
case Pinch:
return "Pinch"
case HoverStart:
return "HoverStart"
case HoverEnd:
return "HoverEnd"
case Longtap:
return "Longtap"
}
log.Panic("unexausted InputType switch")
return ""
}
// InputEvent contains all information associated with an occurred user input.
type InputEvent struct {
Kind InputType
// X and Y coordinates the event occured.
X, Y int
// Ctx contains additional information for the event.
Ctx any
}
// ClickCtx contains the pressed mouse button.
type ClickCtx struct {
Btn ebiten.MouseButton
}
// DistanceCtx contains the input's distance.
// Scroll and Pan events contain a DistanceCtx.
type DistanceCtx struct {
scrollX, scrollY int
}
// TextCtx contains the inputted runes.
type TextCtx struct {
in []rune
}
// Input contains all occurred input events since the last call to ui.Update.
// The input events should be handled in reverse order to prevent modify during iteration errors.
var Input []InputEvent
// ConsumeInput removes the i-ths input from the quehe.
func ConsumeInput(i int) {
if len(Input) == 1 {
Input = []InputEvent{}
} else {
Input[i] = Input[len(Input)-1]
}
}
// AppendInput appends an input event to the input queue.
func AppendInput(ev InputEvent) {
log.Debug("append input event", "event", ev)
Input = append(Input, ev)
}
// Update all ui singletons and collect all occurred input.
func Update() error {
Input = []InputEvent{}
if err := TouchManager.Update(); err != nil {
return err
}
var hoverEv InputEvent
var hoverChange bool
if len(TouchManager.taps) > 0 || TouchManager.pan != nil || TouchManager.pinch != nil {
hoverEv, hoverChange = longtapHoverDetector.reset()
if hoverChange {
AppendInput(hoverEv)
}
}
for _, tap := range TouchManager.taps {
AppendInput(InputEvent{Tap, tap.x, tap.y, nil})
}
if TouchManager.pan != nil {
pan := TouchManager.pan
iX, iY := pan.Incremental()
AppendInput(InputEvent{Pan, pan.originX, pan.originY, DistanceCtx{int(iX) / 10, int(iY) / 10}})
}
hoverEv, hoverChange = longtapHoverDetector.update(TouchManager.longtap)
if hoverChange {
AppendInput(hoverEv)
}
// TODO: handle pinching
if TouchManager.pinch != nil {
}
x, y := ebiten.CursorPosition()
hoverEv, hoverChange = hoverDetector.update(x, y)
if hoverChange {
AppendInput(hoverEv)
}
scrollX, scrollY := ebiten.Wheel()
if scrollX != 0 || scrollY != 0 {
AppendInput(InputEvent{Scroll, x, y, DistanceCtx{int(scrollX), int(scrollY)}})
}
var in []rune
in = ebiten.AppendInputChars(in)
if len(in) > 0 {
AppendInput(InputEvent{Text, x, y, TextCtx{in}})
}
if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
AppendInput(InputEvent{Click, x, y, ClickCtx{ebiten.MouseButtonLeft}})
}
return nil
}
|