mirror of
https://github.com/vsariola/sointu.git
synced 2025-07-25 00:15:00 -04:00
drafting
This commit is contained in:
parent
4e295a3a2f
commit
3c6c24c6af
@ -93,6 +93,16 @@ type (
|
|||||||
*Model
|
*Model
|
||||||
}
|
}
|
||||||
ShowLicense Model
|
ShowLicense Model
|
||||||
|
|
||||||
|
ChooseSendSource struct {
|
||||||
|
ID int
|
||||||
|
*Model
|
||||||
|
}
|
||||||
|
ChooseSendTarget struct {
|
||||||
|
ID int
|
||||||
|
Port int
|
||||||
|
*Model
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Action methods
|
// Action methods
|
||||||
@ -517,6 +527,40 @@ func (d DeleteOrderRow) Do() {
|
|||||||
m.d.Cursor2.OrderRow = m.d.Cursor.OrderRow
|
m.d.Cursor2.OrderRow = m.d.Cursor.OrderRow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChooseSendSource
|
||||||
|
|
||||||
|
func (m *Model) IsChoosingSendTarget() bool {
|
||||||
|
return m.d.SendSource > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Model) ChooseSendSource(id int) Action {
|
||||||
|
return MakeEnabledAction(ChooseSendSource{ID: id, Model: m})
|
||||||
|
}
|
||||||
|
func (s ChooseSendSource) Do() {
|
||||||
|
defer (*Model)(s.Model).change("ChooseSendSource", NoChange, MinorChange)()
|
||||||
|
s.Model.d.SendSource = s.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChooseSendTarget
|
||||||
|
|
||||||
|
func (m *Model) ChooseSendTarget(id int, port int) Action {
|
||||||
|
return MakeEnabledAction(ChooseSendTarget{ID: id, Port: port, Model: m})
|
||||||
|
}
|
||||||
|
func (s ChooseSendTarget) Do() {
|
||||||
|
defer (*Model)(s.Model).change("ChooseSendTarget", SongChange, MinorChange)()
|
||||||
|
sourceID := (*Model)(s.Model).d.SendSource
|
||||||
|
s.d.SendSource = 0
|
||||||
|
if sourceID <= 0 || s.ID <= 0 || s.Port < 0 || s.Port > 7 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
si, su, err := s.d.Song.Patch.FindUnit(sourceID)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.d.Song.Patch[si].Units[su].Parameters["target"] = s.ID
|
||||||
|
s.d.Song.Patch[si].Units[su].Parameters["port"] = s.Port
|
||||||
|
}
|
||||||
|
|
||||||
// NewSong
|
// NewSong
|
||||||
|
|
||||||
func (m *Model) NewSong() Action { return MakeEnabledAction((*NewSong)(m)) }
|
func (m *Model) NewSong() Action { return MakeEnabledAction((*NewSong)(m)) }
|
||||||
|
@ -176,6 +176,7 @@ func (m *Model) deriveParams(unit *sointu.Unit) []Parameter {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
portIndex := 0
|
||||||
for i, up := range unitType {
|
for i, up := range unitType {
|
||||||
if !up.CanSet && !up.CanModulate {
|
if !up.CanSet && !up.CanModulate {
|
||||||
continue // skip parameters that cannot be set or modulated
|
continue // skip parameters that cannot be set or modulated
|
||||||
@ -186,7 +187,12 @@ func (m *Model) deriveParams(unit *sointu.Unit) []Parameter {
|
|||||||
if unit.Type == "send" && up.Name == "port" {
|
if unit.Type == "send" && up.Name == "port" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ret = append(ret, Parameter{m: m, unit: unit, up: &unitType[i], vtable: &namedParameter{}})
|
q := 0
|
||||||
|
if up.CanModulate {
|
||||||
|
portIndex++
|
||||||
|
q = portIndex
|
||||||
|
}
|
||||||
|
ret = append(ret, Parameter{m: m, unit: unit, up: &unitType[i], vtable: &namedParameter{}, port: q})
|
||||||
}
|
}
|
||||||
if unit.Type == "oscillator" && unit.Parameters["type"] == sointu.Sample {
|
if unit.Type == "oscillator" && unit.Parameters["type"] == sointu.Sample {
|
||||||
ret = append(ret, Parameter{m: m, unit: unit, vtable: &gmDlsEntryParameter{}})
|
ret = append(ret, Parameter{m: m, unit: unit, vtable: &gmDlsEntryParameter{}})
|
||||||
|
@ -149,15 +149,6 @@ func (k *KnobWidget) update(gtx C) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *KnobWidget) strokeBg(gtx C) {
|
|
||||||
diam := gtx.Dp(k.Style.Diameter)
|
|
||||||
circle := clip.Ellipse{
|
|
||||||
Min: image.Pt(0, 0),
|
|
||||||
Max: image.Pt(diam, diam),
|
|
||||||
}.Op(gtx.Ops)
|
|
||||||
paint.FillShape(gtx.Ops, k.Style.Bg, circle)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KnobWidget) strokeKnobArc(gtx C, color color.NRGBA, strokeWidth, diameter int, start, end float32) {
|
func (k *KnobWidget) strokeKnobArc(gtx C, color color.NRGBA, strokeWidth, diameter int, start, end float32) {
|
||||||
rad := float32(diameter) / 2
|
rad := float32(diameter) / 2
|
||||||
end = min(max(end, 0), 1)
|
end = min(max(end, 0), 1)
|
||||||
|
66
tracker/gioui/port.go
Normal file
66
tracker/gioui/port.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package gioui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
"image/color"
|
||||||
|
"math"
|
||||||
|
|
||||||
|
"gioui.org/f32"
|
||||||
|
"gioui.org/gesture"
|
||||||
|
"gioui.org/io/event"
|
||||||
|
"gioui.org/op/clip"
|
||||||
|
"gioui.org/op/paint"
|
||||||
|
"gioui.org/unit"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
PortState struct {
|
||||||
|
click gesture.Click
|
||||||
|
}
|
||||||
|
|
||||||
|
PortStyle struct {
|
||||||
|
Diameter unit.Dp
|
||||||
|
StrokeWidth unit.Dp
|
||||||
|
Color color.NRGBA
|
||||||
|
}
|
||||||
|
|
||||||
|
PortWidget struct {
|
||||||
|
Theme *Theme
|
||||||
|
Style *PortStyle
|
||||||
|
State *PortState
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func Port(t *Theme, p *PortState) PortWidget {
|
||||||
|
return PortWidget{Theme: t, Style: &t.Port, State: p}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PortWidget) Layout(gtx C) D {
|
||||||
|
d := gtx.Dp(p.Style.Diameter)
|
||||||
|
defer clip.Rect(image.Rectangle{Max: image.Pt(d, d)}).Push(gtx.Ops).Pop()
|
||||||
|
event.Op(gtx.Ops, p.State)
|
||||||
|
p.State.click.Add(gtx.Ops)
|
||||||
|
p.strokeCircle(gtx)
|
||||||
|
return D{Size: image.Pt(d, d)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PortState) Clicked(gtx C) bool {
|
||||||
|
ev, ok := p.click.Update(gtx.Source)
|
||||||
|
return ok && ev.Kind == gesture.KindClick
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PortWidget) strokeCircle(gtx C) {
|
||||||
|
sw := float32(gtx.Dp(p.Style.StrokeWidth))
|
||||||
|
d := float32(gtx.Dp(p.Style.Diameter))
|
||||||
|
rad := d / 2
|
||||||
|
center := f32.Point{X: rad, Y: rad}
|
||||||
|
var path clip.Path
|
||||||
|
path.Begin(gtx.Ops)
|
||||||
|
path.MoveTo(f32.Pt(sw/2, rad))
|
||||||
|
path.ArcTo(center, center, float32(math.Pi*2))
|
||||||
|
paint.FillShape(gtx.Ops, p.Style.Color,
|
||||||
|
clip.Stroke{
|
||||||
|
Path: path.End(),
|
||||||
|
Width: sw,
|
||||||
|
}.Op())
|
||||||
|
}
|
@ -85,16 +85,20 @@ type Theme struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
UnitEditor struct {
|
UnitEditor struct {
|
||||||
Name LabelStyle
|
Name LabelStyle
|
||||||
Chooser LabelStyle
|
Chooser LabelStyle
|
||||||
Hint LabelStyle
|
Hint LabelStyle
|
||||||
InvalidParam color.NRGBA
|
InvalidParam color.NRGBA
|
||||||
SendTarget color.NRGBA
|
SendTarget color.NRGBA
|
||||||
Width unit.Dp
|
Width unit.Dp
|
||||||
Height unit.Dp
|
Height unit.Dp
|
||||||
RowTitle LabelStyle
|
UnitList struct {
|
||||||
RowTitleWidth unit.Dp
|
LabelWidth unit.Dp
|
||||||
Error color.NRGBA
|
Name LabelStyle
|
||||||
|
Disabled LabelStyle
|
||||||
|
Error color.NRGBA
|
||||||
|
}
|
||||||
|
Error color.NRGBA
|
||||||
}
|
}
|
||||||
Cursor CursorStyle
|
Cursor CursorStyle
|
||||||
Selection CursorStyle
|
Selection CursorStyle
|
||||||
@ -110,6 +114,7 @@ type Theme struct {
|
|||||||
ScrollBar ScrollBarStyle
|
ScrollBar ScrollBarStyle
|
||||||
Knob KnobStyle
|
Knob KnobStyle
|
||||||
SignalRail SignalRailStyle
|
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
|
||||||
|
@ -214,9 +214,12 @@ uniteditor:
|
|||||||
sendtarget: *secondarycolor
|
sendtarget: *secondarycolor
|
||||||
width: 60
|
width: 60
|
||||||
height: 70
|
height: 70
|
||||||
rowtitle: { textsize: 12, color: *white, alignment: 2 }
|
unitlist:
|
||||||
rowtitlewidth: 16
|
labelwidth: 16
|
||||||
error: *errorcolor
|
name: { textsize: 12, color: *white, alignment: 2 }
|
||||||
|
disabled:
|
||||||
|
{ textsize: 12, color: *disabled, font: { style: 1 }, alignment: 2 }
|
||||||
|
error: *errorcolor
|
||||||
knob:
|
knob:
|
||||||
diameter: 36
|
diameter: 36
|
||||||
value: { textsize: 12, color: *highemphasis }
|
value: { textsize: 12, color: *highemphasis }
|
||||||
@ -231,3 +234,7 @@ signalrail:
|
|||||||
linewidth: 2
|
linewidth: 2
|
||||||
portdiameter: 8
|
portdiameter: 8
|
||||||
portcolor: *primarycolor
|
portcolor: *primarycolor
|
||||||
|
port:
|
||||||
|
diameter: 36
|
||||||
|
strokewidth: 4
|
||||||
|
color: *secondarycolor
|
||||||
|
@ -31,7 +31,7 @@ type (
|
|||||||
UnitEditor struct {
|
UnitEditor struct {
|
||||||
paramTable *ScrollTable
|
paramTable *ScrollTable
|
||||||
searchList *DragList
|
searchList *DragList
|
||||||
Parameters [][]*ParameterWidget
|
Parameters [][]*ParameterState
|
||||||
DeleteUnitBtn *Clickable
|
DeleteUnitBtn *Clickable
|
||||||
CopyUnitBtn *Clickable
|
CopyUnitBtn *Clickable
|
||||||
ClearUnitBtn *Clickable
|
ClearUnitBtn *Clickable
|
||||||
@ -157,18 +157,18 @@ func (pe *UnitEditor) layoutRack(gtx C) D {
|
|||||||
// create enough parameter widget to match the number of parameters
|
// create enough parameter widget to match the number of parameters
|
||||||
width := pe.paramTable.Table.Width()
|
width := pe.paramTable.Table.Width()
|
||||||
for len(pe.Parameters) < pe.paramTable.Table.Height() {
|
for len(pe.Parameters) < pe.paramTable.Table.Height() {
|
||||||
pe.Parameters = append(pe.Parameters, make([]*ParameterWidget, 0))
|
pe.Parameters = append(pe.Parameters, make([]*ParameterState, 0))
|
||||||
}
|
}
|
||||||
cellWidth := gtx.Dp(t.Theme.UnitEditor.Width)
|
cellWidth := gtx.Dp(t.Theme.UnitEditor.Width)
|
||||||
cellHeight := gtx.Dp(t.Theme.UnitEditor.Height)
|
cellHeight := gtx.Dp(t.Theme.UnitEditor.Height)
|
||||||
rowTitleLabelWidth := gtx.Dp(t.Theme.UnitEditor.RowTitleWidth)
|
rowTitleLabelWidth := gtx.Dp(t.Theme.UnitEditor.UnitList.LabelWidth)
|
||||||
rowTitleSignalWidth := gtx.Dp(t.Theme.SignalRail.SignalWidth) * t.SignalRail().MaxWidth()
|
rowTitleSignalWidth := gtx.Dp(t.Theme.SignalRail.SignalWidth) * t.SignalRail().MaxWidth()
|
||||||
rowTitleWidth := rowTitleLabelWidth + rowTitleSignalWidth
|
rowTitleWidth := rowTitleLabelWidth + rowTitleSignalWidth
|
||||||
signalError := t.SignalRail().Error()
|
signalError := t.SignalRail().Error()
|
||||||
columnTitleHeight := gtx.Dp(0)
|
columnTitleHeight := gtx.Dp(0)
|
||||||
for i := range pe.Parameters {
|
for i := range pe.Parameters {
|
||||||
for len(pe.Parameters[i]) < width {
|
for len(pe.Parameters[i]) < width {
|
||||||
pe.Parameters[i] = append(pe.Parameters[i], &ParameterWidget{})
|
pe.Parameters[i] = append(pe.Parameters[i], &ParameterState{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
coltitle := func(gtx C, x int) D {
|
coltitle := func(gtx C, x int) D {
|
||||||
@ -184,9 +184,12 @@ func (pe *UnitEditor) layoutRack(gtx C) D {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sr := SignalRail(t.Theme, t.SignalRail().Item(y))
|
sr := SignalRail(t.Theme, t.SignalRail().Item(y))
|
||||||
label := Label(t.Theme, &t.Theme.UnitEditor.RowTitle, t.Units().Item(y).Type)
|
label := Label(t.Theme, &t.Theme.UnitEditor.UnitList.Name, t.Units().Item(y).Type)
|
||||||
if signalError.Err != nil && signalError.UnitIndex == y {
|
switch {
|
||||||
label.Color = t.Theme.UnitEditor.Error
|
case t.Units().Item(y).Disabled:
|
||||||
|
label.LabelStyle = t.Theme.UnitEditor.UnitList.Disabled
|
||||||
|
case signalError.Err != nil && signalError.UnitIndex == y:
|
||||||
|
label.Color = t.Theme.UnitEditor.UnitList.Error
|
||||||
}
|
}
|
||||||
gtx.Constraints = layout.Exact(image.Pt(rowTitleWidth, cellHeight))
|
gtx.Constraints = layout.Exact(image.Pt(rowTitleWidth, cellHeight))
|
||||||
sr.Layout(gtx)
|
sr.Layout(gtx)
|
||||||
@ -210,10 +213,8 @@ func (pe *UnitEditor) layoutRack(gtx C) D {
|
|||||||
paint.FillShape(gtx.Ops, c, clip.Rect{Min: image.Pt(0, 0), Max: image.Pt(gtx.Constraints.Min.X, gtx.Constraints.Min.Y)}.Op())
|
paint.FillShape(gtx.Ops, c, clip.Rect{Min: image.Pt(0, 0), Max: image.Pt(gtx.Constraints.Min.X, gtx.Constraints.Min.Y)}.Op())
|
||||||
}
|
}
|
||||||
|
|
||||||
param := t.Model.Params().Item(tracker.Point{X: x, Y: y})
|
param := t.Model.Params().Item(point)
|
||||||
pe.Parameters[y][x].Parameter = param
|
paramStyle := t.ParamStyle(param, t.Theme, pe.Parameters[y][x], pe.paramTable.Table.Cursor() == point)
|
||||||
paramStyle := t.ParamStyle(t.Theme, pe.Parameters[y][x])
|
|
||||||
paramStyle.Focus = pe.paramTable.Table.Cursor() == tracker.Point{X: x, Y: y}
|
|
||||||
paramStyle.Layout(gtx)
|
paramStyle.Layout(gtx)
|
||||||
return D{Size: image.Pt(gtx.Constraints.Max.X, gtx.Constraints.Max.Y)}
|
return D{Size: image.Pt(gtx.Constraints.Max.X, gtx.Constraints.Max.Y)}
|
||||||
}
|
}
|
||||||
@ -351,63 +352,61 @@ func (t *UnitEditor) Tags(level int, yield TagYieldFunc) bool {
|
|||||||
return yield(level, widget) && yield(level+1, &t.commentEditor.widgetEditor)
|
return yield(level, widget) && yield(level+1, &t.commentEditor.widgetEditor)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ParameterWidget struct {
|
type ParameterState struct {
|
||||||
knobState KnobState
|
knobState KnobState
|
||||||
boolWidget widget.Bool
|
boolWidget widget.Bool
|
||||||
instrBtn Clickable
|
clickable Clickable
|
||||||
instrMenu MenuState
|
portState PortState
|
||||||
unitBtn Clickable
|
|
||||||
unitMenu MenuState
|
|
||||||
Parameter tracker.Parameter
|
|
||||||
tipArea TipArea
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ParameterStyle struct {
|
type ParameterStyle struct {
|
||||||
tracker *Tracker
|
Parameter tracker.Parameter
|
||||||
w *ParameterWidget
|
State *ParameterState
|
||||||
Theme *Theme
|
Theme *Theme
|
||||||
SendTargetTheme *material.Theme
|
Focus bool
|
||||||
Focus bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tracker) ParamStyle(th *Theme, paramWidget *ParameterWidget) ParameterStyle {
|
func (t *Tracker) ParamStyle(Parameter tracker.Parameter, th *Theme, paramWidget *ParameterState, focus bool) ParameterStyle {
|
||||||
sendTargetTheme := th.Material.WithPalette(material.Palette{
|
|
||||||
Bg: th.Material.Bg,
|
|
||||||
Fg: th.UnitEditor.SendTarget,
|
|
||||||
ContrastBg: th.Material.ContrastBg,
|
|
||||||
ContrastFg: th.Material.ContrastFg,
|
|
||||||
})
|
|
||||||
return ParameterStyle{
|
return ParameterStyle{
|
||||||
tracker: t, // TODO: we need this to pull the instrument names for ID style parameters, find out another way
|
Theme: th,
|
||||||
Theme: th,
|
State: paramWidget,
|
||||||
SendTargetTheme: &sendTargetTheme,
|
Parameter: Parameter,
|
||||||
w: paramWidget,
|
Focus: focus,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p ParameterStyle) Layout(gtx C) D {
|
func (p ParameterStyle) Layout(gtx C) D {
|
||||||
//_, _ := p.w.Parameter.Info()
|
//_, _ := p.w.Parameter.Info()
|
||||||
title := Label(p.Theme, &p.Theme.UnitEditor.Name, p.w.Parameter.Name())
|
title := Label(p.Theme, &p.Theme.UnitEditor.Name, p.Parameter.Name())
|
||||||
|
t := TrackerFromContext(gtx)
|
||||||
widget := func(gtx C) D {
|
widget := func(gtx C) D {
|
||||||
switch p.w.Parameter.Type() {
|
if port, ok := p.Parameter.Port(); t.IsChoosingSendTarget() && ok {
|
||||||
|
for p.State.portState.Clicked(gtx) {
|
||||||
|
t.ChooseSendTarget(p.Parameter.UnitID(), port).Do()
|
||||||
|
}
|
||||||
|
k := Port(p.Theme, &p.State.portState)
|
||||||
|
return k.Layout(gtx)
|
||||||
|
}
|
||||||
|
switch p.Parameter.Type() {
|
||||||
case tracker.IntegerParameter:
|
case tracker.IntegerParameter:
|
||||||
k := Knob(p.w.Parameter, p.Theme, &p.w.knobState, p.w.Parameter.Hint().Label, p.Focus)
|
k := Knob(p.Parameter, p.Theme, &p.State.knobState, p.Parameter.Hint().Label, p.Focus)
|
||||||
return k.Layout(gtx)
|
return k.Layout(gtx)
|
||||||
case tracker.BoolParameter:
|
case tracker.BoolParameter:
|
||||||
ra := p.w.Parameter.Range()
|
ra := p.Parameter.Range()
|
||||||
p.w.boolWidget.Value = p.w.Parameter.Value() > ra.Min
|
p.State.boolWidget.Value = p.Parameter.Value() > ra.Min
|
||||||
boolStyle := material.Switch(&p.Theme.Material, &p.w.boolWidget, "Toggle boolean parameter")
|
boolStyle := material.Switch(&p.Theme.Material, &p.State.boolWidget, "Toggle boolean parameter")
|
||||||
boolStyle.Color.Disabled = p.Theme.Material.Fg
|
boolStyle.Color.Disabled = p.Theme.Material.Fg
|
||||||
defer pointer.PassOp{}.Push(gtx.Ops).Pop()
|
defer pointer.PassOp{}.Push(gtx.Ops).Pop()
|
||||||
dims := layout.Center.Layout(gtx, boolStyle.Layout)
|
dims := layout.Center.Layout(gtx, boolStyle.Layout)
|
||||||
if p.w.boolWidget.Value {
|
if p.State.boolWidget.Value {
|
||||||
p.w.Parameter.SetValue(ra.Max)
|
p.Parameter.SetValue(ra.Max)
|
||||||
} else {
|
} else {
|
||||||
p.w.Parameter.SetValue(ra.Min)
|
p.Parameter.SetValue(ra.Min)
|
||||||
}
|
}
|
||||||
return dims
|
return dims
|
||||||
case tracker.IDParameter:
|
case tracker.IDParameter:
|
||||||
return drawCircle(gtx, gtx.Dp(p.Theme.Knob.Diameter), p.Theme.Knob.Pos.Bg)
|
btn := ActionBtn(t.ChooseSendSource(p.Parameter.UnitID()), t.Theme, &p.State.clickable, "Set", p.Parameter.Hint().Label)
|
||||||
|
return btn.Layout(gtx)
|
||||||
/*instrItems := make([]ActionMenuItem, p.tracker.Instruments().Count())
|
/*instrItems := make([]ActionMenuItem, p.tracker.Instruments().Count())
|
||||||
for i := range instrItems {
|
for i := range instrItems {
|
||||||
i := i
|
i := i
|
||||||
@ -449,6 +448,10 @@ func (p ParameterStyle) Layout(gtx C) D {
|
|||||||
}),
|
}),
|
||||||
)*/
|
)*/
|
||||||
}
|
}
|
||||||
|
if _, ok := p.Parameter.Port(); ok {
|
||||||
|
k := Port(p.Theme, &p.State.portState)
|
||||||
|
return k.Layout(gtx)
|
||||||
|
}
|
||||||
return D{}
|
return D{}
|
||||||
}
|
}
|
||||||
title.Layout(gtx)
|
title.Layout(gtx)
|
||||||
|
@ -240,6 +240,7 @@ func (m *Model) change(kind string, t ChangeType, severity ChangeSeverity) func(
|
|||||||
m.d.UnitIndex2 = clamp(m.d.UnitIndex2, 0, unitCount-1)
|
m.d.UnitIndex2 = clamp(m.d.UnitIndex2, 0, unitCount-1)
|
||||||
m.d.UnitSearching = false // if we change anything in the patch, reset the unit searching
|
m.d.UnitSearching = false // if we change anything in the patch, reset the unit searching
|
||||||
m.d.UnitSearchString = ""
|
m.d.UnitSearchString = ""
|
||||||
|
m.d.SendSource = 0
|
||||||
m.updateDerivedPatchData()
|
m.updateDerivedPatchData()
|
||||||
TrySend(m.broker.ToPlayer, any(m.d.Song.Patch.Copy()))
|
TrySend(m.broker.ToPlayer, any(m.d.Song.Patch.Copy()))
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ type (
|
|||||||
up *sointu.UnitParameter
|
up *sointu.UnitParameter
|
||||||
index int
|
index int
|
||||||
vtable parameterVtable
|
vtable parameterVtable
|
||||||
|
port int
|
||||||
}
|
}
|
||||||
|
|
||||||
parameterVtable interface {
|
parameterVtable interface {
|
||||||
@ -70,6 +71,12 @@ func (p *Parameter) Value() int {
|
|||||||
}
|
}
|
||||||
return p.vtable.Value(p)
|
return p.vtable.Value(p)
|
||||||
}
|
}
|
||||||
|
func (p *Parameter) Port() (int, bool) {
|
||||||
|
if p.port <= 0 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return p.port - 1, true
|
||||||
|
}
|
||||||
func (p *Parameter) SetValue(value int) bool {
|
func (p *Parameter) SetValue(value int) bool {
|
||||||
if p.vtable == nil {
|
if p.vtable == nil {
|
||||||
return false
|
return false
|
||||||
@ -123,6 +130,12 @@ func (p *Parameter) Reset() {
|
|||||||
}
|
}
|
||||||
p.vtable.Reset(p)
|
p.vtable.Reset(p)
|
||||||
}
|
}
|
||||||
|
func (p *Parameter) UnitID() int {
|
||||||
|
if p.unit == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return p.unit.ID
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
@ -212,6 +225,9 @@ func (n *namedParameter) Range(p *Parameter) IntRange {
|
|||||||
return IntRange{Min: p.up.MinValue, Max: p.up.MaxValue}
|
return IntRange{Min: p.up.MinValue, Max: p.up.MaxValue}
|
||||||
}
|
}
|
||||||
func (n *namedParameter) Type(p *Parameter) ParameterType {
|
func (n *namedParameter) Type(p *Parameter) ParameterType {
|
||||||
|
if p.up == nil || !p.up.CanSet {
|
||||||
|
return NoParameter
|
||||||
|
}
|
||||||
if p.unit.Type == "send" && p.up.Name == "target" {
|
if p.unit.Type == "send" && p.up.Name == "target" {
|
||||||
return IDParameter
|
return IDParameter
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user