mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-12-26 12:06:24 -05:00
295 lines
6.8 KiB
Go
295 lines
6.8 KiB
Go
package d2input
|
|
|
|
import (
|
|
"sort"
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
|
ebiten_input "github.com/OpenDiablo2/OpenDiablo2/d2core/d2input/ebiten"
|
|
)
|
|
|
|
type inputManager struct {
|
|
inputService d2interface.InputService
|
|
cursorX int
|
|
cursorY int
|
|
|
|
buttonMod d2enum.MouseButtonMod
|
|
keyMod d2enum.KeyMod
|
|
|
|
entries handlerEntryList
|
|
}
|
|
|
|
// NewInputManager returns a new input manager instance
|
|
func NewInputManager() d2interface.InputManager {
|
|
return &inputManager{
|
|
inputService: ebiten_input.InputService{},
|
|
}
|
|
}
|
|
|
|
// Advance advances the inputManager
|
|
func (im *inputManager) Advance(_, _ float64) error {
|
|
im.updateKeyMod()
|
|
im.updateButtonMod()
|
|
|
|
cursorX, cursorY := im.inputService.CursorPosition()
|
|
eventBase := HandlerEvent{
|
|
im.keyMod,
|
|
im.buttonMod,
|
|
cursorX,
|
|
cursorY,
|
|
}
|
|
|
|
for key := d2enum.KeyMin; key <= d2enum.KeyMax; key++ {
|
|
im.updateJustPressedKey(key, eventBase)
|
|
im.updateJustReleasedKey(key, eventBase)
|
|
im.updatePressedKey(key, eventBase)
|
|
}
|
|
|
|
im.updateInputChars(eventBase)
|
|
|
|
for button := d2enum.MouseButtonMin; button <= d2enum.MouseButtonMax; button++ {
|
|
im.updateJustPressedButton(button, eventBase)
|
|
im.updateJustReleasedButton(button, eventBase)
|
|
im.updatePressedButton(button, eventBase)
|
|
}
|
|
|
|
im.updateCursor(cursorX, cursorY, eventBase)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (im *inputManager) updateKeyMod() {
|
|
im.keyMod = 0
|
|
if im.inputService.IsKeyPressed(d2enum.KeyAlt) {
|
|
im.keyMod |= d2enum.KeyModAlt
|
|
}
|
|
|
|
if im.inputService.IsKeyPressed(d2enum.KeyControl) {
|
|
im.keyMod |= d2enum.KeyModControl
|
|
}
|
|
|
|
if im.inputService.IsKeyPressed(d2enum.KeyShift) {
|
|
im.keyMod |= d2enum.KeyModShift
|
|
}
|
|
}
|
|
|
|
func (im *inputManager) updateButtonMod() {
|
|
im.buttonMod = 0
|
|
if im.inputService.IsMouseButtonPressed(d2enum.MouseButtonLeft) {
|
|
im.buttonMod |= d2enum.MouseButtonModLeft
|
|
}
|
|
|
|
if im.inputService.IsMouseButtonPressed(d2enum.MouseButtonMiddle) {
|
|
im.buttonMod |= d2enum.MouseButtonModMiddle
|
|
}
|
|
|
|
if im.inputService.IsMouseButtonPressed(d2enum.MouseButtonRight) {
|
|
im.buttonMod |= d2enum.MouseButtonModRight
|
|
}
|
|
}
|
|
|
|
func (im *inputManager) updateJustPressedKey(k d2enum.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 d2enum.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 d2enum.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 d2enum.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 d2enum.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 d2enum.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 d2enum.Priority) error {
|
|
return im.bindHandler(h, p)
|
|
}
|
|
|
|
// BindHandler adds an event handler
|
|
func (im *inputManager) BindHandler(h d2interface.InputEventHandler) error {
|
|
return im.bindHandler(h, d2enum.PriorityDefault)
|
|
}
|
|
|
|
// BindHandler adds an event handler
|
|
func (im *inputManager) bindHandler(h d2interface.InputEventHandler, p d2enum.Priority) error {
|
|
for _, entry := range im.entries {
|
|
if entry.handler == h {
|
|
return ErrHasReg
|
|
}
|
|
}
|
|
|
|
entry := handlerEntry{h, p}
|
|
im.entries = append(im.entries, entry)
|
|
sort.Sort(im.entries)
|
|
|
|
return nil
|
|
}
|
|
|
|
// 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
|
|
}
|
|
}
|
|
|
|
return ErrNotReg
|
|
}
|
|
|
|
func (im *inputManager) propagate(callback func(d2interface.InputEventHandler) bool) {
|
|
var priority d2enum.Priority
|
|
|
|
var handled bool
|
|
|
|
for _, entry := range im.entries {
|
|
if priority > entry.priority && handled {
|
|
break
|
|
}
|
|
|
|
if callback(entry.handler) {
|
|
handled = true
|
|
}
|
|
|
|
priority = entry.priority
|
|
}
|
|
}
|
|
|
|
type handlerEntry struct {
|
|
handler d2interface.InputEventHandler
|
|
priority d2enum.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
|
|
}
|