Add mouse support

This commit is contained in:
Trevor Slocum 2020-01-03 08:08:25 -08:00
parent 2d50065a82
commit 58d1dc5ea3
7 changed files with 238 additions and 208 deletions

View file

@ -1,5 +1,6 @@
0.1.4:
- Allow ghost piece to be disabled
- Add mouse support
0.1.3:
- Animate game over display

View file

@ -86,25 +86,11 @@ func resetPlayerSettingsForm() {
playerSettingsForm.Clear(true).AddInputField("Name", nickname, 0, nil, func(text string) {
nicknameDraft = text
}).AddButton("Cancel", func() {
titleScreen = 1
titleSelectedButton = 0
app.SetRoot(titleContainerGrid, true)
updateTitle()
selectTitleButton()
}).AddButton("Save", func() {
if nicknameDraft != "" && game.Nickname(nicknameDraft) != nickname {
nickname = game.Nickname(nicknameDraft)
if activeGame != nil {
activeGame.Event <- &event.NicknameEvent{Nickname: nickname}
}
}
titleScreen = 1
titleSelectedButton = 0
app.SetRoot(titleContainerGrid, true)
updateTitle()
titleSelectedButton = 1
selectTitleButton()
})
}

View file

@ -12,7 +12,7 @@ import (
)
func initGUI(skipTitle bool) (*cview.Application, error) {
app = cview.NewApplication()
app = cview.NewApplication().EnableMouse()
app.SetAfterResizeFunc(handleResize)
@ -135,13 +135,31 @@ func initGUI(skipTitle bool) (*cview.Application, error) {
go handleTitle()
buttonA = cview.NewButton("A")
buttonA = cview.NewButton("A").SetSelectedFunc(func() {
titleSelectedButton = 0
if titleScreen == 4 {
titleSelectedButton++
}
selectTitleButton()
})
buttonLabelA = cview.NewTextView().SetTextAlign(cview.AlignCenter)
buttonB = cview.NewButton("B")
buttonB = cview.NewButton("B").SetSelectedFunc(func() {
titleSelectedButton = 1
if titleScreen == 4 {
titleSelectedButton++
}
selectTitleButton()
})
buttonLabelB = cview.NewTextView().SetTextAlign(cview.AlignCenter)
buttonC = cview.NewButton("C")
buttonC = cview.NewButton("C").SetSelectedFunc(func() {
titleSelectedButton = 2
if titleScreen == 4 {
titleSelectedButton++
}
selectTitleButton()
})
buttonLabelC = cview.NewTextView().SetTextAlign(cview.AlignCenter)
titleNameGrid := cview.NewGrid().SetRows(3, 2).
@ -188,8 +206,8 @@ func initGUI(skipTitle bool) (*cview.Application, error) {
SetWrap(false).
SetWordWrap(false).SetText("\nRefresh: R\nPrevious: Shift+Tab - Next: Tab"), 4, 1, 1, 1, 0, 0, true)
buttonCancel = cview.NewButton("Cancel")
buttonStart = cview.NewButton("Start")
buttonCancel = cview.NewButton("Cancel").SetSelectedFunc(selectTitleFunc(3))
buttonStart = cview.NewButton("Start").SetSelectedFunc(selectTitleFunc(4))
newGameSubmitGrid := cview.NewGrid().
SetColumns(-1, 10, 1, 10, -1).
@ -271,20 +289,21 @@ func initGUI(skipTitle bool) (*cview.Application, error) {
SetWrap(false).
SetWordWrap(false).SetText("Game Settings")
buttonGhostPiece = cview.NewButton("Enabled")
buttonGhostPiece = cview.NewButton("Enabled").SetSelectedFunc(selectTitleFunc(0))
ghostPieceGrid := cview.NewGrid().SetColumns(19, -1).
AddItem(cview.NewTextView().SetText("Ghost Piece"), 0, 0, 1, 1, 0, 0, false).
AddItem(buttonGhostPiece, 0, 1, 1, 1, 0, 0, false)
buttonKeybindRotateCCW = cview.NewButton("Set")
buttonKeybindRotateCW = cview.NewButton("Set")
buttonKeybindMoveLeft = cview.NewButton("Set")
buttonKeybindMoveRight = cview.NewButton("Set")
buttonKeybindSoftDrop = cview.NewButton("Set")
buttonKeybindHardDrop = cview.NewButton("Set")
buttonKeybindCancel = cview.NewButton("Cancel")
buttonKeybindSave = cview.NewButton("Save")
buttonKeybindRotateCCW = cview.NewButton("Set").SetSelectedFunc(selectTitleFunc(1))
buttonKeybindRotateCW = cview.NewButton("Set").SetSelectedFunc(selectTitleFunc(2))
buttonKeybindMoveLeft = cview.NewButton("Set").SetSelectedFunc(selectTitleFunc(3))
buttonKeybindMoveRight = cview.NewButton("Set").SetSelectedFunc(selectTitleFunc(4))
buttonKeybindSoftDrop = cview.NewButton("Set").SetSelectedFunc(selectTitleFunc(5))
buttonKeybindHardDrop = cview.NewButton("Set").SetSelectedFunc(selectTitleFunc(6))
buttonKeybindCancel = cview.NewButton("Cancel").SetSelectedFunc(selectTitleFunc(7))
buttonKeybindSave = cview.NewButton("Save").SetSelectedFunc(selectTitleFunc(8))
rotateCCWGrid := cview.NewGrid().SetColumns(27, -1).
AddItem(cview.NewTextView().SetText("Rotate CCW"), 0, 0, 1, 1, 0, 0, false).

View file

@ -7,7 +7,6 @@ import (
"runtime/pprof"
"strings"
"git.sr.ht/~tslocum/cview"
"git.sr.ht/~tslocum/netris/pkg/event"
"git.sr.ht/~tslocum/netris/pkg/game"
"github.com/gdamore/tcell"
@ -71,7 +70,7 @@ func handleKeypress(ev *tcell.EventKey) *tcell.EventKey {
draftKeybindings = nil
app.SetRoot(gameSettingsContainerGrid, true)
updateGameSettings()
updateTitle()
return nil
}
@ -86,7 +85,7 @@ func handleKeypress(ev *tcell.EventKey) *tcell.EventKey {
}
var action event.GameAction
switch gameSettingsSelectedButton {
switch titleSelectedButton {
case 1:
action = event.ActionRotateCCW
case 2:
@ -106,7 +105,7 @@ func handleKeypress(ev *tcell.EventKey) *tcell.EventKey {
draftKeybindings = append(draftKeybindings, &Keybinding{k: k, r: r, m: ev.Modifiers(), a: action})
app.SetRoot(gameSettingsContainerGrid, true)
updateGameSettings()
updateTitle()
return nil
} else if titleVisible {
if titleScreen > 1 {
@ -135,48 +134,23 @@ func handleKeypress(ev *tcell.EventKey) *tcell.EventKey {
if titleScreen == 3 {
switch k {
case tcell.KeyTab:
gameSettingsSelectedButton++
if gameSettingsSelectedButton > 8 {
gameSettingsSelectedButton = 8
titleSelectedButton++
if titleSelectedButton > 8 {
titleSelectedButton = 8
}
updateGameSettings()
updateTitle()
return nil
case tcell.KeyBacktab:
gameSettingsSelectedButton--
if gameSettingsSelectedButton < 0 {
gameSettingsSelectedButton = 0
titleSelectedButton--
if titleSelectedButton < 0 {
titleSelectedButton = 0
}
updateGameSettings()
updateTitle()
return nil
case tcell.KeyEnter:
if gameSettingsSelectedButton == 0 {
// TODO Cache until saved
drawGhostPieceUnsaved = !drawGhostPieceUnsaved
updateGameSettings()
return nil
} else if gameSettingsSelectedButton == 7 || gameSettingsSelectedButton == 8 {
if gameSettingsSelectedButton == 8 {
drawGhostPiece = drawGhostPieceUnsaved
keybindings = make([]*Keybinding, len(draftKeybindings))
copy(keybindings, draftKeybindings)
}
draftKeybindings = nil
titleScreen = 1
titleSelectedButton = 0
app.SetRoot(titleContainerGrid, true)
updateTitle()
return nil
}
modal := cview.NewModal().SetText("Press desired key(s) to set keybinding or press Escape to cancel.").ClearButtons()
app.SetRoot(modal, true)
capturingKeybind = true
selectTitleButton()
return nil
}
} else if titleScreen == 4 {
@ -208,31 +182,7 @@ func handleKeypress(ev *tcell.EventKey) *tcell.EventKey {
renderGameList()
return nil
case tcell.KeyEnter:
if titleSelectedButton == 0 {
if gameListSelected >= 0 && gameListSelected < len(gameList) {
joinGame <- gameList[gameListSelected].ID
}
} else if titleSelectedButton == 1 {
titleScreen = 5
titleSelectedButton = 0
resetNewGameInputs()
app.SetRoot(newGameContainerGrid, true).SetFocus(nil)
updateTitle()
} else if titleSelectedButton == 2 {
titleScreen = 5
titleSelectedButton = 0
modal := cview.NewModal().SetText("Joining another server by IP via GUI is not yet implemented.\nPlease re-launch netris with the --connect argument instead.\n\nPress Escape to return.").ClearButtons()
app.SetRoot(modal, true)
} else if titleSelectedButton == 3 {
titleScreen = 0
titleSelectedButton = 0
app.SetRoot(titleContainerGrid, true)
updateTitle()
}
selectTitleButton()
return nil
default:
if titleSelectedButton == 0 {
@ -266,17 +216,7 @@ func handleKeypress(ev *tcell.EventKey) *tcell.EventKey {
updateTitle()
return nil
case tcell.KeyEnter:
if titleSelectedButton == 3 {
titleScreen = 4
gameListSelected = 0
titleSelectedButton = 0
app.SetRoot(gameListContainerGrid, true)
renderGameList()
updateTitle()
} else if titleSelectedButton == 4 {
joinGame <- event.GameIDNewCustom
}
selectTitleButton()
return nil
}
}
@ -286,77 +226,7 @@ func handleKeypress(ev *tcell.EventKey) *tcell.EventKey {
switch k {
case tcell.KeyEnter:
if titleScreen == 1 {
switch titleSelectedButton {
case 0:
resetPlayerSettingsForm()
titleScreen = 2
titleSelectedButton = 0
app.SetRoot(playerSettingsContainerGrid, true).SetFocus(playerSettingsForm)
return nil
case 1:
titleScreen = 3
titleSelectedButton = 0
gameSettingsSelectedButton = 0
drawGhostPieceUnsaved = drawGhostPiece
draftKeybindings = make([]*Keybinding, len(keybindings))
copy(draftKeybindings, keybindings)
app.SetRoot(gameSettingsContainerGrid, true)
updateGameSettings()
return nil
case 2:
titleScreen = 0
titleSelectedButton = 0
updateTitle()
return nil
}
} else {
if joinedGame {
switch titleSelectedButton {
case 0:
setTitleVisible(false)
return nil
case 1:
titleScreen = 1
titleSelectedButton = 0
updateTitle()
return nil
case 2:
done <- true
return nil
}
} else {
switch titleSelectedButton {
case 0:
titleScreen = 4
titleSelectedButton = 0
gameListSelected = 0
refreshGameList()
renderGameList()
app.SetRoot(gameListContainerGrid, true).SetFocus(nil)
updateTitle()
return nil
case 1:
joinGame <- event.GameIDNewLocal
return nil
case 2:
titleScreen = 1
titleSelectedButton = 0
updateTitle()
return nil
}
}
}
selectTitleButton()
return nil
case tcell.KeyUp, tcell.KeyBacktab:
previousTitleButton()

View file

@ -7,6 +7,7 @@ import (
"time"
"git.sr.ht/~tslocum/cview"
"git.sr.ht/~tslocum/netris/pkg/event"
"git.sr.ht/~tslocum/netris/pkg/game"
"git.sr.ht/~tslocum/netris/pkg/mino"
)
@ -16,11 +17,10 @@ const (
)
var (
titleVisible bool
titleScreen int
titleSelectedButton int
gameSettingsSelectedButton int
drawTitle = make(chan struct{}, game.CommandQueueSize)
titleVisible bool
titleScreen int
titleSelectedButton int
drawTitle = make(chan struct{}, game.CommandQueueSize)
titleGrid *cview.Grid
titleContainerGrid *cview.Grid
@ -88,32 +88,151 @@ func nextTitleButton() {
titleSelectedButton++
}
func updateGameSettings() {
if drawGhostPieceUnsaved {
buttonGhostPiece.SetLabel("Enabled")
} else {
buttonGhostPiece.SetLabel("Disabled")
func selectTitleButton() {
if !titleVisible {
return
}
switch gameSettingsSelectedButton {
case 0:
app.SetFocus(buttonGhostPiece)
switch titleScreen {
case 1:
app.SetFocus(buttonKeybindRotateCCW)
switch titleSelectedButton {
case 0:
resetPlayerSettingsForm()
titleScreen = 2
titleSelectedButton = 0
app.SetRoot(playerSettingsContainerGrid, true).SetFocus(playerSettingsForm)
case 1:
titleScreen = 3
titleSelectedButton = 0
drawGhostPieceUnsaved = drawGhostPiece
draftKeybindings = make([]*Keybinding, len(keybindings))
copy(draftKeybindings, keybindings)
app.SetRoot(gameSettingsContainerGrid, true)
updateTitle()
case 2:
titleScreen = 0
titleSelectedButton = 0
updateTitle()
}
case 2:
app.SetFocus(buttonKeybindRotateCW)
if titleSelectedButton == 1 {
// Save
if nicknameDraft != "" && game.Nickname(nicknameDraft) != nickname {
nickname = game.Nickname(nicknameDraft)
if activeGame != nil {
activeGame.Event <- &event.NicknameEvent{Nickname: nickname}
}
}
}
titleScreen = 1
titleSelectedButton = 0
app.SetRoot(titleContainerGrid, true)
updateTitle()
case 3:
app.SetFocus(buttonKeybindMoveLeft)
if titleSelectedButton == 0 {
drawGhostPieceUnsaved = !drawGhostPieceUnsaved
updateTitle()
return
} else if titleSelectedButton == 7 || titleSelectedButton == 8 {
if titleSelectedButton == 8 {
drawGhostPiece = drawGhostPieceUnsaved
keybindings = make([]*Keybinding, len(draftKeybindings))
copy(keybindings, draftKeybindings)
}
draftKeybindings = nil
titleScreen = 1
titleSelectedButton = 0
app.SetRoot(titleContainerGrid, true)
updateTitle()
return
}
modal := cview.NewModal().SetText("Press desired key(s) to set keybinding or press Escape to cancel.").ClearButtons()
app.SetRoot(modal, true)
capturingKeybind = true
case 4:
app.SetFocus(buttonKeybindMoveRight)
if titleSelectedButton == 0 {
if gameListSelected >= 0 && gameListSelected < len(gameList) {
joinGame <- gameList[gameListSelected].ID
}
} else if titleSelectedButton == 1 {
titleScreen = 5
titleSelectedButton = 0
resetNewGameInputs()
app.SetRoot(newGameContainerGrid, true).SetFocus(nil)
updateTitle()
} else if titleSelectedButton == 2 {
titleScreen = 5
titleSelectedButton = 0
modal := cview.NewModal().SetText("Joining another server by IP via GUI is not yet implemented.\nPlease re-launch netris with the --connect argument instead.\n\nPress Escape to return.").ClearButtons()
app.SetRoot(modal, true)
} else if titleSelectedButton == 3 {
titleScreen = 0
titleSelectedButton = 0
app.SetRoot(titleContainerGrid, true)
updateTitle()
}
case 5:
app.SetFocus(buttonKeybindSoftDrop)
case 6:
app.SetFocus(buttonKeybindHardDrop)
case 7:
app.SetFocus(buttonKeybindCancel)
case 8:
app.SetFocus(buttonKeybindSave)
if titleSelectedButton == 3 {
titleScreen = 4
gameListSelected = 0
titleSelectedButton = 0
app.SetRoot(gameListContainerGrid, true)
renderGameList()
updateTitle()
} else if titleSelectedButton == 4 {
joinGame <- event.GameIDNewCustom
}
default: // Title screen 0
if joinedGame {
switch titleSelectedButton {
case 0:
setTitleVisible(false)
case 1:
titleScreen = 1
titleSelectedButton = 0
updateTitle()
case 2:
done <- true
}
} else {
switch titleSelectedButton {
case 0:
titleScreen = 4
titleSelectedButton = 0
gameListSelected = 0
refreshGameList()
renderGameList()
app.SetRoot(gameListContainerGrid, true).SetFocus(nil)
updateTitle()
case 1:
joinGame <- event.GameIDNewLocal
case 2:
titleScreen = 1
titleSelectedButton = 0
updateTitle()
}
}
}
}
@ -178,7 +297,35 @@ func updateTitle() {
}
}
if titleScreen == 4 {
if titleScreen == 3 {
if drawGhostPieceUnsaved {
buttonGhostPiece.SetLabel("Enabled")
} else {
buttonGhostPiece.SetLabel("Disabled")
}
switch titleSelectedButton {
case 0:
app.SetFocus(buttonGhostPiece)
case 1:
app.SetFocus(buttonKeybindRotateCCW)
case 2:
app.SetFocus(buttonKeybindRotateCW)
case 3:
app.SetFocus(buttonKeybindMoveLeft)
case 4:
app.SetFocus(buttonKeybindMoveRight)
case 5:
app.SetFocus(buttonKeybindSoftDrop)
case 6:
app.SetFocus(buttonKeybindHardDrop)
case 7:
app.SetFocus(buttonKeybindCancel)
case 8:
app.SetFocus(buttonKeybindSave)
}
return
} else if titleScreen == 4 {
switch titleSelectedButton {
case 2:
app.SetFocus(buttonB)
@ -449,3 +596,10 @@ func resetNewGameInputs() {
newGameMaxPlayersInput.SetText("0")
newGameSpeedLimitInput.SetText("0")
}
func selectTitleFunc(i int) func() {
return func() {
titleSelectedButton = i
selectTitleButton()
}
}

4
go.mod
View file

@ -3,7 +3,7 @@ module git.sr.ht/~tslocum/netris
go 1.13
require (
git.sr.ht/~tslocum/cview v0.2.1-0.20191231040847-3c1736c9c849
git.sr.ht/~tslocum/cview v0.2.2-0.20200103004846-1207c71f9f20
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 // indirect
github.com/creack/pty v1.1.9
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
@ -13,5 +13,5 @@ require (
github.com/mattn/go-isatty v0.0.11
github.com/mattn/go-runewidth v0.0.7 // indirect
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8 // indirect
golang.org/x/sys v0.0.0-20200103143344-a1369afcdac7 // indirect
)

8
go.sum
View file

@ -1,5 +1,5 @@
git.sr.ht/~tslocum/cview v0.2.1-0.20191231040847-3c1736c9c849 h1:t18Zd/LG2cxJwAQVSsncquNjAgcn4RpRkCq7EV++Ba8=
git.sr.ht/~tslocum/cview v0.2.1-0.20191231040847-3c1736c9c849/go.mod h1:92oD1V0TlLtAeJUruA+p5/P6sVL0p8TMMosPwqz0/gM=
git.sr.ht/~tslocum/cview v0.2.2-0.20200103004846-1207c71f9f20 h1:bEvYUKm++WdkbJXhxeYpwNr55jBmTfQ8TRLMKxaCHzE=
git.sr.ht/~tslocum/cview v0.2.2-0.20200103004846-1207c71f9f20/go.mod h1:92oD1V0TlLtAeJUruA+p5/P6sVL0p8TMMosPwqz0/gM=
github.com/DATA-DOG/go-sqlmock v1.3.3 h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFDnH08=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
@ -36,8 +36,8 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191018095205-727590c5006e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8 h1:JA8d3MPx/IToSyXZG/RhwYEtfrKO1Fxrqe8KrkiLXKM=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200103143344-a1369afcdac7 h1:/W9OPMnnpmFXHYkcp2rQsbFUbRlRzfECQjmAFiOyHE8=
golang.org/x/sys v0.0.0-20200103143344-a1369afcdac7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=