func drawMoon(canvas gxui.Canvas, center math.Point, radius float32) { c := 40 p := make(gxui.Polygon, c*2) for i := 0; i < c; i++ { frac := float32(i) / float32(c) α := math.Lerpf(math.Pi*1.2, math.Pi*-0.2, frac) p[i] = gxui.PolygonVertex{ Position: math.Point{ X: center.X + int(radius*math.Sinf(α)), Y: center.Y + int(radius*math.Cosf(α)), }, RoundedRadius: 0, } } for i := 0; i < c; i++ { frac := float32(i) / float32(c) α := math.Lerpf(math.Pi*-0.2, math.Pi*1.2, frac) r := math.Lerpf(radius, radius*0.5, math.Sinf(frac*math.Pi)) p[i+c] = gxui.PolygonVertex{ Position: math.Point{ X: center.X + int(r*math.Sinf(α)), Y: center.Y + int(r*math.Cosf(α)), }, RoundedRadius: 0, } } canvas.DrawPolygon(p, gxui.CreatePen(3, gxui.Gray80), gxui.CreateBrush(gxui.Gray40)) }
func (a *customAdapter) Create(theme gxui.Theme, index int) gxui.Control { phase := float32(index) / 1000 c := gxui.Color{ R: 0.5 + 0.5*math.Sinf(math.TwoPi*(phase+0.000)), G: 0.5 + 0.5*math.Sinf(math.TwoPi*(phase+0.333)), B: 0.5 + 0.5*math.Sinf(math.TwoPi*(phase+0.666)), A: 1.0, } i := theme.CreateImage() i.SetBackgroundBrush(gxui.CreateBrush(c)) i.SetMargin(math.Spacing{L: 3, T: 3, R: 3, B: 3}) i.OnMouseEnter(func(ev gxui.MouseEvent) { i.SetBorderPen(gxui.CreatePen(2, gxui.Gray80)) }) i.OnMouseExit(func(ev gxui.MouseEvent) { i.SetBorderPen(gxui.TransparentPen) }) i.OnMouseDown(func(ev gxui.MouseEvent) { i.SetBackgroundBrush(gxui.CreateBrush(c.MulRGB(0.7))) }) i.OnMouseUp(func(ev gxui.MouseEvent) { i.SetBackgroundBrush(gxui.CreateBrush(c)) }) return i }
func buildMoon(theme gxui.Theme, center math.Point, radius float32) gxui.Image { c := 40 p := make(gxui.Polygon, c*2) for i := 0; i < c; i++ { frac := float32(i) / float32(c) α := math.Lerpf(math.Pi*1.2, math.Pi*-0.2, frac) p[i] = gxui.PolygonVertex{ Position: math.Point{ X: center.X + int(radius*math.Sinf(α)), Y: center.Y + int(radius*math.Cosf(α)), }, RoundedRadius: 0, } } for i := 0; i < c; i++ { frac := float32(i) / float32(c) α := math.Lerpf(math.Pi*-0.2, math.Pi*1.2, frac) r := math.Lerpf(radius, radius*0.5, math.Sinf(frac*math.Pi)) p[i+c] = gxui.PolygonVertex{ Position: math.Point{ X: center.X + int(r*math.Sinf(α)), Y: center.Y + int(r*math.Cosf(α)), }, RoundedRadius: 0, } } image := theme.CreateImage() image.SetPolygon(p, gxui.CreatePen(3, gxui.Gray80), gxui.CreateBrush(gxui.Gray40)) return image }
func drawStar(canvas gxui.Canvas, center math.Point, radius, rotation float32, points int) { p := make(gxui.Polygon, points*2) for i := 0; i < points*2; i++ { frac := float32(i) / float32(points*2) α := frac*math.TwoPi + rotation r := []float32{radius, radius / 2}[i&1] p[i] = gxui.PolygonVertex{ Position: math.Point{ X: center.X + int(r*math.Cosf(α)), Y: center.Y + int(r*math.Sinf(α)), }, RoundedRadius: []float32{0, 50}[i&1], } } canvas.DrawPolygon(p, gxui.CreatePen(3, gxui.Red), gxui.CreateBrush(gxui.Yellow)) }
func buildStar(theme gxui.Theme, center math.Point, radius, rotation float32, points int) gxui.Image { p := make(gxui.Polygon, points*2) for i := 0; i < points*2; i++ { frac := float32(i) / float32(points*2) α := frac*math.TwoPi + rotation r := []float32{radius, radius / 2}[i&1] p[i] = gxui.PolygonVertex{ Position: math.Point{ X: center.X + int(r*math.Cosf(α)), Y: center.Y + int(r*math.Sinf(α)), }, RoundedRadius: []float32{0, 50}[i&1], } } image := theme.CreateImage() image.SetPolygon(p, gxui.CreatePen(3, gxui.Red), gxui.CreateBrush(gxui.Yellow)) return image }
func segment(penWidth, r float32, a, b, c math.Vec2, aIsLast bool, vsEdgePos []float32, fillEdge []math.Vec2) ([]float32, []math.Vec2) { ba, ca := a.Sub(b), a.Sub(c) baLen, caLen := ba.Len(), ca.Len() baDir, caDir := ba.DivS(baLen), ca.DivS(caLen) dp := baDir.Dot(caDir) if dp < -0.99999 { // Straight lines cause DBZs, special case inner := a.Sub(caDir.Tangent().MulS(penWidth)) vsEdgePos = appendVec2(vsEdgePos, a, inner) if fillEdge != nil /*&& i != 0*/ { fillEdge = append(fillEdge, inner) } return vsEdgePos, fillEdge } α := math.Acosf(dp) / 2 // ╔═══════════════════════════╦════════════════╗ // ║ ║ ║ // ║ A ║ ║ // ║ ╱:╲ ║ ║ // ║ ╱α:α╲ ║ A ║ // ║ ╱ : ╲ ║ |╲ ║ // ║ ╱ . d . ╲ ║ |α╲ ║ // ║ . : . ║ | ╲ ║ // ║ .P : Q. ║ | ╲ ║ // ║ ╱ X ╲ ║ | ╲ ║ // ║ ╱ . ┊ . ╲ ║ | ╲ ║ // ║ ╱ . r . ╲ ║ | ╲ ║ // ║ ╱ . ┊ . ╲ ║ |┐ β╲ ║ // ║ B ┊ C ║ P————————X ║ // ║ ║ ║ // ║ ^ ║ ║ // ║ ┊v ║ ║ // ║ ┊ u ║ ║ // ║ ┊—————> ║ ║ // ║ ║ ║ // ╚═══════════════════════════╩════════════════╝ v := baDir.Add(caDir).Normalize() u := v.Tangent() // // cos(2 • α) = dp // // cos⁻¹(dp) // α = ─────────── // 2 // // r // sin(α) = ─── // d // // r // d = ────── // sin(α) // d := r / math.Sinf(α) // X cannot be futher than half way along ab or ac dMax := math.Minf(baLen, caLen) / (2 * math.Cosf(α)) if d > dMax { // Adjust d and r to compensate d = dMax r = d * math.Sinf(α) } x := a.Sub(v.MulS(d)) convex := baDir.Tangent().Dot(caDir) <= 0 w := penWidth β := math.Pi/2 - α // Special case for convex vertices where the pen width is greater than // the rounding. Without dealing with this, we'd end up with the inner // vertices overlapping. Instead use a point calculated much the same as // x, but using the pen width. useFixedInnerPoint := convex && w > r fixedInnerPoint := a.Sub(v.MulS(math.Minf(w/math.Sinf(α), dMax))) // Concave vertices behave much the same as convex, but we have to flip // β as the sweep is reversed and w as we're extruding. if !convex { w, β = -w, -β } steps := 1 + int(d*α) if aIsLast { // No curvy edge required for the last vertex. // This is already done by the first vertex. steps = 1 } for j := 0; j < steps; j++ { γ := float32(0) if steps > 1 { γ = math.Lerpf(-β, β, float32(j)/float32(steps-1)) } dir := v.MulS(math.Cosf(γ)).Add(u.MulS(math.Sinf(γ))) va := x.Add(dir.MulS(r)) vb := va.Sub(dir.MulS(w)) if useFixedInnerPoint { vb = fixedInnerPoint } vsEdgePos = appendVec2(vsEdgePos, va, vb) if fillEdge != nil { fillEdge = append(fillEdge, vb) } } return vsEdgePos, fillEdge }