ca6d12ef8cf3573d11bc2c45cedd4f147af90648 — Trevor Slocum 18 days ago 133d956
Allow ghost piece to be disabled

Resolves #19
M cmd/netris/gui.go => cmd/netris/gui.go +14 -2
@@ 48,10 48,14 @@ var (
 	nickname      = "Anonymous"
 	nicknameDraft string
 
+	drawGhostPiece        = true
+	drawGhostPieceUnsaved bool
+
 	inputHeight, mainHeight, previewWidth, newLogLines int
 
 	profileCPU *os.File
 
+	buttonGhostPiece       *tview.Button
 	buttonKeybindRotateCCW *tview.Button
 	buttonKeybindRotateCW  *tview.Button
 	buttonKeybindMoveLeft  *tview.Button


@@ 276,7 280,7 @@ func renderPlayerGUI() {
 	if !player.Matrix.GameOver {
 		err := player.Preview.Add(p, p.Solid, mino.Point{0, 0}, false)
 		if err != nil {
-			log.Fatalf("failed to render preview matrix: failed to add ghost piece: %+v", err)
+			log.Fatalf("failed to render preview matrix: failed to add preview piece: %+v", err)
 		}
 	}
 


@@ 435,7 439,15 @@ func renderMatrixes(mx []*mino.Matrix) {
 
 	for i := range mx {
 		mx[i].Lock()
-		mx[i].DrawPiecesL()
+		if mt == mino.MatrixCustom {
+			continue
+		}
+
+		mx[i].ClearOverlayL()
+		if drawGhostPiece {
+			mx[i].DrawGhostPieceL()
+		}
+		mx[i].DrawActivePieceL()
 	}
 
 	if mt == mino.MatrixStandard {

M cmd/netris/gui_init.go => cmd/netris/gui_init.go +37 -23
@@ 271,6 271,12 @@ func initGUI(skipTitle bool) (*tview.Application, error) {
 		SetWrap(false).
 		SetWordWrap(false).SetText("Game Settings")
 
+	buttonGhostPiece = tview.NewButton("Enabled")
+
+	ghostPieceGrid := tview.NewGrid().SetColumns(19, -1).
+		AddItem(tview.NewTextView().SetText("Ghost Piece"), 0, 0, 1, 1, 0, 0, false).
+		AddItem(buttonGhostPiece, 0, 1, 1, 1, 0, 0, false)
+
 	buttonKeybindRotateCCW = tview.NewButton("Set")
 	buttonKeybindRotateCW = tview.NewButton("Set")
 	buttonKeybindMoveLeft = tview.NewButton("Set")


@@ 280,27 286,27 @@ func initGUI(skipTitle bool) (*tview.Application, error) {
 	buttonKeybindCancel = tview.NewButton("Cancel")
 	buttonKeybindSave = tview.NewButton("Save")
 
-	rotateCCWGrid := tview.NewGrid().
+	rotateCCWGrid := tview.NewGrid().SetColumns(27, -1).
 		AddItem(tview.NewTextView().SetText("Rotate CCW"), 0, 0, 1, 1, 0, 0, false).
 		AddItem(buttonKeybindRotateCCW, 0, 1, 1, 1, 0, 0, false)
 
-	rotateCWGrid := tview.NewGrid().
+	rotateCWGrid := tview.NewGrid().SetColumns(27, -1).
 		AddItem(tview.NewTextView().SetText("Rotate CW"), 0, 0, 1, 1, 0, 0, false).
 		AddItem(buttonKeybindRotateCW, 0, 1, 1, 1, 0, 0, false)
 
-	moveLeftGrid := tview.NewGrid().
+	moveLeftGrid := tview.NewGrid().SetColumns(27, -1).
 		AddItem(tview.NewTextView().SetText("Move Left"), 0, 0, 1, 1, 0, 0, false).
 		AddItem(buttonKeybindMoveLeft, 0, 1, 1, 1, 0, 0, false)
 
-	moveRightGrid := tview.NewGrid().
+	moveRightGrid := tview.NewGrid().SetColumns(27, -1).
 		AddItem(tview.NewTextView().SetText("Move Right"), 0, 0, 1, 1, 0, 0, false).
 		AddItem(buttonKeybindMoveRight, 0, 1, 1, 1, 0, 0, false)
 
-	softDropGrid := tview.NewGrid().
+	softDropGrid := tview.NewGrid().SetColumns(27, -1).
 		AddItem(tview.NewTextView().SetText("Soft Drop"), 0, 0, 1, 1, 0, 0, false).
 		AddItem(buttonKeybindSoftDrop, 0, 1, 1, 1, 0, 0, false)
 
-	hardDropGrid := tview.NewGrid().
+	hardDropGrid := tview.NewGrid().SetColumns(27, -1).
 		AddItem(tview.NewTextView().SetText("Hard Drop"), 0, 0, 1, 1, 0, 0, false).
 		AddItem(buttonKeybindHardDrop, 0, 1, 1, 1, 0, 0, false)
 


@@ 313,29 319,37 @@ func initGUI(skipTitle bool) (*tview.Application, error) {
 		AddItem(pad, 0, 4, 1, 1, 0, 0, false)
 
 	gameSettingsGrid = tview.NewGrid().
-		SetRows(5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1).
+		SetRows(5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1).
 		SetColumns(-1, 34, -1).
-		AddItem(titleL, 0, 0, 16, 1, 0, 0, false).
+		AddItem(titleL, 0, 0, 18, 1, 0, 0, false).
 		AddItem(titleNameGrid, 0, 1, 1, 1, 0, 0, false).
-		AddItem(titleR, 0, 2, 16, 1, 0, 0, false).
+		AddItem(titleR, 0, 2, 18, 1, 0, 0, false).
 		AddItem(gameSettingsTitle, 1, 1, 1, 1, 0, 0, false).
-		AddItem(rotateCCWGrid, 2, 1, 1, 1, 0, 0, false).
-		AddItem(pad, 3, 1, 1, 1, 0, 0, false).
-		AddItem(rotateCWGrid, 4, 1, 1, 1, 0, 0, false).
-		AddItem(pad, 5, 1, 1, 1, 0, 0, false).
-		AddItem(moveLeftGrid, 6, 1, 1, 1, 0, 0, false).
-		AddItem(pad, 7, 1, 1, 1, 0, 0, false).
-		AddItem(moveRightGrid, 8, 1, 1, 1, 0, 0, false).
-		AddItem(pad, 9, 1, 1, 1, 0, 0, false).
-		AddItem(softDropGrid, 10, 1, 1, 1, 0, 0, false).
-		AddItem(pad, 11, 1, 1, 1, 0, 0, false).
-		AddItem(hardDropGrid, 12, 1, 1, 1, 0, 0, false).
-		AddItem(pad, 13, 1, 1, 1, 0, 0, false).
-		AddItem(gameSettingsSubmitGrid, 14, 1, 1, 1, 0, 0, false).
+		AddItem(pad, 2, 1, 1, 1, 0, 0, false).
+		AddItem(tview.NewTextView().
+			SetTextAlign(tview.AlignCenter).
+			SetWrap(false).
+			SetWordWrap(false).SetText("Options"), 3, 1, 1, 1, 0, 0, false).
+		AddItem(ghostPieceGrid, 4, 1, 1, 1, 0, 0, false).
+		AddItem(ghostPieceGrid, 5, 1, 1, 1, 0, 0, false).
+		AddItem(pad, 6, 1, 1, 1, 0, 0, false).
+		AddItem(tview.NewTextView().
+			SetTextAlign(tview.AlignCenter).
+			SetWrap(false).
+			SetWordWrap(false).SetText("Keybindings"), 7, 1, 1, 1, 0, 0, false).
+		AddItem(pad, 8, 1, 1, 1, 0, 0, false).
+		AddItem(rotateCCWGrid, 9, 1, 1, 1, 0, 0, false).
+		AddItem(rotateCWGrid, 10, 1, 1, 1, 0, 0, false).
+		AddItem(moveLeftGrid, 11, 1, 1, 1, 0, 0, false).
+		AddItem(moveRightGrid, 12, 1, 1, 1, 0, 0, false).
+		AddItem(softDropGrid, 13, 1, 1, 1, 0, 0, false).
+		AddItem(hardDropGrid, 14, 1, 1, 1, 0, 0, false).
+		AddItem(pad, 15, 1, 1, 1, 0, 0, false).
+		AddItem(gameSettingsSubmitGrid, 16, 1, 1, 1, 0, 0, false).
 		AddItem(tview.NewTextView().
 			SetTextAlign(tview.AlignCenter).
 			SetWrap(false).
-			SetWordWrap(false).SetText("\nPrevious: Shift+Tab - Next: Tab"), 15, 1, 1, 1, 0, 0, false)
+			SetWordWrap(false).SetText("\nPrevious: Shift+Tab - Next: Tab"), 17, 1, 1, 1, 0, 0, false)
 
 	titleContainerGrid = tview.NewGrid().SetColumns(-1, 80, -1).SetRows(-1, 24, -1).
 		AddItem(pad, 0, 0, 1, 3, 0, 0, false).

M cmd/netris/gui_input.go => cmd/netris/gui_input.go +21 -11
@@ 87,17 87,17 @@ func handleKeypress(ev *tcell.EventKey) *tcell.EventKey {
 
 		var action event.GameAction
 		switch gameSettingsSelectedButton {
-		case 0:
-			action = event.ActionRotateCCW
 		case 1:
-			action = event.ActionRotateCW
+			action = event.ActionRotateCCW
 		case 2:
-			action = event.ActionMoveLeft
+			action = event.ActionRotateCW
 		case 3:
-			action = event.ActionMoveRight
+			action = event.ActionMoveLeft
 		case 4:
-			action = event.ActionSoftDrop
+			action = event.ActionMoveRight
 		case 5:
+			action = event.ActionSoftDrop
+		case 6:
 			action = event.ActionHardDrop
 		default:
 			log.Fatal("setting keybind for unknown action")


@@ 136,8 136,8 @@ func handleKeypress(ev *tcell.EventKey) *tcell.EventKey {
 				switch k {
 				case tcell.KeyTab:
 					gameSettingsSelectedButton++
-					if gameSettingsSelectedButton > 7 {
-						gameSettingsSelectedButton = 7
+					if gameSettingsSelectedButton > 8 {
+						gameSettingsSelectedButton = 8
 					}
 
 					updateGameSettings()


@@ 151,8 151,15 @@ func handleKeypress(ev *tcell.EventKey) *tcell.EventKey {
 					updateGameSettings()
 					return nil
 				case tcell.KeyEnter:
-					if gameSettingsSelectedButton == 6 || gameSettingsSelectedButton == 7 {
-						if gameSettingsSelectedButton == 7 {
+					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)
 						}


@@ 294,10 301,13 @@ func handleKeypress(ev *tcell.EventKey) *tcell.EventKey {
 					titleSelectedButton = 0
 					gameSettingsSelectedButton = 0
 
+					drawGhostPieceUnsaved = drawGhostPiece
+
 					draftKeybindings = make([]*Keybinding, len(keybindings))
 					copy(draftKeybindings, keybindings)
 
-					app.SetRoot(gameSettingsContainerGrid, true).SetFocus(buttonKeybindRotateCCW)
+					app.SetRoot(gameSettingsContainerGrid, true)
+					updateGameSettings()
 					return nil
 				case 2:
 					titleScreen = 0

M cmd/netris/gui_title.go => cmd/netris/gui_title.go +15 -7
@@ 89,22 89,30 @@ func nextTitleButton() {
 }
 
 func updateGameSettings() {
+	if drawGhostPieceUnsaved {
+		buttonGhostPiece.SetLabel("Enabled")
+	} else {
+		buttonGhostPiece.SetLabel("Disabled")
+	}
+
 	switch gameSettingsSelectedButton {
 	case 0:
-		app.SetFocus(buttonKeybindRotateCCW)
+		app.SetFocus(buttonGhostPiece)
 	case 1:
-		app.SetFocus(buttonKeybindRotateCW)
+		app.SetFocus(buttonKeybindRotateCCW)
 	case 2:
-		app.SetFocus(buttonKeybindMoveLeft)
+		app.SetFocus(buttonKeybindRotateCW)
 	case 3:
-		app.SetFocus(buttonKeybindMoveRight)
+		app.SetFocus(buttonKeybindMoveLeft)
 	case 4:
-		app.SetFocus(buttonKeybindSoftDrop)
+		app.SetFocus(buttonKeybindMoveRight)
 	case 5:
-		app.SetFocus(buttonKeybindHardDrop)
+		app.SetFocus(buttonKeybindSoftDrop)
 	case 6:
-		app.SetFocus(buttonKeybindCancel)
+		app.SetFocus(buttonKeybindHardDrop)
 	case 7:
+		app.SetFocus(buttonKeybindCancel)
+	case 8:
 		app.SetFocus(buttonKeybindSave)
 	}
 }

M pkg/mino/matrix.go => pkg/mino/matrix.go +11 -23
@@ 380,10 380,10 @@ func (m *Matrix) ClearOverlay() {
 	m.Lock()
 	defer m.Unlock()
 
-	m.clearOverlay()
+	m.ClearOverlayL()
 }
 
-func (m *Matrix) clearOverlay() {
+func (m *Matrix) ClearOverlayL() {
 	for i, b := range m.O {
 		if b == BlockNone {
 			continue


@@ 421,30 421,12 @@ func (m *Matrix) Clear() {
 	}
 }
 
-func (m *Matrix) DrawPieces() {
-	m.Lock()
-	defer m.Unlock()
-
-	m.DrawPiecesL()
-}
-
-func (m *Matrix) DrawPiecesL() {
-	if m.Type != MatrixStandard {
-		return
-	}
-
-	m.clearOverlay()
-
-	if m.GameOver {
-		return
-	}
-
+func (m *Matrix) DrawGhostPieceL() {
 	p := m.P
-	if p == nil {
+	if m.Type != MatrixStandard || m.GameOver || p == nil {
 		return
 	}
 
-	// Draw ghost piece
 	for y := p.Y; y >= 0; y-- {
 		if y == 0 || !m.canAddAt(p, Point{p.X, y - 1}) {
 			err := m.add(p, p.Ghost, Point{p.X, y}, true)


@@ 455,8 437,14 @@ func (m *Matrix) DrawPiecesL() {
 			break
 		}
 	}
+}
+
+func (m *Matrix) DrawActivePieceL() {
+	p := m.P
+	if m.Type != MatrixStandard || m.GameOver || p == nil {
+		return
+	}
 
-	// Draw active piece
 	err := m.add(p, p.Solid, Point{p.X, p.Y}, true)
 	if err != nil {
 		log.Fatalf("failed to draw active piece: %+v", err)