diff --git a/README.md b/README.md
index 3f5a707..00c5092 100644
--- a/README.md
+++ b/README.md
@@ -34,7 +34,7 @@ go get github.com/yohamta/furex/v2
## Example
[Full source code of the example](examples/game/main.go)
-Assets by [Kenney](https://kenney.nl).
+Assets by [Kenney](https://kenney.nl). Fonts by [00ff](http://www17.plala.or.jp/xxxxxxx/00ff/)
diff --git a/assets/example.gif b/assets/example.gif
index 15d7aeb..1326f25 100644
Binary files a/assets/example.gif and b/assets/example.gif differ
diff --git a/examples/game/assets/fonts/x14y20pxScoreDozer.ttf b/examples/game/assets/fonts/x14y20pxScoreDozer.ttf
new file mode 100644
index 0000000..1a8384e
Binary files /dev/null and b/examples/game/assets/fonts/x14y20pxScoreDozer.ttf differ
diff --git a/examples/game/assets/images/uipackSpace_sheet.png b/examples/game/assets/images/uipackSpace_sheet.png
new file mode 100644
index 0000000..6a9799d
Binary files /dev/null and b/examples/game/assets/images/uipackSpace_sheet.png differ
diff --git a/examples/game/assets/images/uipackSpace_sheet.xml b/examples/game/assets/images/uipackSpace_sheet.xml
new file mode 100644
index 0000000..d8b20f5
--- /dev/null
+++ b/examples/game/assets/images/uipackSpace_sheet.xml
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/game/assets/uipack_rpg_sheet.png b/examples/game/assets/images/uipack_rpg_sheet.png
similarity index 100%
rename from examples/game/assets/uipack_rpg_sheet.png
rename to examples/game/assets/images/uipack_rpg_sheet.png
diff --git a/examples/game/assets/uipack_rpg_sheet.xml b/examples/game/assets/images/uipack_rpg_sheet.xml
similarity index 100%
rename from examples/game/assets/uipack_rpg_sheet.xml
rename to examples/game/assets/images/uipack_rpg_sheet.xml
diff --git a/examples/game/main.go b/examples/game/main.go
index 4204b99..2db94f8 100644
--- a/examples/game/main.go
+++ b/examples/game/main.go
@@ -5,8 +5,10 @@ import (
"sync"
"github.com/hajimehoshi/ebiten/v2"
+ "github.com/tinne26/etxt"
"github.com/yohamta/furex/v2"
"github.com/yohamta/furex/v2/examples/game/sprites"
+ "github.com/yohamta/furex/v2/examples/game/text"
"github.com/yohamta/furex/v2/examples/game/widgets"
)
@@ -41,33 +43,53 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
}
func NewGame() (*Game, error) {
- sprites.LoadSprites(sprites.LoadOpts{
- PanelOpts: []sprites.PanelOpts{
- {
- Name: "panelInset_beige.png",
- Border: 32,
+ text.LoadFonts()
+ sprites.LoadSprites(
+ "assets/images/uipack_rpg_sheet.xml",
+ "assets/images/uipack_rpg_sheet.png",
+ sprites.LoadOpts{
+ PanelOpts: map[string]sprites.PanelOpts{
+ "panelInset_beige.png": {
+ Border: 32,
+ Center: 36,
+ },
+ "panel_brown.png": {
+ Border: 32,
+ Center: 36,
+ },
},
- {
- Name: "panel_brown.png",
- Border: 32,
+ })
+ sprites.LoadSprites(
+ "assets/images/uipackSpace_sheet.xml",
+ "assets/images/uipackSpace_sheet.png",
+ sprites.LoadOpts{
+ PanelOpts: map[string]sprites.PanelOpts{
+ "glassPanel_corners.png": {
+ Border: 40,
+ Center: 20,
+ },
+ "glassPanel_projection.png": {
+ Border: 20,
+ Center: 10,
+ },
},
- },
- })
+ })
game := &Game{}
return game, nil
}
func (g *Game) setupUI() {
- newButton := func() *furex.View {
+ newButton := func(txt string) *furex.View {
return (&furex.View{
Width: 45,
Height: 49,
MarginTop: 5,
MarginBottom: 10,
- MarginLeft: 5,
- MarginRight: 5,
+ MarginLeft: 20,
+ MarginRight: 20,
Handler: &widgets.Button{
- Text: "Button",
+ Text: txt,
+ Color: color.RGBA{210, 178, 144, 255},
Sprite: "buttonSquare_brown.png",
SpritePressed: "buttonSquare_brown_pressed.png",
OnClick: func() { println("button clicked") },
@@ -93,6 +115,8 @@ func (g *Game) setupUI() {
(&furex.View{
Width: 300,
Height: 300,
+ MarginTop: 120,
+ MarginLeft: 130,
Handler: &widgets.Panel{Sprite: "panel_brown.png"},
Direction: furex.Column,
AlignItems: furex.AlignItemCenter,
@@ -121,6 +145,7 @@ func (g *Game) setupUI() {
Width: 180,
MarginBottom: 2,
Handler: &widgets.Text{
+ Color: color.RGBA{50, 48, 41, 255},
Value: "Health",
},
},
@@ -146,6 +171,7 @@ func (g *Game) setupUI() {
Width: 180,
MarginBottom: 2,
Handler: &widgets.Text{
+ Color: color.RGBA{50, 48, 41, 255},
Value: "Mana",
},
},
@@ -195,8 +221,10 @@ func (g *Game) setupUI() {
// close button
(&furex.View{
Position: furex.PositionAbsolute,
- Left: 296,
- Top: 4,
+ Left: 300 - 35/2,
+ Top: 4 - 38/2,
+ Width: 35,
+ Height: 38,
Handler: &widgets.Button{
Sprite: "buttonRound_blue.png",
OnClick: func() { println("button clicked") },
@@ -204,8 +232,8 @@ func (g *Game) setupUI() {
}).AddChild(
&furex.View{
Position: furex.PositionAbsolute,
- Left: 1,
- Top: -2,
+ Left: 18,
+ Top: 17,
Handler: &widgets.Sprite{
Sprite: "iconCross_beige.png",
},
@@ -222,10 +250,68 @@ func (g *Game) setupUI() {
AlignItems: furex.AlignItemEnd,
MarginBottom: 20,
}).AddChild(
- newButton(),
- newButton(),
- newButton(),
- newButton(),
+ newButton("A"),
+ newButton("B"),
+ newButton("C"),
+ newButton("D"),
+ ),
+ ).AddChild(
+ (&furex.View{
+ Position: furex.PositionAbsolute,
+ Left: 20,
+ Top: 52,
+ }).AddChild(
+ // panel
+ (&furex.View{
+ Width: 260,
+ Height: 140,
+ Handler: &widgets.Panel{Sprite: "glassPanel_corners.png"},
+ Direction: furex.Column,
+ AlignItems: furex.AlignItemCenter,
+ Justify: furex.JustifyCenter,
+ }).AddChild(
+ &furex.View{
+ Width: 100,
+ Height: 8,
+ MarginBottom: 20,
+ Direction: furex.Row,
+ AlignItems: furex.AlignItemCenter,
+ Justify: furex.JustifyCenter,
+ Handler: &widgets.Text{
+ Color: color.RGBA{45, 73, 94, 255},
+ Value: "PLAY THE GAME?",
+ HorzAlign: etxt.XCenter,
+ VertAlign: etxt.YCenter,
+ },
+ },
+ (&furex.View{
+ Width: 100,
+ Height: 50,
+ Direction: furex.Row,
+ AlignItems: furex.AlignItemCenter,
+ Justify: furex.JustifyCenter,
+ }).AddChild(
+ &furex.View{
+ Width: 100,
+ Height: 50,
+ Handler: &widgets.Panel{
+ Sprite: "glassPanel_projection.png",
+ Text: "YES",
+ OnClick: func() { println("button clicked") },
+ },
+ },
+ &furex.View{
+ Width: 100,
+ Height: 50,
+ MarginLeft: 20,
+ Handler: &widgets.Panel{
+ Sprite: "glassPanel_projection.png",
+ Text: "NO",
+ OnClick: func() { println("button clicked") },
+ },
+ },
+ ),
+ ),
),
).AddChild(
// panels that draws mouse cursor
diff --git a/examples/game/sprites/panel.go b/examples/game/sprites/panel.go
index dfb1381..cce6cb9 100644
--- a/examples/game/sprites/panel.go
+++ b/examples/game/sprites/panel.go
@@ -7,35 +7,44 @@ import (
"github.com/yohamta/ganim8/v2"
)
-func createPanels(img *ebiten.Image, r image.Rectangle, border int) map[string]*ganim8.Sprite {
+type PanelOpts struct {
+ Border int
+ Center int
+}
+
+func createPanels(img *ebiten.Image, r image.Rectangle, opts PanelOpts) map[string]*ganim8.Sprite {
ret := map[string]*ganim8.Sprite{}
+ w, h := img.Bounds().Dx(), img.Bounds().Dy()
+ border := opts.Border
+ center := opts.Center
+ cx, cy := r.Min.X+r.Dx()/2, r.Min.Y+r.Dy()/2
// top left
- g := ganim8.NewGrid(border, border, img.Bounds().Dx(), img.Bounds().Dy(), r.Min.X, r.Min.Y)
+ g := ganim8.NewGrid(border, border, w, h, r.Min.X, r.Min.Y)
ret["top_left"] = ganim8.NewSprite(img, g.Frames())
// top
- g = ganim8.NewGrid(r.Dx()-border*2, r.Dy()-border*2, img.Bounds().Dx(), img.Bounds().Dy(), r.Min.X+border, r.Min.Y)
+ g = ganim8.NewGrid(center, border, w, h, cx-center/2, r.Min.Y)
ret["top"] = ganim8.NewSprite(img, g.Frames())
// top right
- g = ganim8.NewGrid(border, border, img.Bounds().Dx(), img.Bounds().Dy(), r.Min.X+r.Dx()-border, r.Min.Y)
+ g = ganim8.NewGrid(border, border, w, h, r.Min.X+r.Dx()-border, r.Min.Y)
ret["top_right"] = ganim8.NewSprite(img, g.Frames())
// left
- g = ganim8.NewGrid(border, r.Dy()-border*2, img.Bounds().Dx(), img.Bounds().Dy(), r.Min.X, r.Min.Y+border)
+ g = ganim8.NewGrid(border, center, w, h, r.Min.X, cy-center/2)
ret["left"] = ganim8.NewSprite(img, g.Frames())
// center
- g = ganim8.NewGrid(r.Dx()-border*2, r.Dy()-border*2, img.Bounds().Dx(), img.Bounds().Dy(), r.Min.X+border, r.Min.Y+border)
+ g = ganim8.NewGrid(center, center, w, h, cx-center/2, cy-center/2)
ret["center"] = ganim8.NewSprite(img, g.Frames())
// right
- g = ganim8.NewGrid(border, r.Dy()-border*2, img.Bounds().Dx(), img.Bounds().Dy(), r.Min.X+r.Dx()-border, r.Min.Y+border)
+ g = ganim8.NewGrid(border, center, w, h, r.Min.X+r.Dx()-border, cy-center/2)
ret["right"] = ganim8.NewSprite(img, g.Frames())
// bottom left
- g = ganim8.NewGrid(border, border, img.Bounds().Dx(), img.Bounds().Dy(), r.Min.X, r.Min.Y+r.Dy()-border)
+ g = ganim8.NewGrid(border, border, w, h, r.Min.X, r.Min.Y+r.Dy()-border)
ret["bottom_left"] = ganim8.NewSprite(img, g.Frames())
// bottom
- g = ganim8.NewGrid(r.Dx()-border*2, border, img.Bounds().Dx(), img.Bounds().Dy(), r.Min.X+border, r.Min.Y+r.Dy()-border)
+ g = ganim8.NewGrid(center, border, w, h, cx-center/2, r.Max.Y-border)
ret["bottom"] = ganim8.NewSprite(img, g.Frames())
// bottom right
- g = ganim8.NewGrid(border, border, img.Bounds().Dx(), img.Bounds().Dy(), r.Min.X+r.Dx()-border, r.Min.Y+r.Dy()-border)
+ g = ganim8.NewGrid(border, border, w, h, r.Min.X+r.Dx()-border, r.Min.Y+r.Dy()-border)
ret["bottom_right"] = ganim8.NewSprite(img, g.Frames())
return ret
diff --git a/examples/game/sprites/sprites.go b/examples/game/sprites/sprites.go
index ce88b31..2fa8484 100644
--- a/examples/game/sprites/sprites.go
+++ b/examples/game/sprites/sprites.go
@@ -26,17 +26,12 @@ type subTexture struct {
Height int `xml:"height,attr"`
}
-type PanelOpts struct {
- Name string
- Border int
-}
-
type LoadOpts struct {
- PanelOpts []PanelOpts
+ PanelOpts map[string]PanelOpts
}
-func LoadSprites(opts LoadOpts) {
- dat, err := os.ReadFile("assets/uipack_rpg_sheet.xml")
+func LoadSprites(xmlPath string, imgPath string, opts LoadOpts) {
+ dat, err := os.ReadFile(xmlPath)
if err != nil {
panic(err)
}
@@ -45,7 +40,7 @@ func LoadSprites(opts LoadOpts) {
panic(err)
}
- img, _, err := ebitenutil.NewImageFromFile("assets/uipack_rpg_sheet.png")
+ img, _, err := ebitenutil.NewImageFromFile(imgPath)
if err != nil {
panic(err)
}
@@ -58,14 +53,14 @@ func LoadSprites(opts LoadOpts) {
rects[s.Name] = rect
}
- for _, o := range opts.PanelOpts {
- r, ok := rects[o.Name]
+ for k, o := range opts.PanelOpts {
+ r, ok := rects[k]
if !ok {
- panic("panel not found: " + o.Name)
+ panic("panel not found: " + k)
}
- panels := createPanels(img, r, o.Border)
- for k, v := range panels {
- sprites[fmt.Sprintf("%s_%s", o.Name, k)] = v
+ panels := createPanels(img, r, o)
+ for kk, v := range panels {
+ sprites[fmt.Sprintf("%s_%s", k, kk)] = v
}
}
}
diff --git a/examples/game/text/text.go b/examples/game/text/text.go
new file mode 100644
index 0000000..a1428fa
--- /dev/null
+++ b/examples/game/text/text.go
@@ -0,0 +1,24 @@
+package text
+
+import "github.com/tinne26/etxt"
+
+var (
+ R *etxt.Renderer
+ Font = "x14y20pxScoreDozer"
+)
+
+func LoadFonts() {
+ fontLib := etxt.NewFontLibrary()
+ _, _, err := fontLib.ParseDirFonts("./assets/fonts")
+ if err != nil {
+ panic(err)
+ }
+
+ // create a new text renderer and configure it
+ R = etxt.NewStdRenderer()
+ glyphsCache := etxt.NewDefaultCache(10 * 1024 * 1024) // 10MB
+ R.SetCacheHandler(glyphsCache.NewHandler())
+ R.SetFont(fontLib.GetFont(Font))
+ R.SetAlign(etxt.YCenter, etxt.XCenter)
+ R.SetSizePx(14)
+}
diff --git a/examples/game/widgets/button.go b/examples/game/widgets/button.go
index 4dc4db3..3d103cb 100644
--- a/examples/game/widgets/button.go
+++ b/examples/game/widgets/button.go
@@ -2,16 +2,19 @@ package widgets
import (
"image"
+ "image/color"
"github.com/hajimehoshi/ebiten/v2"
- "github.com/hajimehoshi/ebiten/v2/ebitenutil"
+ "github.com/tinne26/etxt"
"github.com/yohamta/furex/v2"
"github.com/yohamta/furex/v2/examples/game/sprites"
+ "github.com/yohamta/furex/v2/examples/game/text"
"github.com/yohamta/ganim8/v2"
)
type Button struct {
Text string
+ Color color.Color
OnClick func()
Sprite string
SpritePressed string
@@ -52,8 +55,14 @@ func (b *Button) HandleDraw(screen *ebiten.Image, frame image.Rectangle) {
ganim8.DrawSpriteWithOpts(screen, sprites.Get(b.Sprite), 0, opts, nil)
}
- ebitenutil.DebugPrintAt(screen, b.Text,
- frame.Min.X+((frame.Dx()-len(b.Text)*6)/2), frame.Min.Y+frame.Dy()/2-8)
+ text.R.SetAlign(etxt.YCenter, etxt.XCenter)
+ text.R.SetTarget(screen)
+ if b.Color != nil {
+ text.R.SetColor(b.Color)
+ } else {
+ text.R.SetColor(color.White)
+ }
+ text.R.Draw(b.Text, int(x), int(y))
}
func (b *Button) HandleMouseEnter(x, y int) bool {
diff --git a/examples/game/widgets/panel.go b/examples/game/widgets/panel.go
index 46b4864..8e072f8 100644
--- a/examples/game/widgets/panel.go
+++ b/examples/game/widgets/panel.go
@@ -3,33 +3,49 @@ package widgets
import (
"fmt"
"image"
+ "image/color"
"github.com/hajimehoshi/ebiten/v2"
+ "github.com/tinne26/etxt"
"github.com/yohamta/furex/v2"
"github.com/yohamta/furex/v2/examples/game/sprites"
+ "github.com/yohamta/furex/v2/examples/game/text"
"github.com/yohamta/ganim8/v2"
)
type Panel struct {
- Sprite string
+ Sprite string
+ Text string
+ Color color.Color
+ OnClick func()
+
+ mouseover bool
+ pressed bool
}
-var _ furex.DrawHandler = (*Panel)(nil)
+var (
+ _ furex.ButtonHandler = (*Panel)(nil)
+ _ furex.NotButton = (*Panel)(nil)
+ _ furex.DrawHandler = (*Panel)(nil)
+ _ furex.MouseEnterLeaveHandler = (*Panel)(nil)
+)
func (p *Panel) HandleDraw(screen *ebiten.Image, frame image.Rectangle) {
// This code is just for demo.
- // It's super dirty and not optimized.
+ // It's dirty and not optimized.
PanelName := p.Sprite
border := sprites.Get(fmt.Sprintf("%s_top_left", PanelName)).Width()
+ top := sprites.Get(fmt.Sprintf("%s_top", PanelName)).Height()
fborder := float64(border)
spr := sprites.Get(fmt.Sprintf("%s_center", PanelName))
x := float64(frame.Min.X) + fborder
- for x < float64(frame.Max.X)-fborder-2 {
- y := float64(frame.Min.Y) + fborder - 2
+ for x < float64(frame.Max.X)-fborder {
+ y := float64(frame.Min.Y) + float64(top)
for y < float64(frame.Max.Y)-fborder {
- ganim8.DrawSprite(screen, spr, 0, x, y, 0, 1, 1, 0, 0)
+ opts := ganim8.DrawOpts(x, y, 0, 1, 1, 0, 0)
+ p.drawSprite(screen, spr, opts)
y += float64(spr.H())
}
x += float64(spr.W())
@@ -37,34 +53,92 @@ func (p *Panel) HandleDraw(screen *ebiten.Image, frame image.Rectangle) {
// top_left
spr = sprites.Get(fmt.Sprintf("%s_top_left", PanelName))
- ganim8.DrawSprite(screen, spr, 0, float64(frame.Min.X), float64(frame.Min.Y), 0, 1, 1, 0, 0)
+ opts := ganim8.DrawOpts(float64(frame.Min.X), float64(frame.Min.Y), 0, 1, 1, 0, 0)
+ p.drawSprite(screen, spr, opts)
+
// top
spr = sprites.Get(fmt.Sprintf("%s_top", PanelName))
for x := float64(frame.Min.X + border); x < float64(frame.Max.X-border); x += float64(spr.W()) {
- ganim8.DrawSprite(screen, spr, 0, x, float64(frame.Min.Y), 0, 1, 1, 0, 0)
+ opts := ganim8.DrawOpts(x, float64(frame.Min.Y), 0, 1, 1, 0, 0)
+ p.drawSprite(screen, spr, opts)
}
// top_right
spr = sprites.Get(fmt.Sprintf("%s_top_right", PanelName))
- ganim8.DrawSprite(screen, spr, 0, float64(frame.Max.X-border), float64(frame.Min.Y), 0, 1, 1, 0, 0)
+ opts = ganim8.DrawOpts(float64(frame.Max.X-border), float64(frame.Min.Y), 0, 1, 1, 0, 0)
+ p.drawSprite(screen, spr, opts)
// left
spr = sprites.Get(fmt.Sprintf("%s_left", PanelName))
for y := float64(frame.Min.Y + border); y < float64(frame.Max.Y-border); y += float64(spr.H()) {
- ganim8.DrawSprite(screen, spr, 0, float64(frame.Min.X), y, 0, 1, 1, 0, 0)
+ opts = ganim8.DrawOpts(float64(frame.Min.X), y, 0, 1, 1, 0, 0)
+ p.drawSprite(screen, spr, opts)
}
// right
spr = sprites.Get(fmt.Sprintf("%s_right", PanelName))
for y := float64(frame.Min.Y + border); y < float64(frame.Max.Y-border); y += float64(spr.H()) {
- ganim8.DrawSprite(screen, spr, 0, float64(frame.Max.X-spr.W()), y, 0, 1, 1, 0, 0)
+ opts = ganim8.DrawOpts(float64(frame.Max.X-spr.W()), y, 0, 1, 1, 0, 0)
+ p.drawSprite(screen, spr, opts)
}
// bottom_left
spr = sprites.Get(fmt.Sprintf("%s_bottom_left", PanelName))
- ganim8.DrawSprite(screen, spr, 0, float64(frame.Min.X), float64(frame.Max.Y-border), 0, 1, 1, 0, 0)
+ opts = ganim8.DrawOpts(float64(frame.Min.X), float64(frame.Max.Y-border), 0, 1, 1, 0, 0)
+ p.drawSprite(screen, spr, opts)
// bottom
spr = sprites.Get(fmt.Sprintf("%s_bottom", PanelName))
for x := float64(frame.Min.X + border); x < float64(frame.Max.X-border); x += float64(spr.W()) {
- ganim8.DrawSprite(screen, spr, 0, x, float64(frame.Max.Y-spr.H()), 0, 1, 1, 0, 0)
+ opts = ganim8.DrawOpts(x, float64(frame.Max.Y-spr.H()), 0, 1, 1, 0, 0)
+ p.drawSprite(screen, spr, opts)
}
// bottom_right
spr = sprites.Get(fmt.Sprintf("%s_bottom_right", PanelName))
- ganim8.DrawSprite(screen, spr, 0, float64(frame.Max.X-border), float64(frame.Max.Y-border), 0, 1, 1, 0, 0)
+ opts = ganim8.DrawOpts(float64(frame.Max.X-border), float64(frame.Max.Y-border), 0, 1, 1, 0, 0)
+ p.drawSprite(screen, spr, opts)
+
+ if p.Text != "" {
+ x, y := float64(frame.Min.X+frame.Dx()/2), float64(frame.Min.Y+frame.Dy()/2)
+ text.R.SetAlign(etxt.YCenter, etxt.XCenter)
+ text.R.SetTarget(screen)
+ if p.Color != nil {
+ text.R.SetColor(p.Color)
+ } else {
+ text.R.SetColor(color.White)
+ }
+ text.R.Draw(p.Text, int(x), int(y))
+ }
+}
+
+func (p *Panel) drawSprite(screen *ebiten.Image, spr *ganim8.Sprite, opts *ganim8.DrawOptions) {
+ if p.IsButton() {
+ if p.pressed {
+ opts.ColorM.Scale(0.9, 0.9, 0.9, 1)
+ } else if p.mouseover {
+ opts.ColorM.Scale(1.1, 1.1, 1.1, 1)
+ }
+ }
+ ganim8.DrawSpriteWithOpts(screen, spr, 0, opts, nil)
+}
+
+func (p *Panel) IsButton() bool {
+ return p.OnClick != nil
+}
+
+func (p *Panel) HandleMouseEnter(x, y int) bool {
+ p.mouseover = true
+ return true
+}
+
+func (p *Panel) HandleMouseLeave() {
+ p.mouseover = false
+}
+
+func (p *Panel) HandlePress(x, y int, t ebiten.TouchID) {
+ p.pressed = true
+}
+
+func (p *Panel) HandleRelease(x, y int, isCancel bool) {
+ p.pressed = false
+ if !isCancel {
+ if p.OnClick != nil {
+ p.OnClick()
+ }
+ }
}
diff --git a/examples/game/widgets/text.go b/examples/game/widgets/text.go
index 5c34549..c5a259b 100644
--- a/examples/game/widgets/text.go
+++ b/examples/game/widgets/text.go
@@ -6,11 +6,17 @@ import (
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
+ "github.com/tinne26/etxt"
"github.com/yohamta/furex/v2"
+ "github.com/yohamta/furex/v2/examples/game/text"
)
type Text struct {
- Value string
+ Color color.Color
+ Value string
+ Shadow bool
+ HorzAlign etxt.HorzAlign
+ VertAlign etxt.VertAlign
}
var (
@@ -18,8 +24,23 @@ var (
)
func (t *Text) HandleDraw(screen *ebiten.Image, frame image.Rectangle) {
- ebitenutil.DrawRect(
- screen, float64(frame.Min.X), float64(frame.Min.Y), float64(len(t.Value)*6+4), float64(frame.Dy()), color.RGBA{0, 0, 0, 50})
- ebitenutil.DebugPrintAt(screen, t.Value,
- frame.Min.X+2, frame.Min.Y+frame.Dy()/2-8)
+ if t.Shadow {
+ ebitenutil.DrawRect(
+ screen, float64(frame.Min.X), float64(frame.Min.Y), float64(len(t.Value)*6+4), float64(frame.Dy()), color.RGBA{0, 0, 0, 50})
+ }
+ x, y := frame.Min.X+frame.Dx()/2, frame.Min.Y+frame.Dy()/2
+ if t.HorzAlign == etxt.Left {
+ x = frame.Min.X
+ }
+ if t.VertAlign == etxt.Top {
+ y = frame.Min.Y
+ }
+ if t.Color != nil {
+ text.R.SetColor(t.Color)
+ } else {
+ text.R.SetColor(color.White)
+ }
+ text.R.SetAlign(t.VertAlign, t.HorzAlign)
+ text.R.SetTarget(screen)
+ text.R.Draw(t.Value, x, y)
}
diff --git a/go.mod b/go.mod
index 5aa917a..ea94bc9 100644
--- a/go.mod
+++ b/go.mod
@@ -10,6 +10,7 @@ require (
github.com/hajimehoshi/file2byteslice v1.0.0 // indirect
github.com/jezek/xgb v1.1.0 // indirect
github.com/stretchr/testify v1.8.1
+ github.com/tinne26/etxt v0.0.7
github.com/yohamta/ganim8/v2 v2.1.24 // indirect
golang.org/x/exp/shiny v0.0.0-20221126150942-6ab00d035af9 // indirect
golang.org/x/mobile v0.0.0-20221110043201-43a038452099 // indirect
diff --git a/go.sum b/go.sum
index 87680da..e94e04e 100644
--- a/go.sum
+++ b/go.sum
@@ -3,6 +3,7 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/ebitengine/purego v0.0.0-20220816145426-8dbe340b03f1/go.mod h1:Eh8I3yvknDYZeCuXH9kRNaPuHEwvXDCk378o9xszmHg=
github.com/ebitengine/purego v0.0.0-20220905075623-aeed57cda744/go.mod h1:Eh8I3yvknDYZeCuXH9kRNaPuHEwvXDCk378o9xszmHg=
github.com/ebitengine/purego v0.1.1 h1:HI8nW+LniW9Yb34k34jBs8nz+PNzsw68o7JF8jWFHHE=
github.com/ebitengine/purego v0.1.1/go.mod h1:Eh8I3yvknDYZeCuXH9kRNaPuHEwvXDCk378o9xszmHg=
@@ -16,9 +17,11 @@ github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/hajimehoshi/bitmapfont/v2 v2.2.0/go.mod h1:Llj2wTYXMuCTJEw2ATNIO6HbFPOoBYPs08qLdFAxOsQ=
+github.com/hajimehoshi/bitmapfont/v2 v2.2.1/go.mod h1:wjrYAy8vKgj9JsFgnYAOK346/uvE22TlmqouzdnYIs0=
github.com/hajimehoshi/bitmapfont/v2 v2.2.2/go.mod h1:Ua/x9Dkz7M9CU4zr1VHWOqGwjKdXbOTRsH7lWfb1Co0=
github.com/hajimehoshi/ebiten/v2 v2.3.7 h1:a4AUxBZSnQe3MQAfVLkjnTKA4GvLjnTyASeazq/LcZw=
github.com/hajimehoshi/ebiten/v2 v2.3.7/go.mod h1:vxwpo0q0oSi1cIll0Q3Ui33TVZgeHuFVYzIRk7FwuVk=
+github.com/hajimehoshi/ebiten/v2 v2.4.1/go.mod h1:z9L4JZ3XHQqvCuVuAQ1qTByIV2YHGS1w6keUSVC9NDA=
github.com/hajimehoshi/ebiten/v2 v2.4.13 h1:ZZ5y+bFkAbUeD2WGquHF+xSbg83SIbcsxCwEVeZgHWM=
github.com/hajimehoshi/ebiten/v2 v2.4.13/go.mod h1:BZcqCU4XHmScUi+lsKexocWcf4offMFwfp8dVGIB/G4=
github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41/go.mod h1:CqqAHp7Dk/AqQiwuhV1yT2334qbA/tFWQW0MD2dGqUE=
@@ -27,6 +30,7 @@ github.com/hajimehoshi/file2byteslice v1.0.0/go.mod h1:CqqAHp7Dk/AqQiwuhV1yT2334
github.com/hajimehoshi/go-mp3 v0.3.3/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
github.com/hajimehoshi/oto/v2 v2.1.0/go.mod h1:9i0oYbpJ8BhVGkXDKdXKfFthX1JUNfXjeTp944W8TGM=
+github.com/hajimehoshi/oto/v2 v2.3.0/go.mod h1:seWLbgHH7AyUMYKfKYT9pg7PhUu9/SisyJvNTT+ASQo=
github.com/hajimehoshi/oto/v2 v2.3.1/go.mod h1:seWLbgHH7AyUMYKfKYT9pg7PhUu9/SisyJvNTT+ASQo=
github.com/jakecoffman/cp v1.1.0/go.mod h1:JjY/Fp6d8E1CHnu74gWNnU0+b9VzEdUVPoJxg2PsTQg=
github.com/jakecoffman/cp v1.2.1/go.mod h1:JjY/Fp6d8E1CHnu74gWNnU0+b9VzEdUVPoJxg2PsTQg=
@@ -54,6 +58,8 @@ github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PK
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/tinne26/etxt v0.0.7 h1:0260rWgMAN/YlXxZKLKYkOVC74bpe47gwJWIGjuPh2o=
+github.com/tinne26/etxt v0.0.7/go.mod h1:AAR5FluvokKyOblF3JPiCfBZBjRRxAiqem+3XqQOt8w=
github.com/yohamta/ganim8/v2 v2.1.24 h1:D+ga5kLGdtX38ykQi63gxTu9R8E2H2FaborLU1MIGQY=
github.com/yohamta/ganim8/v2 v2.1.24/go.mod h1:TyKLLUSwEGzsz6DcsoTHvNyqOz/HyvqWynQye9J/m2A=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
@@ -78,6 +84,7 @@ golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+o
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/image v0.0.0-20220321031419-a8550c1d254a h1:LnH9RNcpPv5Kzi15lXg42lYMPUf0x8CuPv1YnvBWZAg=
golang.org/x/image v0.0.0-20220321031419-a8550c1d254a/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
+golang.org/x/image v0.0.0-20220722155232-062f8c9fd539/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
golang.org/x/image v0.1.0 h1:r8Oj8ZA2Xy12/b5KZYj3tuv7NG/fBz3TwQVvpJ9l8Rk=
golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
@@ -135,6 +142,7 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=