Last active
April 28, 2022 03:15
-
-
Save DeadlySurgeon/82e881ab936a3a362beb2429384c0c3b to your computer and use it in GitHub Desktop.
SVG Dice Generator for Fusion Project
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"math" | |
"reflect" | |
"strings" | |
) | |
// COLORBLACK ... | |
const COLORBLACK = "black" | |
const dotSize = 1.5 | |
func main() { | |
height := 157.08 | |
width := 15.0 | |
b := &Body{ | |
Width: width, | |
Height: height, | |
XMLNS: "http://www.w3.org/2000/svg", | |
children: combine( | |
generateLines(2, height, 6), | |
generateDice(height, width, 6), | |
), | |
} | |
text := svgWriter(b, 0) | |
fmt.Println(text) | |
} | |
func combine[T any](d ...[]T) []T { | |
var data []T | |
for _, svgs := range d { | |
data = append(data, svgs...) | |
} | |
return data | |
} | |
// Shorthand rounding. | |
func r(x float64) float64 { return math.Round(x*100) / 100 } | |
// Potential Abstraction for later. | |
func hasChildren(svg SVG) bool { return len(svg.Children()) > 0 } | |
func svgStart(svg SVG, indent int) string { | |
s := strings.Repeat("\t", indent) + "<" + svg.Type() + " " + svgFields(svg) | |
if !hasChildren(svg) { | |
s += "/" | |
} | |
s += ">\n" | |
return s | |
} | |
func svgEnd(svg SVG, indent int) string { | |
if hasChildren(svg) { | |
return strings.Repeat("\t", indent) + "</" + svg.Type() + ">\n" | |
} | |
return "" | |
} | |
// svgWriter used for recursion | |
func svgWriter(svg SVG, indent int) string { | |
s := svgStart(svg, indent) | |
for _, child := range svg.Children() { | |
s += svgWriter(child, indent+1) | |
} | |
s += svgEnd(svg, indent) | |
return s | |
} | |
// SVG will allow us to do bullshit god this is dumb. | |
type SVG interface { | |
Type() string | |
Children() []SVG | |
} | |
// Body represents a svg body | |
type Body struct { | |
Width float64 `svg:"width" unit:"mm"` | |
Height float64 `svg:"height" unit:"mm"` | |
Fill string `svg:"fill"` | |
XMLNS string `svg:"xmlns"` | |
children []SVG | |
} | |
// Children ... | |
func (b *Body) Children() []SVG { return b.children } | |
//Type ... | |
func (b *Body) Type() string { return "svg" } | |
// Line ... | |
type Line struct { | |
X1 float64 `svg:"x1" unit:"mm"` | |
X2 float64 `svg:"x2" unit:"mm"` | |
Y1 float64 `svg:"y1" unit:"mm"` | |
Y2 float64 `svg:"y2" unit:"mm"` | |
Width float64 `svg:"stroke-width" unit:"mm"` | |
Stroke string `svg:"stroke"` | |
} | |
// Children ... | |
func (l *Line) Children() []SVG { return nil } | |
//Type ... | |
func (l *Line) Type() string { return "line" } | |
// Circle ... | |
type Circle struct { | |
CX float64 `svg:"cx" unit:"mm"` | |
CY float64 `svg:"cy" unit:"mm"` | |
Radius float64 `svg:"r" unit:"mm"` | |
Fill string `svg:"fill"` | |
Stroke string `svg:"stroke"` | |
} | |
// Children ... | |
func (c *Circle) Children() []SVG { return nil } | |
//Type ... | |
func (c *Circle) Type() string { return "circle" } | |
func svgFields(svg SVG) string { | |
var fields []string | |
v := reflect.ValueOf(svg) | |
if v.Kind() == reflect.Ptr { | |
v = v.Elem() | |
} | |
t := v.Type() | |
for i := 0; i < t.NumField(); i++ { | |
svgTag := t.Field(i).Tag.Get("svg") | |
if svgTag == "" { | |
continue | |
} | |
unit := t.Field(i).Tag.Get("unit") | |
f := v.Field(i) | |
if f.IsZero() { | |
continue | |
} | |
fields = append( | |
fields, | |
fmt.Sprintf( | |
"%s=\"%v%v\"", | |
svgTag, | |
f.Interface(), | |
unit, | |
), | |
) | |
} | |
// Lazy as fuck | |
return strings.Join(fields, " ") | |
} | |
func generateLines(thickness float64, size float64, amount int) []SVG { | |
var svgs []SVG | |
pad := size / float64(amount) | |
for i := 0.0; i <= float64(amount); i++ { | |
svgs = append( | |
svgs, | |
&Line{ | |
X1: 2, X2: 13, | |
Y1: r(pad * i), Y2: r(pad * i), | |
Width: thickness, Stroke: COLORBLACK, | |
}, | |
) | |
} | |
return svgs | |
} | |
/* | |
D = pos | |
157.08/6 == 26.18 * (D/100) | |
*/ | |
var dice = [][][]float64{ | |
{ | |
{50, 50}, | |
}, | |
{ | |
{25, 25}, | |
{75, 75}, | |
}, | |
{ | |
{25, 25}, | |
{50, 50}, | |
{75, 75}, | |
}, | |
{ | |
{25, 25}, | |
{25, 75}, | |
{75, 75}, | |
{75, 25}, | |
}, | |
{ | |
{25, 25}, | |
{25, 75}, | |
{50, 50}, | |
{75, 75}, | |
{75, 25}, | |
}, | |
{ | |
{25, 25}, | |
{25, 50}, | |
{25, 75}, | |
{75, 75}, | |
{75, 50}, | |
{75, 25}, | |
}, | |
} | |
func generateDice(height float64, width float64, amount int) []SVG { | |
var svgs []SVG | |
padHeight := height / float64(amount) | |
// Algs: | |
// Even with Height: r((float64(i) * padHeight) + (padHeight * (circle[1] / 100))) | |
// Scaled for Height | |
/* | |
firstPAD = i * padHeight | |
rPad = padHeight - width | |
circle[i] * width/100 | |
r((i * padHeight) + ((padHeight-width)/2) + (circle[1] * width/100)) | |
*/ | |
for i, dice := range dice { | |
for _, circle := range dice { | |
svgs = append(svgs, &Circle{ | |
CX: circle[0] * (width / 100), | |
CY: r((float64(i) * padHeight) + ((padHeight - width) / 2) + (circle[1] * width / 100)), | |
// TODO: | |
// - Bigger dot for less dots? | |
Radius: dotSize, | |
Stroke: COLORBLACK, | |
Fill: COLORBLACK, | |
}) | |
} | |
} | |
return svgs | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment