151 lines
3.4 KiB
Go
151 lines
3.4 KiB
Go
package graphics
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"image/color"
|
|
rl "github.com/gen2brain/raylib-go/raylib"
|
|
)
|
|
|
|
type Graphics struct {
|
|
layout Layout
|
|
style Style
|
|
}
|
|
|
|
type Layout struct {
|
|
// total monitor bounds
|
|
Monitor Rect
|
|
// bounds of the application window
|
|
Window Rect
|
|
// bounds of the ui controls area
|
|
Controls Rect
|
|
// bounds of the region of the app window reserved for rendering the graphics buffer
|
|
Viewport Rect
|
|
// bounds of the off screen graphics buffer where rendering happens
|
|
Graphics Rect
|
|
}
|
|
|
|
type Color color.RGBA
|
|
|
|
type HSBA struct {
|
|
H uint
|
|
S, B float32
|
|
A uint8
|
|
}
|
|
|
|
type Style struct {
|
|
StrokeColor Color
|
|
StrokeWeight float32
|
|
FillColor Color
|
|
}
|
|
|
|
type Rect rl.Rectangle
|
|
|
|
/**
|
|
* scale the given rect down to the target rect
|
|
* maintaining the aspect ratio of the original rect
|
|
*/
|
|
func (r Rect) ToRL() *rl.Rectangle {
|
|
return &rl.Rectangle { X: r.X, Y: r.Y, Width: r.Width, Height: r.Height }
|
|
}
|
|
|
|
func (r Rect) ScaleTo(tgt Rect) Rect {
|
|
|
|
outputWidth := tgt.Width
|
|
outputHeight := tgt.Height
|
|
|
|
aspect := r.Width / r.Height
|
|
tgtAspect := outputWidth / outputHeight
|
|
|
|
if aspect < tgtAspect {
|
|
// source is relatively taller than the target
|
|
// so we set the output height to the target height
|
|
// and calculate the width based on source aspect and center
|
|
outputWidth = float32(outputHeight) * aspect
|
|
} else {
|
|
// source is relatively wider than the target
|
|
// so we set the output width to the target width
|
|
// and calculate the height based on source aspect and center
|
|
outputHeight = float32(outputWidth) / aspect
|
|
}
|
|
|
|
// output width and height are correct -- center within TargetBounds
|
|
x := tgt.X + tgt.Width / 2.0 - outputWidth / 2.0
|
|
y := tgt.Y + tgt.Height / 2.0 - outputHeight / 2.0
|
|
|
|
return Rect {
|
|
X: x, Y: y,
|
|
Width: outputWidth,
|
|
Height: outputHeight,
|
|
}
|
|
}
|
|
|
|
var (
|
|
FlourescentHues = []float32{
|
|
0, // hot magenta-red
|
|
30, // neon orange
|
|
60, // acid yellow
|
|
120, // laser green
|
|
180, // cyan
|
|
210, // electric blue
|
|
270, // ultraviolet purple
|
|
}
|
|
FlourescentColors = makeFlourescentColors()
|
|
)
|
|
|
|
func Clamp(c rl.Color, min uint8, max uint8) rl.Color {
|
|
return rl.NewColor(
|
|
uint8(rl.Clamp(float32(c.R), float32(min), float32(max))),
|
|
uint8(rl.Clamp(float32(c.G), float32(min), float32(max))),
|
|
uint8(rl.Clamp(float32(c.B), float32(min), float32(max))),
|
|
uint8(rl.Clamp(float32(c.A), float32(min), float32(max))),
|
|
)
|
|
}
|
|
|
|
func makeFlourescentColors() []rl.Color {
|
|
fc := make([]rl.Color, len(FlourescentHues))
|
|
for i, hue := range(FlourescentHues) {
|
|
fc[i] = rl.ColorFromHSV(hue, 1.0, 1.0)
|
|
}
|
|
fmt.Printf("flourescent colors --> %v\n", fc)
|
|
|
|
return fc
|
|
}
|
|
|
|
type ColorCycle interface {
|
|
Next() rl.Color
|
|
}
|
|
|
|
type ArrayBackedColorCycle struct {
|
|
colors []rl.Color
|
|
index int
|
|
}
|
|
|
|
func NewFixedColorCycle(colors []rl.Color) *ArrayBackedColorCycle {
|
|
return &ArrayBackedColorCycle {
|
|
colors: colors,
|
|
index: 0,
|
|
}
|
|
}
|
|
|
|
func (c ArrayBackedColorCycle) Shuffle(seed int64) *ArrayBackedColorCycle {
|
|
r := rand.New(rand.NewSource(seed))
|
|
cprime := &ArrayBackedColorCycle {
|
|
colors: make([]rl.Color, len(c.colors)),
|
|
index: 0,
|
|
}
|
|
copy(cprime.colors, c.colors)
|
|
r.Shuffle(len(c.colors), func(i, j int) {
|
|
cprime.colors[i], cprime.colors[j] = cprime.colors[j], cprime.colors[i]
|
|
})
|
|
fmt.Printf("shuffled colors --> %v\n", cprime.colors)
|
|
return cprime
|
|
}
|
|
|
|
func (c *ArrayBackedColorCycle) Next() rl.Color {
|
|
color := c.colors[c.index]
|
|
c.index = (c.index + 1) % len(c.colors)
|
|
return color
|
|
}
|
|
|