package ui import ( "image/color" "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/text/v2" "github.com/hajimehoshi/ebiten/v2/vector" "muhq.space/muhqs-game/go/font" ) type Button interface { Widget } type SimpleButton struct { WidgetBase label string Bg color.Color Fg color.Color font *text.GoTextFace lineSpacing float64 } func NewSimpleButton(x, y, w, h int, label string, onClick func(b *SimpleButton)) *SimpleButton { sb := &SimpleButton{NewWidgetBase(x, y, w, h), label, Gray, color.White, font.Font24, 1.5} sb.EventHandlersMap["click"] = func(int, int) { onClick(sb) } sb.renderImpl = func() *ebiten.Image { if sb.img == nil { sb.img = sb.renderRect() } return sb.img } return sb } // NewRoundSimpleButton creates a circular SimpleButton. // The shape used for click detection is still a square. // x and y define the left upper corner of the square (x, y) rect (x+r, y+r). func NewRoundSimpleButton(x, y, r int, label string, onClick func(b *SimpleButton)) *SimpleButton { sb := &SimpleButton{NewWidgetBase(x, y, r, r), label, Gray, color.White, font.Font24, 1.5} sb.EventHandlersMap["click"] = func(int, int) { onClick(sb) } sb.renderImpl = func() *ebiten.Image { if sb.img == nil { sb.img = sb.renderCircle() } return sb.img } return sb } func (b *SimpleButton) drawLabel(img *ebiten.Image) { w, h := text.Measure(b.label, b.font, b.font.Size*b.lineSpacing) x := float64(b.Width)/2 - w/2 y := float64(b.Height)/2 - h/2 op := &text.DrawOptions{} op.GeoM.Translate(x, y) op.ColorScale.ScaleWithColor(b.Fg) text.Draw(img, b.label, font.Font24, op) } func (b *SimpleButton) renderRect() *ebiten.Image { img := ebiten.NewImage(b.Width, b.Height) vector.FillRect(img, float32(0), float32(0), float32(b.Width), float32(b.Height), b.Bg, false) b.drawLabel(img) return img } func (b *SimpleButton) renderCircle() *ebiten.Image { img := ebiten.NewImage(b.Width, b.Height) vector.FillCircle(img, float32(b.Width)/2, float32(b.Height)/2, float32(b.Width/2), b.Bg, false) b.drawLabel(img) return img } func (b *SimpleButton) UpdateLabel(label string) { if b.label != label { b.label = label b.ForceRedraw() } } type ImageButton struct { WidgetBase img *ebiten.Image } func NewImageButton(x, y int, img *ebiten.Image, onClick func(b *ImageButton)) *ImageButton { bounds := img.Bounds() sb := &ImageButton{NewWidgetBase(x, y, bounds.Dx(), bounds.Dy()), img} sb.EventHandlersMap["click"] = func(int, int) { onClick(sb) } sb.renderImpl = func() *ebiten.Image { return sb.img } return sb }