package ui import ( "fmt" "image/color" "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/text" "muhq.space/muhqs-game/go/font" "muhq.space/muhqs-game/go/game" ) var ( TEXTBOX_DEFAULT_BACKGROUND = gray TEXTBOX_DEFAULT_FOREGROUND = color.White TEXTBOX_DEFAULT_MARGIN = 3 ) type TextBox struct { WidgetBase Text string Fg color.Color Bg color.Color XMargin int YMargin int Center bool } func NewFixedTextBox(x, y int, width, height int, t string, center bool) *TextBox { tb := &TextBox{ WidgetBase: NewWidgetBase(x, y, width, height), Text: t, Fg: TEXTBOX_DEFAULT_FOREGROUND, Bg: TEXTBOX_DEFAULT_BACKGROUND, XMargin: TEXTBOX_DEFAULT_MARGIN, YMargin: TEXTBOX_DEFAULT_MARGIN, Center: center, } tb.renderImpl = func() *ebiten.Image { return tb.render() } return tb } func NewCenteringFixedTextBox(x, y int, width, height int, t string) *TextBox { return NewFixedTextBox(x, y, width, height, t, true) } func NewAutoTextBox(x, y int, t string) *TextBox { return NewFixedTextBox(x, y, -1, -1, t, false) } func NewCenteringAutoTextBox(x, y int, t string) *TextBox { return NewFixedTextBox(x, y, -1, -1, t, true) } func NewUnitInfo(x, y int, u *game.Unit) *TextBox { info := fmt.Sprintf("%s\nDamage: %d\nHealth: %d\nUpkeep: %d", u.String(), u.Damage(), u.Health, u.Upkeep) if u.Movement != game.INVALID_MOVEMENT() { info = fmt.Sprintf("%s\nMovement: %s", info, u.Movement.String()) } if u.Attack != game.INVALID_ATTACK() { info = fmt.Sprintf("%s\nAttack: %s", info, u.Attack.String()) } return NewAutoTextBox(x, y, info) } func NewPermInfo(x, y int, p game.Permanent) *TextBox { info := fmt.Sprintf("%s\nDamage: %d", p.String(), p.Damage()) return NewAutoTextBox(x, y, info) } func (tb *TextBox) render() *ebiten.Image { var x, y int 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 x = tb.XMargin + b.Min.X y = tb.YMargin - b.Min.Y } else { if !tb.Center { x = tb.XMargin + b.Min.X } else { x = (tb.Width - b.Dx()) / 2 if x < 0 { x = 0 } } y = tb.Height - b.Dy()/2 if y < 0 { y = 0 } } img := ebiten.NewImage(tb.Width, tb.Height) img.Fill(tb.Bg) text.Draw(img, tb.Text, font.Font24, x, y, tb.Fg) return img } type PocList struct { TextBox centerX int bottomY int poc game.PileOfCards } func NewPocList(centerX, bottomY int, poc game.PileOfCards) *PocList { w := &PocList{ TextBox: TextBox{ WidgetBase: NewWidgetBase(-1, -1, -1, -1), Text: "", Fg: TEXTBOX_DEFAULT_FOREGROUND, Bg: TEXTBOX_DEFAULT_BACKGROUND, XMargin: TEXTBOX_DEFAULT_MARGIN, YMargin: TEXTBOX_DEFAULT_MARGIN, Center: true, }, centerX: centerX, bottomY: bottomY, poc: poc, } w.renderImpl = func() *ebiten.Image { w.setText() return w.render() } return w } func (w *PocList) setText() { t := "" for _, c := range w.poc.Cards() { t = fmt.Sprintf("%s%s\n", t, c.Name) } if t != "" { w.Text = t[:len(t)-1] } else { w.Text = "No cards" } b := text.BoundString(font.Font24, w.Text) w.X = w.centerX - b.Dx()/2 - w.XMargin w.Y = w.bottomY - b.Dy() - w.YMargin } func (w *PocList) FindObjectAt(x, y int) interface{} { cards := w.poc.Cards() if len(cards) == 0 { return nil } // b := text.BoundString(font.Font, w.Text) // i := b.Dy() / w.poc.Size() return cards[0] }