mirror of
https://github.com/vsariola/sointu.git
synced 2025-07-22 15:04:36 -04:00
drafting
This commit is contained in:
parent
3c66237fc7
commit
9abb34e575
@ -536,6 +536,10 @@ func (m *Model) ChooseSendSource(id int) Action {
|
||||
}
|
||||
func (s ChooseSendSource) Do() {
|
||||
defer (*Model)(s.Model).change("ChooseSendSource", NoChange, MinorChange)()
|
||||
if s.Model.d.SendSource == s.ID {
|
||||
s.Model.d.SendSource = 0 // unselect
|
||||
return
|
||||
}
|
||||
s.Model.d.SendSource = s.ID
|
||||
}
|
||||
|
||||
|
@ -22,12 +22,33 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
KnobState struct {
|
||||
click gesture.Click
|
||||
ParamState struct {
|
||||
drag gesture.Drag
|
||||
dragStartPt f32.Point // used to calculate the drag amount
|
||||
dragStartVal int
|
||||
tipArea TipArea
|
||||
click gesture.Click
|
||||
clickable Clickable
|
||||
}
|
||||
|
||||
ParamWidget struct {
|
||||
Parameter tracker.Parameter
|
||||
State *ParamState
|
||||
Theme *Theme
|
||||
Focus bool
|
||||
Disabled bool
|
||||
}
|
||||
|
||||
PortStyle struct {
|
||||
Diameter unit.Dp
|
||||
StrokeWidth unit.Dp
|
||||
Color color.NRGBA
|
||||
}
|
||||
|
||||
PortWidget struct {
|
||||
Theme *Theme
|
||||
Style *PortStyle
|
||||
State *ParamState
|
||||
}
|
||||
|
||||
KnobStyle struct {
|
||||
@ -55,7 +76,7 @@ type (
|
||||
KnobWidget struct {
|
||||
Theme *Theme
|
||||
Value tracker.Parameter
|
||||
State *KnobState
|
||||
State *ParamState
|
||||
Style *KnobStyle
|
||||
Hint string
|
||||
Scroll bool
|
||||
@ -84,7 +105,7 @@ type (
|
||||
SwitchWidget struct {
|
||||
Theme *Theme
|
||||
Value tracker.Parameter
|
||||
State *KnobState
|
||||
State *ParamState
|
||||
Style *SwitchStyle
|
||||
Hint string
|
||||
Scroll bool
|
||||
@ -92,9 +113,58 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
// KnobState
|
||||
// ParamState
|
||||
|
||||
func (s *KnobState) update(gtx C, param tracker.Parameter, scroll bool) {
|
||||
func Param(Parameter tracker.Parameter, th *Theme, paramWidget *ParamState, focus, disabled bool) ParamWidget {
|
||||
return ParamWidget{
|
||||
Theme: th,
|
||||
State: paramWidget,
|
||||
Parameter: Parameter,
|
||||
Focus: focus,
|
||||
Disabled: disabled,
|
||||
}
|
||||
}
|
||||
|
||||
func (p ParamWidget) Layout(gtx C) D {
|
||||
title := Label(p.Theme, &p.Theme.UnitEditor.Name, p.Parameter.Name())
|
||||
t := TrackerFromContext(gtx)
|
||||
widget := func(gtx C) D {
|
||||
if port, ok := p.Parameter.Port(); t.IsChoosingSendTarget() && ok {
|
||||
for p.State.clickable.Clicked(gtx) {
|
||||
t.ChooseSendTarget(p.Parameter.UnitID(), port).Do()
|
||||
}
|
||||
k := Port(p.Theme, p.State)
|
||||
return k.Layout(gtx)
|
||||
}
|
||||
switch p.Parameter.Type() {
|
||||
case tracker.IntegerParameter:
|
||||
k := Knob(p.Parameter, p.Theme, p.State, p.Parameter.Hint().Label, p.Focus, p.Disabled)
|
||||
return k.Layout(gtx)
|
||||
case tracker.BoolParameter:
|
||||
s := Switch(p.Parameter, p.Theme, p.State, p.Parameter.Hint().Label, p.Focus, p.Disabled)
|
||||
return s.Layout(gtx)
|
||||
case tracker.IDParameter:
|
||||
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 {
|
||||
k := Port(p.Theme, p.State)
|
||||
return k.Layout(gtx)
|
||||
}
|
||||
return D{}
|
||||
}
|
||||
title.Layout(gtx)
|
||||
layout.Center.Layout(gtx, widget)
|
||||
return D{Size: image.Pt(gtx.Constraints.Max.X, gtx.Constraints.Max.Y)}
|
||||
}
|
||||
|
||||
func (s *ParamState) update(gtx C, param tracker.Parameter, scroll bool) {
|
||||
for {
|
||||
p, ok := s.drag.Update(gtx.Metric, gtx.Source, gesture.Both)
|
||||
if !ok {
|
||||
@ -140,9 +210,9 @@ func (s *KnobState) update(gtx C, param tracker.Parameter, scroll bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// Knob
|
||||
// KnobWidget
|
||||
|
||||
func Knob(v tracker.Parameter, th *Theme, state *KnobState, hint string, scroll, disabled bool) KnobWidget {
|
||||
func Knob(v tracker.Parameter, th *Theme, state *ParamState, hint string, scroll, disabled bool) KnobWidget {
|
||||
ret := KnobWidget{
|
||||
Theme: th,
|
||||
Value: v,
|
||||
@ -251,9 +321,9 @@ func (k *KnobWidget) strokeIndicator(gtx C, amount float32) {
|
||||
paint.FillShape(gtx.Ops, k.Style.Indicator.Color, s.Op(gtx.Ops))
|
||||
}
|
||||
|
||||
// Switch
|
||||
// SwitchWidget
|
||||
|
||||
func Switch(v tracker.Parameter, th *Theme, state *KnobState, hint string, scroll, disabled bool) SwitchWidget {
|
||||
func Switch(v tracker.Parameter, th *Theme, state *ParamState, hint string, scroll, disabled bool) SwitchWidget {
|
||||
return SwitchWidget{
|
||||
Theme: th,
|
||||
Value: v,
|
||||
@ -325,3 +395,34 @@ func (s *SwitchWidget) Layout(gtx C) D {
|
||||
w.Layout(gtx, bg)
|
||||
return D{Size: image.Pt(width, height)}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
func Port(t *Theme, p *ParamState) PortWidget {
|
||||
return PortWidget{Theme: t, Style: &t.Port, State: p}
|
||||
}
|
||||
|
||||
func (p *PortWidget) Layout(gtx C) D {
|
||||
return p.State.clickable.layout(p.State, gtx, func(gtx C) D {
|
||||
d := gtx.Dp(p.Style.Diameter)
|
||||
defer clip.Rect(image.Rectangle{Max: image.Pt(d, d)}).Push(gtx.Ops).Pop()
|
||||
p.strokeCircle(gtx)
|
||||
return D{Size: image.Pt(d, d)}
|
||||
})
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
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())
|
||||
}
|
@ -15,7 +15,7 @@ import (
|
||||
const maxSignalsDrawn = 16
|
||||
|
||||
type (
|
||||
SignalRailStyle struct {
|
||||
RailStyle struct {
|
||||
Color color.NRGBA
|
||||
LineWidth unit.Dp
|
||||
SignalWidth unit.Dp
|
||||
@ -23,22 +23,22 @@ type (
|
||||
PortColor color.NRGBA
|
||||
}
|
||||
|
||||
SignalRailWidget struct {
|
||||
Style *SignalRailStyle
|
||||
RailWidget struct {
|
||||
Style *RailStyle
|
||||
Signal tracker.Rail
|
||||
Height unit.Dp
|
||||
}
|
||||
)
|
||||
|
||||
func SignalRail(th *Theme, signal tracker.Rail) SignalRailWidget {
|
||||
return SignalRailWidget{
|
||||
func Rail(th *Theme, signal tracker.Rail) RailWidget {
|
||||
return RailWidget{
|
||||
Style: &th.SignalRail,
|
||||
Signal: signal,
|
||||
Height: th.UnitEditor.Height,
|
||||
}
|
||||
}
|
||||
|
||||
func (s SignalRailWidget) Layout(gtx C) D {
|
||||
func (s RailWidget) Layout(gtx C) D {
|
||||
sw := gtx.Dp(s.Style.SignalWidth)
|
||||
h := gtx.Dp(s.Height)
|
||||
if s.Signal.PassThrough == 0 && len(s.Signal.StackUse.Inputs) == 0 && s.Signal.StackUse.NumOutputs == 0 {
|
||||
|
@ -118,7 +118,7 @@ type Theme struct {
|
||||
Knob KnobStyle
|
||||
DisabledKnob KnobStyle
|
||||
Switch SwitchStyle
|
||||
SignalRail SignalRailStyle
|
||||
SignalRail RailStyle
|
||||
Port PortStyle
|
||||
|
||||
// iconCache is used to cache the icons created from iconvg data
|
||||
|
@ -26,7 +26,7 @@ type (
|
||||
UnitEditor struct {
|
||||
paramTable *ScrollTable
|
||||
searchList *DragList
|
||||
Parameters [][]*ParameterState
|
||||
Parameters [][]*ParamState
|
||||
DeleteUnitBtn *Clickable
|
||||
CopyUnitBtn *Clickable
|
||||
ClearUnitBtn *Clickable
|
||||
@ -140,7 +140,7 @@ func (pe *UnitEditor) update(gtx C, t *Tracker) {
|
||||
}
|
||||
c := t.Model.Params().Cursor()
|
||||
if c.X >= 0 && c.Y >= 0 && c.Y < len(pe.Parameters) && c.X < len(pe.Parameters[c.Y]) {
|
||||
ta := &pe.Parameters[c.Y][c.X].knobState.tipArea
|
||||
ta := &pe.Parameters[c.Y][c.X].tipArea
|
||||
ta.Appear(gtx.Now)
|
||||
ta.Exit.SetTarget(gtx.Now.Add(ta.ExitDuration))
|
||||
}
|
||||
@ -188,7 +188,7 @@ func (pe *UnitEditor) layoutRack(gtx C) D {
|
||||
// create enough parameter widget to match the number of parameters
|
||||
width := pe.paramTable.Table.Width()
|
||||
for len(pe.Parameters) < pe.paramTable.Table.Height() {
|
||||
pe.Parameters = append(pe.Parameters, make([]*ParameterState, 0))
|
||||
pe.Parameters = append(pe.Parameters, make([]*ParamState, 0))
|
||||
}
|
||||
cellWidth := gtx.Dp(t.Theme.UnitEditor.Width)
|
||||
cellHeight := gtx.Dp(t.Theme.UnitEditor.Height)
|
||||
@ -199,7 +199,7 @@ func (pe *UnitEditor) layoutRack(gtx C) D {
|
||||
columnTitleHeight := gtx.Dp(0)
|
||||
for i := range pe.Parameters {
|
||||
for len(pe.Parameters[i]) < width {
|
||||
pe.Parameters[i] = append(pe.Parameters[i], &ParameterState{knobState: KnobState{tipArea: TipArea{ExitDuration: time.Second * 2}}})
|
||||
pe.Parameters[i] = append(pe.Parameters[i], &ParamState{tipArea: TipArea{ExitDuration: time.Second * 2}})
|
||||
}
|
||||
}
|
||||
coltitle := func(gtx C, x int) D {
|
||||
@ -210,7 +210,7 @@ func (pe *UnitEditor) layoutRack(gtx C) D {
|
||||
return D{}
|
||||
}
|
||||
item := t.Units().Item(y)
|
||||
sr := SignalRail(t.Theme, item.Signals)
|
||||
sr := Rail(t.Theme, item.Signals)
|
||||
label := Label(t.Theme, &t.Theme.UnitEditor.UnitList.Name, item.Type)
|
||||
switch {
|
||||
case item.Disabled:
|
||||
@ -248,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, t.Units().Item(y).Disabled)
|
||||
paramStyle := Param(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) {
|
||||
@ -443,66 +443,3 @@ func (t *UnitEditor) Tags(level int, yield TagYieldFunc) bool {
|
||||
}
|
||||
return yield(level+1, t.paramTable.RowTitleList) && yield(level, t.paramTable) && yield(level+1, &t.commentEditor.widgetEditor)
|
||||
}
|
||||
|
||||
type ParameterState struct {
|
||||
knobState KnobState
|
||||
clickable Clickable
|
||||
portState PortState
|
||||
}
|
||||
|
||||
type ParameterStyle struct {
|
||||
Parameter tracker.Parameter
|
||||
State *ParameterState
|
||||
Theme *Theme
|
||||
Focus bool
|
||||
Disabled bool
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
func (p ParameterStyle) Layout(gtx C) D {
|
||||
title := Label(p.Theme, &p.Theme.UnitEditor.Name, p.Parameter.Name())
|
||||
t := TrackerFromContext(gtx)
|
||||
widget := func(gtx C) D {
|
||||
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:
|
||||
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, p.Disabled)
|
||||
return s.Layout(gtx)
|
||||
case tracker.IDParameter:
|
||||
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 {
|
||||
k := Port(p.Theme, &p.State.portState)
|
||||
return k.Layout(gtx)
|
||||
}
|
||||
return D{}
|
||||
}
|
||||
title.Layout(gtx)
|
||||
layout.Center.Layout(gtx, widget)
|
||||
return D{Size: image.Pt(gtx.Constraints.Max.X, gtx.Constraints.Max.Y)}
|
||||
}
|
||||
|
@ -1,21 +1,21 @@
|
||||
name: Clavi
|
||||
name: clavi
|
||||
numvoices: 1
|
||||
units:
|
||||
- type: envelope
|
||||
id: 1
|
||||
id: 225
|
||||
parameters: {attack: 0, decay: 62, gain: 77, release: 52, stereo: 1, sustain: 66}
|
||||
- type: oscillator
|
||||
id: 2
|
||||
id: 226
|
||||
parameters: {color: 64, detune: 68, gain: 67, looplength: 84, loopstart: 290, phase: 0, samplestart: 401297, shape: 90, stereo: 1, transpose: 76, type: 4, unison: 3}
|
||||
- type: mulp
|
||||
id: 3
|
||||
id: 227
|
||||
parameters: {stereo: 1}
|
||||
- type: pan
|
||||
id: 5
|
||||
parameters: {damp: 0, dry: 128, feedback: 96, notetracking: 2, panning: 64, pregain: 40, stereo: 1}
|
||||
id: 228
|
||||
parameters: {panning: 64, stereo: 1}
|
||||
- type: filter
|
||||
id: 1058
|
||||
parameters: {bandpass: -1, frequency: 96, highpass: -1, lowpass: 1, panning: 64, resonance: 128, stereo: 1}
|
||||
parameters: {bandpass: -1, frequency: 96, highpass: -1, lowpass: 1, resonance: 128, stereo: 1}
|
||||
- type: outaux
|
||||
id: 6
|
||||
parameters: {auxgain: 15, outgain: 54, panning: 64, stereo: 1}
|
||||
id: 1059
|
||||
parameters: {auxgain: 15, outgain: 54, stereo: 1}
|
||||
|
Reference in New Issue
Block a user