diff --git a/tracker/derived.go b/tracker/derived.go index 9884347..457ce0e 100644 --- a/tracker/derived.go +++ b/tracker/derived.go @@ -14,11 +14,12 @@ type ( } Wire struct { - From int - FromSet bool - To Point - ToSet bool - Hint string + From int + FromSet bool + To Point + ToSet bool + Hint string + Highlight bool } RailError struct { @@ -68,6 +69,7 @@ func (m *Model) Wires(yield func(wire Wire) bool) { return } 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) { return } @@ -258,7 +260,7 @@ func (m *Model) updateRails() { m.derived.patch[i].rails[u] = Rail{ PassThrough: len(scratch), StackUse: stackUse, - Send: unit.Type == "send", + Send: !unit.Disabled && unit.Type == "send", } maxWidth = max(maxWidth, len(scratch)+max(len(stackUse.Inputs), stackUse.NumOutputs)) for range stackUse.NumOutputs { @@ -308,7 +310,7 @@ func (m *Model) updateWires() { } for i, instr := range m.d.Song.Patch { for u, unit := range instr.Units { - if unit.Type != "send" { + if unit.Disabled || unit.Type != "send" { continue } tI, tU, err := m.d.Song.Patch.FindUnit(unit.Parameters["target"]) diff --git a/tracker/gioui/knob.go b/tracker/gioui/knob.go index 9014d0b..c847268 100644 --- a/tracker/gioui/knob.go +++ b/tracker/gioui/knob.go @@ -82,12 +82,13 @@ type ( } SwitchWidget struct { - Theme *Theme - Value tracker.Parameter - State *KnobState - Style *SwitchStyle - Hint string - Scroll bool + Theme *Theme + Value tracker.Parameter + State *KnobState + Style *SwitchStyle + Hint string + Scroll bool + Disabled bool } ) @@ -141,8 +142,8 @@ func (s *KnobState) update(gtx C, param tracker.Parameter, scroll bool) { // Knob -func Knob(v tracker.Parameter, th *Theme, state *KnobState, hint string, scroll bool) KnobWidget { - return KnobWidget{ +func Knob(v tracker.Parameter, th *Theme, state *KnobState, hint string, scroll, disabled bool) KnobWidget { + ret := KnobWidget{ Theme: th, Value: v, State: state, @@ -150,6 +151,10 @@ func Knob(v tracker.Parameter, th *Theme, state *KnobState, hint string, scroll Hint: hint, Scroll: scroll, } + if disabled { + ret.Style = &th.DisabledKnob + } + return ret } func (k *KnobWidget) Layout(gtx C) D { @@ -248,14 +253,15 @@ func (k *KnobWidget) strokeIndicator(gtx C, amount float32) { // 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{ - Theme: th, - Value: v, - State: state, - Style: &th.Switch, - Hint: hint, - Scroll: scroll, + Theme: th, + Value: v, + State: state, + Style: &th.Switch, + Hint: hint, + Scroll: scroll, + Disabled: disabled, } } @@ -266,13 +272,13 @@ func (s *SwitchWidget) Layout(gtx C) D { var fg, bg color.NRGBA o := 0 switch { - case s.Value.Value() < 0: - fg = s.Style.Neg.Fg - bg = s.Style.Neg.Bg - case s.Value.Value() == 0: + case s.Disabled || s.Value.Value() == 0: fg = s.Style.Neutral.Fg bg = s.Style.Neutral.Bg 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: fg = s.Style.Pos.Fg bg = s.Style.Pos.Bg diff --git a/tracker/gioui/theme.go b/tracker/gioui/theme.go index cdaabda..9f8a21e 100644 --- a/tracker/gioui/theme.go +++ b/tracker/gioui/theme.go @@ -85,15 +85,16 @@ type Theme struct { } } UnitEditor struct { - Name LabelStyle - Chooser LabelStyle - Hint LabelStyle - WireColor color.NRGBA - WireHint LabelStyle - Width unit.Dp - Height unit.Dp - RackComment LabelStyle - UnitList struct { + Name LabelStyle + Chooser LabelStyle + Hint LabelStyle + WireColor color.NRGBA + WireHint LabelStyle + WireHighlight color.NRGBA + Width unit.Dp + Height unit.Dp + RackComment LabelStyle + UnitList struct { LabelWidth unit.Dp Name LabelStyle Disabled LabelStyle @@ -112,12 +113,13 @@ type Theme struct { Menu PopupStyle Dialog PopupStyle } - Split SplitStyle - ScrollBar ScrollBarStyle - Knob KnobStyle - Switch SwitchStyle - SignalRail SignalRailStyle - Port PortStyle + Split SplitStyle + ScrollBar ScrollBarStyle + Knob KnobStyle + DisabledKnob KnobStyle + Switch SwitchStyle + SignalRail SignalRailStyle + Port PortStyle // iconCache is used to cache the icons created from iconvg data iconCache map[*byte]*widget.Icon diff --git a/tracker/gioui/theme.yml b/tracker/gioui/theme.yml index f9c4bf3..4c89fdc 100644 --- a/tracker/gioui/theme.yml +++ b/tracker/gioui/theme.yml @@ -211,6 +211,7 @@ uniteditor: name: { textsize: 12, alignment: 2, color: *highemphasis, shadowcolor: *black } wirecolor: *secondarycolor + wirehighlight: *white wirehint: { textsize: 12, color: *disabled, shadowcolor: *black } width: 60 height: 70 @@ -230,6 +231,14 @@ knob: pos: { color: *primarycolor, bg: { r: 51, g: 36, b: 54, a: 255 } } neg: { color: *secondarycolor, bg: { r: 32, g: 55, b: 58, a: 255 } } 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: color: *secondarycolor signalwidth: 10 diff --git a/tracker/gioui/unit_editor.go b/tracker/gioui/unit_editor.go index 276e4e9..7e3f73f 100644 --- a/tracker/gioui/unit_editor.go +++ b/tracker/gioui/unit_editor.go @@ -3,6 +3,7 @@ package gioui import ( "bytes" "image" + "image/color" "io" "math" "time" @@ -247,7 +248,7 @@ func (pe *UnitEditor) layoutRack(gtx C) D { } 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) comment := t.Units().Item(y).Comment 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 op.Offset(image.Pt(-colP.Offset, -rowP.Offset)).Push(gtx.Ops).Pop() for wire := range t.Wires { + clr := t.Theme.UnitEditor.WireColor + if wire.Highlight { + clr = t.Theme.UnitEditor.WireHighlight + } switch { case wire.FromSet && !wire.ToSet: pe.drawRemoteSendSignal(gtx, wire, colP.First, rowP.First) 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: - 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) } -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 ey := wire.To.Y - row t := TrackerFromContext(gtx) @@ -328,7 +333,7 @@ func (pe *UnitEditor) drawRemoteReceiveSignal(gtx C, wire tracker.Wire, col, row path.Begin(gtx.Ops) path.MoveTo(from) path.CubeTo(c1, c2, to) - paint.FillShape(gtx.Ops, t.Theme.UnitEditor.WireColor, + paint.FillShape(gtx.Ops, clr, clip.Stroke{ Path: path.End(), 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) } -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 ex := wire.To.X - col 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.CubeTo(from.Add(fromTan), p1.Sub(p1Tan), p1) path.CubeTo(p1.Add(p1Tan), p2, to) - paint.FillShape(gtx.Ops, t.Theme.UnitEditor.WireColor, + paint.FillShape(gtx.Ops, clr, clip.Stroke{ Path: path.End(), Width: float32(gtx.Dp(t.Theme.SignalRail.LineWidth)), @@ -450,14 +455,16 @@ type ParameterStyle struct { State *ParameterState Theme *Theme 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{ Theme: th, State: paramWidget, Parameter: Parameter, Focus: focus, + Disabled: disabled, } } @@ -474,13 +481,19 @@ func (p ParameterStyle) Layout(gtx C) D { } switch p.Parameter.Type() { 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) 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) 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) } if _, ok := p.Parameter.Port(); ok { diff --git a/tracker/presets.go b/tracker/presets.go index d3674a3..94e0be6 100644 --- a/tracker/presets.go +++ b/tracker/presets.go @@ -76,7 +76,7 @@ var defaultUnits = map[string]sointu.Unit{ "in": {Type: "in", Parameters: map[string]int{"stereo": 1, "channel": 2}}, "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}}, - "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{}}, }