This commit is contained in:
5684185+vsariola@users.noreply.github.com
2025-07-03 18:54:02 +03:00
parent c09a3f04db
commit 4e295a3a2f
8 changed files with 206 additions and 112 deletions

View File

@ -12,12 +12,13 @@ import (
"github.com/vsariola/sointu/tracker"
)
const numSignalsDrawn = 8
const maxSignalsDrawn = 16
type (
SignalRailStyle struct {
Color color.NRGBA
LineWidth unit.Dp
SignalWidth unit.Dp
PortDiameter unit.Dp
PortColor color.NRGBA
}
@ -25,7 +26,6 @@ type (
SignalRailWidget struct {
Style *SignalRailStyle
Signal tracker.Signal
Width unit.Dp
Height unit.Dp
}
)
@ -34,63 +34,69 @@ func SignalRail(th *Theme, signal tracker.Signal) SignalRailWidget {
return SignalRailWidget{
Style: &th.SignalRail,
Signal: signal,
Width: th.UnitEditor.Width,
Height: th.UnitEditor.Height,
}
}
func (s SignalRailWidget) Layout(gtx C) D {
w := gtx.Dp(s.Width)
sw := gtx.Dp(s.Style.SignalWidth)
h := gtx.Dp(s.Height)
l := gtx.Dp(s.Style.LineWidth)
d := gtx.Dp(s.Style.PortDiameter)
c := max(l, d) / 2
stride := (w - c*2) / numSignalsDrawn
lw := gtx.Dp(s.Style.LineWidth)
pd := gtx.Dp(s.Style.PortDiameter)
center := sw / 2
var path clip.Path
path.Begin(gtx.Ops)
// Draw pass through signals
for i := range min(numSignalsDrawn, s.Signal.PassThrough) {
x := float32(i*stride + c)
for i := range min(maxSignalsDrawn, s.Signal.PassThrough) {
x := float32(i*sw + center)
path.MoveTo(f32.Pt(x, 0))
path.LineTo(f32.Pt(x, float32(h)))
}
// Draw the routing of input signals
for i := range min(len(s.Signal.StackUse.Inputs), numSignalsDrawn-s.Signal.PassThrough) {
for i := range min(len(s.Signal.StackUse.Inputs), maxSignalsDrawn-s.Signal.PassThrough) {
input := s.Signal.StackUse.Inputs[i]
x1 := float32((i+s.Signal.PassThrough)*stride + c)
x1 := float32((i+s.Signal.PassThrough)*sw + center)
for _, link := range input {
x2 := float32((link+s.Signal.PassThrough)*stride + c)
x2 := float32((link+s.Signal.PassThrough)*sw + center)
path.MoveTo(f32.Pt(x1, 0))
path.LineTo(f32.Pt(x2, float32(h/2)))
}
}
if s.Signal.Send {
for i := range min(len(s.Signal.StackUse.Inputs), maxSignalsDrawn-s.Signal.PassThrough) {
from := f32.Pt(float32((i+s.Signal.PassThrough)*sw+center), float32(h/2))
to := f32.Pt(float32(gtx.Constraints.Max.X), float32(h)-float32(sw/2))
ctrl := f32.Pt(from.X, to.Y)
path.MoveTo(from)
path.QuadTo(ctrl, to)
}
}
// Draw the routing of output signals
for i := range min(s.Signal.StackUse.NumOutputs, numSignalsDrawn-s.Signal.PassThrough) {
x := float32((i+s.Signal.PassThrough)*stride + c)
for i := range min(s.Signal.StackUse.NumOutputs, maxSignalsDrawn-s.Signal.PassThrough) {
x := float32((i+s.Signal.PassThrough)*sw + center)
path.MoveTo(f32.Pt(x, float32(h/2)))
path.LineTo(f32.Pt(x, float32(h)))
}
// Signal paths finished
paint.FillShape(gtx.Ops, s.Style.Color,
clip.Stroke{
Path: path.End(),
Width: float32(l),
Width: float32(lw),
}.Op())
// Draw the circles on modified signals
for i := range min(len(s.Signal.StackUse.Modifies), numSignalsDrawn-s.Signal.PassThrough) {
// Draw the circles on signals that get modified
var circle clip.Path
circle.Begin(gtx.Ops)
for i := range min(len(s.Signal.StackUse.Modifies), maxSignalsDrawn-s.Signal.PassThrough) {
if !s.Signal.StackUse.Modifies[i] {
continue
}
var circle clip.Path
x := float32((i + s.Signal.PassThrough) * stride)
circle.Begin(gtx.Ops)
circle.MoveTo(f32.Pt(x, float32(h/2)))
f := f32.Pt(x+float32(c), float32(h/2))
f := f32.Pt(float32((i+s.Signal.PassThrough)*sw+center), float32(h/2))
circle.MoveTo(f32.Pt(f.X-float32(pd/2), float32(h/2)))
circle.ArcTo(f, f, float32(2*math.Pi))
p := clip.Outline{Path: circle.End()}.Op().Push(gtx.Ops)
paint.ColorOp{Color: s.Style.PortColor}.Add(gtx.Ops)
paint.PaintOp{}.Add(gtx.Ops)
p.Pop()
}
return D{Size: image.Pt(w, h)}
p := clip.Outline{Path: circle.End()}.Op().Push(gtx.Ops)
paint.ColorOp{Color: s.Style.PortColor}.Add(gtx.Ops)
paint.PaintOp{}.Add(gtx.Ops)
p.Pop()
return D{Size: image.Pt(sw, h)}
}