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 }