1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-11-10 14:26:15 -05:00
OpenDiablo2/d2core/d2input/input_manager.go
Tim Sarbin 2461142fbd
Minor changes to project layout (#276)
* Minor changes to reduce interdependencies on modules.
2020-01-31 23:18:11 -05:00

198 lines
4.0 KiB
Go

package d2input
import (
"sort"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/inpututil"
)
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
}
type inputManager struct {
cursorX int
cursorY int
buttonMod MouseButtonMod
keyMod KeyMod
entries handlerEntryList
}
func (im *inputManager) advance(elapsed float64) error {
cursorX, cursorY := ebiten.CursorPosition()
im.keyMod = 0
if ebiten.IsKeyPressed(ebiten.KeyAlt) {
im.keyMod |= KeyModAlt
}
if ebiten.IsKeyPressed(ebiten.KeyControl) {
im.keyMod |= KeyModControl
}
if ebiten.IsKeyPressed(ebiten.KeyShift) {
im.keyMod |= KeyModShift
}
im.buttonMod = 0
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
im.buttonMod |= MouseButtonModLeft
}
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonMiddle) {
im.buttonMod |= MouseButtonModMiddle
}
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonRight) {
im.buttonMod |= MouseButtonModRight
}
eventBase := HandlerEvent{
im.keyMod,
im.buttonMod,
cursorX,
cursorY,
}
for key := ebiten.Key0; key < ebiten.KeyMax; key++ {
if inpututil.IsKeyJustPressed(key) {
event := KeyEvent{eventBase, Key(key)}
im.propagate(func(handler Handler) bool {
if l, ok := handler.(KeyDownHandler); ok {
return l.OnKeyDown(event)
}
return false
})
}
if ebiten.IsKeyPressed(key) {
event := KeyEvent{eventBase, Key(key)}
im.propagate(func(handler Handler) bool {
if l, ok := handler.(KeyRepeatHandler); ok {
return l.OnKeyRepeat(event)
}
return false
})
}
if inpututil.IsKeyJustReleased(key) {
event := KeyEvent{eventBase, Key(key)}
im.propagate(func(handler Handler) bool {
if l, ok := handler.(KeyUpHandler); ok {
return l.OnKeyUp(event)
}
return false
})
}
}
if chars := ebiten.InputChars(); len(chars) > 0 {
event := KeyCharsEvent{eventBase, chars}
im.propagate(func(handler Handler) bool {
if l, ok := handler.(KeyCharsHandler); ok {
l.OnKeyChars(event)
}
return false
})
}
for button := ebiten.MouseButtonLeft; button < ebiten.MouseButtonMiddle; button++ {
if inpututil.IsMouseButtonJustPressed(button) {
event := MouseEvent{eventBase, MouseButton(button)}
im.propagate(func(handler Handler) bool {
if l, ok := handler.(MouseButtonDownHandler); ok {
return l.OnMouseButtonDown(event)
}
return false
})
}
if inpututil.IsMouseButtonJustReleased(button) {
event := MouseEvent{eventBase, MouseButton(button)}
im.propagate(func(handler Handler) bool {
if l, ok := handler.(MouseButtonUpHandler); ok {
return l.OnMouseButtonUp(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
}
return nil
}
func (im *inputManager) bindHandler(handler Handler, priority Priority) error {
for _, entry := range im.entries {
if entry.handler == handler {
return ErrHasReg
}
}
im.entries = append(im.entries, handlerEntry{handler, priority})
sort.Sort(im.entries)
return nil
}
func (im *inputManager) unbindHandler(handler Handler) 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
}
}
return ErrNotReg
}
func (im *inputManager) propagate(callback func(Handler) bool) {
var priority Priority
var handled bool
for _, entry := range im.entries {
if priority > entry.priority && handled {
break
}
if callback(entry.handler) {
handled = true
}
priority = entry.priority
}
}