Display listbox text

This commit is contained in:
2020-04-01 19:45:57 +01:00
parent 7935f78acc
commit 8ce24ce5f8
4 changed files with 184 additions and 91 deletions

View File

@@ -4,11 +4,17 @@ import (
"image"
"log"
"github.com/hajimehoshi/ebiten"
"code.ur.gs/lupine/ordoor/internal/assetstore"
"code.ur.gs/lupine/ordoor/internal/menus"
)
type AlignMode int
const (
AlignModeCentre AlignMode = 0
AlignModeLeft AlignMode = 1
)
func init() {
registerBuilder(menus.TypeStatic, noChildren(registerStatic))
registerBuilder(menus.TypeHypertext, noChildren(registerHypertext))
@@ -27,13 +33,20 @@ type noninteractive struct {
rect image.Rectangle
// Some non-interactives, e.g., overlays, are an image + text to be shown
textImg *ebiten.Image
textOffset image.Point
label *label
clickImpl // Alright, alright, it turns out the bridge mission briefing is clickable
hoverImpl
}
// Paint some text to screen
type label struct {
align AlignMode
rect image.Rectangle
text string
font *assetstore.Font
}
// This particular animation has entry and exit sequences, which are invoked
// when entering and leaving hover, respectively. Example: bridge doors
type animationHover struct {
@@ -106,34 +119,21 @@ func registerOverlay(d *Driver, r *menus.Record) error {
rect: sprite.Rect,
}
d.paintables = append(d.paintables, ni)
if r.Text != "" {
// FIXME: is this always right? Seems to make sense for Main.mnu
fnt := d.menu.Font(r.FontType/10 - 1)
textImg, err := fnt.DrawLine(r.Text)
if err != nil {
return err
ni.label = &label{
font: fnt,
rect: ni.rect, // We will be centered by default
text: r.Text,
}
ni.textImg = textImg
// Centre the image
xSlack := ni.rect.Dx() - textImg.Bounds().Dx()
if xSlack > 0 {
ni.textOffset.X = xSlack / 2
}
ySlack := ni.rect.Dy() - textImg.Bounds().Dy()
if ySlack > 0 {
ni.textOffset.Y = ySlack / 2
}
} else {
log.Printf("Overlay without text detected: %#+v", r)
}
d.paintables = append(d.paintables, ni)
return nil
}
@@ -206,17 +206,14 @@ func (n *noninteractive) bounds() image.Rectangle {
func (n *noninteractive) regions(tick int) []region {
out := oneRegion(n.bounds().Min, n.frames.image(tick))
if n.textImg != nil {
out = append(out, oneRegion(n.textPos(), n.textImg)...)
// Text for a noninteractive is not registered separately
if n.label != nil {
out = append(out, n.label.regions(tick)...)
}
return out
}
func (n *noninteractive) textPos() image.Point {
return image.Pt(n.rect.Min.X+n.textOffset.X, n.rect.Min.Y+n.textOffset.Y)
}
func (a *animationHover) regions(tick int) []region {
if a.opening || a.closing {
var anim animation
@@ -248,3 +245,51 @@ func (a *animationHover) setHoverState(value bool) {
a.hoverImpl.setHoverState(value)
}
// Top-left of where to start drawing the text. We want it to appear to be in
// the centre of the rect.
//
// TODO: additional modes (left-aligned, especially)
func (l *label) pos() image.Point {
pos := l.rect.Min
textRect := l.font.CalculateBounds(l.text)
// Centre the text horizontally
if l.align == AlignModeCentre {
xSlack := l.rect.Dx() - textRect.Dx()
if xSlack > 0 {
pos.X += xSlack / 2
}
} else {
// FIXME: we're giving it 8pts of left to not look horrible
pos.X += 8
}
// Centre the text vertically
ySlack := l.rect.Dy() - textRect.Dy()
if ySlack > 0 {
pos.Y += ySlack / 2
}
return pos
}
func (l *label) regions(tick int) []region {
var out []region
pt := l.pos()
for _, r := range l.text {
glyph, err := l.font.Glyph(r)
if err != nil {
log.Printf("FIXME: ignoring misssing glyph %v", r)
continue
}
out = append(out, oneRegion(pt, glyph.Image)...)
pt.X += glyph.Rect.Dx()
}
return out
}