/
input.go
221 lines (191 loc) · 7.07 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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
package input
import (
"image"
internalinput "github.com/ebitenui/ebitenui/internal/input"
"github.com/hajimehoshi/ebiten/v2"
)
type CursorUpdater interface {
// Called every Update call from Ebiten
// Note that before this is called the current cursor shape is reset to DEFAULT every cycle
Update()
// Called at the beginning of every Draw call.
Draw(screen *ebiten.Image)
// Called at the end of every Draw call
AfterDraw(screen *ebiten.Image)
// MouseButtonPressed returns whether mouse button b is currently pressed.
MouseButtonPressed(b ebiten.MouseButton) bool
// MouseButtonJustPressed returns whether mouse button b has just been pressed.
// It only returns true during the first frame that the button is pressed.
MouseButtonJustPressed(b ebiten.MouseButton) bool
// CursorPosition returns the current cursor position.
// If you define a CursorPosition that doesn't align with a system cursor you will need to
// set the CursorDrawMode to Custom. This is because ebiten doesn't have a way to set the
// cursor location manually
CursorPosition() (int, int)
// Returns the image to use as the cursor
// EbitenUI by default will look for the following cursors:
// "EWResize"
// "NSResize"
// "Default"
GetCursorImage(name string) *ebiten.Image
// Returns how far from the CursorPosition to offset the cursor image.
// This is best used with cursors such as resizing.
GetCursorOffset(name string) image.Point
}
// This flag allows you to disable ebitenui's cursor management
var CursorManagementEnabled = true
var currentCursorUpdater CursorUpdater = internalinput.InputHandler
var isDefaultCursorUpdater = true
var windowSize image.Point
// If this field is updated, it will force the system cursor into Hidden mode.
// This will require you to provide at least a CURSOR_DEFAULT cursor if you wish a cursor to be drawn.
//
// EbitenUI by default will look for the following cursors:
//
// CURSOR_EWRESIZE : "Cursor_EWResize"
// CURSOR_NSRESIZE : "Cursor_NSResize"
// CURSOR_DEFAULT : "Cursor_Default"
// CURSOR_POINTER : "Cursor_Pointer"
// CURSOR_TEXT : "Cursor_Text"
// CURSOR_CROSSHAIR : "Cursor_Crosshair"
func SetCursorUpdater(cursorUpdater CursorUpdater) {
isDefaultCursorUpdater = cursorUpdater == internalinput.InputHandler
currentCursorUpdater = cursorUpdater
}
const (
CURSOR_DEFAULT = "Cursor_Default"
CURSOR_EWRESIZE = "Cursor_EWResize"
CURSOR_NSRESIZE = "Cursor_NSResize"
CURSOR_POINTER = "Cursor_Pointer"
CURSOR_TEXT = "Cursor_Text"
CURSOR_CROSSHAIR = "Cursor_Crosshair"
)
var currentCursor string = CURSOR_DEFAULT
func SetCursorShape(name string) {
currentCursor = name
}
func SetCursorImage(name string, cursorImage *ebiten.Image) {
internalinput.InputHandler.SetCursorImage(name, cursorImage, image.Point{})
}
func SetCursorImageWithOffset(name string, cursorImage *ebiten.Image, offset image.Point) {
internalinput.InputHandler.SetCursorImage(name, cursorImage, offset)
}
// MouseButtonPressed returns whether mouse button b is currently pressed.
func MouseButtonPressed(b ebiten.MouseButton) bool {
return currentCursorUpdater.MouseButtonPressed(b)
}
// MouseButtonJustPressed returns whether mouse button b has just been pressed.
// It only returns true during the first frame that the button is pressed.
func MouseButtonJustPressed(b ebiten.MouseButton) bool {
return currentCursorUpdater.MouseButtonJustPressed(b)
}
// MouseButtonPressedLayer returns whether mouse button b is currently pressed if input layer l is
// eligible to handle it.
func MouseButtonPressedLayer(b ebiten.MouseButton, l *Layer) bool {
if !MouseButtonPressed(b) {
return false
}
x, y := CursorPosition()
return l.ActiveFor(x, y, LayerEventTypeMouseButton)
}
// MouseButtonJustPressedLayer returns whether mouse button b has just been pressed if input layer l
// is eligible to handle it. It only returns true during the first frame that the button is pressed.
func MouseButtonJustPressedLayer(b ebiten.MouseButton, l *Layer) bool {
if !MouseButtonJustPressed(b) {
return false
}
x, y := CursorPosition()
return l.ActiveFor(x, y, LayerEventTypeMouseButton)
}
// CursorPosition returns the current cursor position.
func CursorPosition() (int, int) {
return currentCursorUpdater.CursorPosition()
}
// Wheel returns current mouse wheel movement.
func Wheel() (float64, float64) {
return internalinput.InputHandler.WheelX, internalinput.InputHandler.WheelY
}
// WheelLayer returns current mouse wheel movement if input layer l is eligible to handle it.
// If l is not eligible, it returns 0, 0.
func WheelLayer(l *Layer) (float64, float64) {
x, y := Wheel()
if x == 0 && y == 0 {
return 0, 0
}
cx, cy := CursorPosition()
if !l.ActiveFor(cx, cy, LayerEventTypeWheel) {
return 0, 0
}
return x, y
}
// InputChars returns user keyboard input.
func InputChars() []rune { //nolint:golint
return internalinput.InputHandler.InputChars
}
// KeyPressed returns whether key k is currently pressed.
func KeyPressed(k ebiten.Key) bool {
p, ok := internalinput.InputHandler.KeyPressed[k]
return ok && p
}
// AnyKeyPressed returns whether any key is currently pressed.
func AnyKeyPressed() bool {
return internalinput.InputHandler.AnyKeyPressed
}
// This method returns the drawable screen size whether it is fullscreen or not.
func GetWindowSize() image.Point {
return windowSize
}
func Update() {
SetCursorShape(CURSOR_DEFAULT)
currentCursorUpdater.Update()
}
func Draw(screen *ebiten.Image) {
windowSize = screen.Bounds().Max
currentCursorUpdater.Draw(screen)
}
func AfterDraw(screen *ebiten.Image) {
currentCursorUpdater.AfterDraw(screen)
if CursorManagementEnabled {
// Process Cursor
posX, posY := currentCursorUpdater.CursorPosition()
if posX < 0 || posY < 0 || posX > windowSize.X || posY > windowSize.Y {
return
}
cursorImage := currentCursorUpdater.GetCursorImage(currentCursor)
cursorOffset := currentCursorUpdater.GetCursorOffset(currentCursor)
// If we have a cursor image hide current cursor and use it
if cursorImage != nil {
if ebiten.CursorMode() != ebiten.CursorModeHidden {
ebiten.SetCursorMode(ebiten.CursorModeHidden)
}
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(float64(posX+cursorOffset.X), float64(posY+cursorOffset.Y))
screen.DrawImage(cursorImage, op)
// If we don't have an image and this is the default cursor updater
// Use the system shapes.
} else if isDefaultCursorUpdater {
switch currentCursor {
case CURSOR_DEFAULT:
ebiten.SetCursorShape(ebiten.CursorShapeDefault)
case CURSOR_EWRESIZE:
ebiten.SetCursorShape(ebiten.CursorShapeEWResize)
case CURSOR_NSRESIZE:
ebiten.SetCursorShape(ebiten.CursorShapeNSResize)
case CURSOR_TEXT:
ebiten.SetCursorShape(ebiten.CursorShapeText)
case CURSOR_CROSSHAIR:
ebiten.SetCursorShape(ebiten.CursorShapeCrosshair)
case CURSOR_POINTER:
ebiten.SetCursorShape(ebiten.CursorShapePointer)
}
if ebiten.CursorMode() != ebiten.CursorModeVisible {
ebiten.SetCursorMode(ebiten.CursorModeVisible)
}
// Otherwise hide the cursor
} else {
if ebiten.CursorMode() != ebiten.CursorModeHidden {
ebiten.SetCursorMode(ebiten.CursorModeHidden)
}
}
}
}