149 lines
3.1 KiB
Go
149 lines
3.1 KiB
Go
//go:build example
|
|
// +build example
|
|
|
|
package game
|
|
|
|
import (
|
|
"fmt"
|
|
"image"
|
|
"log"
|
|
"strings"
|
|
|
|
"code.rocketnine.space/tslocum/messeji"
|
|
"github.com/hajimehoshi/ebiten/v2"
|
|
"github.com/hajimehoshi/ebiten/v2/examples/resources/fonts"
|
|
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
|
"golang.org/x/image/font"
|
|
"golang.org/x/image/font/opentype"
|
|
)
|
|
|
|
const initialText = `
|
|
Welcome to the メッセージ (messeji) text widgets demo.
|
|
This is a TextField, which can be used to display text.
|
|
Below is an InputField, which accepts keyboard input.
|
|
Press <Tab> to toggle word wrap.
|
|
Press <Enter> to append input text.
|
|
Press <Ctrl+M> to toggle multi-line.
|
|
`
|
|
|
|
var mplusNormalFont font.Face
|
|
|
|
func init() {
|
|
tt, err := opentype.Parse(fonts.MPlus1pRegular_ttf)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
const dpi = 72
|
|
mplusNormalFont, err = opentype.NewFace(tt, &opentype.FaceOptions{
|
|
Size: 32,
|
|
DPI: dpi,
|
|
Hinting: font.HintingFull,
|
|
})
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
type game struct {
|
|
w, h int
|
|
|
|
buffer *messeji.TextField
|
|
|
|
input *messeji.InputField
|
|
|
|
singleLine bool
|
|
|
|
op *ebiten.DrawImageOptions
|
|
|
|
spinnerIndex int
|
|
}
|
|
|
|
// NewDemoGame returns a new messeji demo game.
|
|
func NewDemoGame() *game {
|
|
g := &game{
|
|
buffer: messeji.NewTextField(mplusNormalFont),
|
|
input: messeji.NewInputField(mplusNormalFont),
|
|
op: &ebiten.DrawImageOptions{
|
|
Filter: ebiten.FilterNearest,
|
|
},
|
|
}
|
|
|
|
g.buffer.SetText(strings.TrimSpace(initialText) + "\n")
|
|
|
|
g.input.SetHandleKeyboard(true)
|
|
g.input.SetSelectedFunc(func() (skipNewline bool) {
|
|
log.Printf("Input: %s", g.input.Text())
|
|
|
|
g.buffer.Write([]byte(fmt.Sprintf("Input: %s\n", g.input.Text())))
|
|
|
|
// Clear the input field.
|
|
g.input.SetText("")
|
|
|
|
return true
|
|
})
|
|
|
|
return g
|
|
}
|
|
|
|
func (g *game) Layout(outsideWidth, outsideHeight int) (int, int) {
|
|
if outsideWidth == g.w && outsideHeight == g.h {
|
|
return outsideWidth, outsideHeight
|
|
}
|
|
|
|
padding := 10
|
|
|
|
w, h := outsideWidth-padding*2, g.input.LineHeight()*3+g.input.Padding()*2
|
|
if h > outsideHeight-padding {
|
|
h = outsideHeight - padding
|
|
}
|
|
|
|
x, y := outsideWidth/2-w/2, outsideHeight-h-padding
|
|
|
|
g.buffer.SetRect(image.Rect(padding, padding, outsideWidth-padding, y-padding))
|
|
|
|
g.input.SetRect(image.Rect(x, y, x+w, y+h))
|
|
|
|
g.w, g.h = outsideWidth, outsideHeight
|
|
return outsideWidth, outsideHeight
|
|
}
|
|
|
|
func (g *game) Update() error {
|
|
if inpututil.IsKeyJustPressed(ebiten.KeyEnter) && !g.input.Visible() {
|
|
g.input.SetVisible(true)
|
|
return nil
|
|
}
|
|
|
|
if inpututil.IsKeyJustPressed(ebiten.KeyTab) {
|
|
wrap := g.buffer.WordWrap()
|
|
g.buffer.SetWordWrap(!wrap)
|
|
g.input.SetWordWrap(!wrap)
|
|
return nil
|
|
}
|
|
|
|
if inpututil.IsKeyJustPressed(ebiten.KeyM) && ebiten.IsKeyPressed(ebiten.KeyControl) {
|
|
g.singleLine = !g.singleLine
|
|
g.input.SetSingleLine(g.singleLine)
|
|
return nil
|
|
}
|
|
|
|
err := g.buffer.Update()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to update buffer: %s", err)
|
|
}
|
|
|
|
err = g.input.Update()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to update input field: %s", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (g *game) Draw(screen *ebiten.Image) {
|
|
// Draw display field.
|
|
g.buffer.Draw(screen)
|
|
|
|
// Draw input field.
|
|
g.input.Draw(screen)
|
|
}
|