mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-11-18 02:16:23 -05:00
Abstract away remaining ebiten references (#409)
* 337 - remove ebiten from character selection * 337 - abstract d2input away from ebiten implementation * WIP 337 - remove ebiten use from d2ui * 337 - fix accidental left->right change * 337 - fix ui button selection bugs * 337 - fix textbox bugs * 337 - fix scrollbar bugs * 337 - address PR comments * 337 - fix invalid hero selection bug Co-authored-by: David Carrell <carrelda@Davids-MacBook-Pro.local>
This commit is contained in:
parent
f729ff6101
commit
37ae98d81b
@ -17,6 +17,7 @@ Intyre
|
|||||||
Gürkan Kaymak
|
Gürkan Kaymak
|
||||||
Maxime "malavv" Lavigne
|
Maxime "malavv" Lavigne
|
||||||
Ripolak
|
Ripolak
|
||||||
|
dafe
|
||||||
|
|
||||||
* DIABLO2 LOGO
|
* DIABLO2 LOGO
|
||||||
Jose Pardilla (th3-prophetman)
|
Jose Pardilla (th3-prophetman)
|
||||||
|
@ -2,8 +2,6 @@ package d2input
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -19,136 +17,6 @@ const (
|
|||||||
PriorityHigh
|
PriorityHigh
|
||||||
)
|
)
|
||||||
|
|
||||||
type Key int
|
|
||||||
|
|
||||||
//noinspection GoUnusedConst
|
|
||||||
const (
|
|
||||||
Key0 = Key(ebiten.Key0)
|
|
||||||
Key1 = Key(ebiten.Key1)
|
|
||||||
Key2 = Key(ebiten.Key2)
|
|
||||||
Key3 = Key(ebiten.Key3)
|
|
||||||
Key4 = Key(ebiten.Key4)
|
|
||||||
Key5 = Key(ebiten.Key5)
|
|
||||||
Key6 = Key(ebiten.Key6)
|
|
||||||
Key7 = Key(ebiten.Key7)
|
|
||||||
Key8 = Key(ebiten.Key8)
|
|
||||||
Key9 = Key(ebiten.Key9)
|
|
||||||
KeyA = Key(ebiten.KeyA)
|
|
||||||
KeyB = Key(ebiten.KeyB)
|
|
||||||
KeyC = Key(ebiten.KeyC)
|
|
||||||
KeyD = Key(ebiten.KeyD)
|
|
||||||
KeyE = Key(ebiten.KeyE)
|
|
||||||
KeyF = Key(ebiten.KeyF)
|
|
||||||
KeyG = Key(ebiten.KeyG)
|
|
||||||
KeyH = Key(ebiten.KeyH)
|
|
||||||
KeyI = Key(ebiten.KeyI)
|
|
||||||
KeyJ = Key(ebiten.KeyJ)
|
|
||||||
KeyK = Key(ebiten.KeyK)
|
|
||||||
KeyL = Key(ebiten.KeyL)
|
|
||||||
KeyM = Key(ebiten.KeyM)
|
|
||||||
KeyN = Key(ebiten.KeyN)
|
|
||||||
KeyO = Key(ebiten.KeyO)
|
|
||||||
KeyP = Key(ebiten.KeyP)
|
|
||||||
KeyQ = Key(ebiten.KeyQ)
|
|
||||||
KeyR = Key(ebiten.KeyR)
|
|
||||||
KeyS = Key(ebiten.KeyS)
|
|
||||||
KeyT = Key(ebiten.KeyT)
|
|
||||||
KeyU = Key(ebiten.KeyU)
|
|
||||||
KeyV = Key(ebiten.KeyV)
|
|
||||||
KeyW = Key(ebiten.KeyW)
|
|
||||||
KeyX = Key(ebiten.KeyX)
|
|
||||||
KeyY = Key(ebiten.KeyY)
|
|
||||||
KeyZ = Key(ebiten.KeyZ)
|
|
||||||
KeyApostrophe = Key(ebiten.KeyApostrophe)
|
|
||||||
KeyBackslash = Key(ebiten.KeyBackslash)
|
|
||||||
KeyBackspace = Key(ebiten.KeyBackspace)
|
|
||||||
KeyCapsLock = Key(ebiten.KeyCapsLock)
|
|
||||||
KeyComma = Key(ebiten.KeyComma)
|
|
||||||
KeyDelete = Key(ebiten.KeyDelete)
|
|
||||||
KeyDown = Key(ebiten.KeyDown)
|
|
||||||
KeyEnd = Key(ebiten.KeyEnd)
|
|
||||||
KeyEnter = Key(ebiten.KeyEnter)
|
|
||||||
KeyEqual = Key(ebiten.KeyEqual)
|
|
||||||
KeyEscape = Key(ebiten.KeyEscape)
|
|
||||||
KeyF1 = Key(ebiten.KeyF1)
|
|
||||||
KeyF2 = Key(ebiten.KeyF2)
|
|
||||||
KeyF3 = Key(ebiten.KeyF3)
|
|
||||||
KeyF4 = Key(ebiten.KeyF4)
|
|
||||||
KeyF5 = Key(ebiten.KeyF5)
|
|
||||||
KeyF6 = Key(ebiten.KeyF6)
|
|
||||||
KeyF7 = Key(ebiten.KeyF7)
|
|
||||||
KeyF8 = Key(ebiten.KeyF8)
|
|
||||||
KeyF9 = Key(ebiten.KeyF9)
|
|
||||||
KeyF10 = Key(ebiten.KeyF10)
|
|
||||||
KeyF11 = Key(ebiten.KeyF11)
|
|
||||||
KeyF12 = Key(ebiten.KeyF12)
|
|
||||||
KeyGraveAccent = Key(ebiten.KeyGraveAccent)
|
|
||||||
KeyHome = Key(ebiten.KeyHome)
|
|
||||||
KeyInsert = Key(ebiten.KeyInsert)
|
|
||||||
KeyKP0 = Key(ebiten.KeyKP0)
|
|
||||||
KeyKP1 = Key(ebiten.KeyKP1)
|
|
||||||
KeyKP2 = Key(ebiten.KeyKP2)
|
|
||||||
KeyKP3 = Key(ebiten.KeyKP3)
|
|
||||||
KeyKP4 = Key(ebiten.KeyKP4)
|
|
||||||
KeyKP5 = Key(ebiten.KeyKP5)
|
|
||||||
KeyKP6 = Key(ebiten.KeyKP6)
|
|
||||||
KeyKP7 = Key(ebiten.KeyKP7)
|
|
||||||
KeyKP8 = Key(ebiten.KeyKP8)
|
|
||||||
KeyKP9 = Key(ebiten.KeyKP9)
|
|
||||||
KeyKPAdd = Key(ebiten.KeyKPAdd)
|
|
||||||
KeyKPDecimal = Key(ebiten.KeyKPDecimal)
|
|
||||||
KeyKPDivide = Key(ebiten.KeyKPDivide)
|
|
||||||
KeyKPEnter = Key(ebiten.KeyKPEnter)
|
|
||||||
KeyKPEqual = Key(ebiten.KeyKPEqual)
|
|
||||||
KeyKPMultiply = Key(ebiten.KeyKPMultiply)
|
|
||||||
KeyKPSubtract = Key(ebiten.KeyKPSubtract)
|
|
||||||
KeyLeft = Key(ebiten.KeyLeft)
|
|
||||||
KeyLeftBracket = Key(ebiten.KeyLeftBracket)
|
|
||||||
KeyMenu = Key(ebiten.KeyMenu)
|
|
||||||
KeyMinus = Key(ebiten.KeyMinus)
|
|
||||||
KeyNumLock = Key(ebiten.KeyNumLock)
|
|
||||||
KeyPageDown = Key(ebiten.KeyPageDown)
|
|
||||||
KeyPageUp = Key(ebiten.KeyPageUp)
|
|
||||||
KeyPause = Key(ebiten.KeyPause)
|
|
||||||
KeyPeriod = Key(ebiten.KeyPeriod)
|
|
||||||
KeyPrintScreen = Key(ebiten.KeyPrintScreen)
|
|
||||||
KeyRight = Key(ebiten.KeyRight)
|
|
||||||
KeyRightBracket = Key(ebiten.KeyRightBracket)
|
|
||||||
KeyScrollLock = Key(ebiten.KeyScrollLock)
|
|
||||||
KeySemicolon = Key(ebiten.KeySemicolon)
|
|
||||||
KeySlash = Key(ebiten.KeySlash)
|
|
||||||
KeySpace = Key(ebiten.KeySpace)
|
|
||||||
KeyTab = Key(ebiten.KeyTab)
|
|
||||||
KeyUp = Key(ebiten.KeyUp)
|
|
||||||
KeyAlt = Key(ebiten.KeyAlt)
|
|
||||||
KeyControl = Key(ebiten.KeyControl)
|
|
||||||
KeyShift = Key(ebiten.KeyShift)
|
|
||||||
)
|
|
||||||
|
|
||||||
type KeyMod int
|
|
||||||
|
|
||||||
const (
|
|
||||||
KeyModAlt = 1 << iota
|
|
||||||
KeyModControl
|
|
||||||
KeyModShift
|
|
||||||
)
|
|
||||||
|
|
||||||
type MouseButton int
|
|
||||||
|
|
||||||
const (
|
|
||||||
MouseButtonLeft = MouseButton(ebiten.MouseButtonLeft)
|
|
||||||
MouseButtonMiddle = MouseButton(ebiten.MouseButtonMiddle)
|
|
||||||
MouseButtonRight = MouseButton(ebiten.MouseButtonRight)
|
|
||||||
)
|
|
||||||
|
|
||||||
type MouseButtonMod int
|
|
||||||
|
|
||||||
const (
|
|
||||||
MouseButtonModLeft MouseButtonMod = 1 << iota
|
|
||||||
MouseButtonModMiddle
|
|
||||||
MouseButtonModRight
|
|
||||||
)
|
|
||||||
|
|
||||||
type HandlerEvent struct {
|
type HandlerEvent struct {
|
||||||
KeyMod KeyMod
|
KeyMod KeyMod
|
||||||
ButtonMod MouseButtonMod
|
ButtonMod MouseButtonMod
|
||||||
@ -159,6 +27,8 @@ type HandlerEvent struct {
|
|||||||
type KeyEvent struct {
|
type KeyEvent struct {
|
||||||
HandlerEvent
|
HandlerEvent
|
||||||
Key Key
|
Key Key
|
||||||
|
// Duration represents the number of frames this key has been pressed for
|
||||||
|
Duration int
|
||||||
}
|
}
|
||||||
|
|
||||||
type KeyCharsEvent struct {
|
type KeyCharsEvent struct {
|
||||||
@ -211,6 +81,12 @@ type MouseMoveHandler interface {
|
|||||||
|
|
||||||
var singleton inputManager
|
var singleton inputManager
|
||||||
|
|
||||||
|
func Initialize(inputService InputService) {
|
||||||
|
singleton = inputManager{
|
||||||
|
inputService: inputService,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Advance(elapsed float64) error {
|
func Advance(elapsed float64) error {
|
||||||
return singleton.advance(elapsed)
|
return singleton.advance(elapsed)
|
||||||
}
|
}
|
||||||
|
156
d2core/d2input/ebiten/ebiten_input.go
Normal file
156
d2core/d2input/ebiten/ebiten_input.go
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
package ebiten
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
|
||||||
|
"github.com/hajimehoshi/ebiten"
|
||||||
|
"github.com/hajimehoshi/ebiten/inpututil"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
mouseButtonToEbiten = map[d2input.MouseButton]ebiten.MouseButton{
|
||||||
|
d2input.MouseButtonLeft: ebiten.MouseButtonLeft,
|
||||||
|
d2input.MouseButtonMiddle: ebiten.MouseButtonMiddle,
|
||||||
|
d2input.MouseButtonRight: ebiten.MouseButtonRight,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// InputService provides an abstraction on ebiten to support handling input events
|
||||||
|
type InputService struct{}
|
||||||
|
|
||||||
|
func (is InputService) CursorPosition() (x int, y int) {
|
||||||
|
return ebiten.CursorPosition()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is InputService) InputChars() []rune {
|
||||||
|
return ebiten.InputChars()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is InputService) IsKeyPressed(key d2input.Key) bool {
|
||||||
|
return ebiten.IsKeyPressed(keyToEbiten[key])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is InputService) IsKeyJustPressed(key d2input.Key) bool {
|
||||||
|
return inpututil.IsKeyJustPressed(keyToEbiten[key])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is InputService) IsKeyJustReleased(key d2input.Key) bool {
|
||||||
|
return inpututil.IsKeyJustReleased(keyToEbiten[key])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is InputService) IsMouseButtonPressed(button d2input.MouseButton) bool {
|
||||||
|
return ebiten.IsMouseButtonPressed(mouseButtonToEbiten[button])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is InputService) IsMouseButtonJustPressed(button d2input.MouseButton) bool {
|
||||||
|
return inpututil.IsMouseButtonJustPressed(mouseButtonToEbiten[button])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is InputService) IsMouseButtonJustReleased(button d2input.MouseButton) bool {
|
||||||
|
return inpututil.IsMouseButtonJustReleased(mouseButtonToEbiten[button])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (is InputService) KeyPressDuration(key d2input.Key) int {
|
||||||
|
return inpututil.KeyPressDuration(keyToEbiten[key])
|
||||||
|
}
|
@ -2,9 +2,6 @@ package d2input
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
"github.com/hajimehoshi/ebiten/inpututil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type handlerEntry struct {
|
type handlerEntry struct {
|
||||||
@ -26,9 +23,22 @@ func (lel handlerEntryList) Less(i, j int) bool {
|
|||||||
return lel[i].priority > lel[j].priority
|
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 {
|
||||||
cursorX int
|
inputService InputService
|
||||||
cursorY int
|
cursorX int
|
||||||
|
cursorY int
|
||||||
|
|
||||||
buttonMod MouseButtonMod
|
buttonMod MouseButtonMod
|
||||||
keyMod KeyMod
|
keyMod KeyMod
|
||||||
@ -36,28 +46,28 @@ type inputManager struct {
|
|||||||
entries handlerEntryList
|
entries handlerEntryList
|
||||||
}
|
}
|
||||||
|
|
||||||
func (im *inputManager) advance(elapsed float64) error {
|
func (im *inputManager) advance(_ float64) error {
|
||||||
cursorX, cursorY := ebiten.CursorPosition()
|
cursorX, cursorY := im.inputService.CursorPosition()
|
||||||
|
|
||||||
im.keyMod = 0
|
im.keyMod = 0
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyAlt) {
|
if im.inputService.IsKeyPressed(KeyAlt) {
|
||||||
im.keyMod |= KeyModAlt
|
im.keyMod |= KeyModAlt
|
||||||
}
|
}
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyControl) {
|
if im.inputService.IsKeyPressed(KeyControl) {
|
||||||
im.keyMod |= KeyModControl
|
im.keyMod |= KeyModControl
|
||||||
}
|
}
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyShift) {
|
if im.inputService.IsKeyPressed(KeyShift) {
|
||||||
im.keyMod |= KeyModShift
|
im.keyMod |= KeyModShift
|
||||||
}
|
}
|
||||||
|
|
||||||
im.buttonMod = 0
|
im.buttonMod = 0
|
||||||
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
|
if im.inputService.IsMouseButtonPressed(MouseButtonLeft) {
|
||||||
im.buttonMod |= MouseButtonModLeft
|
im.buttonMod |= MouseButtonModLeft
|
||||||
}
|
}
|
||||||
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonMiddle) {
|
if im.inputService.IsMouseButtonPressed(MouseButtonMiddle) {
|
||||||
im.buttonMod |= MouseButtonModMiddle
|
im.buttonMod |= MouseButtonModMiddle
|
||||||
}
|
}
|
||||||
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonRight) {
|
if im.inputService.IsMouseButtonPressed(MouseButtonRight) {
|
||||||
im.buttonMod |= MouseButtonModRight
|
im.buttonMod |= MouseButtonModRight
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,9 +78,9 @@ func (im *inputManager) advance(elapsed float64) error {
|
|||||||
cursorY,
|
cursorY,
|
||||||
}
|
}
|
||||||
|
|
||||||
for key := ebiten.Key0; key < ebiten.KeyMax; key++ {
|
for key := keyMin; key < keyMax; key++ {
|
||||||
if inpututil.IsKeyJustPressed(key) {
|
if im.inputService.IsKeyJustPressed(key) {
|
||||||
event := KeyEvent{eventBase, Key(key)}
|
event := KeyEvent{HandlerEvent: eventBase, Key: key}
|
||||||
im.propagate(func(handler Handler) bool {
|
im.propagate(func(handler Handler) bool {
|
||||||
if l, ok := handler.(KeyDownHandler); ok {
|
if l, ok := handler.(KeyDownHandler); ok {
|
||||||
return l.OnKeyDown(event)
|
return l.OnKeyDown(event)
|
||||||
@ -80,8 +90,8 @@ func (im *inputManager) advance(elapsed float64) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if ebiten.IsKeyPressed(key) {
|
if im.inputService.IsKeyPressed(key) {
|
||||||
event := KeyEvent{eventBase, Key(key)}
|
event := KeyEvent{HandlerEvent: eventBase, Key: key, Duration: im.inputService.KeyPressDuration(key)}
|
||||||
im.propagate(func(handler Handler) bool {
|
im.propagate(func(handler Handler) bool {
|
||||||
if l, ok := handler.(KeyRepeatHandler); ok {
|
if l, ok := handler.(KeyRepeatHandler); ok {
|
||||||
return l.OnKeyRepeat(event)
|
return l.OnKeyRepeat(event)
|
||||||
@ -91,8 +101,8 @@ func (im *inputManager) advance(elapsed float64) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if inpututil.IsKeyJustReleased(key) {
|
if im.inputService.IsKeyJustReleased(key) {
|
||||||
event := KeyEvent{eventBase, Key(key)}
|
event := KeyEvent{HandlerEvent: eventBase, Key: key}
|
||||||
im.propagate(func(handler Handler) bool {
|
im.propagate(func(handler Handler) bool {
|
||||||
if l, ok := handler.(KeyUpHandler); ok {
|
if l, ok := handler.(KeyUpHandler); ok {
|
||||||
return l.OnKeyUp(event)
|
return l.OnKeyUp(event)
|
||||||
@ -103,7 +113,7 @@ func (im *inputManager) advance(elapsed float64) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if chars := ebiten.InputChars(); len(chars) > 0 {
|
if chars := im.inputService.InputChars(); len(chars) > 0 {
|
||||||
event := KeyCharsEvent{eventBase, chars}
|
event := KeyCharsEvent{eventBase, chars}
|
||||||
im.propagate(func(handler Handler) bool {
|
im.propagate(func(handler Handler) bool {
|
||||||
if l, ok := handler.(KeyCharsHandler); ok {
|
if l, ok := handler.(KeyCharsHandler); ok {
|
||||||
@ -114,8 +124,8 @@ func (im *inputManager) advance(elapsed float64) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for button := ebiten.MouseButtonLeft; button < ebiten.MouseButtonMiddle; button++ {
|
for button := mouseButtonMin; button < mouseButtonMax; button++ {
|
||||||
if inpututil.IsMouseButtonJustPressed(button) {
|
if im.inputService.IsMouseButtonJustPressed(button) {
|
||||||
event := MouseEvent{eventBase, MouseButton(button)}
|
event := MouseEvent{eventBase, MouseButton(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 {
|
||||||
@ -126,24 +136,21 @@ func (im *inputManager) advance(elapsed float64) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for button := ebiten.MouseButtonLeft; button < ebiten.MouseButtonMiddle; button++ {
|
if im.inputService.IsMouseButtonJustReleased(button) {
|
||||||
if ebiten.IsMouseButtonPressed(button) {
|
|
||||||
event := MouseEvent{eventBase, MouseButton(button)}
|
event := MouseEvent{eventBase, MouseButton(button)}
|
||||||
im.propagate(func(handler Handler) bool {
|
im.propagate(func(handler Handler) bool {
|
||||||
if l, ok := handler.(MouseButtonRepeatHandler); ok {
|
if l, ok := handler.(MouseButtonUpHandler); ok {
|
||||||
return l.OnMouseButtonRepeat(event)
|
return l.OnMouseButtonUp(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
if im.inputService.IsMouseButtonPressed(button) {
|
||||||
|
|
||||||
if inpututil.IsMouseButtonJustReleased(button) {
|
|
||||||
event := MouseEvent{eventBase, MouseButton(button)}
|
event := MouseEvent{eventBase, MouseButton(button)}
|
||||||
im.propagate(func(handler Handler) bool {
|
im.propagate(func(handler Handler) bool {
|
||||||
if l, ok := handler.(MouseButtonUpHandler); ok {
|
if l, ok := handler.(MouseButtonRepeatHandler); ok {
|
||||||
return l.OnMouseButtonUp(event)
|
return l.OnMouseButtonRepeat(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
138
d2core/d2input/key.go
Normal file
138
d2core/d2input/key.go
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
package d2input
|
||||||
|
|
||||||
|
// Key is the physical key of keyboard input
|
||||||
|
type Key int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Key0 Key = iota
|
||||||
|
Key1
|
||||||
|
Key2
|
||||||
|
Key3
|
||||||
|
Key4
|
||||||
|
Key5
|
||||||
|
Key6
|
||||||
|
Key7
|
||||||
|
Key8
|
||||||
|
Key9
|
||||||
|
KeyA
|
||||||
|
KeyB
|
||||||
|
KeyC
|
||||||
|
KeyD
|
||||||
|
KeyE
|
||||||
|
KeyF
|
||||||
|
KeyG
|
||||||
|
KeyH
|
||||||
|
KeyI
|
||||||
|
KeyJ
|
||||||
|
KeyK
|
||||||
|
KeyL
|
||||||
|
KeyM
|
||||||
|
KeyN
|
||||||
|
KeyO
|
||||||
|
KeyP
|
||||||
|
KeyQ
|
||||||
|
KeyR
|
||||||
|
KeyS
|
||||||
|
KeyT
|
||||||
|
KeyU
|
||||||
|
KeyV
|
||||||
|
KeyW
|
||||||
|
KeyX
|
||||||
|
KeyY
|
||||||
|
KeyZ
|
||||||
|
KeyApostrophe
|
||||||
|
KeyBackslash
|
||||||
|
KeyBackspace
|
||||||
|
KeyCapsLock
|
||||||
|
KeyComma
|
||||||
|
KeyDelete
|
||||||
|
KeyDown
|
||||||
|
KeyEnd
|
||||||
|
KeyEnter
|
||||||
|
KeyEqual
|
||||||
|
KeyEscape
|
||||||
|
KeyF1
|
||||||
|
KeyF2
|
||||||
|
KeyF3
|
||||||
|
KeyF4
|
||||||
|
KeyF5
|
||||||
|
KeyF6
|
||||||
|
KeyF7
|
||||||
|
KeyF8
|
||||||
|
KeyF9
|
||||||
|
KeyF10
|
||||||
|
KeyF11
|
||||||
|
KeyF12
|
||||||
|
KeyGraveAccent
|
||||||
|
KeyHome
|
||||||
|
KeyInsert
|
||||||
|
KeyKP0
|
||||||
|
KeyKP1
|
||||||
|
KeyKP2
|
||||||
|
KeyKP3
|
||||||
|
KeyKP4
|
||||||
|
KeyKP5
|
||||||
|
KeyKP6
|
||||||
|
KeyKP7
|
||||||
|
KeyKP8
|
||||||
|
KeyKP9
|
||||||
|
KeyKPAdd
|
||||||
|
KeyKPDecimal
|
||||||
|
KeyKPDivide
|
||||||
|
KeyKPEnter
|
||||||
|
KeyKPEqual
|
||||||
|
KeyKPMultiply
|
||||||
|
KeyKPSubtract
|
||||||
|
KeyLeft
|
||||||
|
KeyLeftBracket
|
||||||
|
KeyMenu
|
||||||
|
KeyMinus
|
||||||
|
KeyNumLock
|
||||||
|
KeyPageDown
|
||||||
|
KeyPageUp
|
||||||
|
KeyPause
|
||||||
|
KeyPeriod
|
||||||
|
KeyPrintScreen
|
||||||
|
KeyRight
|
||||||
|
KeyRightBracket
|
||||||
|
KeyScrollLock
|
||||||
|
KeySemicolon
|
||||||
|
KeySlash
|
||||||
|
KeySpace
|
||||||
|
KeyTab
|
||||||
|
KeyUp
|
||||||
|
KeyAlt
|
||||||
|
KeyControl
|
||||||
|
KeyShift
|
||||||
|
|
||||||
|
keyMin = Key0
|
||||||
|
keyMax = KeyShift
|
||||||
|
)
|
||||||
|
|
||||||
|
type KeyMod int
|
||||||
|
|
||||||
|
const (
|
||||||
|
KeyModAlt KeyMod = 1 << iota
|
||||||
|
KeyModControl
|
||||||
|
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
|
||||||
|
)
|
@ -1,10 +1,12 @@
|
|||||||
package d2ui
|
package d2ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CursorButton represents a mouse button
|
// CursorButton represents a mouse button
|
||||||
@ -17,122 +19,106 @@ const (
|
|||||||
CursorButtonRight CursorButton = 2
|
CursorButtonRight CursorButton = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
var widgets []Widget
|
type UI struct {
|
||||||
var cursorButtons CursorButton
|
widgets []Widget
|
||||||
var pressedIndex int
|
cursorButtons CursorButton // TODO (carrelld) convert dependent code and remove
|
||||||
var CursorX int
|
CursorX int // TODO (carrelld) convert dependent code and remove
|
||||||
var CursorY int
|
CursorY int // TODO (carrelld) convert dependent code and remove
|
||||||
|
pressedWidget Widget
|
||||||
|
}
|
||||||
|
|
||||||
|
var singleton UI
|
||||||
var clickSfx d2audio.SoundEffect
|
var clickSfx d2audio.SoundEffect
|
||||||
var waitForLeftMouseUp bool
|
|
||||||
|
|
||||||
func Initialize() {
|
func Initialize() {
|
||||||
pressedIndex = -1
|
sfx, err := d2audio.LoadSoundEffect(d2resource.SFXButtonClick)
|
||||||
clickSfx, _ = d2audio.LoadSoundEffect(d2resource.SFXButtonClick)
|
if err != nil {
|
||||||
waitForLeftMouseUp = false
|
log.Fatalf("failed to initialize ui: %v", err)
|
||||||
|
}
|
||||||
|
clickSfx = sfx
|
||||||
|
|
||||||
|
d2input.BindHandler(&singleton)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset resets the state of the UI manager. Typically called for new screens
|
// Reset resets the state of the UI manager. Typically called for new screens
|
||||||
func Reset() {
|
func Reset() {
|
||||||
widgets = make([]Widget, 0)
|
singleton.widgets = nil
|
||||||
pressedIndex = -1
|
singleton.pressedWidget = nil
|
||||||
waitForLeftMouseUp = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddWidget adds a widget to the UI manager
|
// AddWidget adds a widget to the UI manager
|
||||||
func AddWidget(widget Widget) {
|
func AddWidget(widget Widget) {
|
||||||
widgets = append(widgets, widget)
|
d2input.BindHandler(widget)
|
||||||
|
singleton.widgets = append(singleton.widgets, widget)
|
||||||
}
|
}
|
||||||
|
|
||||||
func WaitForMouseRelease() {
|
func (u *UI) OnMouseButtonUp(event d2input.MouseEvent) bool {
|
||||||
waitForLeftMouseUp = true
|
singleton.CursorX, singleton.CursorY = event.X, event.Y
|
||||||
|
if event.Button == d2input.MouseButtonLeft {
|
||||||
|
singleton.cursorButtons |= CursorButtonLeft
|
||||||
|
// activate previously pressed widget if cursor is still hovering
|
||||||
|
w := singleton.pressedWidget
|
||||||
|
if w != nil && contains(w, singleton.CursorX, singleton.CursorY) && w.GetVisible() && w.GetEnabled() {
|
||||||
|
w.Activate()
|
||||||
|
}
|
||||||
|
// unpress all widgets that are pressed
|
||||||
|
for _, w := range singleton.widgets {
|
||||||
|
w.SetPressed(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UI) OnMouseButtonDown(event d2input.MouseEvent) bool {
|
||||||
|
singleton.CursorX, singleton.CursorY = event.X, event.Y
|
||||||
|
if event.Button == d2input.MouseButtonLeft {
|
||||||
|
// find and press a widget on screen
|
||||||
|
singleton.pressedWidget = nil
|
||||||
|
for _, w := range singleton.widgets {
|
||||||
|
if contains(w, singleton.CursorX, singleton.CursorY) && w.GetVisible() && w.GetEnabled() {
|
||||||
|
w.SetPressed(true)
|
||||||
|
singleton.pressedWidget = w
|
||||||
|
clickSfx.Play()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if event.Button == d2input.MouseButtonRight {
|
||||||
|
singleton.cursorButtons |= CursorButtonRight
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render renders all of the UI elements
|
// Render renders all of the UI elements
|
||||||
func Render(target d2render.Surface) {
|
func Render(target d2render.Surface) {
|
||||||
for _, widget := range widgets {
|
for _, widget := range singleton.widgets {
|
||||||
if widget.GetVisible() {
|
if widget.GetVisible() {
|
||||||
widget.Render(target)
|
widget.Render(target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// contains determines whether a given x,y coordinate lands within a Widget
|
||||||
|
func contains(w Widget, x, y int) bool {
|
||||||
|
wx, wy := w.GetPosition()
|
||||||
|
ww, wh := w.GetSize()
|
||||||
|
return x >= wx && x <= wx+ww && y >= wy && y <= wy+wh
|
||||||
|
}
|
||||||
|
|
||||||
// Update updates all of the UI elements
|
// Update updates all of the UI elements
|
||||||
func Advance(elapsed float64) {
|
func Advance(elapsed float64) {
|
||||||
for _, widget := range widgets {
|
for _, widget := range singleton.widgets {
|
||||||
if widget.GetVisible() {
|
if widget.GetVisible() {
|
||||||
widget.Advance(elapsed)
|
widget.Advance(elapsed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cursorButtons = 0
|
|
||||||
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
|
|
||||||
if !waitForLeftMouseUp {
|
|
||||||
cursorButtons |= CursorButtonLeft
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if waitForLeftMouseUp {
|
|
||||||
waitForLeftMouseUp = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonRight) {
|
|
||||||
cursorButtons |= CursorButtonRight
|
|
||||||
}
|
|
||||||
CursorX, CursorY = ebiten.CursorPosition()
|
|
||||||
if CursorButtonPressed(CursorButtonLeft) {
|
|
||||||
found := false
|
|
||||||
for i, widget := range widgets {
|
|
||||||
if !widget.GetVisible() || !widget.GetEnabled() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
wx, wy := widget.GetPosition()
|
|
||||||
ww, wh := widget.GetSize()
|
|
||||||
if CursorX >= wx && CursorX <= wx+ww && CursorY >= wy && CursorY <= wy+wh {
|
|
||||||
widget.SetPressed(true)
|
|
||||||
if pressedIndex == -1 {
|
|
||||||
found = true
|
|
||||||
pressedIndex = i
|
|
||||||
clickSfx.Play()
|
|
||||||
} else if pressedIndex > -1 && pressedIndex != i {
|
|
||||||
widgets[i].SetPressed(false)
|
|
||||||
} else {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
widget.SetPressed(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
if pressedIndex > -1 {
|
|
||||||
widgets[pressedIndex].SetPressed(false)
|
|
||||||
} else {
|
|
||||||
pressedIndex = -2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if pressedIndex > -1 {
|
|
||||||
widget := widgets[pressedIndex]
|
|
||||||
wx, wy := widget.GetPosition()
|
|
||||||
ww, wh := widget.GetSize()
|
|
||||||
if CursorX >= wx && CursorX <= wx+ww && CursorY >= wy && CursorY <= wy+wh {
|
|
||||||
widget.Activate()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, widget := range widgets {
|
|
||||||
if !widget.GetVisible() || !widget.GetEnabled() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
widget.SetPressed(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pressedIndex = -1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CursorButtonPressed determines if the specified button has been pressed
|
// CursorButtonPressed determines if the specified button has been pressed
|
||||||
func CursorButtonPressed(button CursorButton) bool {
|
func CursorButtonPressed(button CursorButton) bool {
|
||||||
return cursorButtons&button > 0
|
return singleton.cursorButtons&button > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func KeyPressed(key ebiten.Key) bool {
|
func CursorPosition() (x, y int) {
|
||||||
return ebiten.IsKeyPressed(key)
|
return singleton.CursorX, singleton.CursorY
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Scrollbar struct {
|
type Scrollbar struct {
|
||||||
@ -52,7 +51,7 @@ func (v Scrollbar) getBarPosition() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *Scrollbar) Activate() {
|
func (v *Scrollbar) Activate() {
|
||||||
_, my := ebiten.CursorPosition()
|
_, my := CursorPosition()
|
||||||
barPosition := v.getBarPosition()
|
barPosition := v.getBarPosition()
|
||||||
if my <= v.y+barPosition+15 {
|
if my <= v.y+barPosition+15 {
|
||||||
if v.currentOffset > 0 {
|
if v.currentOffset > 0 {
|
||||||
@ -65,6 +64,7 @@ func (v *Scrollbar) Activate() {
|
|||||||
v.lastDirChange = 1
|
v.lastDirChange = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.onActivate != nil {
|
if v.onActivate != nil {
|
||||||
v.onActivate()
|
v.onActivate()
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,15 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/inpututil"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
"github.com/hajimehoshi/ebiten"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TextBox with cursor focus
|
||||||
|
var focusedTextBox *TextBox
|
||||||
|
|
||||||
// TextBox represents a text input box
|
// TextBox represents a text input box
|
||||||
type TextBox struct {
|
type TextBox struct {
|
||||||
text string
|
text string
|
||||||
@ -29,7 +29,7 @@ type TextBox struct {
|
|||||||
func CreateTextbox() TextBox {
|
func CreateTextbox() TextBox {
|
||||||
animation, _ := d2asset.LoadAnimation(d2resource.TextBox2, d2resource.PaletteUnits)
|
animation, _ := d2asset.LoadAnimation(d2resource.TextBox2, d2resource.PaletteUnits)
|
||||||
bgSprite, _ := LoadSprite(animation)
|
bgSprite, _ := LoadSprite(animation)
|
||||||
result := TextBox{
|
tb := TextBox{
|
||||||
filter: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
filter: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||||
bgSprite: bgSprite,
|
bgSprite: bgSprite,
|
||||||
textLabel: CreateLabel(d2resource.FontFormal11, d2resource.PaletteUnits),
|
textLabel: CreateLabel(d2resource.FontFormal11, d2resource.PaletteUnits),
|
||||||
@ -37,29 +37,15 @@ func CreateTextbox() TextBox {
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
visible: true,
|
visible: true,
|
||||||
}
|
}
|
||||||
result.lineBar.SetText("_")
|
tb.lineBar.SetText("_")
|
||||||
return result
|
|
||||||
|
return tb
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *TextBox) SetFilter(filter string) {
|
func (v *TextBox) SetFilter(filter string) {
|
||||||
v.filter = filter
|
v.filter = filter
|
||||||
}
|
}
|
||||||
|
|
||||||
func repeatingKeyPressed(key ebiten.Key) bool {
|
|
||||||
const (
|
|
||||||
delay = 30
|
|
||||||
interval = 3
|
|
||||||
)
|
|
||||||
d := inpututil.KeyPressDuration(key)
|
|
||||||
if d == 1 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if d >= delay && (d-delay)%interval == 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *TextBox) Render(target d2render.Surface) {
|
func (v *TextBox) Render(target d2render.Surface) {
|
||||||
if !v.visible {
|
if !v.visible {
|
||||||
return
|
return
|
||||||
@ -71,21 +57,47 @@ func (v *TextBox) Render(target d2render.Surface) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *TextBox) Advance(elapsed float64) {
|
func (v *TextBox) OnKeyChars(event d2input.KeyCharsEvent) bool {
|
||||||
if !v.visible || !v.enabled {
|
if !(focusedTextBox == v) || !v.visible || !v.enabled {
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
newText := string(ebiten.InputChars())
|
newText := string(event.Chars)
|
||||||
if len(newText) > 0 {
|
if len(newText) > 0 {
|
||||||
v.text += newText
|
v.text += newText
|
||||||
v.SetText(v.text)
|
v.SetText(v.text)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
if repeatingKeyPressed(ebiten.KeyBackspace) {
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *TextBox) OnKeyRepeat(event d2input.KeyEvent) bool {
|
||||||
|
if event.Key == d2input.KeyBackspace && debounceEvents(event.Duration) {
|
||||||
if len(v.text) >= 1 {
|
if len(v.text) >= 1 {
|
||||||
v.text = v.text[:len(v.text)-1]
|
v.text = v.text[:len(v.text)-1]
|
||||||
}
|
}
|
||||||
v.SetText(v.text)
|
v.SetText(v.text)
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func debounceEvents(numFrames int) bool {
|
||||||
|
const (
|
||||||
|
delay = 30
|
||||||
|
interval = 3
|
||||||
|
)
|
||||||
|
if numFrames == 1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if numFrames >= delay && (numFrames-delay)%interval == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *TextBox) Advance(_ float64) {
|
||||||
|
if !v.visible || !v.enabled {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *TextBox) Update() {
|
func (v *TextBox) Update() {
|
||||||
@ -164,5 +176,5 @@ func (v *TextBox) OnActivated(callback func()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *TextBox) Activate() {
|
func (v *TextBox) Activate() {
|
||||||
//no op
|
focusedTextBox = v
|
||||||
}
|
}
|
||||||
|
@ -6,24 +6,20 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client/d2clientconnectiontype"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2inventory"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2inventory"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2screen"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2screen"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client/d2clientconnectiontype"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CharacterSelect struct {
|
type CharacterSelect struct {
|
||||||
@ -46,7 +42,6 @@ type CharacterSelect struct {
|
|||||||
characterImage [8]*d2mapentity.Player
|
characterImage [8]*d2mapentity.Player
|
||||||
gameStates []*d2player.PlayerState
|
gameStates []*d2player.PlayerState
|
||||||
selectedCharacter int
|
selectedCharacter int
|
||||||
mouseButtonPressed bool
|
|
||||||
showDeleteConfirmation bool
|
showDeleteConfirmation bool
|
||||||
connectionType d2clientconnectiontype.ClientConnectionType
|
connectionType d2clientconnectiontype.ClientConnectionType
|
||||||
connectionHost string
|
connectionHost string
|
||||||
@ -62,6 +57,7 @@ func CreateCharacterSelect(connectionType d2clientconnectiontype.ClientConnectio
|
|||||||
|
|
||||||
func (v *CharacterSelect) OnLoad() error {
|
func (v *CharacterSelect) OnLoad() error {
|
||||||
d2audio.PlayBGM(d2resource.BGMTitle)
|
d2audio.PlayBGM(d2resource.BGMTitle)
|
||||||
|
d2input.BindHandler(v)
|
||||||
|
|
||||||
animation, _ := d2asset.LoadAnimation(d2resource.CharacterSelectionBackground, d2resource.PaletteSky)
|
animation, _ := d2asset.LoadAnimation(d2resource.CharacterSelectionBackground, d2resource.PaletteSky)
|
||||||
v.background, _ = d2ui.LoadSprite(animation)
|
v.background, _ = d2ui.LoadSprite(animation)
|
||||||
@ -222,32 +218,32 @@ func (v *CharacterSelect) moveSelectionBox() {
|
|||||||
v.d2HeroTitle.SetText(v.gameStates[v.selectedCharacter].HeroName)
|
v.d2HeroTitle.SetText(v.gameStates[v.selectedCharacter].HeroName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *CharacterSelect) Advance(tickTime float64) error {
|
func (v *CharacterSelect) OnMouseButtonDown(event d2input.MouseEvent) bool {
|
||||||
if !v.showDeleteConfirmation {
|
if !v.showDeleteConfirmation {
|
||||||
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
|
if event.Button == d2input.MouseButtonLeft {
|
||||||
if !v.mouseButtonPressed {
|
mx, my := event.X, event.Y
|
||||||
v.mouseButtonPressed = true
|
bw := 272
|
||||||
mx, my := ebiten.CursorPosition()
|
bh := 92
|
||||||
bw := 272
|
localMouseX := mx - 37
|
||||||
bh := 92
|
localMouseY := my - 86
|
||||||
localMouseX := mx - 37
|
if localMouseX > 0 && localMouseX < bw*2 && localMouseY >= 0 && localMouseY < bh*4 {
|
||||||
localMouseY := my - 86
|
adjustY := localMouseY / bh
|
||||||
if localMouseX > 0 && localMouseX < bw*2 && localMouseY >= 0 && localMouseY < bh*4 {
|
selectedIndex := adjustY * 2
|
||||||
adjustY := localMouseY / bh
|
if localMouseX > bw {
|
||||||
selectedIndex := adjustY * 2
|
selectedIndex += 1
|
||||||
if localMouseX > bw {
|
}
|
||||||
selectedIndex += 1
|
if (v.charScrollbar.GetCurrentOffset()*2)+selectedIndex < len(v.gameStates) {
|
||||||
}
|
v.selectedCharacter = (v.charScrollbar.GetCurrentOffset() * 2) + selectedIndex
|
||||||
if (v.charScrollbar.GetCurrentOffset()*2)+selectedIndex < len(v.gameStates) {
|
v.moveSelectionBox()
|
||||||
v.selectedCharacter = (v.charScrollbar.GetCurrentOffset() * 2) + selectedIndex
|
|
||||||
v.moveSelectionBox()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
return true
|
||||||
v.mouseButtonPressed = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *CharacterSelect) Advance(tickTime float64) error {
|
||||||
for _, hero := range v.characterImage {
|
for _, hero := range v.characterImage {
|
||||||
if hero != nil {
|
if hero != nil {
|
||||||
hero.AnimatedComposite.Advance(tickTime)
|
hero.AnimatedComposite.Advance(tickTime)
|
||||||
|
@ -8,6 +8,8 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
|
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client/d2clientconnectiontype"
|
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client/d2clientconnectiontype"
|
||||||
@ -238,6 +240,9 @@ func (v *MainMenu) OnLoad() error {
|
|||||||
} else {
|
} else {
|
||||||
v.SetScreenMode(ScreenModeMainMenu)
|
v.SetScreenMode(ScreenModeMainMenu)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d2input.BindHandler(v)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,23 +348,17 @@ func (v *MainMenu) Advance(tickTime float64) error {
|
|||||||
v.diabloLogoRight.Advance(tickTime)
|
v.diabloLogoRight.Advance(tickTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch v.screenMode {
|
|
||||||
case ScreenModeTrademark:
|
|
||||||
if d2ui.CursorButtonPressed(d2ui.CursorButtonLeft) {
|
|
||||||
if v.leftButtonHeld {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
d2ui.WaitForMouseRelease()
|
|
||||||
v.SetScreenMode(ScreenModeMainMenu)
|
|
||||||
v.leftButtonHeld = true
|
|
||||||
} else {
|
|
||||||
v.leftButtonHeld = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *MainMenu) OnMouseButtonDown(event d2input.MouseEvent) bool {
|
||||||
|
if v.screenMode == ScreenModeTrademark && event.Button == d2input.MouseButtonLeft {
|
||||||
|
v.SetScreenMode(ScreenModeMainMenu)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (v *MainMenu) SetScreenMode(screenMode MainMenuScreenMode) {
|
func (v *MainMenu) SetScreenMode(screenMode MainMenuScreenMode) {
|
||||||
v.screenMode = screenMode
|
v.screenMode = screenMode
|
||||||
isMainMenu := screenMode == ScreenModeMainMenu
|
isMainMenu := screenMode == ScreenModeMainMenu
|
||||||
@ -379,6 +378,9 @@ func (v *MainMenu) SetScreenMode(screenMode MainMenuScreenMode) {
|
|||||||
v.btnTcpIpHostGame.SetVisible(isTcpIp)
|
v.btnTcpIpHostGame.SetVisible(isTcpIp)
|
||||||
v.btnTcpIpJoinGame.SetVisible(isTcpIp)
|
v.btnTcpIpJoinGame.SetVisible(isTcpIp)
|
||||||
v.tcpJoinGameEntry.SetVisible(isServerIp)
|
v.tcpJoinGameEntry.SetVisible(isServerIp)
|
||||||
|
if isServerIp {
|
||||||
|
v.tcpJoinGameEntry.Activate()
|
||||||
|
}
|
||||||
v.btnServerIpOk.SetVisible(isServerIp)
|
v.btnServerIpOk.SetVisible(isServerIp)
|
||||||
v.btnServerIpCancel.SetVisible(isServerIp)
|
v.btnServerIpCancel.SetVisible(isServerIp)
|
||||||
}
|
}
|
||||||
|
@ -472,17 +472,10 @@ func (v *SelectHeroClass) Advance(tickTime float64) error {
|
|||||||
canSelect = false
|
canSelect = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
allIdle := true
|
for heroType, _ := range v.heroRenderInfo {
|
||||||
for heroType, data := range v.heroRenderInfo {
|
|
||||||
if allIdle && data.Stance != d2enum.HeroStanceIdle {
|
|
||||||
allIdle = false
|
|
||||||
}
|
|
||||||
v.updateHeroSelectionHover(heroType, canSelect)
|
v.updateHeroSelectionHover(heroType, canSelect)
|
||||||
}
|
}
|
||||||
if v.selectedHero != d2enum.HeroNone && allIdle {
|
v.okButton.SetEnabled(len(v.heroNameTextbox.GetText()) >= 2 && v.selectedHero != d2enum.HeroNone)
|
||||||
v.selectedHero = d2enum.HeroNone
|
|
||||||
}
|
|
||||||
v.okButton.SetEnabled(len(v.heroNameTextbox.GetText()) >= 2)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -509,12 +502,12 @@ func (v *SelectHeroClass) updateHeroSelectionHover(hero d2enum.Hero, canSelect b
|
|||||||
if renderInfo.Stance == d2enum.HeroStanceSelected {
|
if renderInfo.Stance == d2enum.HeroStanceSelected {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mouseX := d2ui.CursorX
|
mouseX, mouseY := d2ui.CursorPosition()
|
||||||
mouseY := d2ui.CursorY
|
|
||||||
b := renderInfo.SelectionBounds
|
b := renderInfo.SelectionBounds
|
||||||
mouseHover := (mouseX >= b.Min.X) && (mouseX <= b.Min.X+b.Max.X) && (mouseY >= b.Min.Y) && (mouseY <= b.Min.Y+b.Max.Y)
|
mouseHover := (mouseX >= b.Min.X) && (mouseX <= b.Min.X+b.Max.X) && (mouseY >= b.Min.Y) && (mouseY <= b.Min.Y+b.Max.Y)
|
||||||
if mouseHover && d2ui.CursorButtonPressed(d2ui.CursorButtonLeft) {
|
if mouseHover && d2ui.CursorButtonPressed(d2ui.CursorButtonLeft) {
|
||||||
v.heroNameTextbox.SetVisible(true)
|
v.heroNameTextbox.SetVisible(true)
|
||||||
|
v.heroNameTextbox.Activate()
|
||||||
v.okButton.SetVisible(true)
|
v.okButton.SetVisible(true)
|
||||||
v.expansionCheckbox.SetVisible(true)
|
v.expansionCheckbox.SetVisible(true)
|
||||||
v.hardcoreCheckbox.SetVisible(true)
|
v.hardcoreCheckbox.SetVisible(true)
|
||||||
|
3
main.go
3
main.go
@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
|
||||||
|
ebiten_input "github.com/OpenDiablo2/OpenDiablo2/d2core/d2input/ebiten"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2inventory"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2inventory"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render/ebiten"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render/ebiten"
|
||||||
@ -113,6 +114,8 @@ func initialize() error {
|
|||||||
config := d2config.Get()
|
config := d2config.Get()
|
||||||
d2resource.LanguageCode = config.Language
|
d2resource.LanguageCode = config.Language
|
||||||
|
|
||||||
|
d2input.Initialize(ebiten_input.InputService{})
|
||||||
|
|
||||||
renderer, err := ebiten.CreateRenderer()
|
renderer, err := ebiten.CreateRenderer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
Loading…
Reference in New Issue
Block a user