From 25d3d8cb0db5470efe360b1c9a1a75a77c4dc0b7 Mon Sep 17 00:00:00 2001 From: squishy Date: Mon, 25 Mar 2024 00:55:14 +0000 Subject: [PATCH] started implementing button --- Run/run.go | 3 +-- font.go | 14 +++++++++++ gui/button.go | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ gui/gui.go | 11 ++++++++- gui/widget.go | 18 +++++++++++++++ image.go | 45 ++++++++++++++++++++++++++++++++++++ test/gui/main.go | 13 +++++++---- 7 files changed, 157 insertions(+), 7 deletions(-) create mode 100644 gui/button.go create mode 100644 gui/widget.go diff --git a/Run/run.go b/Run/run.go index d3a4d43..9a12d85 100644 --- a/Run/run.go +++ b/Run/run.go @@ -37,9 +37,8 @@ func Run(game Runnable) { Cursor: DefaultCursor, } - game.Init(&bloob, &settings) - gui.InitGui(settings.WindowSize) + game.Init(&bloob, &settings) window, _ := sdl.CreateWindow( settings.Title, diff --git a/font.go b/font.go index c5f38b1..8b837ec 100644 --- a/font.go +++ b/font.go @@ -30,3 +30,17 @@ func LoadTilesetFontBytes(data []byte, tilesize Vec2i) *Font { font.lineHeight = tilesize.Y + 2 return &font } + +func (f *Font) StringWidth(str string) int { + var l int + for i := 0; i < len(str); i += 1 { + l += f.chars[i].xForward + } + return l - 1 +} + +func (f *Font) StringBounds(str string) Vec2i { + //todo: multiline + + return Vec2i{X: f.StringWidth(str), Y: f.lineHeight} +} diff --git a/gui/button.go b/gui/button.go new file mode 100644 index 0000000..da99be4 --- /dev/null +++ b/gui/button.go @@ -0,0 +1,60 @@ +package gui + +import . "git.danitheskunk.com/squishy/blooblib" + +type Button struct { + BaseWidget + label string +} + +func NewButton(label string) *Button { + return &Button{ + BaseWidget: BaseWidget{ + Size: Vec2i{X: 80, Y: 22}, + }, + label: label, + } +} + +func (w *Button) Draw(target *Image) { + //col1 := Color(0xffffff) + col2 := Color(0xccccdd) + col3 := Color(0x888899) + col4 := Color(0x555566) + //col5 := Color(0x444444) + + pressed := false + + if pressed { + //todo: non-filled + target.DrawRectRounded(Recti{Pos: w.Pos, Size: w.Size}, 0, 2) + + target.DrawHLine(Vec2i{X: w.Pos.X + 2, Y: w.Pos.Y + 1}, w.Size.X-4, col4) + target.DrawVLine(Vec2i{X: w.Pos.X + 1, Y: w.Pos.Y + 2}, w.Size.Y-4, col4) + + target.DrawHLine(Vec2i{X: w.Pos.X + 2, Y: w.Pos.Y + w.Size.Y - 2}, w.Size.X-4, col2) + target.DrawVLine(Vec2i{X: w.Pos.X + w.Size.X - 2, Y: w.Pos.Y + 2}, w.Size.Y-4, col2) + + innerRect := Recti{Pos: Vec2i{X: w.Pos.X + 2, Y: w.Pos.Y + 2}, Size: Vec2i{X: w.Size.X - 4, Y: w.Size.Y - 4}} + target.DrawRect(innerRect, col3) + innerRect.Pos.X += 1 + innerRect.Pos.Y += 1 + target.DrawTextOutlineCenter(w.label, DefaultFont, innerRect, col2, 0x000000) + } else { + //todo: non-filled + target.DrawRectRounded(Recti{Pos: w.Pos, Size: w.Size}, 0, 2) + + target.DrawHLine(Vec2i{X: w.Pos.X + 2, Y: w.Pos.Y + 1}, w.Size.X-4, col2) + target.DrawVLine(Vec2i{X: w.Pos.X + 1, Y: w.Pos.Y + 2}, w.Size.Y-4, col2) + + target.DrawHLine(Vec2i{X: w.Pos.X + 2, Y: w.Pos.Y + w.Size.Y - 2}, w.Size.X-4, col4) + target.DrawVLine(Vec2i{X: w.Pos.X + w.Size.X - 2, Y: w.Pos.Y + 2}, w.Size.Y-4, col4) + + innerRect := Recti{Pos: Vec2i{X: w.Pos.X + 2, Y: w.Pos.Y + 2}, Size: Vec2i{X: w.Size.X - 4, Y: w.Size.Y - 4}} + target.DrawRect(innerRect, col3) + + target.DrawTextOutlineCenter(w.label, DefaultFont, innerRect, col2, 0x000000) + + } + +} diff --git a/gui/gui.go b/gui/gui.go index dd5faf2..cdcd73a 100644 --- a/gui/gui.go +++ b/gui/gui.go @@ -3,6 +3,7 @@ package gui import . "git.danitheskunk.com/squishy/blooblib" type gui struct { + Root Widget } var Gui gui @@ -12,5 +13,13 @@ func InitGui(size Vec2i) { } func DrawGui(target *Image) { - + if Gui.Root != nil { + Gui.Root.Draw(target) + } +} + +func UpdateGui() { + if Gui.Root != nil { + Gui.Root.Layout() + } } diff --git a/gui/widget.go b/gui/widget.go new file mode 100644 index 0000000..2476b62 --- /dev/null +++ b/gui/widget.go @@ -0,0 +1,18 @@ +package gui + +import . "git.danitheskunk.com/squishy/blooblib" + +type BaseWidget struct { + childs []*Widget + parent *Widget + Pos Vec2i + Size Vec2i +} + +type Widget interface { + Draw(target *Image) + Layout() +} + +func (w *BaseWidget) Draw(target *Image) {} +func (w *BaseWidget) Layout() {} diff --git a/image.go b/image.go index 6824b65..cac4573 100644 --- a/image.go +++ b/image.go @@ -91,6 +91,10 @@ func CropToArea(sizeDst Vec2i, rectSrc Recti, posDst Vec2i) (start, end, dst Vec return } +func (image *Image) DrawPixel(pos Vec2i, color Color) { + image.Data[pos.X+pos.Y*image.Size.X] = color +} + func (image *Image) DrawHLine(pos Vec2i, length int, color Color) { for i := 0; i < length; i += 1 { image.Data[pos.X+i+pos.Y*image.Size.X] = color @@ -103,6 +107,35 @@ func (image *Image) DrawVLine(pos Vec2i, length int, color Color) { } } +func (image *Image) DrawRect(rect Recti, color Color) { + start, end, _ := CropToArea(image.Size, rect, Vec2i{}) + for y := start.Y; y < end.Y; y += 1 { + for x := start.X; x < end.X; x += 1 { + image.Data[x+y*image.Size.X] = color + } + } +} + +func (image *Image) DrawRectRounded(rect Recti, color Color, round int) { + round = min(max(rect.Size.X, rect.Size.Y)/2-1, round) + + start, end, _ := CropToArea(image.Size, rect, Vec2i{}) + for y := start.Y; y < end.Y; y += 1 { + ri := 0 + yt := y - start.Y + yp := -(y - end.Y+1) + if yt < round { + ri = round - yt + } + if yp < round { + ri = round - yp + } + for x := start.X + ri; x < end.X-ri; x += 1 { + image.Data[x+y*image.Size.X] = color + } + } +} + func (image *Image) Draw(other *Image, dst Vec2i) { image.DrawSub(other, dst, Recti{Size: other.Size}) } @@ -278,6 +311,12 @@ func (image *Image) DrawText(str string, font *Font, pos Vec2i, color Color) { } } +func (image *Image) DrawTextCenter(str string, font *Font, rect Recti, color Color) { + size := font.StringBounds(str) + pos := Add(DivScalar(Sub(rect.Size, size), 2), Add(rect.Pos, Vec2i{X: 0, Y: 1})) + image.DrawText(str, font, pos, color) +} + func (image *Image) DrawTextSin(str string, font *Font, pos Vec2i, color Color, freq, amplitude, phase float64) { origX := pos.X for _, ch := range str { @@ -319,6 +358,12 @@ func (image *Image) DrawTextOutline(str string, font *Font, pos Vec2i, color, ou } } +func (image *Image) DrawTextOutlineCenter(str string, font *Font, rect Recti, color, outlineColor Color) { + size := font.StringBounds(str) + pos := Add(DivScalar(Sub(rect.Size, size), 2), Add(rect.Pos, Vec2i{X: 0, Y: 1})) + image.DrawTextOutline(str, font, pos, color, outlineColor) +} + func (image *Image) DrawTextOutlineSin(str string, font *Font, pos Vec2i, color, outlineColor Color, freq, amplitude, phase float64) { origX := pos.X for _, ch := range str { diff --git a/test/gui/main.go b/test/gui/main.go index 72fc0e7..2a1a773 100644 --- a/test/gui/main.go +++ b/test/gui/main.go @@ -1,20 +1,25 @@ package main import ( - bloob "git.danitheskunk.com/squishy/blooblib" + . "git.danitheskunk.com/squishy/blooblib" + . "git.danitheskunk.com/squishy/blooblib/gui" run "git.danitheskunk.com/squishy/blooblib/Run" ) type Game struct { } -func (g Game) Init(bloob *bloob.Bloob, settings *bloob.Settings) { +func (g Game) Init(bloob *Bloob, settings *Settings) { + button := NewButton("Ok") + button.Pos = Vec2i{X: 20, Y: 20} + Gui.Root = button } -func (g Game) Render(bloob *bloob.Bloob, screen *bloob.Image) { +func (g Game) Render(bloob *Bloob, screen *Image) { + screen.Clear(0xcccccc) } -func (g Game) Update(bloob *bloob.Bloob) { +func (g Game) Update(bloob *Bloob) { } func main() {