1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-09-27 21:56:19 -04:00

Working on d2input.go for #487 (#514)

d2input/ is now clear of lint.
This commit is contained in:
Maxime Lavigne (malavv) 2020-07-01 14:03:40 -04:00 committed by GitHub
parent 0272b593fb
commit 973e969002
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 248 additions and 81 deletions

View File

@ -2,6 +2,8 @@ package d2common
import "time" import "time"
// Now returns how many seconds have elapsed since Unix time (January 1, 1970 UTC)
func Now() float64 { func Now() float64 {
// Unix time in nanoseconds divided by how many nanoseconds in a second
return float64(time.Now().UnixNano()) / 1000000000.0 return float64(time.Now().UnixNano()) / 1000000000.0
} }

View File

@ -5,18 +5,15 @@ import (
) )
var ( var (
// ErrHasReg shows the input system already has a registered handler
ErrHasReg = errors.New("input system already has provided handler") ErrHasReg = errors.New("input system already has provided handler")
// ErrNotReg shows the input system has no registered handler
ErrNotReg = errors.New("input system does not have provided handler") ErrNotReg = errors.New("input system does not have provided handler")
) )
type Priority int var singleton inputManager
const (
PriorityLow Priority = iota
PriorityDefault
PriorityHigh
)
// HandlerEvent holds the qualifiers for a key or mouse event
type HandlerEvent struct { type HandlerEvent struct {
KeyMod KeyMod KeyMod KeyMod
ButtonMod MouseButtonMod ButtonMod MouseButtonMod
@ -24,6 +21,7 @@ type HandlerEvent struct {
Y int Y int
} }
// KeyEvent represents an event associated with a keyboard key
type KeyEvent struct { type KeyEvent struct {
HandlerEvent HandlerEvent
Key Key Key Key
@ -31,74 +29,86 @@ type KeyEvent struct {
Duration int Duration int
} }
// KeyCharsEvent represents an event associated with a keyboard character being pressed
type KeyCharsEvent struct { type KeyCharsEvent struct {
HandlerEvent HandlerEvent
Chars []rune Chars []rune
} }
// KeyDownHandler represents a handler for a keyboard key pressed event
type KeyDownHandler interface {
OnKeyDown(event KeyEvent) bool
}
// KeyRepeatHandler represents a handler for a keyboard key held-down event; between a pressed and released.
type KeyRepeatHandler interface {
OnKeyRepeat(event KeyEvent) bool
}
// KeyUpHandler represents a handler for a keyboard key release event
type KeyUpHandler interface {
OnKeyUp(event KeyEvent) bool
}
// KeyCharsHandler represents a handler associated with a keyboard character pressed event
type KeyCharsHandler interface {
OnKeyChars(event KeyCharsEvent) bool
}
// MouseEvent represents a mouse event
type MouseEvent struct { type MouseEvent struct {
HandlerEvent HandlerEvent
Button MouseButton Button MouseButton
} }
// MouseEvent represents a mouse movement event
type MouseMoveEvent struct { type MouseMoveEvent struct {
HandlerEvent HandlerEvent
} }
type Handler interface{} // MouseButtonDownHandler represents a handler for a mouse button pressed event
type KeyDownHandler interface {
OnKeyDown(event KeyEvent) bool
}
type KeyRepeatHandler interface {
OnKeyRepeat(event KeyEvent) bool
}
type KeyUpHandler interface {
OnKeyUp(event KeyEvent) bool
}
type KeyCharsHandler interface {
OnKeyChars(event KeyCharsEvent) bool
}
type MouseButtonDownHandler interface { type MouseButtonDownHandler interface {
OnMouseButtonDown(event MouseEvent) bool OnMouseButtonDown(event MouseEvent) bool
} }
// MouseButtonRepeatHandler represents a handler for a mouse button held-down event; between a pressed and released.
type MouseButtonRepeatHandler interface { type MouseButtonRepeatHandler interface {
OnMouseButtonRepeat(event MouseEvent) bool OnMouseButtonRepeat(event MouseEvent) bool
} }
// MouseButtonUpHandler represents a handler for a mouse button release event
type MouseButtonUpHandler interface { type MouseButtonUpHandler interface {
OnMouseButtonUp(event MouseEvent) bool OnMouseButtonUp(event MouseEvent) bool
} }
// MouseMoveHandler represents a handler for a mouse button release event
type MouseMoveHandler interface { type MouseMoveHandler interface {
OnMouseMove(event MouseMoveEvent) bool OnMouseMove(event MouseMoveEvent) bool
} }
var singleton inputManager // Initialize creates a single global input manager based on a specific input service
func Initialize(inputService InputService) { func Initialize(inputService InputService) {
singleton = inputManager{ singleton = inputManager{
inputService: inputService, inputService: inputService,
} }
} }
// Advance moves the input manager with the elapsed number of seconds.
func Advance(elapsed float64) error { func Advance(elapsed float64) error {
return singleton.advance(elapsed) return singleton.advance(elapsed)
} }
// BindHandlerWithPriority adds an event handler with a specific call priority
func BindHandlerWithPriority(handler Handler, priority Priority) error { func BindHandlerWithPriority(handler Handler, priority Priority) error {
return singleton.bindHandler(handler, priority) return singleton.bindHandler(handler, priority)
} }
// BindHandler adds an event handler
func BindHandler(handler Handler) error { func BindHandler(handler Handler) error {
return BindHandlerWithPriority(handler, PriorityDefault) return BindHandlerWithPriority(handler, PriorityDefault)
} }
// UnbindHandler removes a previously bound event handler
func UnbindHandler(handler Handler) error { func UnbindHandler(handler Handler) error {
return singleton.unbindHandler(handler) return singleton.unbindHandler(handler)
} }

View File

@ -1,12 +1,15 @@
// Package ebiten provides graphics and input API to develop a 2D game.
package ebiten package ebiten
import ( import (
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
"github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/inpututil" "github.com/hajimehoshi/ebiten/inpututil"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
) )
var ( var (
//nolint:gochecknoglobals This is a constant in all but by name, no constant map in go
keyToEbiten = map[d2input.Key]ebiten.Key{ keyToEbiten = map[d2input.Key]ebiten.Key{
d2input.Key0: ebiten.Key0, d2input.Key0: ebiten.Key0,
d2input.Key1: ebiten.Key1, d2input.Key1: ebiten.Key1,
@ -109,6 +112,7 @@ var (
d2input.KeyControl: ebiten.KeyControl, d2input.KeyControl: ebiten.KeyControl,
d2input.KeyShift: ebiten.KeyShift, d2input.KeyShift: ebiten.KeyShift,
} }
//nolint:gochecknoglobals This is a constant in all but by name, no constant map in go
mouseButtonToEbiten = map[d2input.MouseButton]ebiten.MouseButton{ mouseButtonToEbiten = map[d2input.MouseButton]ebiten.MouseButton{
d2input.MouseButtonLeft: ebiten.MouseButtonLeft, d2input.MouseButtonLeft: ebiten.MouseButtonLeft,
d2input.MouseButtonMiddle: ebiten.MouseButtonMiddle, d2input.MouseButtonMiddle: ebiten.MouseButtonMiddle,
@ -119,38 +123,47 @@ var (
// InputService provides an abstraction on ebiten to support handling input events // InputService provides an abstraction on ebiten to support handling input events
type InputService struct{} type InputService struct{}
func (is InputService) CursorPosition() (x int, y int) { // CursorPosition returns a position of a mouse cursor relative to the game screen (window).
func (is InputService) CursorPosition() (x, y int) {
return ebiten.CursorPosition() return ebiten.CursorPosition()
} }
// InputChars return "printable" runes read from the keyboard at the time update is called.
func (is InputService) InputChars() []rune { func (is InputService) InputChars() []rune {
return ebiten.InputChars() return ebiten.InputChars()
} }
// IsKeyPressed checks if the provided key is down.
func (is InputService) IsKeyPressed(key d2input.Key) bool { func (is InputService) IsKeyPressed(key d2input.Key) bool {
return ebiten.IsKeyPressed(keyToEbiten[key]) return ebiten.IsKeyPressed(keyToEbiten[key])
} }
// IsKeyJustPressed checks if the provided key is just transitioned from up to down.
func (is InputService) IsKeyJustPressed(key d2input.Key) bool { func (is InputService) IsKeyJustPressed(key d2input.Key) bool {
return inpututil.IsKeyJustPressed(keyToEbiten[key]) return inpututil.IsKeyJustPressed(keyToEbiten[key])
} }
// IsKeyJustReleased checks if the provided key is just transitioned from down to up.
func (is InputService) IsKeyJustReleased(key d2input.Key) bool { func (is InputService) IsKeyJustReleased(key d2input.Key) bool {
return inpututil.IsKeyJustReleased(keyToEbiten[key]) return inpututil.IsKeyJustReleased(keyToEbiten[key])
} }
// IsMouseButtonPressed checks if the provided mouse button is down.
func (is InputService) IsMouseButtonPressed(button d2input.MouseButton) bool { func (is InputService) IsMouseButtonPressed(button d2input.MouseButton) bool {
return ebiten.IsMouseButtonPressed(mouseButtonToEbiten[button]) return ebiten.IsMouseButtonPressed(mouseButtonToEbiten[button])
} }
// IsMouseButtonJustPressed checks if the provided mouse button is just transitioned from up to down.
func (is InputService) IsMouseButtonJustPressed(button d2input.MouseButton) bool { func (is InputService) IsMouseButtonJustPressed(button d2input.MouseButton) bool {
return inpututil.IsMouseButtonJustPressed(mouseButtonToEbiten[button]) return inpututil.IsMouseButtonJustPressed(mouseButtonToEbiten[button])
} }
// IsMouseButtonJustReleased checks if the provided mouse button is just transitioned from down to up.
func (is InputService) IsMouseButtonJustReleased(button d2input.MouseButton) bool { func (is InputService) IsMouseButtonJustReleased(button d2input.MouseButton) bool {
return inpututil.IsMouseButtonJustReleased(mouseButtonToEbiten[button]) return inpututil.IsMouseButtonJustReleased(mouseButtonToEbiten[button])
} }
// KeyPressDuration returns how long the key is pressed in frames.
func (is InputService) KeyPressDuration(key d2input.Key) int { func (is InputService) KeyPressDuration(key d2input.Key) int {
return inpututil.KeyPressDuration(keyToEbiten[key]) return inpututil.KeyPressDuration(keyToEbiten[key])
} }

View File

@ -4,36 +4,21 @@ import (
"sort" "sort"
) )
type handlerEntry struct { // Priority of the event handler
handler Handler type Priority int
priority Priority
}
type handlerEntryList []handlerEntry //noinspection GoUnusedConst
const (
// PriorityLow is a low priority handler
PriorityLow Priority = iota
// PriorityDefault is a default priority handler
PriorityDefault
// PriorityHigh is a high priority handler
PriorityHigh
)
func (lel handlerEntryList) Len() int { // Handler is an event handler
return len(lel) type Handler interface{}
}
func (lel handlerEntryList) Swap(i, j int) {
lel[i], lel[j] = lel[j], lel[i]
}
func (lel handlerEntryList) Less(i, j int) bool {
return lel[i].priority > lel[j].priority
}
type InputService interface {
CursorPosition() (x int, y int)
InputChars() []rune
IsKeyPressed(key Key) bool
IsKeyJustPressed(key Key) bool
IsKeyJustReleased(key Key) bool
IsMouseButtonPressed(button MouseButton) bool
IsMouseButtonJustPressed(button MouseButton) bool
IsMouseButtonJustReleased(button MouseButton) bool
KeyPressDuration(key Key) int
}
type inputManager struct { type inputManager struct {
inputService InputService inputService InputService
@ -126,7 +111,7 @@ func (im *inputManager) advance(_ float64) error {
for button := mouseButtonMin; button <= mouseButtonMax; button++ { for button := mouseButtonMin; button <= mouseButtonMax; button++ {
if im.inputService.IsMouseButtonJustPressed(button) { if im.inputService.IsMouseButtonJustPressed(button) {
event := MouseEvent{eventBase, MouseButton(button)} event := MouseEvent{eventBase, button}
im.propagate(func(handler Handler) bool { im.propagate(func(handler Handler) bool {
if l, ok := handler.(MouseButtonDownHandler); ok { if l, ok := handler.(MouseButtonDownHandler); ok {
return l.OnMouseButtonDown(event) return l.OnMouseButtonDown(event)
@ -137,7 +122,7 @@ func (im *inputManager) advance(_ float64) error {
} }
if im.inputService.IsMouseButtonJustReleased(button) { if im.inputService.IsMouseButtonJustReleased(button) {
event := MouseEvent{eventBase, MouseButton(button)} event := MouseEvent{eventBase, button}
im.propagate(func(handler Handler) bool { im.propagate(func(handler Handler) bool {
if l, ok := handler.(MouseButtonUpHandler); ok { if l, ok := handler.(MouseButtonUpHandler); ok {
return l.OnMouseButtonUp(event) return l.OnMouseButtonUp(event)
@ -147,7 +132,7 @@ func (im *inputManager) advance(_ float64) error {
}) })
} }
if im.inputService.IsMouseButtonPressed(button) { if im.inputService.IsMouseButtonPressed(button) {
event := MouseEvent{eventBase, MouseButton(button)} event := MouseEvent{eventBase, button}
im.propagate(func(handler Handler) bool { im.propagate(func(handler Handler) bool {
if l, ok := handler.(MouseButtonRepeatHandler); ok { if l, ok := handler.(MouseButtonRepeatHandler); ok {
return l.OnMouseButtonRepeat(event) return l.OnMouseButtonRepeat(event)
@ -215,3 +200,22 @@ func (im *inputManager) propagate(callback func(Handler) bool) {
priority = entry.priority priority = entry.priority
} }
} }
type handlerEntry struct {
handler Handler
priority Priority
}
type handlerEntryList []handlerEntry
func (lel handlerEntryList) Len() int {
return len(lel)
}
func (lel handlerEntryList) Swap(i, j int) {
lel[i], lel[j] = lel[j], lel[i]
}
func (lel handlerEntryList) Less(i, j int) bool {
return lel[i].priority > lel[j].priority
}

View File

@ -0,0 +1,23 @@
package d2input
// InputService represents an interface offering Keyboard and Mouse interactions.
type InputService interface {
// CursorPosition returns a position of a mouse cursor relative to the game screen (window).
CursorPosition() (x int, y int)
// InputChars return "printable" runes read from the keyboard at the time update is called.
InputChars() []rune
// IsKeyPressed checks if the provided key is down.
IsKeyPressed(key Key) bool
// IsKeyJustPressed checks if the provided key is just transitioned from up to down.
IsKeyJustPressed(key Key) bool
// IsKeyJustReleased checks if the provided key is just transitioned from down to up.
IsKeyJustReleased(key Key) bool
// IsMouseButtonPressed checks if the provided mouse button is down.
IsMouseButtonPressed(button MouseButton) bool
// IsMouseButtonJustPressed checks if the provided mouse button is just transitioned from up to down.
IsMouseButtonJustPressed(button MouseButton) bool
// IsMouseButtonJustReleased checks if the provided mouse button is just transitioned from down to up.
IsMouseButtonJustReleased(button MouseButton) bool
// KeyPressDuration returns how long the key is pressed in frames.
KeyPressDuration(key Key) int
}

View File

@ -1,138 +1,225 @@
// Package d2input provides interaction with input services providing key and mouse interactions.
package d2input package d2input
// Key is the physical key of keyboard input // Key represents button on a traditional keyboard.
type Key int type Key int
const ( const (
// Key0 is the number 0
Key0 Key = iota Key0 Key = iota
// Key1 is the number 1
Key1 Key1
// Key2 is the number 2
Key2 Key2
// Key3 is the number 3
Key3 Key3
// Key4 is the number 4
Key4 Key4
// Key5 is the number 5
Key5 Key5
// Key6 is the number 6
Key6 Key6
// Key7 is the number 7
Key7 Key7
// Key8 is the number 8
Key8 Key8
// Key9 is the number 9
Key9 Key9
// KeyA is the letter A
KeyA KeyA
// KeyB is the letter B
KeyB KeyB
// KeyC is the letter C
KeyC KeyC
// KeyD is the letter D
KeyD KeyD
// KeyE is the letter E
KeyE KeyE
// KeyF is the letter F
KeyF KeyF
// KeyG is the letter G
KeyG KeyG
// KeyH is the letter H
KeyH KeyH
// KeyI is the letter I
KeyI KeyI
// KeyJ is the letter J
KeyJ KeyJ
// KeyK is the letter K
KeyK KeyK
// KeyL is the letter L
KeyL KeyL
// KeyM is the letter M
KeyM KeyM
// KeyN is the letter N
KeyN KeyN
// KeyO is the letter O
KeyO KeyO
// KeyP is the letter P
KeyP KeyP
// KeyQ is the letter Q
KeyQ KeyQ
// KeyR is the letter R
KeyR KeyR
// KeyS is the letter S
KeyS KeyS
// KeyT is the letter T
KeyT KeyT
// KeyU is the letter U
KeyU KeyU
// KeyV is the letter V
KeyV KeyV
// KeyW is the letter W
KeyW KeyW
// KeyX is the letter X
KeyX KeyX
// KeyY is the letter Y
KeyY KeyY
// KeyZ is the letter Z
KeyZ KeyZ
// KeyApostrophe is the Apostrophe
KeyApostrophe KeyApostrophe
// KeyBackslash is the Backslash
KeyBackslash KeyBackslash
// KeyBackspace is the Backspace
KeyBackspace KeyBackspace
// KeyCapsLock is the CapsLock
KeyCapsLock KeyCapsLock
// KeyComma is the Comma
KeyComma KeyComma
// KeyDelete is the Delete
KeyDelete KeyDelete
// KeyDown is the down arrow key
KeyDown KeyDown
// KeyEnd is the End
KeyEnd KeyEnd
// KeyEnter is the Enter
KeyEnter KeyEnter
// KeyEqual is the Equal
KeyEqual KeyEqual
// KeyEscape is the Escape
KeyEscape KeyEscape
// KeyF1 is the function F1
KeyF1 KeyF1
// KeyF2 is the function F2
KeyF2 KeyF2
// KeyF3 is the function F3
KeyF3 KeyF3
// KeyF4 is the function F4
KeyF4 KeyF4
// KeyF5 is the function F5
KeyF5 KeyF5
// KeyF6 is the function F6
KeyF6 KeyF6
// KeyF7 is the function F7
KeyF7 KeyF7
// KeyF8 is the function F8
KeyF8 KeyF8
// KeyF9 is the function F9
KeyF9 KeyF9
// KeyF10 is the function F10
KeyF10 KeyF10
// KeyF11 is the function F11
KeyF11 KeyF11
// KeyF12 is the function F12
KeyF12 KeyF12
// KeyGraveAccent is the Grave Accent
KeyGraveAccent KeyGraveAccent
// KeyHome is the home key
KeyHome KeyHome
// KeyInsert is the insert key
KeyInsert KeyInsert
// KeyKP0 is keypad 0
KeyKP0 KeyKP0
// KeyKP1 is keypad 1
KeyKP1 KeyKP1
// KeyKP2 is keypad 2
KeyKP2 KeyKP2
// KeyKP3 is keypad 3
KeyKP3 KeyKP3
// KeyKP4 is keypad 4
KeyKP4 KeyKP4
// KeyKP5 is keypad 5
KeyKP5 KeyKP5
// KeyKP6 is keypad 6
KeyKP6 KeyKP6
// KeyKP7 is keypad 7
KeyKP7 KeyKP7
// KeyKP8 is keypad 8
KeyKP8 KeyKP8
// KeyKP9 is keypad 9
KeyKP9 KeyKP9
// KeyKPAdd is keypad Add
KeyKPAdd KeyKPAdd
// KeyKPDecimal is keypad Decimal
KeyKPDecimal KeyKPDecimal
// KeyKPDivide is keypad Divide
KeyKPDivide KeyKPDivide
// KeyKPEnter is keypad Enter
KeyKPEnter KeyKPEnter
// KeyKPEqual is keypad Equal
KeyKPEqual KeyKPEqual
// KeyKPMultiply is keypad Multiply
KeyKPMultiply KeyKPMultiply
// KeyKPSubtract is keypad Subtract
KeyKPSubtract KeyKPSubtract
// KeyLeft is the left arrow key
KeyLeft KeyLeft
// KeyLeftBracket is the left bracket
KeyLeftBracket KeyLeftBracket
// KeyMenu is the Menu key
KeyMenu KeyMenu
// KeyMinus is the Minus key
KeyMinus KeyMinus
// KeyNumLock is the NumLock key
KeyNumLock KeyNumLock
// KeyPageDown is the PageDown key
KeyPageDown KeyPageDown
// KeyPageUp is the PageUp key
KeyPageUp KeyPageUp
// KeyPause is the Pause key
KeyPause KeyPause
// KeyPeriod is the Period key
KeyPeriod KeyPeriod
// KeyPrintScreen is the PrintScreen key
KeyPrintScreen KeyPrintScreen
// KeyRight is the right arrow key
KeyRight KeyRight
// KeyRightBracket is the right bracket key
KeyRightBracket KeyRightBracket
// KeyScrollLock is the scroll lock key
KeyScrollLock KeyScrollLock
// KeySemicolon is the semicolon key
KeySemicolon KeySemicolon
// KeySlash is the front slash key
KeySlash KeySlash
// KeySpace is the space key
KeySpace KeySpace
// KeyTab is the tab key
KeyTab KeyTab
// KeyUp is the up arrow key
KeyUp KeyUp
// KeyAlt is the alt key
KeyAlt KeyAlt
// KeyControl is the control key
KeyControl KeyControl
// KeyShift is the shift key
KeyShift KeyShift
// Lowest key in key constants
keyMin = Key0 keyMin = Key0
// Highest key is key constants
keyMax = KeyShift keyMax = KeyShift
) )
// KeyMod represents a "modified" key action. This could mean, for example, ctrl-S
type KeyMod int type KeyMod int
const ( const (
// KeyModAlt is the Alt key modifier
KeyModAlt KeyMod = 1 << iota KeyModAlt KeyMod = 1 << iota
// KeyModControl is the Control key modifier
KeyModControl KeyModControl
// KeyModShift is the Shift key modifier
KeyModShift KeyModShift
) )
// MouseButton is the physical button for mouse input
type MouseButton int
const (
MouseButtonLeft MouseButton = iota
MouseButtonMiddle
MouseButtonRight
mouseButtonMin = MouseButtonLeft
mouseButtonMax = MouseButtonRight
)
type MouseButtonMod int
const (
MouseButtonModLeft MouseButtonMod = 1 << iota
MouseButtonModMiddle
MouseButtonModRight
)

View File

@ -0,0 +1,28 @@
package d2input
// MouseButton represents a traditional 3-button mouse
type MouseButton int
const (
// MouseButtonLeft is the left mouse button
MouseButtonLeft MouseButton = iota
// MouseButtonMiddle is the middle mouse button
MouseButtonMiddle
// MouseButtonRight is the right mouse button
MouseButtonRight
mouseButtonMin = MouseButtonLeft
mouseButtonMax = MouseButtonRight
)
// MouseButtonMod represents a "modified" mouse button action. This could mean, for example, ctrl-mouse_left
type MouseButtonMod int
const (
// MouseButtonLeft is a modified left mouse button
MouseButtonModLeft MouseButtonMod = 1 << iota
// MouseButtonModMiddle is a modified middle mouse button
MouseButtonModMiddle
// MouseButtonModRight is a modified right mouse button
MouseButtonModRight
)