Feat(KeyMapping): Adds a configurable keymap to GameControls, resolves #793 (#893)

* Feat(KeyMapping): Adds a configurable keymap to GameControls + Updates help overlay to use it

Co-authored-by: gravestench <dknuth0101@gmail.com>
This commit is contained in:
Julien Ganichot 2020-11-02 04:43:23 +01:00 committed by GitHub
parent 1f2771e8bc
commit 8365400ff5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 418 additions and 247 deletions

View File

@ -0,0 +1,70 @@
package d2enum
// GameEvent represents an envent in the game engine
type GameEvent int
// Game events
const (
// ToggleGameMenu will display the game menu
ToggleGameMenu GameEvent = iota + 1
// panel toggles
ToggleCharacterPanel
ToggleInventoryPanel
TogglePartyPanel
ToggleSkillTreePanel
ToggleHirelingPanel
ToggleQuestLog
ToggleHelpScreen
ToggleChatOverlay
ToggleMessageLog
ToggleRightSkillSelector // these two are for left/right speed-skill panel toggles
ToggleLeftSkillSelector
ToggleAutomap
CenterAutomap // recenters the automap when opened
FadeAutomap // reduces the brightness of the map (not the players/npcs)
TogglePartyOnAutomap // toggles the display of the party members on the automap
ToggleNamesOnAutomap // toggles the display of party members names and npcs on the automap
// there can be 16 hotkeys, each hotkey can have a skill assigned
UseSkill1
UseSkill2
UseSkill3
UseSkill4
UseSkill5
UseSkill6
UseSkill7
UseSkill8
UseSkill9
UseSkill10
UseSkill11
UseSkill12
UseSkill13
UseSkill14
UseSkill15
UseSkill16
// switching between prev/next skill
SelectPreviousSkill
SelectNextSkill
// ToggleBelts toggles the display of the different level for
// the currently equipped belt
ToggleBelts
UseBeltSlot1
UseBeltSlot2
UseBeltSlot3
UseBeltSlot4
SwapWeapons
ToggleRunWalk
// these events are fired while a player holds the corresponding key
HoldRun
HoldStandStill
HoldShowGroundItems
HoldShowPortraits
ClearScreen // closes all active menus/panels
)

View File

@ -3,211 +3,133 @@ package d2enum
// Key represents button on a traditional keyboard.
type Key int
const (
// Key0 is the number 0
Key0 Key = iota
// Key1 is the number 1
Key1
// Key2 is the number 2
Key2
// Key3 is the number 3
Key3
// Key4 is the number 4
Key4
// Key5 is the number 5
Key5
// Key6 is the number 6
Key6
// Key7 is the number 7
Key7
// Key8 is the number 8
Key8
// Key9 is the number 9
Key9
// KeyA is the letter A
KeyA
// KeyB is the letter B
KeyB
// KeyC is the letter C
KeyC
// KeyD is the letter D
KeyD
// KeyE is the letter E
KeyE
// KeyF is the letter F
KeyF
// KeyG is the letter G
KeyG
// KeyH is the letter H
KeyH
// KeyI is the letter I
KeyI
// KeyJ is the letter J
KeyJ
// KeyK is the letter K
KeyK
// KeyL is the letter L
KeyL
// KeyM is the letter M
KeyM
// KeyN is the letter N
KeyN
// KeyO is the letter O
KeyO
// KeyP is the letter P
KeyP
// KeyQ is the letter Q
KeyQ
// KeyR is the letter R
KeyR
// KeyS is the letter S
KeyS
// KeyT is the letter T
KeyT
// KeyU is the letter U
KeyU
// KeyV is the letter V
KeyV
// KeyW is the letter W
KeyW
// KeyX is the letter X
KeyX
// KeyY is the letter Y
KeyY
// KeyZ is the letter Z
KeyZ
// KeyApostrophe is the Apostrophe
KeyApostrophe
// KeyBackslash is the Backslash
KeyBackslash
// KeyBackspace is the Backspace
KeyBackspace
// KeyCapsLock is the CapsLock
KeyCapsLock
// KeyComma is the Comma
KeyComma
// KeyDelete is the Delete
KeyDelete
// KeyDown is the down arrow key
KeyDown
// KeyEnd is the End
KeyEnd
// KeyEnter is the Enter
KeyEnter
// KeyEqual is the Equal
KeyEqual
// KeyEscape is the Escape
KeyEscape
// KeyF1 is the function F1
KeyF1
// KeyF2 is the function F2
KeyF2
// KeyF3 is the function F3
KeyF3
// KeyF4 is the function F4
KeyF4
// KeyF5 is the function F5
KeyF5
// KeyF6 is the function F6
KeyF6
// KeyF7 is the function F7
KeyF7
// KeyF8 is the function F8
KeyF8
// KeyF9 is the function F9
KeyF9
// KeyF10 is the function F10
KeyF10
// KeyF11 is the function F11
KeyF11
// KeyF12 is the function F12
KeyF12
// KeyGraveAccent is the Grave Accent
KeyGraveAccent
// KeyHome is the home key
KeyHome
// KeyInsert is the insert key
KeyInsert
// KeyKP0 is keypad 0
KeyKP0
// KeyKP1 is keypad 1
KeyKP1
// KeyKP2 is keypad 2
KeyKP2
// KeyKP3 is keypad 3
KeyKP3
// KeyKP4 is keypad 4
KeyKP4
// KeyKP5 is keypad 5
KeyKP5
// KeyKP6 is keypad 6
KeyKP6
// KeyKP7 is keypad 7
KeyKP7
// KeyKP8 is keypad 8
KeyKP8
// KeyKP9 is keypad 9
KeyKP9
// KeyKPAdd is keypad Add
KeyKPAdd
// KeyKPDecimal is keypad Decimal
KeyKPDecimal
// KeyKPDivide is keypad Divide
KeyKPDivide
// KeyKPEnter is keypad Enter
KeyKPEnter
// KeyKPEqual is keypad Equal
KeyKPEqual
// KeyKPMultiply is keypad Multiply
KeyKPMultiply
// KeyKPSubtract is keypad Subtract
KeyKPSubtract
// KeyLeft is the left arrow key
KeyLeft
// KeyLeftBracket is the left bracket
KeyLeftBracket
// KeyMenu is the Menu key
KeyMenu
// KeyMinus is the Minus key
KeyMinus
// KeyNumLock is the NumLock key
KeyNumLock
// KeyPageDown is the PageDown key
KeyPageDown
// KeyPageUp is the PageUp key
KeyPageUp
// KeyPause is the Pause key
KeyPause
// KeyPeriod is the Period key
KeyPeriod
// KeyPrintScreen is the PrintScreen key
KeyPrintScreen
// KeyRight is the right arrow key
KeyRight
// KeyRightBracket is the right bracket key
KeyRightBracket
// KeyScrollLock is the scroll lock key
KeyScrollLock
// KeySemicolon is the semicolon key
KeySemicolon
// KeySlash is the front slash key
KeySlash
// KeySpace is the space key
KeySpace
// KeyTab is the tab key
KeyTab
// KeyUp is the up arrow key
KeyUp
// KeyAlt is the alt key
KeyAlt
// KeyControl is the control key
KeyControl
// KeyShift is the shift key
KeyShift
// GetString returns a string representing the key
func (k Key) GetString() string {
switch k {
case -1:
return "None"
case KeyControl:
return "Ctrl"
case KeyShift:
return "Shift"
case KeySpace:
return "Space"
case KeyAlt:
return "Alt"
case KeyTab:
return "Tab"
case KeyH:
return "H"
default:
return "Unknown"
}
}
// Input keys
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
KeyTilde
// KeyMin is the lowest key
KeyMin = Key0
// KeyMax is the highest key
KeyMax = KeyShift
)

View File

@ -12,7 +12,6 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player/help"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
@ -235,6 +234,7 @@ const (
// GameControls represents the game's controls on the screen
type GameControls struct {
keyMap *KeyMap
actionableRegions []actionableRegion
asset *d2asset.AssetManager
renderer d2interface.Renderer // https://github.com/OpenDiablo2/OpenDiablo2/issues/798
@ -248,7 +248,7 @@ type GameControls struct {
inventory *Inventory
skilltree *skillTree
heroStatsPanel *HeroStatsPanel
HelpOverlay *help.Overlay
HelpOverlay *HelpOverlay
miniPanel *miniPanel
bottomMenuRect *d2geom.Rectangle
leftMenuRect *d2geom.Rectangle
@ -352,7 +352,10 @@ func NewGameControls(
return nil, err
}
keyMap := getDefaultKeyMap()
gc := &GameControls{
keyMap: keyMap,
asset: asset,
ui: ui,
renderer: renderer,
@ -366,7 +369,7 @@ func NewGameControls(
skillSelectMenu: NewSkillSelectMenu(asset, ui, hero),
skilltree: newSkillTree(hero.Skills, hero.Class, asset, renderer, ui, guiManager),
heroStatsPanel: NewHeroStatsPanel(asset, ui, hero.Name(), hero.Class, hero.Stats),
HelpOverlay: help.NewHelpOverlay(asset, renderer, ui, guiManager),
HelpOverlay: NewHelpOverlay(asset, renderer, ui, guiManager, keyMap),
miniPanel: newMiniPanel(asset, ui, isSinglePlayer),
nameLabel: hoverLabel,
zoneChangeText: zoneLabel,
@ -553,21 +556,34 @@ func (g *GameControls) OnKeyRepeat(event d2interface.KeyEvent) bool {
// OnKeyDown handles key presses
func (g *GameControls) OnKeyDown(event d2interface.KeyEvent) bool {
switch event.Key() {
case d2enum.KeyEscape:
if event.Key() == d2enum.KeyEscape {
g.onEscKey()
case d2enum.KeyI:
return true
}
gameEvent := g.keyMap.getGameEvent(event.Key())
switch gameEvent {
case d2enum.ClearScreen:
g.inventory.Close()
g.skilltree.Close()
g.heroStatsPanel.Close()
g.HelpOverlay.Close()
g.updateLayout()
case d2enum.ToggleInventoryPanel:
g.inventory.Toggle()
g.updateLayout()
case d2enum.KeyT:
case d2enum.ToggleSkillTreePanel:
g.skilltree.Toggle()
g.updateLayout()
case d2enum.KeyC:
case d2enum.ToggleCharacterPanel:
g.heroStatsPanel.Toggle()
g.updateLayout()
case d2enum.KeyR, d2enum.KeyControl:
g.onToggleRunButton()
case d2enum.KeyH:
case d2enum.ToggleRunWalk:
g.onToggleRunButton(false)
case d2enum.HoldRun:
g.onToggleRunButton(true)
case d2enum.ToggleHelpScreen:
g.HelpOverlay.Toggle()
g.updateLayout()
default:
@ -579,9 +595,11 @@ func (g *GameControls) OnKeyDown(event d2interface.KeyEvent) bool {
// OnKeyUp handles key release
func (g *GameControls) OnKeyUp(event d2interface.KeyEvent) bool {
switch event.Key() {
case d2enum.KeyControl:
g.onToggleRunButton()
gameEvent := g.keyMap.getGameEvent(event.Key())
switch gameEvent {
case d2enum.HoldRun:
g.onToggleRunButton(true)
default:
return false
}
@ -833,15 +851,18 @@ func (g *GameControls) loadUIButtons() {
g.runButton = g.ui.NewButton(d2ui.ButtonTypeRun, "")
g.runButton.SetPosition(runButtonX, runButtonY)
g.runButton.OnActivated(func() { g.onToggleRunButton() })
g.runButton.OnActivated(func() { g.onToggleRunButton(false) })
if g.hero.IsRunToggled() {
g.runButton.Toggle()
}
}
func (g *GameControls) onToggleRunButton() {
g.runButton.Toggle()
func (g *GameControls) onToggleRunButton(noButton bool) {
if !noButton {
g.runButton.Toggle()
}
g.hero.ToggleRunWalk()
// https://github.com/OpenDiablo2/OpenDiablo2/issues/800

View File

@ -1,11 +1,11 @@
// Package help contains the in-game diablo2 help panel
package help
package d2player
import (
"fmt"
"image/color"
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
@ -157,8 +157,8 @@ const (
beltDotY = 568
)
// Overlay represents the in-game overlay that toggles visibility when the h key is pressed
type Overlay struct {
// HelpOverlay represents the in-game overlay that toggles visibility when the h key is pressed
type HelpOverlay struct {
asset *d2asset.AssetManager
isOpen bool
renderer d2interface.Renderer
@ -169,6 +169,7 @@ type Overlay struct {
layout *d2gui.Layout
closeButton *d2ui.Button
guiManager *d2gui.GuiManager
keyMap *KeyMap
}
// NewHelpOverlay creates a new HelpOverlay instance
@ -177,35 +178,38 @@ func NewHelpOverlay(
renderer d2interface.Renderer,
ui *d2ui.UIManager,
guiManager *d2gui.GuiManager,
) *Overlay {
h := &Overlay{
keyMap *KeyMap,
) *HelpOverlay {
h := &HelpOverlay{
asset: asset,
renderer: renderer,
uiManager: ui,
guiManager: guiManager,
keyMap: keyMap,
}
return h
}
// Toggle the visibility state of the overlay
func (h *Overlay) Toggle() {
func (h *HelpOverlay) Toggle() {
fmt.Print("Help overlay toggled\n")
if h.isOpen {
h.close()
h.Close()
} else {
h.open()
}
}
func (h *Overlay) close() {
// Close will hide the help overlay
func (h *HelpOverlay) Close() {
h.isOpen = false
h.closeButton.SetVisible(false)
h.guiManager.SetLayout(nil)
}
func (h *Overlay) open() {
func (h *HelpOverlay) open() {
h.isOpen = true
if h.layout == nil {
h.layout = d2gui.CreateLayout(h.renderer, d2gui.PositionTypeHorizontal, h.asset)
@ -218,12 +222,12 @@ func (h *Overlay) open() {
}
// IsOpen returns whether or not the overlay is visible/open
func (h *Overlay) IsOpen() bool {
func (h *HelpOverlay) IsOpen() bool {
return h.isOpen
}
// IsInRect checks if the given point is within the overlay layout rectangle
func (h *Overlay) IsInRect(px, py int) bool {
func (h *HelpOverlay) IsInRect(px, py int) bool {
ww, hh := h.layout.GetSize()
x, y := h.layout.GetPosition()
@ -235,14 +239,14 @@ func (h *Overlay) IsInRect(px, py int) bool {
}
// Load the overlay graphical assets
func (h *Overlay) Load() {
func (h *HelpOverlay) Load() {
h.setupOverlayFrame()
h.setupTitleAndButton()
h.setupBulletedList()
h.setupLabelsWithLines()
}
func (h *Overlay) setupOverlayFrame() {
func (h *HelpOverlay) setupOverlayFrame() {
frames := []int{
frameTopLeft,
frameBottomLeft,
@ -304,7 +308,7 @@ func (h *Overlay) setupOverlayFrame() {
}
}
func (h *Overlay) setupTitleAndButton() {
func (h *HelpOverlay) setupTitleAndButton() {
// Title
text := d2tbl.TranslateString("Strhelp1") // "Diablo II Help"
newLabel := h.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteSky)
@ -319,7 +323,7 @@ func (h *Overlay) setupTitleAndButton() {
h.closeButton = h.uiManager.NewButton(d2ui.ButtonTypeSquareClose, "")
h.closeButton.SetPosition(closeButtonX, closeButtonY)
h.closeButton.SetVisible(false)
h.closeButton.OnActivated(func() { h.close() })
h.closeButton.OnActivated(func() { h.Close() })
newLabel = h.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteSky)
newLabel.SetText(d2tbl.TranslateString("strClose")) // "Close"
@ -327,23 +331,35 @@ func (h *Overlay) setupTitleAndButton() {
h.text = append(h.text, newLabel)
}
func (h *Overlay) setupBulletedList() {
func (h *HelpOverlay) setupBulletedList() {
// Bullets
// the hotkeys displayed here should be pulled from a mapping of input events to game events
// https://github.com/OpenDiablo2/OpenDiablo2/issues/793
// https://github.com/OpenDiablo2/OpenDiablo2/issues/794
callouts := []struct{ text string }{
// "Ctrl" should be hotkey // "Hold Down <%s> to Run"
{text: fmt.Sprintf(d2tbl.TranslateString("StrHelp2"), "Ctrl")},
{text: fmt.Sprintf(
d2tbl.TranslateString("StrHelp2"),
h.keyMap.GetKeysForGameEvent(d2enum.HoldRun).Primary.GetString(),
)},
// "Alt" should be hotkey // "Hold down <%s> to highlight items on the ground"
{text: fmt.Sprintf(d2tbl.TranslateString("StrHelp3"), "Alt")},
{text: fmt.Sprintf(
d2tbl.TranslateString("StrHelp3"),
h.keyMap.GetKeysForGameEvent(d2enum.HoldShowGroundItems).Primary.GetString(),
)},
// "Shift" should be hotkey // "Hold down <%s> to attack while standing still"
{text: fmt.Sprintf(d2tbl.TranslateString("StrHelp4"), "Shift")},
{text: fmt.Sprintf(
d2tbl.TranslateString("StrHelp4"),
h.keyMap.GetKeysForGameEvent(d2enum.HoldStandStill).Primary.GetString(),
)},
// "Tab" should be hotkey // "Hit <%s> to toggle the automap on and off"
{text: fmt.Sprintf(d2tbl.TranslateString("StrHelp5"), "Tab")},
{text: fmt.Sprintf(
d2tbl.TranslateString("StrHelp5"),
h.keyMap.GetKeysForGameEvent(d2enum.ToggleAutomap).Primary.GetString(),
)},
// "Hit <Esc> to bring up the Game Menu"
{text: d2tbl.TranslateString("StrHelp6")},
@ -355,7 +371,10 @@ func (h *Overlay) setupBulletedList() {
{text: d2tbl.TranslateString("StrHelp8")},
// "H" should be hotkey,
{text: fmt.Sprintf(d2tbl.TranslateString("StrHelp8a"), "H")},
{text: fmt.Sprintf(
d2tbl.TranslateString("StrHelp8a"),
h.keyMap.GetKeysForGameEvent(d2enum.ToggleHelpScreen).Primary.GetString(),
)},
}
for idx := range callouts {
@ -372,7 +391,7 @@ func (h *Overlay) setupBulletedList() {
}
// nolint:funlen // can't reduce
func (h *Overlay) setupLabelsWithLines() {
func (h *HelpOverlay) setupLabelsWithLines() {
h.createCallout(callout{
LabelText: d2tbl.TranslateString("strlvlup"), // "New Stats"
LabelX: newStatsLabelX,
@ -533,7 +552,7 @@ type callout struct {
DotY int
}
func (h *Overlay) createBullet(c callout) {
func (h *HelpOverlay) createBullet(c callout) {
newLabel := h.uiManager.NewLabel(d2resource.FontFormal12, d2resource.PaletteSky)
newLabel.SetText(c.LabelText)
newLabel.SetPosition(c.LabelX, c.LabelY)
@ -553,7 +572,7 @@ func (h *Overlay) createBullet(c callout) {
h.frames = append(h.frames, newDot)
}
func (h *Overlay) createLabel(c callout) {
func (h *HelpOverlay) createLabel(c callout) {
newLabel := h.uiManager.NewLabel(d2resource.FontFormal12, d2resource.PaletteSky)
newLabel.SetText(c.LabelText)
newLabel.SetPosition(c.LabelX, c.LabelY)
@ -561,7 +580,7 @@ func (h *Overlay) createLabel(c callout) {
newLabel.Alignment = d2gui.HorizontalAlignCenter
}
func (h *Overlay) createCallout(c callout) {
func (h *HelpOverlay) createCallout(c callout) {
newLabel := h.uiManager.NewLabel(d2resource.FontFormal12, d2resource.PaletteSky)
newLabel.Color[0] = color.White
newLabel.SetText(c.LabelText)
@ -596,7 +615,7 @@ func (h *Overlay) createCallout(c callout) {
}
// Render the overlay to the given surface
func (h *Overlay) Render(target d2interface.Surface) error {
func (h *HelpOverlay) Render(target d2interface.Surface) error {
if !h.isOpen {
return nil
}

139
d2game/d2player/key_map.go Normal file
View File

@ -0,0 +1,139 @@
package d2player
import (
"sync"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
)
// KeyMap represents the key mappings of the game. Each game event
// can be associated to 2 different keys. A key of -1 means none
type KeyMap struct {
mutex sync.RWMutex
mapping map[d2enum.Key]d2enum.GameEvent
controls map[d2enum.GameEvent]*KeyBinding
}
// NewKeyMap returns a new instance of a KeyMap
func NewKeyMap() *KeyMap {
return &KeyMap{
mapping: make(map[d2enum.Key]d2enum.GameEvent),
controls: make(map[d2enum.GameEvent]*KeyBinding),
}
}
// SetPrimaryBinding binds the first key for gameEvent
func (km *KeyMap) SetPrimaryBinding(gameEvent d2enum.GameEvent, key d2enum.Key) {
if key == d2enum.KeyEscape {
return
}
km.mutex.Lock()
defer km.mutex.Unlock()
if km.controls[gameEvent] == nil {
km.controls[gameEvent] = &KeyBinding{}
}
currentKey := km.controls[gameEvent].Primary
delete(km.mapping, currentKey)
km.mapping[key] = gameEvent
km.controls[gameEvent].Primary = key
}
// SetSecondaryBinding binds the second key for gameEvent
func (km *KeyMap) SetSecondaryBinding(gameEvent d2enum.GameEvent, key d2enum.Key) {
if key == d2enum.KeyEscape {
return
}
km.mutex.Lock()
defer km.mutex.Unlock()
if km.controls[gameEvent] == nil {
km.controls[gameEvent] = &KeyBinding{}
}
currentKey := km.controls[gameEvent].Secondary
delete(km.mapping, currentKey)
km.mapping[key] = gameEvent
if km.controls[gameEvent].Primary == key {
km.controls[gameEvent].Primary = d2enum.Key(-1)
}
km.controls[gameEvent].Secondary = key
}
func (km *KeyMap) getGameEvent(key d2enum.Key) d2enum.GameEvent {
km.mutex.RLock()
defer km.mutex.RUnlock()
return km.mapping[key]
}
// GetKeysForGameEvent returns the bindings for a givent game event
func (km *KeyMap) GetKeysForGameEvent(gameEvent d2enum.GameEvent) *KeyBinding {
km.mutex.RLock()
defer km.mutex.RUnlock()
return km.controls[gameEvent]
}
// KeyBinding holds the primary and secondary keys assigned to a GameEvent
type KeyBinding struct {
Primary d2enum.Key
Secondary d2enum.Key
}
func getDefaultKeyMap() *KeyMap {
keyMap := NewKeyMap()
defaultControls := map[d2enum.GameEvent]KeyBinding{
d2enum.ToggleCharacterPanel: {d2enum.KeyA, d2enum.KeyC},
d2enum.ToggleInventoryPanel: {d2enum.KeyB, d2enum.KeyI},
d2enum.ToggleHelpScreen: {d2enum.KeyH, -1},
d2enum.TogglePartyPanel: {d2enum.KeyP, -1},
d2enum.ToggleMessageLog: {d2enum.KeyM, -1},
d2enum.ToggleQuestLog: {d2enum.KeyQ, -1},
d2enum.ToggleChatOverlay: {d2enum.KeyEnter, -1},
d2enum.ToggleAutomap: {d2enum.KeyTab, -1},
d2enum.CenterAutomap: {d2enum.KeyHome, -1},
d2enum.ToggleSkillTreePanel: {d2enum.KeyT, -1},
d2enum.ToggleRightSkillSelector: {d2enum.KeyS, -1},
d2enum.UseSkill1: {d2enum.KeyF1, -1},
d2enum.UseSkill2: {d2enum.KeyF2, -1},
d2enum.UseSkill3: {d2enum.KeyF3, -1},
d2enum.UseSkill4: {d2enum.KeyF4, -1},
d2enum.UseSkill5: {d2enum.KeyF5, -1},
d2enum.UseSkill6: {d2enum.KeyF6, -1},
d2enum.UseSkill7: {d2enum.KeyF7, -1},
d2enum.UseSkill8: {d2enum.KeyF8, -1},
d2enum.UseSkill9: {-1, -1},
d2enum.UseSkill10: {-1, -1},
d2enum.UseSkill11: {-1, -1},
d2enum.UseSkill12: {-1, -1},
d2enum.UseSkill13: {-1, -1},
d2enum.UseSkill14: {-1, -1},
d2enum.UseSkill15: {-1, -1},
d2enum.UseSkill16: {-1, -1},
d2enum.ToggleBelts: {d2enum.KeyTilde, -1},
d2enum.UseBeltSlot1: {d2enum.Key1, -1},
d2enum.UseBeltSlot2: {d2enum.Key2, -1},
d2enum.UseBeltSlot3: {d2enum.Key3, -1},
d2enum.UseBeltSlot4: {d2enum.Key4, -1},
d2enum.ToggleRunWalk: {d2enum.KeyR, -1},
d2enum.HoldRun: {d2enum.KeyControl, -1},
d2enum.HoldShowGroundItems: {d2enum.KeyAlt, -1},
d2enum.HoldShowPortraits: {d2enum.KeyZ, -1},
d2enum.HoldStandStill: {d2enum.KeyShift, -1},
d2enum.ClearScreen: {d2enum.KeySpace, -1},
}
for gameEvent, keys := range defaultControls {
keyMap.SetPrimaryBinding(gameEvent, keys.Primary)
keyMap.SetSecondaryBinding(gameEvent, keys.Secondary)
}
return keyMap
}