mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-04 15:46:51 -05:00
Help and Escape Menu click through and close behavior (#761)
* Disallow clicking through the help menu to control the game * Move Navigator and EscapeMenu up in package tree to be accessible by GameControls. Disallow GameControls input when EscapeMenu is open * Make ESC key behavior more consistent with D2
This commit is contained in:
parent
2e42fcee15
commit
b1cdb47302
@ -1,4 +1,4 @@
|
|||||||
package d2gamescreen
|
package d2interface
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client/d2clientconnectiontype"
|
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client/d2clientconnectiontype"
|
@ -268,6 +268,10 @@ func (l *Layout) getContentSize() (width, height int) {
|
|||||||
return width, height
|
return width, height
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *Layout) GetSize() (width, height int) {
|
||||||
|
return l.getSize()
|
||||||
|
}
|
||||||
|
|
||||||
func (l *Layout) getSize() (width, height int) {
|
func (l *Layout) getSize() (width, height int) {
|
||||||
width, height = l.getContentSize()
|
width, height = l.getContentSize()
|
||||||
return d2math.MaxInt(width, l.width), d2math.MaxInt(height, l.height)
|
return d2math.MaxInt(width, l.width), d2math.MaxInt(height, l.height)
|
||||||
|
@ -54,12 +54,12 @@ type CharacterSelect struct {
|
|||||||
inputManager d2interface.InputManager
|
inputManager d2interface.InputManager
|
||||||
audioProvider d2interface.AudioProvider
|
audioProvider d2interface.AudioProvider
|
||||||
renderer d2interface.Renderer
|
renderer d2interface.Renderer
|
||||||
navigator Navigator
|
navigator d2interface.Navigator
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateCharacterSelect creates the character select screen and returns a pointer to it
|
// CreateCharacterSelect creates the character select screen and returns a pointer to it
|
||||||
func CreateCharacterSelect(
|
func CreateCharacterSelect(
|
||||||
navigator Navigator,
|
navigator d2interface.Navigator,
|
||||||
asset *d2asset.AssetManager,
|
asset *d2asset.AssetManager,
|
||||||
renderer d2interface.Renderer,
|
renderer d2interface.Renderer,
|
||||||
inputManager d2interface.InputManager,
|
inputManager d2interface.InputManager,
|
||||||
|
@ -41,12 +41,12 @@ type Credits struct {
|
|||||||
|
|
||||||
asset *d2asset.AssetManager
|
asset *d2asset.AssetManager
|
||||||
renderer d2interface.Renderer
|
renderer d2interface.Renderer
|
||||||
navigator Navigator
|
navigator d2interface.Navigator
|
||||||
uiManager *d2ui.UIManager
|
uiManager *d2ui.UIManager
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateCredits creates an instance of the credits screen
|
// CreateCredits creates an instance of the credits screen
|
||||||
func CreateCredits(navigator Navigator, asset *d2asset.AssetManager, renderer d2interface.Renderer,
|
func CreateCredits(navigator d2interface.Navigator, asset *d2asset.AssetManager, renderer d2interface.Renderer,
|
||||||
ui *d2ui.UIManager) *Credits {
|
ui *d2ui.UIManager) *Credits {
|
||||||
result := &Credits{
|
result := &Credits{
|
||||||
asset: asset,
|
asset: asset,
|
||||||
|
@ -42,7 +42,7 @@ type Game struct {
|
|||||||
localPlayer *d2mapentity.Player
|
localPlayer *d2mapentity.Player
|
||||||
lastRegionType d2enum.RegionIdType
|
lastRegionType d2enum.RegionIdType
|
||||||
ticksSinceLevelCheck float64
|
ticksSinceLevelCheck float64
|
||||||
escapeMenu *EscapeMenu
|
escapeMenu *d2player.EscapeMenu
|
||||||
soundEngine *d2audio.SoundEngine
|
soundEngine *d2audio.SoundEngine
|
||||||
soundEnv d2audio.SoundEnvironment
|
soundEnv d2audio.SoundEnvironment
|
||||||
guiManager *d2gui.GuiManager
|
guiManager *d2gui.GuiManager
|
||||||
@ -55,7 +55,7 @@ type Game struct {
|
|||||||
|
|
||||||
// CreateGame creates the Gameplay screen and returns a pointer to it
|
// CreateGame creates the Gameplay screen and returns a pointer to it
|
||||||
func CreateGame(
|
func CreateGame(
|
||||||
navigator Navigator,
|
navigator d2interface.Navigator,
|
||||||
asset *d2asset.AssetManager,
|
asset *d2asset.AssetManager,
|
||||||
ui *d2ui.UIManager,
|
ui *d2ui.UIManager,
|
||||||
renderer d2interface.Renderer,
|
renderer d2interface.Renderer,
|
||||||
@ -88,7 +88,7 @@ func CreateGame(
|
|||||||
ticksSinceLevelCheck: 0,
|
ticksSinceLevelCheck: 0,
|
||||||
mapRenderer: d2maprenderer.CreateMapRenderer(asset, renderer,
|
mapRenderer: d2maprenderer.CreateMapRenderer(asset, renderer,
|
||||||
gameClient.MapEngine, term, startX, startY),
|
gameClient.MapEngine, term, startX, startY),
|
||||||
escapeMenu: NewEscapeMenu(navigator, renderer, audioProvider, guiManager, asset),
|
escapeMenu: d2player.NewEscapeMenu(navigator, renderer, audioProvider, guiManager, asset),
|
||||||
inputManager: inputManager,
|
inputManager: inputManager,
|
||||||
audioProvider: audioProvider,
|
audioProvider: audioProvider,
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
@ -99,7 +99,7 @@ func CreateGame(
|
|||||||
}
|
}
|
||||||
result.soundEnv = d2audio.NewSoundEnvironment(result.soundEngine)
|
result.soundEnv = d2audio.NewSoundEnvironment(result.soundEngine)
|
||||||
|
|
||||||
result.escapeMenu.onLoad()
|
result.escapeMenu.OnLoad()
|
||||||
|
|
||||||
if err := inputManager.BindHandler(result.escapeMenu); err != nil {
|
if err := inputManager.BindHandler(result.escapeMenu); err != nil {
|
||||||
fmt.Println("failed to add gameplay screen as event handler")
|
fmt.Println("failed to add gameplay screen as event handler")
|
||||||
@ -219,7 +219,7 @@ func (v *Game) Render(screen d2interface.Surface) error {
|
|||||||
func (v *Game) Advance(elapsed float64) error {
|
func (v *Game) Advance(elapsed float64) error {
|
||||||
v.soundEngine.Advance(elapsed)
|
v.soundEngine.Advance(elapsed)
|
||||||
|
|
||||||
if (v.escapeMenu != nil && !v.escapeMenu.isOpen) || len(v.gameClient.Players) != 1 {
|
if (v.escapeMenu != nil && !v.escapeMenu.IsOpen()) || len(v.gameClient.Players) != 1 {
|
||||||
v.gameClient.MapEngine.Advance(elapsed) // TODO: Hack
|
v.gameClient.MapEngine.Advance(elapsed) // TODO: Hack
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,7 +285,7 @@ func (v *Game) bindGameControls() error {
|
|||||||
|
|
||||||
var err error
|
var err error
|
||||||
v.gameControls, err = d2player.NewGameControls(v.asset, v.renderer, player, v.gameClient.MapEngine,
|
v.gameControls, err = d2player.NewGameControls(v.asset, v.renderer, player, v.gameClient.MapEngine,
|
||||||
v.mapRenderer, v, v.terminal, v.uiManager, v.guiManager, v.gameClient.IsSinglePlayer())
|
v.escapeMenu, v.mapRenderer, v, v.terminal, v.uiManager, v.guiManager, v.gameClient.IsSinglePlayer())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -117,7 +117,7 @@ type MainMenu struct {
|
|||||||
renderer d2interface.Renderer
|
renderer d2interface.Renderer
|
||||||
audioProvider d2interface.AudioProvider
|
audioProvider d2interface.AudioProvider
|
||||||
scriptEngine *d2script.ScriptEngine
|
scriptEngine *d2script.ScriptEngine
|
||||||
navigator Navigator
|
navigator d2interface.Navigator
|
||||||
uiManager *d2ui.UIManager
|
uiManager *d2ui.UIManager
|
||||||
heroState *d2hero.HeroStateFactory
|
heroState *d2hero.HeroStateFactory
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ type MainMenu struct {
|
|||||||
|
|
||||||
// CreateMainMenu creates an instance of MainMenu
|
// CreateMainMenu creates an instance of MainMenu
|
||||||
func CreateMainMenu(
|
func CreateMainMenu(
|
||||||
navigator Navigator,
|
navigator d2interface.Navigator,
|
||||||
asset *d2asset.AssetManager,
|
asset *d2asset.AssetManager,
|
||||||
renderer d2interface.Renderer,
|
renderer d2interface.Renderer,
|
||||||
inputManager d2interface.InputManager,
|
inputManager d2interface.InputManager,
|
||||||
|
@ -297,12 +297,12 @@ type SelectHeroClass struct {
|
|||||||
|
|
||||||
audioProvider d2interface.AudioProvider
|
audioProvider d2interface.AudioProvider
|
||||||
renderer d2interface.Renderer
|
renderer d2interface.Renderer
|
||||||
navigator Navigator
|
navigator d2interface.Navigator
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateSelectHeroClass creates an instance of a SelectHeroClass
|
// CreateSelectHeroClass creates an instance of a SelectHeroClass
|
||||||
func CreateSelectHeroClass(
|
func CreateSelectHeroClass(
|
||||||
navigator Navigator,
|
navigator d2interface.Navigator,
|
||||||
asset *d2asset.AssetManager,
|
asset *d2asset.AssetManager,
|
||||||
renderer d2interface.Renderer,
|
renderer d2interface.Renderer,
|
||||||
audioProvider d2interface.AudioProvider,
|
audioProvider d2interface.AudioProvider,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package d2gamescreen
|
package d2player
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -71,7 +71,7 @@ type EscapeMenu struct {
|
|||||||
|
|
||||||
renderer d2interface.Renderer
|
renderer d2interface.Renderer
|
||||||
audioProvider d2interface.AudioProvider
|
audioProvider d2interface.AudioProvider
|
||||||
navigator Navigator
|
navigator d2interface.Navigator
|
||||||
guiManager *d2gui.GuiManager
|
guiManager *d2gui.GuiManager
|
||||||
assetManager *d2asset.AssetManager
|
assetManager *d2asset.AssetManager
|
||||||
}
|
}
|
||||||
@ -127,7 +127,7 @@ type actionableElement interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewEscapeMenu creates a new escape menu
|
// NewEscapeMenu creates a new escape menu
|
||||||
func NewEscapeMenu(navigator Navigator,
|
func NewEscapeMenu(navigator d2interface.Navigator,
|
||||||
renderer d2interface.Renderer,
|
renderer d2interface.Renderer,
|
||||||
audioProvider d2interface.AudioProvider,
|
audioProvider d2interface.AudioProvider,
|
||||||
guiManager *d2gui.GuiManager,
|
guiManager *d2gui.GuiManager,
|
||||||
@ -351,7 +351,7 @@ func (m *EscapeMenu) addEnumLabel(l *layout, optID optionID, text string, values
|
|||||||
l.actionableElements = append(l.actionableElements, label)
|
l.actionableElements = append(l.actionableElements, label)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *EscapeMenu) onLoad() {
|
func (m *EscapeMenu) OnLoad() {
|
||||||
var err error
|
var err error
|
||||||
m.selectSound, err = m.audioProvider.LoadSound(d2resource.SFXCursorSelect, false, false)
|
m.selectSound, err = m.audioProvider.LoadSound(d2resource.SFXCursorSelect, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -359,12 +359,7 @@ func (m *EscapeMenu) onLoad() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *EscapeMenu) onEscKey() {
|
func (m *EscapeMenu) OnEscKey() {
|
||||||
if !m.isOpen {
|
|
||||||
m.open()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch m.currentLayout {
|
switch m.currentLayout {
|
||||||
case optionsLayoutID:
|
case optionsLayoutID:
|
||||||
m.setLayout(mainLayoutID)
|
m.setLayout(mainLayoutID)
|
||||||
@ -466,11 +461,13 @@ func (m *EscapeMenu) onEnterKey() {
|
|||||||
m.layouts[m.currentLayout].actionableElements[m.layouts[m.currentLayout].currentEl].Trigger()
|
m.layouts[m.currentLayout].actionableElements[m.layouts[m.currentLayout].currentEl].Trigger()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *EscapeMenu) IsOpen() bool {
|
||||||
|
return m.isOpen
|
||||||
|
}
|
||||||
|
|
||||||
// OnKeyDown defines the actions of the Escape Menu when a key is pressed
|
// OnKeyDown defines the actions of the Escape Menu when a key is pressed
|
||||||
func (m *EscapeMenu) OnKeyDown(event d2interface.KeyEvent) bool {
|
func (m *EscapeMenu) OnKeyDown(event d2interface.KeyEvent) bool {
|
||||||
switch event.Key() {
|
switch event.Key() {
|
||||||
case d2enum.KeyEscape:
|
|
||||||
m.onEscKey()
|
|
||||||
case d2enum.KeyUp:
|
case d2enum.KeyUp:
|
||||||
m.onUpKey()
|
m.onUpKey()
|
||||||
case d2enum.KeyDown:
|
case d2enum.KeyDown:
|
@ -55,6 +55,7 @@ type GameControls struct {
|
|||||||
heroState *d2hero.HeroStateFactory
|
heroState *d2hero.HeroStateFactory
|
||||||
mapEngine *d2mapengine.MapEngine
|
mapEngine *d2mapengine.MapEngine
|
||||||
mapRenderer *d2maprenderer.MapRenderer
|
mapRenderer *d2maprenderer.MapRenderer
|
||||||
|
escapeMenu *EscapeMenu
|
||||||
ui *d2ui.UIManager
|
ui *d2ui.UIManager
|
||||||
inventory *Inventory
|
inventory *Inventory
|
||||||
heroStatsPanel *HeroStatsPanel
|
heroStatsPanel *HeroStatsPanel
|
||||||
@ -122,11 +123,13 @@ func NewGameControls(
|
|||||||
renderer d2interface.Renderer,
|
renderer d2interface.Renderer,
|
||||||
hero *d2mapentity.Player,
|
hero *d2mapentity.Player,
|
||||||
mapEngine *d2mapengine.MapEngine,
|
mapEngine *d2mapengine.MapEngine,
|
||||||
|
escapeMenu *EscapeMenu,
|
||||||
mapRenderer *d2maprenderer.MapRenderer,
|
mapRenderer *d2maprenderer.MapRenderer,
|
||||||
inputListener InputCallbackListener,
|
inputListener InputCallbackListener,
|
||||||
term d2interface.Terminal,
|
term d2interface.Terminal,
|
||||||
ui *d2ui.UIManager,
|
ui *d2ui.UIManager,
|
||||||
guiManager *d2gui.GuiManager,
|
guiManager *d2gui.GuiManager,
|
||||||
|
|
||||||
isSinglePlayer bool,
|
isSinglePlayer bool,
|
||||||
) (*GameControls, error) {
|
) (*GameControls, error) {
|
||||||
|
|
||||||
@ -181,6 +184,7 @@ func NewGameControls(
|
|||||||
hero: hero,
|
hero: hero,
|
||||||
heroState: heroState,
|
heroState: heroState,
|
||||||
mapEngine: mapEngine,
|
mapEngine: mapEngine,
|
||||||
|
escapeMenu: escapeMenu,
|
||||||
inputListener: inputListener,
|
inputListener: inputListener,
|
||||||
mapRenderer: mapRenderer,
|
mapRenderer: mapRenderer,
|
||||||
inventory: NewInventory(asset, ui, inventoryRecord),
|
inventory: NewInventory(asset, ui, inventoryRecord),
|
||||||
@ -293,13 +297,8 @@ func (g *GameControls) OnKeyRepeat(event d2interface.KeyEvent) bool {
|
|||||||
func (g *GameControls) OnKeyDown(event d2interface.KeyEvent) bool {
|
func (g *GameControls) OnKeyDown(event d2interface.KeyEvent) bool {
|
||||||
switch event.Key() {
|
switch event.Key() {
|
||||||
case d2enum.KeyEscape:
|
case d2enum.KeyEscape:
|
||||||
if g.inventory.IsOpen() || g.heroStatsPanel.IsOpen() {
|
g.onEscKey()
|
||||||
g.inventory.Close()
|
|
||||||
g.heroStatsPanel.Close()
|
|
||||||
g.updateLayout()
|
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
|
||||||
case d2enum.KeyI:
|
case d2enum.KeyI:
|
||||||
g.inventory.Toggle()
|
g.inventory.Toggle()
|
||||||
g.updateLayout()
|
g.updateLayout()
|
||||||
@ -330,6 +329,35 @@ func (g *GameControls) OnKeyUp(event d2interface.KeyEvent) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *GameControls) onEscKey() {
|
||||||
|
// When escape is pressed:
|
||||||
|
// 1. If there was some overlay or panel open, close it
|
||||||
|
// 2. Otherwise, if the Escape Menu was open, let the Escape Menu handle it
|
||||||
|
// 3. If nothing was open, open the Escape Menu
|
||||||
|
|
||||||
|
escHandled := false
|
||||||
|
if g.inventory.IsOpen() {
|
||||||
|
g.inventory.Close()
|
||||||
|
escHandled = true
|
||||||
|
}
|
||||||
|
if g.heroStatsPanel.IsOpen() {
|
||||||
|
g.heroStatsPanel.Close()
|
||||||
|
escHandled = true
|
||||||
|
}
|
||||||
|
if g.HelpOverlay.IsOpen() {
|
||||||
|
g.HelpOverlay.Toggle()
|
||||||
|
escHandled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if escHandled {
|
||||||
|
g.updateLayout()
|
||||||
|
} else if g.escapeMenu.isOpen {
|
||||||
|
g.escapeMenu.OnEscKey()
|
||||||
|
} else {
|
||||||
|
g.escapeMenu.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// OnMouseButtonRepeat handles repeated mouse clicks
|
// OnMouseButtonRepeat handles repeated mouse clicks
|
||||||
func (g *GameControls) OnMouseButtonRepeat(event d2interface.MouseEvent) bool {
|
func (g *GameControls) OnMouseButtonRepeat(event d2interface.MouseEvent) bool {
|
||||||
px, py := g.mapRenderer.ScreenToWorld(event.X(), event.Y())
|
px, py := g.mapRenderer.ScreenToWorld(event.X(), event.Y())
|
||||||
@ -557,6 +585,10 @@ func (g *GameControls) isInActiveMenusRect(px, py int) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if g.escapeMenu.IsOpen() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
if g.HelpOverlay.IsOpen() && g.HelpOverlay.IsInRect(px, py) {
|
if g.HelpOverlay.IsOpen() && g.HelpOverlay.IsInRect(px, py) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -56,11 +56,6 @@ func NewHelpOverlay(
|
|||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Overlay) onMouseDown() {
|
|
||||||
// If mouse over close button
|
|
||||||
// close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Overlay) Toggle() {
|
func (h *Overlay) Toggle() {
|
||||||
fmt.Print("Help overlay toggled\n")
|
fmt.Print("Help overlay toggled\n")
|
||||||
if h.isOpen {
|
if h.isOpen {
|
||||||
@ -93,8 +88,9 @@ func (h *Overlay) IsOpen() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Overlay) IsInRect(px, py int) bool {
|
func (h *Overlay) IsInRect(px, py int) bool {
|
||||||
ww, hh := h.closeButton.GetSize()
|
|
||||||
x, y := h.closeButton.GetPosition()
|
ww, hh := h.layout.GetSize()
|
||||||
|
x, y := h.layout.GetPosition()
|
||||||
|
|
||||||
if px >= x && px <= x+ww && py >= y && py <= y+hh {
|
if px >= x && px <= x+ww && py >= y && py <= y+hh {
|
||||||
return true
|
return true
|
||||||
|
Loading…
Reference in New Issue
Block a user