MORE MESSING AROUND

This commit is contained in:
Caleb Gardner
2025-01-11 13:16:58 -06:00
parent c8e0f08aae
commit 6e8d97f29b
4 changed files with 227 additions and 53 deletions
+1
View File
@@ -0,0 +1 @@
testing/
+180 -46
View File
@@ -1,8 +1,10 @@
package ui package ui
import ( import (
"fmt"
"image" "image"
"image/color" "image/color"
"time"
rl "github.com/gen2brain/raylib-go/raylib" rl "github.com/gen2brain/raylib-go/raylib"
) )
@@ -10,21 +12,25 @@ import (
// A rectangle with borders. // A rectangle with borders.
// Default only has black borders. // Default only has black borders.
type Rect struct { type Rect struct {
x int32 x int32
y int32 y int32
h int32 h int32
w int32 w int32
radius int32 radius int32
reload bool
shown bool
rendering bool
borderWidth int32 borderWidth int32
borderColor color.RGBA borderColor color.RGBA
fillColor color.RGBA fillColor color.RGBA
tex *rl.Texture2D curTweens map[string]*Tween
tex rl.RenderTexture2D
} }
func NewRect(x, y, height, width int32) *Rect { func NewRect(x, y, height, width int32) *Rect {
return &Rect{ r := &Rect{
x: x, x: x,
y: y, y: y,
h: height, h: height,
@@ -33,93 +39,221 @@ func NewRect(x, y, height, width int32) *Rect {
borderWidth: 2, borderWidth: 2,
borderColor: rl.Black, borderColor: rl.Black,
fillColor: rl.Blank, fillColor: rl.Blank,
reload: true,
curTweens: make(map[string]*Tween),
} }
r.tex = rl.LoadRenderTexture(width, height)
rl.SetTextureFilter(r.tex.Texture, rl.FilterAnisotropic8x|rl.FilterBilinear)
return r
}
func (r *Rect) Copy() *Rect {
return &Rect{
x: r.x,
y: r.y,
h: r.h,
w: r.w,
radius: r.radius,
borderWidth: r.borderWidth,
borderColor: r.borderColor,
fillColor: r.fillColor,
}
}
func (r *Rect) addTween(key string, old, new int32) {
r.curTweens[key] = NewTween(old, new, 1000*time.Millisecond)
} }
func (r *Rect) SetPosition(x, y int32) { func (r *Rect) SetPosition(x, y int32) {
r.x, r.y = x, y if !r.shown {
r.x, r.y = x, y
return
}
if r.x != x {
r.addTween("x", r.x, x)
}
if r.y != y {
r.addTween("y", r.y, y)
}
} }
func (r *Rect) SetSize(h, w int32) { func (r *Rect) SetSize(h, w int32) {
r.h, r.w = h, w if !r.shown {
r.Unload() r.h, r.w = h, w
return
}
if r.h != h {
r.addTween("h", r.h, h)
r.reload = true
}
if r.w != w {
r.addTween("w", r.w, w)
r.reload = true
}
} }
func (r *Rect) SetBorderRadius(radius int32) { func (r *Rect) SetBorderRadius(radius int32) {
r.radius = radius if !r.shown {
r.Unload() r.radius = radius
return
}
if r.radius != radius {
r.addTween("radius", r.radius, radius)
r.reload = true
}
} }
func (r *Rect) SetBorderWidth(w int32) { func (r *Rect) SetBorderWidth(w int32) {
r.borderWidth = w if !r.shown {
r.Unload() r.borderWidth = w
return
}
if r.borderWidth != w {
r.addTween("borderWidth", r.borderWidth, w)
r.reload = true
}
} }
func (r *Rect) SetBorderColor(c color.RGBA) { func (r *Rect) SetBorderColor(c color.RGBA) {
if r.borderColor != c {
r.reload = true
}
r.borderColor = c r.borderColor = c
r.Unload()
} }
func (r *Rect) SetFillColor(c color.RGBA) { func (r *Rect) SetFillColor(c color.RGBA) {
r.fillColor = c if r.fillColor != c {
r.Unload() r.reload = true
}
func (r *Rect) Unload() {
if r.tex != nil {
rl.UnloadTexture(*r.tex)
r.tex = nil
} }
r.fillColor = c
} }
func (r *Rect) Draw() { func (r *Rect) Draw() {
if r.tex != nil { r.shown = true
rl.DrawTextureEx(*r.tex, rl.NewVector2(float32(r.x), float32(r.y)), 0, 1, rl.White) if !r.reload && len(r.curTweens) == 0 {
rl.DrawTextureEx(r.tex.Texture, rl.NewVector2(float32(r.x), float32(r.y)), 0, 1, rl.White)
return return
} }
// Create image at 16x resolution then resize down so it looks better var curRect *Rect
img := rl.NewImageFromImage(image.NewAlpha(image.Rect(0, 0, int(r.w*4), int(r.h*4)))) updateTex := false
if len(r.curTweens) != 0 {
curRect = r.Copy()
tween, ok := r.curTweens["x"]
if ok {
curRect.x = tween.CurVal()
if tween.Ended() {
r.x = curRect.x
delete(r.curTweens, "x")
}
}
tween, ok = r.curTweens["y"]
if ok {
curRect.y = tween.CurVal()
if tween.Ended() {
r.y = curRect.y
delete(r.curTweens, "y")
}
}
tween, ok = r.curTweens["h"]
if ok {
curRect.h = tween.CurVal()
if curRect.h != r.h {
updateTex = true
}
fmt.Println("h", curRect.h, r.h)
if tween.Ended() {
r.h = curRect.h
delete(r.curTweens, "h")
}
}
tween, ok = r.curTweens["w"]
if ok {
curRect.w = tween.CurVal()
if curRect.w != r.w {
updateTex = true
}
fmt.Println("w", curRect.w, r.w)
if tween.Ended() {
r.w = curRect.w
delete(r.curTweens, "w")
}
}
tween, ok = r.curTweens["radius"]
if ok {
curRect.radius = tween.CurVal()
if curRect.radius != r.radius {
updateTex = true
}
if tween.Ended() {
r.radius = curRect.radius
delete(r.curTweens, "radius")
}
}
tween, ok = r.curTweens["borderWidth"]
if ok {
curRect.borderWidth = tween.CurVal()
if curRect.borderWidth != r.borderWidth {
updateTex = true
}
if tween.Ended() {
r.borderWidth = curRect.borderWidth
delete(r.curTweens, "borderWidth")
}
}
} else {
curRect = r
}
if r.reload || updateTex {
// rl.UnloadTexture(r.tex)
// r.tex = rl.LoadTextureFromImage(curRect.buildImage())
// rl.UpdateTexture(r.tex, rl.LoadImageColors(curRect.buildImage()))
rl.BeginTextureMode(r.tex)
rl.UpdateTextureRec(r.tex.Texture, rl.NewRectangle(0, 0, float32(curRect.w), float32(curRect.h)), rl.LoadImageColors(curRect.buildImage()))
rl.EndTextureMode()
}
rl.DrawTextureEx(r.tex.Texture, rl.NewVector2(float32(curRect.x), float32(curRect.y)), 0, 1, rl.White)
r.reload = false
}
func (r Rect) buildImage() *rl.Image {
// Create image at 16x resolution then resize down so it looks better
img := rl.NewImageFromImage(image.NewAlpha(image.Rect(0, 0, int(r.w), int(r.h))))
// Filled areas // Filled areas
if r.fillColor != rl.Blank { if r.fillColor != rl.Blank {
rl.ImageDrawRectangle(img, 4*r.radius, 0, 4*(r.w-(2*r.radius)), 4*r.h, r.fillColor) rl.ImageDrawRectangle(img, r.radius, 0, (r.w - (2 * r.radius)), r.h, r.fillColor)
if r.radius > 0 { if r.radius > 0 {
rl.ImageDrawRectangle(img, 4*(r.w-r.radius), 4*r.radius, 4*r.radius, 4*(r.h-(2*r.radius)), r.fillColor) rl.ImageDrawRectangle(img, (r.w - r.radius), r.radius, r.radius, (r.h - (2 * r.radius)), r.fillColor)
rl.ImageDrawRectangle(img, 0, 4*r.radius, 4*r.radius, 4*(r.h-(2*r.radius)), r.fillColor) rl.ImageDrawRectangle(img, 0, r.radius, r.radius, (r.h - (2 * r.radius)), r.fillColor)
} }
} }
if r.borderColor != rl.Blank { if r.borderColor != rl.Blank {
// Horizontal lines // Horizontal lines
rl.ImageDrawRectangle(img, 4*r.radius, 0, 4*(r.w-(2*r.radius)), r.borderWidth*4, r.borderColor) rl.ImageDrawRectangle(img, r.radius, 0, (r.w - (2 * r.radius)), r.borderWidth, r.borderColor)
rl.ImageDrawRectangle(img, 4*r.radius, (4*r.h)-(r.borderWidth*4), 4*(r.w-(2*r.radius)), r.borderWidth*4, r.borderColor) rl.ImageDrawRectangle(img, r.radius, (r.h)-(r.borderWidth), (r.w - (2 * r.radius)), r.borderWidth, r.borderColor)
// Vertical lines // Vertical lines
rl.ImageDrawRectangle(img, 0, 4*r.radius, r.borderWidth*4, 4*(r.h-(2*r.radius)), r.borderColor) rl.ImageDrawRectangle(img, 0, r.radius, r.borderWidth, (r.h - (2 * r.radius)), r.borderColor)
rl.ImageDrawRectangle(img, (4*r.w)-(4*r.borderWidth), 4*r.radius, r.borderWidth*4, 4*(r.h-(2*r.radius)), r.borderColor) rl.ImageDrawRectangle(img, (r.w)-(r.borderWidth), r.radius, r.borderWidth, (r.h - (2 * r.radius)), r.borderColor)
} }
if r.radius > 0 { if r.radius > 0 {
r.placeCorners(r.radius, img) r.placeCorners(r.radius, img)
} }
return img
rl.ImageResize(img, r.w, r.h)
tmp := rl.LoadTextureFromImage(img)
r.tex = &tmp
rl.DrawTextureEx(*r.tex, rl.NewVector2(float32(r.x), float32(r.y)), 0, 1, r.borderColor)
} }
func (r Rect) placeCorners(radius float32, img *rl.Image) { func (r Rect) placeCorners(radius int32, img *rl.Image) {
// Setup corner // Setup corner
corner := rl.NewImageFromImage(image.NewAlpha(image.Rect(0, 0, int(radius*4), int(radius*4)))) corner := rl.NewImageFromImage(image.NewAlpha(image.Rect(0, 0, int(radius), int(radius))))
if r.borderWidth > 0 { if r.borderWidth > 0 {
rl.ImageDrawCircleV(corner, 4*radius, 4*radius, 4*radius, r.borderColor) rl.ImageDrawCircle(corner, radius, radius, radius, r.borderColor)
} }
rl.ImageDrawCircle(corner, 4*radius, 4*radius, (4*radius)-(4*r.borderWidth), r.fillColor) rl.ImageDrawCircle(corner, radius, radius, (radius)-(r.borderWidth), r.fillColor)
// Add corners to actual image // Add corners to actual image
rl.ImageDraw(img, corner, rl.NewRectangle(0, 0, float32(corner.Width), float32(corner.Height)), rl.NewRectangle(0, 0, float32(corner.Width), float32(corner.Height)), rl.White) rl.ImageDraw(img, corner, rl.NewRectangle(0, 0, float32(corner.Width), float32(corner.Height)), rl.NewRectangle(0, 0, float32(corner.Width), float32(corner.Height)), rl.White)
rl.ImageRotateCW(corner) rl.ImageRotateCW(corner)
rl.ImageDraw(img, corner, rl.NewRectangle(0, 0, float32(corner.Width), float32(corner.Height)), rl.NewRectangle(float32(4*(r.w-radius)), 0, float32(corner.Width), float32(corner.Height)), rl.White) rl.ImageDraw(img, corner, rl.NewRectangle(0, 0, float32(corner.Width), float32(corner.Height)), rl.NewRectangle(float32((r.w-radius)), 0, float32(corner.Width), float32(corner.Height)), rl.White)
rl.ImageRotateCW(corner) rl.ImageRotateCW(corner)
rl.ImageDraw(img, corner, rl.NewRectangle(0, 0, float32(corner.Width), float32(corner.Height)), rl.NewRectangle(float32(4*(r.w-radius)), float32(4*(r.h-radius)), float32(corner.Width), float32(corner.Height)), rl.White) rl.ImageDraw(img, corner, rl.NewRectangle(0, 0, float32(corner.Width), float32(corner.Height)), rl.NewRectangle(float32((r.w-radius)), float32((r.h-radius)), float32(corner.Width), float32(corner.Height)), rl.White)
rl.ImageRotateCW(corner) rl.ImageRotateCW(corner)
rl.ImageDraw(img, corner, rl.NewRectangle(0, 0, float32(corner.Width), float32(corner.Height)), rl.NewRectangle(0, float32(4*(r.h-radius)), float32(corner.Width), float32(corner.Height)), rl.White) rl.ImageDraw(img, corner, rl.NewRectangle(0, 0, float32(corner.Width), float32(corner.Height)), rl.NewRectangle(0, float32((r.h-radius)), float32(corner.Width), float32(corner.Height)), rl.White)
} }
+12 -1
View File
@@ -1,6 +1,8 @@
package ui package ui
import ( import (
"time"
rl "github.com/gen2brain/raylib-go/raylib" rl "github.com/gen2brain/raylib-go/raylib"
) )
@@ -8,7 +10,7 @@ type Window struct{}
func Test() { func Test() {
rl.InitWindow(800, 450, "raylib [core] example - basic window") rl.InitWindow(800, 450, "raylib [core] example - basic window")
rl.SetWindowState(rl.FlagWindowResizable | rl.FlagWindowHighdpi) rl.SetWindowState(rl.FlagWindowResizable | rl.FlagWindowHighdpi | rl.FlagVsyncHint)
rl.SetConfigFlags(rl.FlagMsaa4xHint) rl.SetConfigFlags(rl.FlagMsaa4xHint)
defer rl.CloseWindow() defer rl.CloseWindow()
rl.Scalef(2, 2, 2) rl.Scalef(2, 2, 2)
@@ -20,9 +22,18 @@ func Test() {
tmpRect := NewRect(10, 10, 250, 500) tmpRect := NewRect(10, 10, 250, 500)
tmpRect.SetBorderRadius(25) tmpRect.SetBorderRadius(25)
go func() {
for {
time.Sleep(5 * time.Second)
tmpRect.SetSize(200, 400)
time.Sleep(5 * time.Second)
tmpRect.SetSize(250, 500)
}
}()
// tmpRect.SetFillColor(rl.Green) // tmpRect.SetFillColor(rl.Green)
for !rl.WindowShouldClose() { for !rl.WindowShouldClose() {
rl.BeginDrawing() rl.BeginDrawing()
rl.DrawFPS(0, 0)
rl.ClearBackground(rl.DarkGray) rl.ClearBackground(rl.DarkGray)
// rl.DrawText("Congrats! You created your first window!", 190, 100, 20, rl.LightGray) // rl.DrawText("Congrats! You created your first window!", 190, 100, 20, rl.LightGray)
+34 -6
View File
@@ -1,11 +1,39 @@
package ui package ui
type num interface { import (
int32 | float32 "math"
"time"
)
type Tween struct {
startVal int32
startTime time.Time
dif int32
dur time.Duration
} }
type Tween[T num] struct { func NewTween(startVal, endVal int32, duration time.Duration) *Tween {
start T return &Tween{
nextMult float32 startVal: startVal,
end T dif: endVal - startVal,
dur: duration,
startTime: time.Now().Round(time.Millisecond),
}
}
func (t *Tween) CurVal() int32 {
since := time.Now().Round(time.Millisecond).Sub(t.startTime)
if since <= 0 {
return t.startVal
}
if since >= t.dur {
return t.startVal + t.dif
}
m := float32(since.Milliseconds()) / float32(t.dur.Milliseconds())
m = -1 * float32(math.Log10(-.9*float64(m)+1))
return t.startVal + int32(math.Round(float64(float32(t.dif)*m)))
}
func (t *Tween) Ended() bool {
return time.Now().Round(time.Millisecond).Sub(t.startTime) >= t.dur
} }