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 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 depthToImage(img *image.RGBA, w int, h int, buffer []byte) { for y := 0; y < h; y++ { for x := 0; x < w; x++ { bits := (uint32(buffer[3]) << 24) | (uint32(buffer[2]) << 16) | (uint32(buffer[1]) << 8) | (uint32(buffer[0]) << 0) depth := gomath.Float32frombits(bits) buffer = buffer[4:] d := 0.01 / (1.0 - depth) c := color.RGBA{ R: byte(math.Cosf(d+math.TwoPi*0.000)*127.0 + 128.0), G: byte(math.Cosf(d+math.TwoPi*0.333)*127.0 + 128.0), B: byte(math.Cosf(d+math.TwoPi*0.666)*127.0 + 128.0), A: byte(0xFF), } img.Set(x, y, c) } } }
func appMain(driver gxui.Driver) { theme := flags.CreateTheme(driver) font, err := driver.CreateFont(gxfont.Default, 75) if err != nil { panic(err) } window := theme.CreateWindow(380, 100, "Hi") window.SetBackgroundBrush(gxui.CreateBrush(gxui.Gray50)) label := theme.CreateLabel() label.SetFont(font) label.SetText("Hello world") window.AddChild(label) ticker := time.NewTicker(time.Millisecond * 30) go func() { phase := float32(0) for _ = range ticker.C { c := gxui.Color{ R: 0.75 + 0.25*math.Cosf((phase+0.000)*math.TwoPi), G: 0.75 + 0.25*math.Cosf((phase+0.333)*math.TwoPi), B: 0.75 + 0.25*math.Cosf((phase+0.666)*math.TwoPi), A: 0.50 + 0.50*math.Cosf(phase*10), } phase += 0.01 driver.Call(func() { label.SetColor(c) }) } }() window.OnClose(ticker.Stop) window.OnClose(driver.Terminate) }
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 }
func appMain(driver gxui.Driver) { theme := flags.CreateTheme(driver) font, err := driver.CreateFont(gxfont.Default, 75) if err != nil { panic(err) } window := theme.CreateWindow(800, 480, "Привет") window.SetBackgroundBrush(gxui.CreateBrush(gxui.Gray50)) window.SetBorderPen(gxui.Pen{Width: 5, Color: gxui.Yellow}) f, err := os.Open("wallpaper.jpg") if err != nil { fmt.Printf("Failed to open image %v\n", err) os.Exit(1) } source, _, err := image.Decode(f) if err != nil { fmt.Printf("Failed to open image %v\n", err) os.Exit(2) } wallpaper := theme.CreateImage() window.AddChild(wallpaper) // Copy the image to a RGBA format before handing to a gxui.Texture rgba := image.NewRGBA(source.Bounds()) draw.Draw(rgba, source.Bounds(), source, image.ZP, draw.Src) texture := driver.CreateTexture(rgba, 1) wallpaper.SetTexture(texture) layout := theme.CreateLinearLayout() layout.SetDirection(gxui.TopToBottom) window.AddChild(layout) label := theme.CreateLabel() label.SetFont(font) label.SetText("Здравствуй мир") label.OnMouseMove(func(e gxui.MouseEvent) { fmt.Printf("X=%d; Y=%d\n", e.Point.X, e.Point.Y) }) layout.AddChild(label) lTimer := theme.CreateLabel() lTimer.SetFont(font) lTimer.SetColor(gxui.Green30) layout.AddChild(lTimer) button := theme.CreateButton() button.SetText("Exit") button.SetPadding(math.Spacing{20, 10, 20, 10}) button.SetMargin(math.Spacing{20, 10, 20, 10}) button.OnClick(func(e gxui.MouseEvent) { window.Close() }) layout.AddChild(button) ticker := time.NewTicker(time.Millisecond * 30) go func() { phase := float32(0) for _ = range ticker.C { c := gxui.Color{ R: 0.75 + 0.25*math.Cosf((phase+0.000)*math.TwoPi), G: 0.75 + 0.25*math.Cosf((phase+0.333)*math.TwoPi), B: 0.75 + 0.25*math.Cosf((phase+0.666)*math.TwoPi), A: 0.50 + 0.50*math.Cosf(phase*10), } phase += 0.01 driver.Call(func() { label.SetColor(c) }) } }() ticker2 := time.NewTicker(time.Millisecond * 100) go func() { for t := range ticker.C { driver.Call(func() { lTimer.SetText(t.Format(time.Stamp)) }) } }() window.OnClose(ticker.Stop) window.OnClose(ticker2.Stop) window.OnClose(driver.Terminate) }