aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fischer@muhq.space>2023-02-03 14:05:14 +0100
committerFlorian Fischer <florian.fischer@muhq.space>2025-08-20 15:46:38 +0200
commit8802f30ff720fcb64d9207c4cb673dc6805390c2 (patch)
tree9be529221105fc8681e3afb0e673e229ef9504d4
parente8f44219976edf8cf57cbd9e964f66fe9d145a9c (diff)
downloadmuhqs-game-8802f30ff720fcb64d9207c4cb673dc6805390c2.tar.gz
muhqs-game-8802f30ff720fcb64d9207c4cb673dc6805390c2.zip
add text input and properly center text
-rw-r--r--go/client/startMenu.go71
-rw-r--r--go/ui/buffer.go13
-rw-r--r--go/ui/button.go11
-rw-r--r--go/ui/stateBar.go4
-rw-r--r--go/ui/textBox.go67
-rw-r--r--go/ui/textInput.go1
-rw-r--r--go/ui/utils.go19
7 files changed, 149 insertions, 37 deletions
diff --git a/go/client/startMenu.go b/go/client/startMenu.go
index 735753b0..9d5d6129 100644
--- a/go/client/startMenu.go
+++ b/go/client/startMenu.go
@@ -1,6 +1,7 @@
package main
import (
+ "image/color"
"log"
"github.com/hajimehoshi/ebiten/v2"
@@ -32,13 +33,38 @@ func NewStartMenu(app *app) *StartMenu {
}
func (m *StartMenu) build() {
+ playerLabel := ui.NewCenteringFixedTextBox(
+ (m.width-START_BUTTON_WIDTH)/2-START_BUTTON_WIDTH,
+ (m.height-START_BUTTON_HEIGHT)/2-START_BUTTON_HEIGHT,
+ START_BUTTON_WIDTH,
+ START_BUTTON_HEIGHT,
+ "name:",
+ )
+ playerLabel.Bg = color.Black
+ m.widgets = append(m.widgets, playerLabel)
+
+ playerInputLabel := "player name"
+ if m.playerName != "" {
+ playerInputLabel = m.playerName
+ }
+
+ playerInput := ui.NewTextInput(
+ (m.width-START_BUTTON_WIDTH)/2,
+ (m.height-START_BUTTON_HEIGHT)/2-START_BUTTON_HEIGHT,
+ START_BUTTON_WIDTH,
+ START_BUTTON_HEIGHT,
+ playerInputLabel,
+ )
+ m.widgets = append(m.widgets, playerInput)
+
m.widgets = append(m.widgets, ui.NewSimpleButton(
(m.width-START_BUTTON_WIDTH)/2,
(m.height-START_BUTTON_HEIGHT)/2,
- 150,
- 50,
+ START_BUTTON_WIDTH,
+ START_BUTTON_HEIGHT,
"Start",
func(*ui.SimpleButton) {
+ m.playerName = playerInput.Text()
m.app.active = m.next()
}))
}
@@ -49,15 +75,40 @@ func (m *StartMenu) Update() error {
}
x, y := ebiten.CursorPosition()
+
+ var activeWidget ui.Widget
+ for _, w := range m.widgets {
+ if !w.Contains(x, y) {
+ continue
+ }
+ activeWidget = w
+ break
+ }
+
+ if activeWidget == nil {
+ return nil
+ }
+
+ scrollX, scrollY := ebiten.Wheel()
+ if scrollX != 0 || scrollY != 0 {
+ if scrollable, ok := activeWidget.(ui.Scrollable); ok {
+ scrollable.Scroll(int(scrollX), int(scrollY))
+ }
+ }
+
+ if textInput, ok := activeWidget.(*ui.TextInput); ok {
+ // var input []rune
+ // ebiten.AppendInputChars(input)
+ input := ebiten.InputChars()
+ if len(input) > 0 {
+ textInput.AddInput(input)
+ }
+ textInput.HandleKey()
+ }
+
if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
- for _, w := range m.widgets {
- if !w.Contains(x, y) {
- continue
- }
-
- if btn, ok := w.(ui.Button); ok {
- btn.Click(x, y)
- }
+ if btn, ok := activeWidget.(ui.Button); ok {
+ btn.Click(x, y)
}
}
diff --git a/go/ui/buffer.go b/go/ui/buffer.go
index c451d7fc..e95102fe 100644
--- a/go/ui/buffer.go
+++ b/go/ui/buffer.go
@@ -64,3 +64,16 @@ func (b *Buffer) Remove(idx int) {
b.lines = append(b.lines[:idx], b.lines[idx+1:]...)
b.ForceRedraw()
}
+
+func (b *Buffer) Scroll(x, y int) {
+ if y == 0 {
+ return
+ }
+
+ if y < 0 && b.pos > 0 {
+ b.pos--
+ } else if y > 0 && b.pos < len(b.lines)-1 {
+ b.pos++
+ }
+ b.ForceRedraw()
+}
diff --git a/go/ui/button.go b/go/ui/button.go
index 6454ccac..0fd26936 100644
--- a/go/ui/button.go
+++ b/go/ui/button.go
@@ -35,15 +35,8 @@ func (b *SimpleButton) render() *ebiten.Image {
ebitenutil.DrawRect(img, float64(0), float64(0), float64(b.Width), float64(b.Height), b.BG)
bounds := text.BoundString(font.Font24, b.label)
- x := (b.Width - bounds.Dx()) / 2
- if x < 0 {
- x = 0
- }
-
- y := b.Height - bounds.Dy()/2
- if y < 0 {
- y = 0
- }
+ x := b.Width/2 - centerTextXOffset(bounds)
+ y := b.Height/2 - centerTextYOffset(bounds)
text.Draw(img, b.label, font.Font24, x, y, b.FG)
return img
}
diff --git a/go/ui/stateBar.go b/go/ui/stateBar.go
index 6914de6e..3b9407b5 100644
--- a/go/ui/stateBar.go
+++ b/go/ui/stateBar.go
@@ -50,12 +50,12 @@ func (sb *StateBar) FindObjectAt(x, y int) interface{} {
func (sb *StateBar) ForceRedraw() {
if sb.resourceView != nil {
- sb.resourceView.Text = sb.resourceLabel()
+ sb.resourceView.text = sb.resourceLabel()
sb.resourceView.ForceRedraw()
}
if sb.phaseView != nil {
- sb.phaseView.Text = sb.phaseLabel()
+ sb.phaseView.text = sb.phaseLabel()
sb.phaseView.ForceRedraw()
}
}
diff --git a/go/ui/textBox.go b/go/ui/textBox.go
index b4a580bf..d0afbd9b 100644
--- a/go/ui/textBox.go
+++ b/go/ui/textBox.go
@@ -5,6 +5,7 @@ import (
"image/color"
"github.com/hajimehoshi/ebiten/v2"
+ "github.com/hajimehoshi/ebiten/v2/inpututil"
"github.com/hajimehoshi/ebiten/v2/text"
"muhq.space/muhqs-game/go/font"
"muhq.space/muhqs-game/go/game"
@@ -19,7 +20,7 @@ var (
type TextBox struct {
WidgetBase
- Text string
+ text string
Fg color.Color
Bg color.Color
XMargin int
@@ -30,7 +31,7 @@ type TextBox struct {
func NewFixedTextBox(x, y int, width, height int, t string, center bool) *TextBox {
tb := &TextBox{
WidgetBase: NewWidgetBase(x, y, width, height),
- Text: t,
+ text: t,
Fg: TEXTBOX_DEFAULT_FOREGROUND,
Bg: TEXTBOX_DEFAULT_BACKGROUND,
XMargin: TEXTBOX_DEFAULT_MARGIN,
@@ -75,7 +76,7 @@ func NewPermInfo(x, y int, p game.Permanent) *TextBox {
func (tb *TextBox) render() *ebiten.Image {
var x, y int
- b := text.BoundString(font.Font24, tb.Text)
+ b := text.BoundString(font.Font24, tb.text)
if tb.Width == -1 || tb.Height == -1 {
tb.Width = b.Dx() + 2*tb.XMargin
tb.Height = b.Dy() + 2*tb.YMargin
@@ -85,21 +86,15 @@ func (tb *TextBox) render() *ebiten.Image {
if !tb.Center {
x = tb.XMargin + b.Min.X
} else {
- x = (tb.Width - b.Dx()) / 2
- if x < 0 {
- x = 0
- }
+ x = tb.Width/2 - centerTextXOffset(b)
}
- y = tb.Height - b.Dy()/2
- if y < 0 {
- y = 0
- }
+ y = tb.Height/2 - centerTextYOffset(b)
}
img := ebiten.NewImage(tb.Width, tb.Height)
img.Fill(tb.Bg)
- text.Draw(img, tb.Text, font.Font24, x, y, tb.Fg)
+ text.Draw(img, tb.text, font.Font24, x, y, tb.Fg)
return img
}
@@ -114,7 +109,7 @@ func NewPocList(centerX, bottomY int, poc game.PileOfCards) *PocList {
w := &PocList{
TextBox: TextBox{
WidgetBase: NewWidgetBase(-1, -1, -1, -1),
- Text: "",
+ text: "",
Fg: TEXTBOX_DEFAULT_FOREGROUND,
Bg: TEXTBOX_DEFAULT_BACKGROUND,
XMargin: TEXTBOX_DEFAULT_MARGIN,
@@ -139,12 +134,12 @@ func (w *PocList) setText() {
}
if t != "" {
- w.Text = t[:len(t)-1]
+ w.text = t[:len(t)-1]
} else {
- w.Text = "No cards"
+ w.text = "No cards"
}
- b := text.BoundString(font.Font24, w.Text)
+ b := text.BoundString(font.Font24, w.text)
w.X = w.centerX - b.Dx()/2 - w.XMargin
w.Y = w.bottomY - b.Dy() - w.YMargin
}
@@ -159,3 +154,43 @@ func (w *PocList) FindObjectAt(x, y int) interface{} {
// i := b.Dy() / w.poc.Size()
return cards[0]
}
+
+type TextInput struct {
+ TextBox
+ input string
+ label string
+}
+
+func NewTextInput(x, y int, width, height int, label string) *TextInput {
+ w := &TextInput{*NewCenteringFixedTextBox(x, y, width, height, ""), "", label}
+
+ w.renderImpl = func() *ebiten.Image {
+ if w.input == "" {
+ w.text = w.label
+ } else {
+ w.text = w.input
+ }
+
+ return w.render()
+ }
+
+ return w
+}
+
+func (ti *TextInput) AddInput(input []rune) {
+ ti.input += string(input)
+ ti.ForceRedraw()
+}
+
+func (ti *TextInput) HandleKey() {
+ if inpututil.IsKeyJustPressed(ebiten.KeyBackspace) {
+ if len(ti.input) > 0 {
+ ti.input = ti.input[:len(ti.input)-1]
+ ti.ForceRedraw()
+ }
+ }
+}
+
+func (ti *TextInput) Text() string {
+ return ti.input
+}
diff --git a/go/ui/textInput.go b/go/ui/textInput.go
new file mode 100644
index 00000000..5b1faa29
--- /dev/null
+++ b/go/ui/textInput.go
@@ -0,0 +1 @@
+package ui
diff --git a/go/ui/utils.go b/go/ui/utils.go
new file mode 100644
index 00000000..fd15b642
--- /dev/null
+++ b/go/ui/utils.go
@@ -0,0 +1,19 @@
+package ui
+
+import (
+ "image"
+)
+
+func centerTextXOffset(b image.Rectangle) int {
+ return (b.Dx() / 2) - b.Min.X
+}
+
+func centerTextYOffset(b image.Rectangle) int {
+ return (b.Dy() / 2) + b.Min.Y
+}
+
+func centerText(b image.Rectangle) (x int, y int) {
+ x = centerTextXOffset(b)
+ y = centerTextYOffset(b)
+ return
+}