This commit is contained in:
5684185+vsariola@users.noreply.github.com
2025-07-08 14:50:56 +03:00
parent dec7322474
commit 3c66237fc7
6 changed files with 85 additions and 53 deletions

View File

@ -14,11 +14,12 @@ type (
} }
Wire struct { Wire struct {
From int From int
FromSet bool FromSet bool
To Point To Point
ToSet bool ToSet bool
Hint string Hint string
Highlight bool
} }
RailError struct { RailError struct {
@ -68,6 +69,7 @@ func (m *Model) Wires(yield func(wire Wire) bool) {
return return
} }
for _, wire := range m.derived.patch[i].wires { for _, wire := range m.derived.patch[i].wires {
wire.Highlight = (wire.FromSet && m.d.UnitIndex == wire.From) || (wire.ToSet && m.d.UnitIndex == wire.To.Y && m.d.ParamIndex == wire.To.X)
if !yield(wire) { if !yield(wire) {
return return
} }
@ -258,7 +260,7 @@ func (m *Model) updateRails() {
m.derived.patch[i].rails[u] = Rail{ m.derived.patch[i].rails[u] = Rail{
PassThrough: len(scratch), PassThrough: len(scratch),
StackUse: stackUse, StackUse: stackUse,
Send: unit.Type == "send", Send: !unit.Disabled && unit.Type == "send",
} }
maxWidth = max(maxWidth, len(scratch)+max(len(stackUse.Inputs), stackUse.NumOutputs)) maxWidth = max(maxWidth, len(scratch)+max(len(stackUse.Inputs), stackUse.NumOutputs))
for range stackUse.NumOutputs { for range stackUse.NumOutputs {
@ -308,7 +310,7 @@ func (m *Model) updateWires() {
} }
for i, instr := range m.d.Song.Patch { for i, instr := range m.d.Song.Patch {
for u, unit := range instr.Units { for u, unit := range instr.Units {
if unit.Type != "send" { if unit.Disabled || unit.Type != "send" {
continue continue
} }
tI, tU, err := m.d.Song.Patch.FindUnit(unit.Parameters["target"]) tI, tU, err := m.d.Song.Patch.FindUnit(unit.Parameters["target"])

View File

@ -82,12 +82,13 @@ type (
} }
SwitchWidget struct { SwitchWidget struct {
Theme *Theme Theme *Theme
Value tracker.Parameter Value tracker.Parameter
State *KnobState State *KnobState
Style *SwitchStyle Style *SwitchStyle
Hint string Hint string
Scroll bool Scroll bool
Disabled bool
} }
) )
@ -141,8 +142,8 @@ func (s *KnobState) update(gtx C, param tracker.Parameter, scroll bool) {
// Knob // Knob
func Knob(v tracker.Parameter, th *Theme, state *KnobState, hint string, scroll bool) KnobWidget { func Knob(v tracker.Parameter, th *Theme, state *KnobState, hint string, scroll, disabled bool) KnobWidget {
return KnobWidget{ ret := KnobWidget{
Theme: th, Theme: th,
Value: v, Value: v,
State: state, State: state,
@ -150,6 +151,10 @@ func Knob(v tracker.Parameter, th *Theme, state *KnobState, hint string, scroll
Hint: hint, Hint: hint,
Scroll: scroll, Scroll: scroll,
} }
if disabled {
ret.Style = &th.DisabledKnob
}
return ret
} }
func (k *KnobWidget) Layout(gtx C) D { func (k *KnobWidget) Layout(gtx C) D {
@ -248,14 +253,15 @@ func (k *KnobWidget) strokeIndicator(gtx C, amount float32) {
// Switch // Switch
func Switch(v tracker.Parameter, th *Theme, state *KnobState, hint string, scroll bool) SwitchWidget { func Switch(v tracker.Parameter, th *Theme, state *KnobState, hint string, scroll, disabled bool) SwitchWidget {
return SwitchWidget{ return SwitchWidget{
Theme: th, Theme: th,
Value: v, Value: v,
State: state, State: state,
Style: &th.Switch, Style: &th.Switch,
Hint: hint, Hint: hint,
Scroll: scroll, Scroll: scroll,
Disabled: disabled,
} }
} }
@ -266,13 +272,13 @@ func (s *SwitchWidget) Layout(gtx C) D {
var fg, bg color.NRGBA var fg, bg color.NRGBA
o := 0 o := 0
switch { switch {
case s.Value.Value() < 0: case s.Disabled || s.Value.Value() == 0:
fg = s.Style.Neg.Fg
bg = s.Style.Neg.Bg
case s.Value.Value() == 0:
fg = s.Style.Neutral.Fg fg = s.Style.Neutral.Fg
bg = s.Style.Neutral.Bg bg = s.Style.Neutral.Bg
o = gtx.Dp(s.Style.Outline) o = gtx.Dp(s.Style.Outline)
case s.Value.Value() < 0:
fg = s.Style.Neg.Fg
bg = s.Style.Neg.Bg
case s.Value.Value() > 0: case s.Value.Value() > 0:
fg = s.Style.Pos.Fg fg = s.Style.Pos.Fg
bg = s.Style.Pos.Bg bg = s.Style.Pos.Bg

View File

@ -85,15 +85,16 @@ type Theme struct {
} }
} }
UnitEditor struct { UnitEditor struct {
Name LabelStyle Name LabelStyle
Chooser LabelStyle Chooser LabelStyle
Hint LabelStyle Hint LabelStyle
WireColor color.NRGBA WireColor color.NRGBA
WireHint LabelStyle WireHint LabelStyle
Width unit.Dp WireHighlight color.NRGBA
Height unit.Dp Width unit.Dp
RackComment LabelStyle Height unit.Dp
UnitList struct { RackComment LabelStyle
UnitList struct {
LabelWidth unit.Dp LabelWidth unit.Dp
Name LabelStyle Name LabelStyle
Disabled LabelStyle Disabled LabelStyle
@ -112,12 +113,13 @@ type Theme struct {
Menu PopupStyle Menu PopupStyle
Dialog PopupStyle Dialog PopupStyle
} }
Split SplitStyle Split SplitStyle
ScrollBar ScrollBarStyle ScrollBar ScrollBarStyle
Knob KnobStyle Knob KnobStyle
Switch SwitchStyle DisabledKnob KnobStyle
SignalRail SignalRailStyle Switch SwitchStyle
Port PortStyle SignalRail SignalRailStyle
Port PortStyle
// iconCache is used to cache the icons created from iconvg data // iconCache is used to cache the icons created from iconvg data
iconCache map[*byte]*widget.Icon iconCache map[*byte]*widget.Icon

View File

@ -211,6 +211,7 @@ uniteditor:
name: name:
{ textsize: 12, alignment: 2, color: *highemphasis, shadowcolor: *black } { textsize: 12, alignment: 2, color: *highemphasis, shadowcolor: *black }
wirecolor: *secondarycolor wirecolor: *secondarycolor
wirehighlight: *white
wirehint: { textsize: 12, color: *disabled, shadowcolor: *black } wirehint: { textsize: 12, color: *disabled, shadowcolor: *black }
width: 60 width: 60
height: 70 height: 70
@ -230,6 +231,14 @@ knob:
pos: { color: *primarycolor, bg: { r: 51, g: 36, b: 54, a: 255 } } pos: { color: *primarycolor, bg: { r: 51, g: 36, b: 54, a: 255 } }
neg: { color: *secondarycolor, bg: { r: 32, g: 55, b: 58, a: 255 } } neg: { color: *secondarycolor, bg: { r: 32, g: 55, b: 58, a: 255 } }
indicator: { color: *white, width: 2, innerdiam: 24, outerdiam: 36 } indicator: { color: *white, width: 2, innerdiam: 24, outerdiam: 36 }
disabledknob:
diameter: 36
value: { textsize: 12, color: { r: 147, g: 143, b: 153, a: 255 }}
strokewidth: 4
bg: { r: 40, g: 40, b: 40, a: 255 }
pos: { color: { r: 147, g: 143, b: 153, a: 255 }, bg: { r: 54, g: 52, b: 59, a: 255 } }
neg: { color: { r: 147, g: 143, b: 153, a: 255 }, bg: { r: 54, g: 52, b: 59, a: 255 } }
indicator: { color: { r: 147, g: 143, b: 153, a: 255 }, width: 2, innerdiam: 24, outerdiam: 36 }
signalrail: signalrail:
color: *secondarycolor color: *secondarycolor
signalwidth: 10 signalwidth: 10

View File

@ -3,6 +3,7 @@ package gioui
import ( import (
"bytes" "bytes"
"image" "image"
"image/color"
"io" "io"
"math" "math"
"time" "time"
@ -247,7 +248,7 @@ func (pe *UnitEditor) layoutRack(gtx C) D {
} }
param := t.Model.Params().Item(point) param := t.Model.Params().Item(point)
paramStyle := t.ParamStyle(param, t.Theme, pe.Parameters[y][x], pe.paramTable.Table.Cursor() == point) paramStyle := t.ParamStyle(param, t.Theme, pe.Parameters[y][x], pe.paramTable.Table.Cursor() == point, t.Units().Item(y).Disabled)
paramStyle.Layout(gtx) paramStyle.Layout(gtx)
comment := t.Units().Item(y).Comment comment := t.Units().Item(y).Comment
if comment != "" && x == t.Model.Params().RowWidth(y) { if comment != "" && x == t.Model.Params().RowWidth(y) {
@ -281,13 +282,17 @@ func (pe *UnitEditor) drawSignals(gtx C, rowTitleWidth int) {
defer clip.Rect(image.Rectangle{Max: gtx.Constraints.Max}).Push(gtx.Ops).Pop() defer clip.Rect(image.Rectangle{Max: gtx.Constraints.Max}).Push(gtx.Ops).Pop()
defer op.Offset(image.Pt(-colP.Offset, -rowP.Offset)).Push(gtx.Ops).Pop() defer op.Offset(image.Pt(-colP.Offset, -rowP.Offset)).Push(gtx.Ops).Pop()
for wire := range t.Wires { for wire := range t.Wires {
clr := t.Theme.UnitEditor.WireColor
if wire.Highlight {
clr = t.Theme.UnitEditor.WireHighlight
}
switch { switch {
case wire.FromSet && !wire.ToSet: case wire.FromSet && !wire.ToSet:
pe.drawRemoteSendSignal(gtx, wire, colP.First, rowP.First) pe.drawRemoteSendSignal(gtx, wire, colP.First, rowP.First)
case !wire.FromSet && wire.ToSet: case !wire.FromSet && wire.ToSet:
pe.drawRemoteReceiveSignal(gtx, wire, colP.First, rowP.First) pe.drawRemoteReceiveSignal(gtx, wire, colP.First, rowP.First, clr)
case wire.FromSet && wire.ToSet: case wire.FromSet && wire.ToSet:
pe.drawSignal(gtx, wire, colP.First, rowP.First) pe.drawSignal(gtx, wire, colP.First, rowP.First, clr)
} }
} }
} }
@ -309,7 +314,7 @@ func (pe *UnitEditor) drawRemoteSendSignal(gtx C, wire tracker.Wire, col, row in
Label(t.Theme, &t.Theme.UnitEditor.WireHint, wire.Hint).Layout(gtx) Label(t.Theme, &t.Theme.UnitEditor.WireHint, wire.Hint).Layout(gtx)
} }
func (pe *UnitEditor) drawRemoteReceiveSignal(gtx C, wire tracker.Wire, col, row int) { func (pe *UnitEditor) drawRemoteReceiveSignal(gtx C, wire tracker.Wire, col, row int, clr color.NRGBA) {
ex := wire.To.X - col ex := wire.To.X - col
ey := wire.To.Y - row ey := wire.To.Y - row
t := TrackerFromContext(gtx) t := TrackerFromContext(gtx)
@ -328,7 +333,7 @@ func (pe *UnitEditor) drawRemoteReceiveSignal(gtx C, wire tracker.Wire, col, row
path.Begin(gtx.Ops) path.Begin(gtx.Ops)
path.MoveTo(from) path.MoveTo(from)
path.CubeTo(c1, c2, to) path.CubeTo(c1, c2, to)
paint.FillShape(gtx.Ops, t.Theme.UnitEditor.WireColor, paint.FillShape(gtx.Ops, clr,
clip.Stroke{ clip.Stroke{
Path: path.End(), Path: path.End(),
Width: float32(gtx.Dp(t.Theme.SignalRail.LineWidth)), Width: float32(gtx.Dp(t.Theme.SignalRail.LineWidth)),
@ -337,7 +342,7 @@ func (pe *UnitEditor) drawRemoteReceiveSignal(gtx C, wire tracker.Wire, col, row
Label(t.Theme, &t.Theme.UnitEditor.WireHint, wire.Hint).Layout(gtx) Label(t.Theme, &t.Theme.UnitEditor.WireHint, wire.Hint).Layout(gtx)
} }
func (pe *UnitEditor) drawSignal(gtx C, wire tracker.Wire, col, row int) { func (pe *UnitEditor) drawSignal(gtx C, wire tracker.Wire, col, row int, clr color.NRGBA) {
sy := wire.From - row sy := wire.From - row
ex := wire.To.X - col ex := wire.To.X - col
ey := wire.To.Y - row ey := wire.To.Y - row
@ -371,7 +376,7 @@ func (pe *UnitEditor) drawSignal(gtx C, wire tracker.Wire, col, row int) {
path.MoveTo(from) path.MoveTo(from)
path.CubeTo(from.Add(fromTan), p1.Sub(p1Tan), p1) path.CubeTo(from.Add(fromTan), p1.Sub(p1Tan), p1)
path.CubeTo(p1.Add(p1Tan), p2, to) path.CubeTo(p1.Add(p1Tan), p2, to)
paint.FillShape(gtx.Ops, t.Theme.UnitEditor.WireColor, paint.FillShape(gtx.Ops, clr,
clip.Stroke{ clip.Stroke{
Path: path.End(), Path: path.End(),
Width: float32(gtx.Dp(t.Theme.SignalRail.LineWidth)), Width: float32(gtx.Dp(t.Theme.SignalRail.LineWidth)),
@ -450,14 +455,16 @@ type ParameterStyle struct {
State *ParameterState State *ParameterState
Theme *Theme Theme *Theme
Focus bool Focus bool
Disabled bool
} }
func (t *Tracker) ParamStyle(Parameter tracker.Parameter, th *Theme, paramWidget *ParameterState, focus bool) ParameterStyle { func (t *Tracker) ParamStyle(Parameter tracker.Parameter, th *Theme, paramWidget *ParameterState, focus, disabled bool) ParameterStyle {
return ParameterStyle{ return ParameterStyle{
Theme: th, Theme: th,
State: paramWidget, State: paramWidget,
Parameter: Parameter, Parameter: Parameter,
Focus: focus, Focus: focus,
Disabled: disabled,
} }
} }
@ -474,13 +481,19 @@ func (p ParameterStyle) Layout(gtx C) D {
} }
switch p.Parameter.Type() { switch p.Parameter.Type() {
case tracker.IntegerParameter: case tracker.IntegerParameter:
k := Knob(p.Parameter, p.Theme, &p.State.knobState, p.Parameter.Hint().Label, p.Focus) k := Knob(p.Parameter, p.Theme, &p.State.knobState, p.Parameter.Hint().Label, p.Focus, p.Disabled)
return k.Layout(gtx) return k.Layout(gtx)
case tracker.BoolParameter: case tracker.BoolParameter:
s := Switch(p.Parameter, p.Theme, &p.State.knobState, p.Parameter.Hint().Label, p.Focus) s := Switch(p.Parameter, p.Theme, &p.State.knobState, p.Parameter.Hint().Label, p.Focus, p.Disabled)
return s.Layout(gtx) return s.Layout(gtx)
case tracker.IDParameter: case tracker.IDParameter:
btn := ActionBtn(t.ChooseSendSource(p.Parameter.UnitID()), t.Theme, &p.State.clickable, "Set", p.Parameter.Hint().Label) for p.State.clickable.Clicked(gtx) {
t.ChooseSendSource(p.Parameter.UnitID()).Do()
}
btn := Btn(t.Theme, &t.Theme.Button.Text, &p.State.clickable, "Set", p.Parameter.Hint().Label)
if p.Disabled {
btn.Style = &t.Theme.Button.Disabled
}
return btn.Layout(gtx) return btn.Layout(gtx)
} }
if _, ok := p.Parameter.Port(); ok { if _, ok := p.Parameter.Port(); ok {

View File

@ -76,7 +76,7 @@ var defaultUnits = map[string]sointu.Unit{
"in": {Type: "in", Parameters: map[string]int{"stereo": 1, "channel": 2}}, "in": {Type: "in", Parameters: map[string]int{"stereo": 1, "channel": 2}},
"speed": {Type: "speed", Parameters: map[string]int{}}, "speed": {Type: "speed", Parameters: map[string]int{}},
"compressor": {Type: "compressor", Parameters: map[string]int{"stereo": 0, "attack": 64, "release": 64, "invgain": 64, "threshold": 64, "ratio": 64}}, "compressor": {Type: "compressor", Parameters: map[string]int{"stereo": 0, "attack": 64, "release": 64, "invgain": 64, "threshold": 64, "ratio": 64}},
"send": {Type: "send", Parameters: map[string]int{"stereo": 0, "amount": 128, "voice": 0, "unit": 0, "port": 0, "sendpop": 1}}, "send": {Type: "send", Parameters: map[string]int{"stereo": 0, "amount": 64, "voice": 0, "unit": 0, "port": 0, "sendpop": 1}},
"sync": {Type: "sync", Parameters: map[string]int{}}, "sync": {Type: "sync", Parameters: map[string]int{}},
} }