D2input abstraction (#532)

* abstract d2input manager/service/events/keys/buttons to interface

* abstract d2input manager/service/events/keys/buttons to interface

* fixing lint error
This commit is contained in:
dk 2020-07-03 12:09:16 -07:00 committed by GitHub
parent 5bfec3ccb0
commit 62b8a610c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 684 additions and 491 deletions

View File

@ -415,7 +415,7 @@ func (p *App) advance(elapsed, current float64) error {
d2ui.Advance(elapsed)
if err := d2input.Advance(elapsed); err != nil {
if err := d2input.Advance(elapsed, current); err != nil {
return err
}

View File

@ -1,4 +1,4 @@
package d2input
package d2interface
// MouseButton represents a traditional 3-button mouse
type MouseButton int
@ -10,16 +10,17 @@ const (
MouseButtonMiddle
// MouseButtonRight is the right mouse button
MouseButtonRight
mouseButtonMin = MouseButtonLeft
mouseButtonMax = MouseButtonRight
// MouseButtonMin is the lowest MouseButton
MouseButtonMin = MouseButtonLeft
// MouseButtonMax is the highest MouseButton
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 is a modified left mouse button
MouseButtonModLeft MouseButtonMod = 1 << iota
// MouseButtonModMiddle is a modified middle mouse button
MouseButtonModMiddle

View File

@ -0,0 +1,34 @@
package d2interface
// HandlerEvent holds the qualifiers for a key or mouse event
type HandlerEvent interface {
KeyMod() KeyMod
ButtonMod() MouseButtonMod
X() int
Y() int
}
// KeyEvent represents an event associated with a keyboard key
type KeyEvent interface {
HandlerEvent
Key() Key
// Duration represents the number of frames this key has been pressed for
Duration() int
}
// KeyCharsEvent represents an event associated with a keyboard character being pressed
type KeyCharsEvent interface {
HandlerEvent
Chars() []rune
}
// MouseEvent represents a mouse event
type MouseEvent interface {
HandlerEvent
Button() MouseButton
}
// MouseMoveEvent represents a mouse movement event
type MouseMoveEvent interface {
HandlerEvent
}

View File

@ -0,0 +1,44 @@
package d2interface
// InputEventHandler is an event handler
type InputEventHandler interface{}
// 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
}
// MouseButtonDownHandler represents a handler for a mouse button pressed event
type MouseButtonDownHandler interface {
OnMouseButtonDown(event MouseEvent) bool
}
// MouseButtonRepeatHandler represents a handler for a mouse button held-down event; between a pressed and released.
type MouseButtonRepeatHandler interface {
OnMouseButtonRepeat(event MouseEvent) bool
}
// MouseButtonUpHandler represents a handler for a mouse button release event
type MouseButtonUpHandler interface {
OnMouseButtonUp(event MouseEvent) bool
}
// MouseMoveHandler represents a handler for a mouse button release event
type MouseMoveHandler interface {
OnMouseMove(event MouseMoveEvent) bool
}

View File

@ -1,5 +1,4 @@
// Package d2input provides interaction with input services providing key and mouse interactions.
package d2input
package d2interface
// Key represents button on a traditional keyboard.
type Key int
@ -206,10 +205,10 @@ const (
// KeyShift is the shift key
KeyShift
// Lowest key in key constants
keyMin = Key0
// Highest key is key constants
keyMax = KeyShift
// KeyMin is the lowest key
KeyMin = Key0
// KeyMax is the highest key
KeyMax = KeyShift
)
// KeyMod represents a "modified" key action. This could mean, for example, ctrl-S

View File

@ -0,0 +1,9 @@
package d2interface
// InputManager manages an InputService
type InputManager interface {
Advance(elapsedTime, currentTime float64) error
BindHandlerWithPriority(InputEventHandler, Priority) error
BindHandler(h InputEventHandler) error
UnbindHandler(handler InputEventHandler) error
}

View File

@ -0,0 +1,14 @@
package d2interface
// Priority of the event handler
type Priority int
//noinspection GoUnusedConst // nothing is low priority yet
const (
// PriorityLow is a low priority handler
PriorityLow Priority = iota
// PriorityDefault is a default priority handler
PriorityDefault
// PriorityHigh is a high priority handler
PriorityHigh
)

View File

@ -1,4 +1,4 @@
package d2input
package d2interface
// InputService represents an interface offering Keyboard and Mouse interactions.
type InputService interface {

View File

@ -1,9 +1,5 @@
package d2interface
import (
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
)
// TermCategory applies styles to the lines in the Terminal
type TermCategory int
@ -22,8 +18,8 @@ type Terminal interface {
BindLogger()
Advance(elapsed float64) error
OnKeyDown(event d2input.KeyEvent) bool
OnKeyChars(event d2input.KeyCharsEvent) bool
OnKeyDown(event KeyEvent) bool
OnKeyChars(event KeyCharsEvent) bool
Render(surface Surface) error
Execute(command string) error
OutputRaw(text string, category TermCategory)

View File

@ -7,7 +7,6 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
)
type buttonState int
@ -107,17 +106,17 @@ func createButton(renderer d2interface.Renderer, text string, buttonStyle Button
return button, nil
}
func (b *Button) onMouseButtonDown(_ d2input.MouseEvent) bool {
func (b *Button) onMouseButtonDown(event d2interface.MouseEvent) bool {
b.state = buttonStatePressed
return false
}
func (b *Button) onMouseButtonUp(_ d2input.MouseEvent) bool {
func (b *Button) onMouseButtonUp(event d2interface.MouseEvent) bool {
b.state = buttonStateDefault
return false
}
func (b *Button) onMouseLeave(_ d2input.MouseMoveEvent) bool {
func (b *Button) onMouseLeave(event d2interface.MouseMoveEvent) bool {
b.state = buttonStateDefault
return false
}

View File

@ -6,7 +6,6 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
)
type layoutEntry struct {
@ -240,41 +239,41 @@ func (l *Layout) getSize() (int, int) {
return d2common.MaxInt(width, l.width), d2common.MaxInt(height, l.height)
}
func (l *Layout) onMouseButtonDown(event d2input.MouseEvent) bool {
func (l *Layout) onMouseButtonDown(event d2interface.MouseEvent) bool {
for _, entry := range l.entries {
eventLocal := event
if l.adjustEntryEvent(entry, &eventLocal.X, &eventLocal.Y) {
if l.adjustEntryEvent(entry, eventLocal.X(), eventLocal.Y()) {
entry.widget.onMouseButtonDown(eventLocal)
entry.mouseDown[event.Button] = true
entry.mouseDown[event.Button()] = true
}
}
return false
}
func (l *Layout) onMouseButtonUp(event d2input.MouseEvent) bool {
func (l *Layout) onMouseButtonUp(event d2interface.MouseEvent) bool {
for _, entry := range l.entries {
eventLocal := event
if l.adjustEntryEvent(entry, &eventLocal.X, &eventLocal.Y) {
if entry.mouseDown[event.Button] {
if l.adjustEntryEvent(entry, eventLocal.X(), eventLocal.Y()) {
if entry.mouseDown[event.Button()] {
entry.widget.onMouseButtonClick(eventLocal)
entry.widget.onMouseButtonUp(eventLocal)
}
}
entry.mouseDown[event.Button] = false
entry.mouseDown[event.Button()] = false
}
return false
}
func (l *Layout) onMouseMove(event d2input.MouseMoveEvent) bool {
func (l *Layout) onMouseMove(event d2interface.MouseMoveEvent) bool {
for _, entry := range l.entries {
eventLocal := event
if l.adjustEntryEvent(entry, &eventLocal.X, &eventLocal.Y) {
if l.adjustEntryEvent(entry, eventLocal.X(), eventLocal.Y()) {
entry.widget.onMouseMove(eventLocal)
if entry.mouseOver {
entry.widget.onMouseOver(eventLocal)
@ -291,11 +290,11 @@ func (l *Layout) onMouseMove(event d2input.MouseMoveEvent) bool {
return false
}
func (l *Layout) adjustEntryEvent(entry *layoutEntry, eventX, eventY *int) bool {
*eventX -= entry.x
*eventY -= entry.y
func (l *Layout) adjustEntryEvent(entry *layoutEntry, eventX, eventY int) bool {
eventX -= entry.x
eventY -= entry.y
if *eventX < 0 || *eventY < 0 || *eventX >= entry.width || *eventY >= entry.height {
if eventX < 0 || eventY < 0 || eventX >= entry.width || eventY >= entry.height {
return false
}

View File

@ -52,7 +52,7 @@ func (m *manager) SetLayout(layout *Layout) {
}
}
func (m *manager) OnMouseButtonDown(event d2input.MouseEvent) bool {
func (m *manager) OnMouseButtonDown(event d2interface.MouseEvent) bool {
if m.layout == nil {
return false
}
@ -60,7 +60,7 @@ func (m *manager) OnMouseButtonDown(event d2input.MouseEvent) bool {
return m.layout.onMouseButtonDown(event)
}
func (m *manager) OnMouseButtonUp(event d2input.MouseEvent) bool {
func (m *manager) OnMouseButtonUp(event d2interface.MouseEvent) bool {
if m.layout == nil {
return false
}
@ -68,9 +68,9 @@ func (m *manager) OnMouseButtonUp(event d2input.MouseEvent) bool {
return m.layout.onMouseButtonUp(event)
}
func (m *manager) OnMouseMove(event d2input.MouseMoveEvent) bool {
m.cursorX = event.X
m.cursorY = event.Y
func (m *manager) OnMouseMove(event d2interface.MouseMoveEvent) bool {
m.cursorX = event.X()
m.cursorY = event.Y()
if m.layout == nil {
return false

View File

@ -2,23 +2,22 @@ package d2gui
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
)
type MouseHandler func(d2input.MouseEvent)
type MouseMoveHandler func(d2input.MouseMoveEvent)
type MouseHandler func(d2interface.MouseEvent)
type MouseMoveHandler func(d2interface.MouseMoveEvent)
type widget interface {
render(target d2interface.Surface) error
advance(elapsed float64) error
onMouseMove(event d2input.MouseMoveEvent) bool
onMouseEnter(event d2input.MouseMoveEvent) bool
onMouseLeave(event d2input.MouseMoveEvent) bool
onMouseOver(event d2input.MouseMoveEvent) bool
onMouseButtonDown(event d2input.MouseEvent) bool
onMouseButtonUp(event d2input.MouseEvent) bool
onMouseButtonClick(event d2input.MouseEvent) bool
onMouseMove(event d2interface.MouseMoveEvent) bool
onMouseEnter(event d2interface.MouseMoveEvent) bool
onMouseLeave(event d2interface.MouseMoveEvent) bool
onMouseOver(event d2interface.MouseMoveEvent) bool
onMouseButtonDown(event d2interface.MouseEvent) bool
onMouseButtonUp(event d2interface.MouseEvent) bool
onMouseButtonClick(event d2interface.MouseEvent) bool
getPosition() (int, int)
setOffset(x, y int)
@ -113,7 +112,7 @@ func (w *widgetBase) advance(elapsed float64) error {
return nil
}
func (w *widgetBase) onMouseEnter(event d2input.MouseMoveEvent) bool {
func (w *widgetBase) onMouseEnter(event d2interface.MouseMoveEvent) bool {
if w.mouseEnterHandler != nil {
w.mouseEnterHandler(event)
}
@ -121,7 +120,7 @@ func (w *widgetBase) onMouseEnter(event d2input.MouseMoveEvent) bool {
return false
}
func (w *widgetBase) onMouseLeave(event d2input.MouseMoveEvent) bool {
func (w *widgetBase) onMouseLeave(event d2interface.MouseMoveEvent) bool {
if w.mouseLeaveHandler != nil {
w.mouseLeaveHandler(event)
}
@ -129,7 +128,7 @@ func (w *widgetBase) onMouseLeave(event d2input.MouseMoveEvent) bool {
return false
}
func (w *widgetBase) onMouseButtonClick(event d2input.MouseEvent) bool {
func (w *widgetBase) onMouseButtonClick(event d2interface.MouseEvent) bool {
if w.mouseClickHandler != nil {
w.mouseClickHandler(event)
}
@ -137,18 +136,18 @@ func (w *widgetBase) onMouseButtonClick(event d2input.MouseEvent) bool {
return false
}
func (w *widgetBase) onMouseMove(event d2input.MouseMoveEvent) bool {
func (w *widgetBase) onMouseMove(event d2interface.MouseMoveEvent) bool {
return false
}
func (w *widgetBase) onMouseOver(event d2input.MouseMoveEvent) bool {
func (w *widgetBase) onMouseOver(event d2interface.MouseMoveEvent) bool {
return false
}
func (w *widgetBase) onMouseButtonDown(event d2input.MouseEvent) bool {
func (w *widgetBase) onMouseButtonDown(event d2interface.MouseEvent) bool {
return false
}
func (w *widgetBase) onMouseButtonUp(event d2input.MouseEvent) bool {
func (w *widgetBase) onMouseButtonUp(event d2interface.MouseEvent) bool {
return false
}

View File

@ -2,6 +2,10 @@ package d2input
import (
"errors"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
ebiten_input "github.com/OpenDiablo2/OpenDiablo2/d2core/d2input/ebiten"
)
var (
@ -11,104 +15,33 @@ var (
ErrNotReg = errors.New("input system does not have provided handler")
)
var singleton inputManager
// HandlerEvent holds the qualifiers for a key or mouse event
type HandlerEvent struct {
KeyMod KeyMod
ButtonMod MouseButtonMod
X int
Y int
}
// KeyEvent represents an event associated with a keyboard key
type KeyEvent struct {
HandlerEvent
Key Key
// Duration represents the number of frames this key has been pressed for
Duration int
}
// KeyCharsEvent represents an event associated with a keyboard character being pressed
type KeyCharsEvent struct {
HandlerEvent
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 {
HandlerEvent
Button MouseButton
}
// MouseEvent represents a mouse movement event
type MouseMoveEvent struct {
HandlerEvent
}
// MouseButtonDownHandler represents a handler for a mouse button pressed event
type MouseButtonDownHandler interface {
OnMouseButtonDown(event MouseEvent) bool
}
// MouseButtonRepeatHandler represents a handler for a mouse button held-down event; between a pressed and released.
type MouseButtonRepeatHandler interface {
OnMouseButtonRepeat(event MouseEvent) bool
}
// MouseButtonUpHandler represents a handler for a mouse button release event
type MouseButtonUpHandler interface {
OnMouseButtonUp(event MouseEvent) bool
}
// MouseMoveHandler represents a handler for a mouse button release event
type MouseMoveHandler interface {
OnMouseMove(event MouseMoveEvent) bool
}
var singleton *inputManager // TODO remove this singleton
// Initialize creates a single global input manager based on a specific input service
func Initialize(inputService InputService) {
singleton = inputManager{
inputService: inputService,
func Create() (d2interface.InputManager, error) {
singleton = &inputManager{
inputService: ebiten_input.InputService{},
}
return singleton, nil
}
// Advance moves the input manager with the elapsed number of seconds.
func Advance(elapsed float64) error {
return singleton.advance(elapsed)
func Advance(elapsed, current float64) error {
return singleton.Advance(elapsed, current)
}
// BindHandlerWithPriority adds an event handler with a specific call priority
func BindHandlerWithPriority(handler Handler, priority Priority) error {
return singleton.bindHandler(handler, priority)
func BindHandlerWithPriority(handler d2interface.InputEventHandler, priority d2interface.Priority) error {
return singleton.BindHandlerWithPriority(handler, priority)
}
// BindHandler adds an event handler
func BindHandler(handler Handler) error {
return BindHandlerWithPriority(handler, PriorityDefault)
func BindHandler(handler d2interface.InputEventHandler) error {
return BindHandlerWithPriority(handler, d2interface.PriorityDefault)
}
// UnbindHandler removes a previously bound event handler
func UnbindHandler(handler Handler) error {
return singleton.unbindHandler(handler)
func UnbindHandler(handler d2interface.InputEventHandler) error {
return singleton.UnbindHandler(handler)
}

View File

@ -2,121 +2,120 @@
package ebiten
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/inpututil"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
)
var (
//nolint:gochecknoglobals This is a constant in all but by name, no constant map in go
keyToEbiten = map[d2input.Key]ebiten.Key{
d2input.Key0: ebiten.Key0,
d2input.Key1: ebiten.Key1,
d2input.Key2: ebiten.Key2,
d2input.Key3: ebiten.Key3,
d2input.Key4: ebiten.Key4,
d2input.Key5: ebiten.Key5,
d2input.Key6: ebiten.Key6,
d2input.Key7: ebiten.Key7,
d2input.Key8: ebiten.Key8,
d2input.Key9: ebiten.Key9,
d2input.KeyA: ebiten.KeyA,
d2input.KeyB: ebiten.KeyB,
d2input.KeyC: ebiten.KeyC,
d2input.KeyD: ebiten.KeyD,
d2input.KeyE: ebiten.KeyE,
d2input.KeyF: ebiten.KeyF,
d2input.KeyG: ebiten.KeyG,
d2input.KeyH: ebiten.KeyH,
d2input.KeyI: ebiten.KeyI,
d2input.KeyJ: ebiten.KeyJ,
d2input.KeyK: ebiten.KeyK,
d2input.KeyL: ebiten.KeyL,
d2input.KeyM: ebiten.KeyM,
d2input.KeyN: ebiten.KeyN,
d2input.KeyO: ebiten.KeyO,
d2input.KeyP: ebiten.KeyP,
d2input.KeyQ: ebiten.KeyQ,
d2input.KeyR: ebiten.KeyR,
d2input.KeyS: ebiten.KeyS,
d2input.KeyT: ebiten.KeyT,
d2input.KeyU: ebiten.KeyU,
d2input.KeyV: ebiten.KeyV,
d2input.KeyW: ebiten.KeyW,
d2input.KeyX: ebiten.KeyX,
d2input.KeyY: ebiten.KeyY,
d2input.KeyZ: ebiten.KeyZ,
d2input.KeyApostrophe: ebiten.KeyApostrophe,
d2input.KeyBackslash: ebiten.KeyBackslash,
d2input.KeyBackspace: ebiten.KeyBackspace,
d2input.KeyCapsLock: ebiten.KeyCapsLock,
d2input.KeyComma: ebiten.KeyComma,
d2input.KeyDelete: ebiten.KeyDelete,
d2input.KeyDown: ebiten.KeyDown,
d2input.KeyEnd: ebiten.KeyEnd,
d2input.KeyEnter: ebiten.KeyEnter,
d2input.KeyEqual: ebiten.KeyEqual,
d2input.KeyEscape: ebiten.KeyEscape,
d2input.KeyF1: ebiten.KeyF1,
d2input.KeyF2: ebiten.KeyF2,
d2input.KeyF3: ebiten.KeyF3,
d2input.KeyF4: ebiten.KeyF4,
d2input.KeyF5: ebiten.KeyF5,
d2input.KeyF6: ebiten.KeyF6,
d2input.KeyF7: ebiten.KeyF7,
d2input.KeyF8: ebiten.KeyF8,
d2input.KeyF9: ebiten.KeyF9,
d2input.KeyF10: ebiten.KeyF10,
d2input.KeyF11: ebiten.KeyF11,
d2input.KeyF12: ebiten.KeyF12,
d2input.KeyGraveAccent: ebiten.KeyGraveAccent,
d2input.KeyHome: ebiten.KeyHome,
d2input.KeyInsert: ebiten.KeyInsert,
d2input.KeyKP0: ebiten.KeyKP0,
d2input.KeyKP1: ebiten.KeyKP1,
d2input.KeyKP2: ebiten.KeyKP2,
d2input.KeyKP3: ebiten.KeyKP3,
d2input.KeyKP4: ebiten.KeyKP4,
d2input.KeyKP5: ebiten.KeyKP5,
d2input.KeyKP6: ebiten.KeyKP6,
d2input.KeyKP7: ebiten.KeyKP7,
d2input.KeyKP8: ebiten.KeyKP8,
d2input.KeyKP9: ebiten.KeyKP9,
d2input.KeyKPAdd: ebiten.KeyKPAdd,
d2input.KeyKPDecimal: ebiten.KeyKPDecimal,
d2input.KeyKPDivide: ebiten.KeyKPDivide,
d2input.KeyKPEnter: ebiten.KeyKPEnter,
d2input.KeyKPEqual: ebiten.KeyKPEqual,
d2input.KeyKPMultiply: ebiten.KeyKPMultiply,
d2input.KeyKPSubtract: ebiten.KeyKPSubtract,
d2input.KeyLeft: ebiten.KeyLeft,
d2input.KeyLeftBracket: ebiten.KeyLeftBracket,
d2input.KeyMenu: ebiten.KeyMenu,
d2input.KeyMinus: ebiten.KeyMinus,
d2input.KeyNumLock: ebiten.KeyNumLock,
d2input.KeyPageDown: ebiten.KeyPageDown,
d2input.KeyPageUp: ebiten.KeyPageUp,
d2input.KeyPause: ebiten.KeyPause,
d2input.KeyPeriod: ebiten.KeyPeriod,
d2input.KeyPrintScreen: ebiten.KeyPrintScreen,
d2input.KeyRight: ebiten.KeyRight,
d2input.KeyRightBracket: ebiten.KeyRightBracket,
d2input.KeyScrollLock: ebiten.KeyScrollLock,
d2input.KeySemicolon: ebiten.KeySemicolon,
d2input.KeySlash: ebiten.KeySlash,
d2input.KeySpace: ebiten.KeySpace,
d2input.KeyTab: ebiten.KeyTab,
d2input.KeyUp: ebiten.KeyUp,
d2input.KeyAlt: ebiten.KeyAlt,
d2input.KeyControl: ebiten.KeyControl,
d2input.KeyShift: ebiten.KeyShift,
keyToEbiten = map[d2interface.Key]ebiten.Key{
d2interface.Key0: ebiten.Key0,
d2interface.Key1: ebiten.Key1,
d2interface.Key2: ebiten.Key2,
d2interface.Key3: ebiten.Key3,
d2interface.Key4: ebiten.Key4,
d2interface.Key5: ebiten.Key5,
d2interface.Key6: ebiten.Key6,
d2interface.Key7: ebiten.Key7,
d2interface.Key8: ebiten.Key8,
d2interface.Key9: ebiten.Key9,
d2interface.KeyA: ebiten.KeyA,
d2interface.KeyB: ebiten.KeyB,
d2interface.KeyC: ebiten.KeyC,
d2interface.KeyD: ebiten.KeyD,
d2interface.KeyE: ebiten.KeyE,
d2interface.KeyF: ebiten.KeyF,
d2interface.KeyG: ebiten.KeyG,
d2interface.KeyH: ebiten.KeyH,
d2interface.KeyI: ebiten.KeyI,
d2interface.KeyJ: ebiten.KeyJ,
d2interface.KeyK: ebiten.KeyK,
d2interface.KeyL: ebiten.KeyL,
d2interface.KeyM: ebiten.KeyM,
d2interface.KeyN: ebiten.KeyN,
d2interface.KeyO: ebiten.KeyO,
d2interface.KeyP: ebiten.KeyP,
d2interface.KeyQ: ebiten.KeyQ,
d2interface.KeyR: ebiten.KeyR,
d2interface.KeyS: ebiten.KeyS,
d2interface.KeyT: ebiten.KeyT,
d2interface.KeyU: ebiten.KeyU,
d2interface.KeyV: ebiten.KeyV,
d2interface.KeyW: ebiten.KeyW,
d2interface.KeyX: ebiten.KeyX,
d2interface.KeyY: ebiten.KeyY,
d2interface.KeyZ: ebiten.KeyZ,
d2interface.KeyApostrophe: ebiten.KeyApostrophe,
d2interface.KeyBackslash: ebiten.KeyBackslash,
d2interface.KeyBackspace: ebiten.KeyBackspace,
d2interface.KeyCapsLock: ebiten.KeyCapsLock,
d2interface.KeyComma: ebiten.KeyComma,
d2interface.KeyDelete: ebiten.KeyDelete,
d2interface.KeyDown: ebiten.KeyDown,
d2interface.KeyEnd: ebiten.KeyEnd,
d2interface.KeyEnter: ebiten.KeyEnter,
d2interface.KeyEqual: ebiten.KeyEqual,
d2interface.KeyEscape: ebiten.KeyEscape,
d2interface.KeyF1: ebiten.KeyF1,
d2interface.KeyF2: ebiten.KeyF2,
d2interface.KeyF3: ebiten.KeyF3,
d2interface.KeyF4: ebiten.KeyF4,
d2interface.KeyF5: ebiten.KeyF5,
d2interface.KeyF6: ebiten.KeyF6,
d2interface.KeyF7: ebiten.KeyF7,
d2interface.KeyF8: ebiten.KeyF8,
d2interface.KeyF9: ebiten.KeyF9,
d2interface.KeyF10: ebiten.KeyF10,
d2interface.KeyF11: ebiten.KeyF11,
d2interface.KeyF12: ebiten.KeyF12,
d2interface.KeyGraveAccent: ebiten.KeyGraveAccent,
d2interface.KeyHome: ebiten.KeyHome,
d2interface.KeyInsert: ebiten.KeyInsert,
d2interface.KeyKP0: ebiten.KeyKP0,
d2interface.KeyKP1: ebiten.KeyKP1,
d2interface.KeyKP2: ebiten.KeyKP2,
d2interface.KeyKP3: ebiten.KeyKP3,
d2interface.KeyKP4: ebiten.KeyKP4,
d2interface.KeyKP5: ebiten.KeyKP5,
d2interface.KeyKP6: ebiten.KeyKP6,
d2interface.KeyKP7: ebiten.KeyKP7,
d2interface.KeyKP8: ebiten.KeyKP8,
d2interface.KeyKP9: ebiten.KeyKP9,
d2interface.KeyKPAdd: ebiten.KeyKPAdd,
d2interface.KeyKPDecimal: ebiten.KeyKPDecimal,
d2interface.KeyKPDivide: ebiten.KeyKPDivide,
d2interface.KeyKPEnter: ebiten.KeyKPEnter,
d2interface.KeyKPEqual: ebiten.KeyKPEqual,
d2interface.KeyKPMultiply: ebiten.KeyKPMultiply,
d2interface.KeyKPSubtract: ebiten.KeyKPSubtract,
d2interface.KeyLeft: ebiten.KeyLeft,
d2interface.KeyLeftBracket: ebiten.KeyLeftBracket,
d2interface.KeyMenu: ebiten.KeyMenu,
d2interface.KeyMinus: ebiten.KeyMinus,
d2interface.KeyNumLock: ebiten.KeyNumLock,
d2interface.KeyPageDown: ebiten.KeyPageDown,
d2interface.KeyPageUp: ebiten.KeyPageUp,
d2interface.KeyPause: ebiten.KeyPause,
d2interface.KeyPeriod: ebiten.KeyPeriod,
d2interface.KeyPrintScreen: ebiten.KeyPrintScreen,
d2interface.KeyRight: ebiten.KeyRight,
d2interface.KeyRightBracket: ebiten.KeyRightBracket,
d2interface.KeyScrollLock: ebiten.KeyScrollLock,
d2interface.KeySemicolon: ebiten.KeySemicolon,
d2interface.KeySlash: ebiten.KeySlash,
d2interface.KeySpace: ebiten.KeySpace,
d2interface.KeyTab: ebiten.KeyTab,
d2interface.KeyUp: ebiten.KeyUp,
d2interface.KeyAlt: ebiten.KeyAlt,
d2interface.KeyControl: ebiten.KeyControl,
d2interface.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{
d2input.MouseButtonLeft: ebiten.MouseButtonLeft,
d2input.MouseButtonMiddle: ebiten.MouseButtonMiddle,
d2input.MouseButtonRight: ebiten.MouseButtonRight,
mouseButtonToEbiten = map[d2interface.MouseButton]ebiten.MouseButton{
d2interface.MouseButtonLeft: ebiten.MouseButtonLeft,
d2interface.MouseButtonMiddle: ebiten.MouseButtonMiddle,
d2interface.MouseButtonRight: ebiten.MouseButtonRight,
}
)
@ -134,36 +133,36 @@ func (is InputService) InputChars() []rune {
}
// IsKeyPressed checks if the provided key is down.
func (is InputService) IsKeyPressed(key d2input.Key) bool {
func (is InputService) IsKeyPressed(key d2interface.Key) bool {
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 d2interface.Key) bool {
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 d2interface.Key) bool {
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 d2interface.MouseButton) bool {
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 d2interface.MouseButton) bool {
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 d2interface.MouseButton) bool {
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 d2interface.Key) int {
return inpututil.KeyPressDuration(keyToEbiten[key])
}

View File

@ -0,0 +1,101 @@
package d2input
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
)
// HandlerEvent is an event that EventHandlers will process and respond to
type HandlerEvent struct {
keyMod d2interface.KeyMod
buttonMod d2interface.MouseButtonMod
x int
y int
}
// KeyMod yields the modifier for a key action
func (e *HandlerEvent) KeyMod() d2interface.KeyMod {
return e.keyMod
}
// ButtonMod yields the modifier for a button action
func (e *HandlerEvent) ButtonMod() d2interface.MouseButtonMod {
return e.buttonMod
}
// X returns the x screen coordinate for the event
func (e *HandlerEvent) X() int {
return e.x
}
//Y returns the y screen coordinate for the event
func (e *HandlerEvent) Y() int {
return e.y
}
type KeyCharsEvent struct {
HandlerEvent
chars []rune
}
func (e *KeyCharsEvent) Chars() []rune {
return e.chars
}
type KeyEvent struct {
HandlerEvent
key d2interface.Key
// Duration represents the number of frames this key has been pressed for
duration int
}
func (e *KeyEvent) Key() d2interface.Key {
return e.key
}
func (e *KeyEvent) Duration() int {
return e.duration
}
type MouseEvent struct {
HandlerEvent
mouseButton d2interface.MouseButton
}
func (e *MouseEvent) KeyMod() d2interface.KeyMod {
return e.HandlerEvent.keyMod
}
func (e *MouseEvent) ButtonMod() d2interface.MouseButtonMod {
return e.HandlerEvent.buttonMod
}
func (e *MouseEvent) X() int {
return e.HandlerEvent.x
}
func (e *MouseEvent) Y() int {
return e.HandlerEvent.y
}
func (e *MouseEvent) Button() d2interface.MouseButton {
return e.mouseButton
}
type MouseMoveEvent struct {
HandlerEvent
}
func (e *MouseMoveEvent) KeyMod() d2interface.KeyMod {
return e.HandlerEvent.keyMod
}
func (e *MouseMoveEvent) ButtonMod() d2interface.MouseButtonMod {
return e.HandlerEvent.buttonMod
}
func (e *MouseMoveEvent) X() int {
return e.HandlerEvent.x
}
func (e *MouseMoveEvent) Y() int {
return e.HandlerEvent.y
}

View File

@ -2,60 +2,27 @@ package d2input
import (
"sort"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
)
// Priority of the event handler
type Priority int
//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
)
// Handler is an event handler
type Handler interface{}
type inputManager struct {
inputService InputService
inputService d2interface.InputService
cursorX int
cursorY int
buttonMod MouseButtonMod
keyMod KeyMod
buttonMod d2interface.MouseButtonMod
keyMod d2interface.KeyMod
entries handlerEntryList
}
func (im *inputManager) advance(_ float64) error {
// Advance advances the inputManager
func (im *inputManager) Advance(_, _ float64) error {
im.updateKeyMod()
im.updateButtonMod()
cursorX, cursorY := im.inputService.CursorPosition()
im.keyMod = 0
if im.inputService.IsKeyPressed(KeyAlt) {
im.keyMod |= KeyModAlt
}
if im.inputService.IsKeyPressed(KeyControl) {
im.keyMod |= KeyModControl
}
if im.inputService.IsKeyPressed(KeyShift) {
im.keyMod |= KeyModShift
}
im.buttonMod = 0
if im.inputService.IsMouseButtonPressed(MouseButtonLeft) {
im.buttonMod |= MouseButtonModLeft
}
if im.inputService.IsMouseButtonPressed(MouseButtonMiddle) {
im.buttonMod |= MouseButtonModMiddle
}
if im.inputService.IsMouseButtonPressed(MouseButtonRight) {
im.buttonMod |= MouseButtonModRight
}
eventBase := HandlerEvent{
im.keyMod,
im.buttonMod,
@ -63,120 +30,216 @@ func (im *inputManager) advance(_ float64) error {
cursorY,
}
for key := keyMin; key <= keyMax; key++ {
if im.inputService.IsKeyJustPressed(key) {
event := KeyEvent{HandlerEvent: eventBase, Key: key}
im.propagate(func(handler Handler) bool {
if l, ok := handler.(KeyDownHandler); ok {
return l.OnKeyDown(event)
}
return false
})
}
if im.inputService.IsKeyPressed(key) {
event := KeyEvent{HandlerEvent: eventBase, Key: key, Duration: im.inputService.KeyPressDuration(key)}
im.propagate(func(handler Handler) bool {
if l, ok := handler.(KeyRepeatHandler); ok {
return l.OnKeyRepeat(event)
}
return false
})
}
if im.inputService.IsKeyJustReleased(key) {
event := KeyEvent{HandlerEvent: eventBase, Key: key}
im.propagate(func(handler Handler) bool {
if l, ok := handler.(KeyUpHandler); ok {
return l.OnKeyUp(event)
}
return false
})
}
for key := d2interface.KeyMin; key <= d2interface.KeyMax; key++ {
im.updateJustPressedKey(key, eventBase)
im.updateJustReleasedKey(key, eventBase)
im.updatePressedKey(key, eventBase)
}
if chars := im.inputService.InputChars(); len(chars) > 0 {
event := KeyCharsEvent{eventBase, chars}
im.propagate(func(handler Handler) bool {
if l, ok := handler.(KeyCharsHandler); ok {
l.OnKeyChars(event)
}
im.updateInputChars(eventBase)
return false
})
for button := d2interface.MouseButtonMin; button <= d2interface.MouseButtonMax; button++ {
im.updateJustPressedButton(button, eventBase)
im.updateJustReleasedButton(button, eventBase)
im.updatePressedButton(button, eventBase)
}
for button := mouseButtonMin; button <= mouseButtonMax; button++ {
if im.inputService.IsMouseButtonJustPressed(button) {
event := MouseEvent{eventBase, button}
im.propagate(func(handler Handler) bool {
if l, ok := handler.(MouseButtonDownHandler); ok {
return l.OnMouseButtonDown(event)
}
return false
})
}
if im.inputService.IsMouseButtonJustReleased(button) {
event := MouseEvent{eventBase, button}
im.propagate(func(handler Handler) bool {
if l, ok := handler.(MouseButtonUpHandler); ok {
return l.OnMouseButtonUp(event)
}
return false
})
}
if im.inputService.IsMouseButtonPressed(button) {
event := MouseEvent{eventBase, button}
im.propagate(func(handler Handler) bool {
if l, ok := handler.(MouseButtonRepeatHandler); ok {
return l.OnMouseButtonRepeat(event)
}
return false
})
}
}
if im.cursorX != cursorX || im.cursorY != cursorY {
event := MouseMoveEvent{eventBase}
im.propagate(func(handler Handler) bool {
if l, ok := handler.(MouseMoveHandler); ok {
return l.OnMouseMove(event)
}
return false
})
im.cursorX, im.cursorY = cursorX, cursorY
}
im.updateCursor(cursorX, cursorY, eventBase)
return nil
}
func (im *inputManager) bindHandler(handler Handler, priority Priority) error {
func (im *inputManager) updateKeyMod() {
im.keyMod = 0
if im.inputService.IsKeyPressed(d2interface.KeyAlt) {
im.keyMod |= d2interface.KeyModAlt
}
if im.inputService.IsKeyPressed(d2interface.KeyControl) {
im.keyMod |= d2interface.KeyModControl
}
if im.inputService.IsKeyPressed(d2interface.KeyShift) {
im.keyMod |= d2interface.KeyModShift
}
}
func (im *inputManager) updateButtonMod() {
im.buttonMod = 0
if im.inputService.IsMouseButtonPressed(d2interface.MouseButtonLeft) {
im.buttonMod |= d2interface.MouseButtonModLeft
}
if im.inputService.IsMouseButtonPressed(d2interface.MouseButtonMiddle) {
im.buttonMod |= d2interface.MouseButtonModMiddle
}
if im.inputService.IsMouseButtonPressed(d2interface.MouseButtonRight) {
im.buttonMod |= d2interface.MouseButtonModRight
}
}
func (im *inputManager) updateJustPressedKey(k d2interface.Key, e HandlerEvent) {
if im.inputService.IsKeyJustPressed(k) {
event := KeyEvent{HandlerEvent: e, key: k}
fn := func(handler d2interface.InputEventHandler) bool {
if l, ok := handler.(d2interface.KeyDownHandler); ok {
return l.OnKeyDown(&event)
}
return false
}
im.propagate(fn)
}
}
func (im *inputManager) updateJustReleasedKey(k d2interface.Key, e HandlerEvent) {
if im.inputService.IsKeyJustReleased(k) {
event := KeyEvent{HandlerEvent: e, key: k}
fn := func(handler d2interface.InputEventHandler) bool {
if l, ok := handler.(d2interface.KeyUpHandler); ok {
return l.OnKeyUp(&event)
}
return false
}
im.propagate(fn)
}
}
func (im *inputManager) updatePressedKey(k d2interface.Key, e HandlerEvent) {
if im.inputService.IsKeyPressed(k) {
event := KeyEvent{
HandlerEvent: e,
key: k,
duration: im.inputService.KeyPressDuration(k),
}
fn := func(handler d2interface.InputEventHandler) bool {
if l, ok := handler.(d2interface.KeyRepeatHandler); ok {
return l.OnKeyRepeat(&event)
}
return false
}
im.propagate(fn)
}
}
func (im *inputManager) updateInputChars(eventBase HandlerEvent) {
if chars := im.inputService.InputChars(); len(chars) > 0 {
event := KeyCharsEvent{eventBase, chars}
fn := func(handler d2interface.InputEventHandler) bool {
if l, ok := handler.(d2interface.KeyCharsHandler); ok {
l.OnKeyChars(&event)
}
return false
}
im.propagate(fn)
}
}
func (im *inputManager) updateJustPressedButton(b d2interface.MouseButton, e HandlerEvent) {
if im.inputService.IsMouseButtonJustPressed(b) {
event := MouseEvent{e, b}
fn := func(handler d2interface.InputEventHandler) bool {
if l, ok := handler.(d2interface.MouseButtonDownHandler); ok {
return l.OnMouseButtonDown(&event)
}
return false
}
im.propagate(fn)
}
}
func (im *inputManager) updateJustReleasedButton(b d2interface.MouseButton, e HandlerEvent) {
if im.inputService.IsMouseButtonJustReleased(b) {
event := MouseEvent{e, b}
fn := func(handler d2interface.InputEventHandler) bool {
if l, ok := handler.(d2interface.MouseButtonUpHandler); ok {
return l.OnMouseButtonUp(&event)
}
return false
}
im.propagate(fn)
}
}
func (im *inputManager) updatePressedButton(b d2interface.MouseButton, e HandlerEvent) {
if im.inputService.IsMouseButtonPressed(b) {
event := MouseEvent{e, b}
fn := func(handler d2interface.InputEventHandler) bool {
if l, ok := handler.(d2interface.MouseButtonRepeatHandler); ok {
return l.OnMouseButtonRepeat(&event)
}
return false
}
im.propagate(fn)
}
}
func (im *inputManager) updateCursor(cursorX, cursorY int, e HandlerEvent) {
if im.cursorX != cursorX || im.cursorY != cursorY {
event := MouseMoveEvent{e}
fn := func(handler d2interface.InputEventHandler) bool {
if l, ok := handler.(d2interface.MouseMoveHandler); ok {
return l.OnMouseMove(&event)
}
return false
}
im.propagate(fn)
im.cursorX, im.cursorY = cursorX, cursorY
}
}
// BindHandlerWithPriority adds an event handler with a specific call priority
func (im *inputManager) BindHandlerWithPriority(
h d2interface.InputEventHandler,
p d2interface.Priority) error {
return singleton.bindHandler(h, p)
}
// BindHandler adds an event handler
func (im *inputManager) BindHandler(h d2interface.InputEventHandler) error {
return im.bindHandler(h, d2interface.PriorityDefault)
}
// BindHandler adds an event handler
func (im *inputManager) bindHandler(h d2interface.InputEventHandler, p d2interface.Priority) error {
for _, entry := range im.entries {
if entry.handler == handler {
if entry.handler == h {
return ErrHasReg
}
}
im.entries = append(im.entries, handlerEntry{handler, priority})
entry := handlerEntry{h, p}
im.entries = append(im.entries, entry)
sort.Sort(im.entries)
return nil
}
func (im *inputManager) unbindHandler(handler Handler) error {
// UnbindHandler removes a previously bound event handler
func (im *inputManager) UnbindHandler(handler d2interface.InputEventHandler) error {
for i, entry := range im.entries {
if entry.handler == handler {
copy(im.entries[i:], im.entries[i+1:])
im.entries = im.entries[:len(im.entries)-1]
return nil
}
}
@ -184,8 +247,9 @@ func (im *inputManager) unbindHandler(handler Handler) error {
return ErrNotReg
}
func (im *inputManager) propagate(callback func(Handler) bool) {
var priority Priority
func (im *inputManager) propagate(callback func(d2interface.InputEventHandler) bool) {
var priority d2interface.Priority
var handled bool
for _, entry := range im.entries {
@ -202,8 +266,8 @@ func (im *inputManager) propagate(callback func(Handler) bool) {
}
type handlerEntry struct {
handler Handler
priority Priority
handler d2interface.InputEventHandler
priority d2interface.Priority
}
type handlerEntryList []handlerEntry

View File

@ -12,7 +12,7 @@ func Initialize() (d2interface.Terminal, error) {
return nil, err
}
if err := d2input.BindHandlerWithPriority(term, d2input.PriorityHigh); err != nil {
if err := d2input.BindHandlerWithPriority(term, d2interface.PriorityHigh); err != nil {
return nil, err
}

View File

@ -15,7 +15,6 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
)
// TermCategory applies styles to the lines in the Terminal
@ -103,8 +102,8 @@ func (t *terminal) Advance(elapsed float64) error {
return nil
}
func (t *terminal) OnKeyDown(event d2input.KeyEvent) bool {
if event.Key == d2input.KeyGraveAccent {
func (t *terminal) OnKeyDown(event d2interface.KeyEvent) bool {
if event.Key() == d2interface.KeyGraveAccent {
t.toggleTerminal()
}
@ -112,27 +111,27 @@ func (t *terminal) OnKeyDown(event d2input.KeyEvent) bool {
return false
}
switch event.Key {
case d2input.KeyEscape:
switch event.Key() {
case d2interface.KeyEscape:
t.command = ""
case d2input.KeyEnd:
case d2interface.KeyEnd:
t.outputIndex = 0
case d2input.KeyHome:
case d2interface.KeyHome:
t.outputIndex = d2common.MaxInt(0, len(t.outputHistory)-t.lineCount)
case d2input.KeyPageUp:
case d2interface.KeyPageUp:
maxOutputIndex := d2common.MaxInt(0, len(t.outputHistory)-t.lineCount)
if t.outputIndex += t.lineCount; t.outputIndex >= maxOutputIndex {
t.outputIndex = maxOutputIndex
}
case d2input.KeyPageDown:
case d2interface.KeyPageDown:
if t.outputIndex -= t.lineCount; t.outputIndex < 0 {
t.outputIndex = 0
}
case d2input.KeyUp, d2input.KeyDown:
t.handleControlKey(event.Key, event.KeyMod)
case d2input.KeyEnter:
case d2interface.KeyUp, d2interface.KeyDown:
t.handleControlKey(event.Key(), event.KeyMod())
case d2interface.KeyEnter:
t.processCommand()
case d2input.KeyBackspace:
case d2interface.KeyBackspace:
if len(t.command) > 0 {
t.command = t.command[:len(t.command)-1]
}
@ -168,10 +167,10 @@ func (t *terminal) processCommand() {
t.command = ""
}
func (t *terminal) handleControlKey(eventKey d2input.Key, keyMod d2input.KeyMod) {
func (t *terminal) handleControlKey(eventKey d2interface.Key, keyMod d2interface.KeyMod) {
switch eventKey {
case d2input.KeyUp:
if keyMod == d2input.KeyModControl {
case d2interface.KeyUp:
if keyMod == d2interface.KeyModControl {
t.lineCount = d2common.MaxInt(0, t.lineCount-1)
} else if len(t.commandHistory) > 0 {
t.command = t.commandHistory[t.commandIndex]
@ -181,8 +180,8 @@ func (t *terminal) handleControlKey(eventKey d2input.Key, keyMod d2input.KeyMod)
t.commandIndex--
}
}
case d2input.KeyDown:
if keyMod == d2input.KeyModControl {
case d2interface.KeyDown:
if keyMod == d2interface.KeyModControl {
t.lineCount = d2common.MinInt(t.lineCount+1, termRowCountMax)
}
}
@ -196,14 +195,14 @@ func (t *terminal) toggleTerminal() {
}
}
func (t *terminal) OnKeyChars(event d2input.KeyCharsEvent) bool {
func (t *terminal) OnKeyChars(event d2interface.KeyCharsEvent) bool {
if !t.IsVisible() {
return false
}
var handled bool
for _, c := range event.Chars {
for _, c := range event.Chars() {
if c != '`' {
t.command += string(c)
handled = true

View File

@ -52,9 +52,9 @@ func AddWidget(widget Widget) {
singleton.widgets = append(singleton.widgets, widget)
}
func (u *UI) OnMouseButtonUp(event d2input.MouseEvent) bool {
singleton.CursorX, singleton.CursorY = event.X, event.Y
if event.Button == d2input.MouseButtonLeft {
func (u *UI) OnMouseButtonUp(event d2interface.MouseEvent) bool {
singleton.CursorX, singleton.CursorY = event.X(), event.Y()
if event.Button() == d2interface.MouseButtonLeft {
singleton.cursorButtons |= CursorButtonLeft
// activate previously pressed widget if cursor is still hovering
w := singleton.pressedWidget
@ -69,9 +69,9 @@ func (u *UI) OnMouseButtonUp(event d2input.MouseEvent) bool {
return false
}
func (u *UI) OnMouseButtonDown(event d2input.MouseEvent) bool {
singleton.CursorX, singleton.CursorY = event.X, event.Y
if event.Button == d2input.MouseButtonLeft {
func (u *UI) OnMouseButtonDown(event d2interface.MouseEvent) bool {
singleton.CursorX, singleton.CursorY = event.X(), event.Y()
if event.Button() == d2interface.MouseButtonLeft {
// find and press a widget on screen
singleton.pressedWidget = nil
for _, w := range singleton.widgets {
@ -83,7 +83,7 @@ func (u *UI) OnMouseButtonDown(event d2input.MouseEvent) bool {
}
}
}
if event.Button == d2input.MouseButtonRight {
if event.Button() == d2interface.MouseButtonRight {
singleton.cursorButtons |= CursorButtonRight
}
return false

View File

@ -8,7 +8,6 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
)
// TextBox with cursor focus
@ -58,11 +57,11 @@ func (v *TextBox) Render(target d2interface.Surface) {
}
}
func (v *TextBox) OnKeyChars(event d2input.KeyCharsEvent) bool {
func (v *TextBox) OnKeyChars(event d2interface.KeyCharsEvent) bool {
if !(focusedTextBox == v) || !v.visible || !v.enabled {
return false
}
newText := string(event.Chars)
newText := string(event.Chars())
if len(newText) > 0 {
v.text += newText
v.SetText(v.text)
@ -71,8 +70,8 @@ func (v *TextBox) OnKeyChars(event d2input.KeyCharsEvent) bool {
return false
}
func (v *TextBox) OnKeyRepeat(event d2input.KeyEvent) bool {
if event.Key == d2input.KeyBackspace && debounceEvents(event.Duration) {
func (v *TextBox) OnKeyRepeat(event d2interface.KeyEvent) bool {
if event.Key() == d2interface.KeyBackspace && debounceEvents(event.Duration()) {
if len(v.text) >= 1 {
v.text = v.text[:len(v.text)-1]
}

View File

@ -280,10 +280,10 @@ func (v *CharacterSelect) moveSelectionBox() {
}
// OnMouseButtonDown is called when a mouse button is clicked
func (v *CharacterSelect) OnMouseButtonDown(event d2input.MouseEvent) bool {
func (v *CharacterSelect) OnMouseButtonDown(event d2interface.MouseEvent) bool {
if !v.showDeleteConfirmation {
if event.Button == d2input.MouseButtonLeft {
mx, my := event.X, event.Y
if event.Button() == d2interface.MouseButtonLeft {
mx, my := event.X(), event.Y()
bw := 272
bh := 92
localMouseX := mx - 37

View File

@ -7,7 +7,6 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2screen"
)
@ -255,13 +254,13 @@ func (m *EscapeMenu) addTitle(l *layout, text string) {
func (m *EscapeMenu) addBigSelectionLabel(l *layout, text string, targetLayout layoutID) {
guiLabel, _ := l.AddLabel(text, d2gui.FontStyle42Units)
label := &showLayoutLabel{Label: guiLabel, target: targetLayout, showLayout: m.showLayout}
label.SetMouseClickHandler(func(_ d2input.MouseEvent) {
label.SetMouseClickHandler(func(_ d2interface.MouseEvent) {
label.Trigger()
})
elID := len(l.actionableElements)
label.SetMouseEnterHandler(func(_ d2input.MouseMoveEvent) {
label.SetMouseEnterHandler(func(_ d2interface.MouseMoveEvent) {
m.onHoverElement(elID)
})
l.AddSpacerStatic(10, labelGutter)
@ -272,13 +271,13 @@ func (m *EscapeMenu) addPreviousMenuLabel(l *layout) {
l.AddSpacerStatic(10, labelGutter)
guiLabel, _ := l.AddLabel("PREVIOUS MENU", d2gui.FontStyle30Units)
label := &showLayoutLabel{Label: guiLabel, target: optionsLayoutID, showLayout: m.showLayout}
label.SetMouseClickHandler(func(_ d2input.MouseEvent) {
label.SetMouseClickHandler(func(_ d2interface.MouseEvent) {
label.Trigger()
})
elID := len(l.actionableElements)
label.SetMouseEnterHandler(func(_ d2input.MouseMoveEvent) {
label.SetMouseEnterHandler(func(_ d2interface.MouseMoveEvent) {
m.onHoverElement(elID)
})
@ -297,7 +296,7 @@ func (m *EscapeMenu) addEnumLabel(l *layout, optID optionID, text string, values
elID := len(l.actionableElements)
layout.SetMouseEnterHandler(func(_ d2input.MouseMoveEvent) {
layout.SetMouseEnterHandler(func(_ d2interface.MouseMoveEvent) {
m.onHoverElement(elID)
})
layout.AddSpacerDynamic()
@ -312,7 +311,7 @@ func (m *EscapeMenu) addEnumLabel(l *layout, optID optionID, text string, values
updateValue: m.onUpdateValue,
}
layout.SetMouseClickHandler(func(_ d2input.MouseEvent) {
layout.SetMouseClickHandler(func(_ d2interface.MouseEvent) {
label.Trigger()
})
l.AddSpacerStatic(10, labelGutter)
@ -434,15 +433,15 @@ func (m *EscapeMenu) onEnterKey() {
}
// OnKeyDown defines the actions of the Escape Menu when a key is pressed
func (m *EscapeMenu) OnKeyDown(event d2input.KeyEvent) bool {
switch event.Key {
case d2input.KeyEscape:
func (m *EscapeMenu) OnKeyDown(event d2interface.KeyEvent) bool {
switch event.Key() {
case d2interface.KeyEscape:
m.onEscKey()
case d2input.KeyUp:
case d2interface.KeyUp:
m.onUpKey()
case d2input.KeyDown:
case d2interface.KeyDown:
m.onDownKey()
case d2input.KeyEnter:
case d2interface.KeyEnter:
m.onEnterKey()
default:
return false

View File

@ -429,8 +429,8 @@ func (v *MainMenu) Advance(tickTime float64) error {
}
// OnMouseButtonDown is called when a mouse button is clicked
func (v *MainMenu) OnMouseButtonDown(event d2input.MouseEvent) bool {
if v.screenMode == screenModeTrademark && event.Button == d2input.MouseButtonLeft {
func (v *MainMenu) OnMouseButtonDown(event d2interface.MouseEvent) bool {
if v.screenMode == screenModeTrademark && event.Button() == d2interface.MouseButtonLeft {
v.setScreenMode(screenModeMainMenu)
return true
}

View File

@ -292,28 +292,28 @@ func (met *MapEngineTest) Advance(tickTime float64) error {
}
// OnKeyRepeat is called to handle repeated key presses
func (met *MapEngineTest) OnKeyRepeat(event d2input.KeyEvent) bool {
func (met *MapEngineTest) OnKeyRepeat(event d2interface.KeyEvent) bool {
var moveSpeed float64 = 8
if event.KeyMod == d2input.KeyModShift {
if event.KeyMod() == d2interface.KeyModShift {
moveSpeed *= 2
}
if event.Key == d2input.KeyDown {
if event.Key() == d2interface.KeyDown {
met.mapRenderer.MoveCameraBy(0, moveSpeed)
return true
}
if event.Key == d2input.KeyUp {
if event.Key() == d2interface.KeyUp {
met.mapRenderer.MoveCameraBy(0, -moveSpeed)
return true
}
if event.Key == d2input.KeyRight {
if event.Key() == d2interface.KeyRight {
met.mapRenderer.MoveCameraBy(moveSpeed, 0)
return true
}
if event.Key == d2input.KeyLeft {
if event.Key() == d2interface.KeyLeft {
met.mapRenderer.MoveCameraBy(-moveSpeed, 0)
return true
}
@ -322,18 +322,18 @@ func (met *MapEngineTest) OnKeyRepeat(event d2input.KeyEvent) bool {
}
// OnKeyDown defines the actions of the Map Engine Test screen when a key is pressed
func (met *MapEngineTest) OnKeyDown(event d2input.KeyEvent) bool {
if event.Key == d2input.KeyEscape {
func (met *MapEngineTest) OnKeyDown(event d2interface.KeyEvent) bool {
if event.Key() == d2interface.KeyEscape {
os.Exit(0)
return true
}
if event.Key == d2input.KeyN {
switch event.KeyMod {
case d2input.KeyModControl:
if event.Key() == d2interface.KeyN {
switch event.KeyMod() {
case d2interface.KeyModControl:
met.fileIndex++
d2screen.SetNextScreen(met)
case d2input.KeyModShift:
case d2interface.KeyModShift:
met.levelPreset = increment(met.levelPreset, met.regionSpec.startPresetIndex, met.regionSpec.endPresetIndex)
d2screen.SetNextScreen(met)
default:
@ -344,12 +344,12 @@ func (met *MapEngineTest) OnKeyDown(event d2input.KeyEvent) bool {
return true
}
if event.Key == d2input.KeyP {
switch event.KeyMod {
case d2input.KeyModControl:
if event.Key() == d2interface.KeyP {
switch event.KeyMod() {
case d2interface.KeyModControl:
met.fileIndex--
d2screen.SetNextScreen(met)
case d2input.KeyModShift:
case d2interface.KeyModShift:
met.levelPreset = decrement(met.levelPreset, met.regionSpec.startPresetIndex, met.regionSpec.endPresetIndex)
d2screen.SetNextScreen(met)
default:

View File

@ -13,7 +13,6 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapengine"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2maprenderer"
@ -125,29 +124,29 @@ func NewGameControls(renderer d2interface.Renderer, hero *d2mapentity.Player, ma
return gc
}
func (g *GameControls) OnKeyRepeat(event d2input.KeyEvent) bool {
func (g *GameControls) OnKeyRepeat(event d2interface.KeyEvent) bool {
if g.FreeCam {
var moveSpeed float64 = 8
if event.KeyMod == d2input.KeyModShift {
if event.KeyMod() == d2interface.KeyModShift {
moveSpeed *= 2
}
if event.Key == d2input.KeyDown {
if event.Key() == d2interface.KeyDown {
g.mapRenderer.MoveCameraBy(0, moveSpeed)
return true
}
if event.Key == d2input.KeyUp {
if event.Key() == d2interface.KeyUp {
g.mapRenderer.MoveCameraBy(0, -moveSpeed)
return true
}
if event.Key == d2input.KeyRight {
if event.Key() == d2interface.KeyRight {
g.mapRenderer.MoveCameraBy(moveSpeed, 0)
return true
}
if event.Key == d2input.KeyLeft {
if event.Key() == d2interface.KeyLeft {
g.mapRenderer.MoveCameraBy(-moveSpeed, 0)
return true
}
@ -156,22 +155,22 @@ func (g *GameControls) OnKeyRepeat(event d2input.KeyEvent) bool {
return false
}
func (g *GameControls) OnKeyDown(event d2input.KeyEvent) bool {
switch event.Key {
case d2input.KeyEscape:
func (g *GameControls) OnKeyDown(event d2interface.KeyEvent) bool {
switch event.Key() {
case d2interface.KeyEscape:
if g.inventory.IsOpen() || g.heroStatsPanel.IsOpen() {
g.inventory.Close()
g.heroStatsPanel.Close()
g.updateLayout()
break
}
case d2input.KeyI:
case d2interface.KeyI:
g.inventory.Toggle()
g.updateLayout()
case d2input.KeyC:
case d2interface.KeyC:
g.heroStatsPanel.Toggle()
g.updateLayout()
case d2input.KeyR:
case d2interface.KeyR:
g.onToggleRunButton()
default:
return false
@ -183,19 +182,28 @@ var lastLeftBtnActionTime float64 = 0
var lastRightBtnActionTime float64 = 0
var mouseBtnActionsTreshhold = 0.25
func (g *GameControls) OnMouseButtonRepeat(event d2input.MouseEvent) bool {
px, py := g.mapRenderer.ScreenToWorld(event.X, event.Y)
func (g *GameControls) OnMouseButtonRepeat(event d2interface.MouseEvent) bool {
px, py := g.mapRenderer.ScreenToWorld(event.X(), event.Y())
px = float64(int(px*10)) / 10.0
py = float64(int(py*10)) / 10.0
now := d2common.Now()
if event.Button == d2input.MouseButtonLeft && now-lastLeftBtnActionTime >= mouseBtnActionsTreshhold && !g.isInActiveMenusRect(event.X, event.Y) {
button := event.Button()
isLeft := button == d2interface.MouseButtonLeft
isRight := button == d2interface.MouseButtonRight
lastLeft:= now-lastLeftBtnActionTime
lastRight:= now-lastRightBtnActionTime
inRect := !g.isInActiveMenusRect(event.X(), event.Y())
shouldDoLeft := lastLeft >= mouseBtnActionsTreshhold
shouldDoRight := lastRight >= mouseBtnActionsTreshhold
if isLeft && shouldDoLeft && inRect {
lastLeftBtnActionTime = now
g.inputListener.OnPlayerMove(px, py)
return true
}
if event.Button == d2input.MouseButtonRight && now-lastRightBtnActionTime >= mouseBtnActionsTreshhold && !g.isInActiveMenusRect(event.X, event.Y) {
if isRight && shouldDoRight && inRect {
lastRightBtnActionTime = now
g.inputListener.OnPlayerCast(missileID, px, py)
return true
@ -204,8 +212,8 @@ func (g *GameControls) OnMouseButtonRepeat(event d2input.MouseEvent) bool {
return true
}
func (g *GameControls) OnMouseMove(event d2input.MouseMoveEvent) bool {
mx, my := event.X, event.Y
func (g *GameControls) OnMouseMove(event d2interface.MouseMoveEvent) bool {
mx, my := event.X(), event.Y()
g.lastMouseX = mx
g.lastMouseY = my
@ -219,8 +227,8 @@ func (g *GameControls) OnMouseMove(event d2input.MouseMoveEvent) bool {
return false
}
func (g *GameControls) OnMouseButtonDown(event d2input.MouseEvent) bool {
mx, my := event.X, event.Y
func (g *GameControls) OnMouseButtonDown(event d2interface.MouseEvent) bool {
mx, my := event.X(), event.Y()
for i := range g.actionableRegions {
// If click is on a game control element
if g.actionableRegions[i].Rect.IsInRect(mx, my) {
@ -233,13 +241,13 @@ func (g *GameControls) OnMouseButtonDown(event d2input.MouseEvent) bool {
px = float64(int(px*10)) / 10.0
py = float64(int(py*10)) / 10.0
if event.Button == d2input.MouseButtonLeft && !g.isInActiveMenusRect(mx, my) {
if event.Button() == d2interface.MouseButtonLeft && !g.isInActiveMenusRect(mx, my) {
lastLeftBtnActionTime = d2common.Now()
g.inputListener.OnPlayerMove(px, py)
return true
}
if event.Button == d2input.MouseButtonRight && !g.isInActiveMenusRect(mx, my) {
if event.Button() == d2interface.MouseButtonRight && !g.isInActiveMenusRect(mx, my) {
lastRightBtnActionTime = d2common.Now()
g.inputListener.OnPlayerCast(missileID, px, py)
return true

View File

@ -4,11 +4,9 @@ import (
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render/ebiten"
"github.com/OpenDiablo2/OpenDiablo2/d2app"
ebiten_input "github.com/OpenDiablo2/OpenDiablo2/d2core/d2input/ebiten"
ebiten2 "github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio/ebiten"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
@ -38,8 +36,7 @@ func main() {
panic(err)
}
d2input.Initialize(ebiten_input.InputService{}) // TODO d2input singleton must be init before d2term
d2input.Create() // TODO d2input singleton must be init before d2term
term, err := d2term.Initialize()
if err != nil {