mirror of
https://github.com/vsariola/sointu.git
synced 2025-11-12 04:46:13 -05:00
feat: add ability to disable units temporarily
Quite often the user wants to experiment what particular unit(s) add to the sound. This commit adds ability to disable any set of units temporarily, without actually deleting them. Ctrl-D disables and re-enables the units. Disabled units are considered non-existent in the patch. Closes #116.
This commit is contained in:
parent
2b3f6d8200
commit
17312bbe4e
@ -19,6 +19,7 @@ type (
|
||||
CommentExpanded Model
|
||||
NoteTracking Model
|
||||
UnitSearching Model
|
||||
UnitDisabled Model
|
||||
)
|
||||
|
||||
func (v Bool) Toggle() {
|
||||
@ -41,6 +42,7 @@ func (m *Model) Effect() *Effect { return (*Effect)(m) }
|
||||
func (m *Model) CommentExpanded() *CommentExpanded { return (*CommentExpanded)(m) }
|
||||
func (m *Model) NoteTracking() *NoteTracking { return (*NoteTracking)(m) }
|
||||
func (m *Model) UnitSearching() *UnitSearching { return (*UnitSearching)(m) }
|
||||
func (m *Model) UnitDisabled() *UnitDisabled { return (*UnitDisabled)(m) }
|
||||
|
||||
// Panic methods
|
||||
|
||||
@ -126,3 +128,36 @@ func (m *UnitSearching) setValue(val bool) {
|
||||
}
|
||||
}
|
||||
func (m *UnitSearching) Enabled() bool { return true }
|
||||
|
||||
// UnitDisabled methods
|
||||
|
||||
func (m *UnitDisabled) Bool() Bool { return Bool{m} }
|
||||
func (m *UnitDisabled) Value() bool {
|
||||
if m.d.InstrIndex < 0 || m.d.InstrIndex >= len(m.d.Song.Patch) {
|
||||
return false
|
||||
}
|
||||
if m.d.UnitIndex < 0 || m.d.UnitIndex >= len(m.d.Song.Patch[m.d.InstrIndex].Units) {
|
||||
return false
|
||||
}
|
||||
return m.d.Song.Patch[m.d.InstrIndex].Units[m.d.UnitIndex].Disabled
|
||||
}
|
||||
func (m *UnitDisabled) setValue(val bool) {
|
||||
if m.d.InstrIndex < 0 || m.d.InstrIndex >= len(m.d.Song.Patch) {
|
||||
return
|
||||
}
|
||||
l := ((*Model)(m)).Units().List()
|
||||
a, b := l.listRange()
|
||||
defer (*Model)(m).change("UnitDisabledSet", PatchChange, MajorChange)()
|
||||
for i := a; i <= b; i++ {
|
||||
m.d.Song.Patch[m.d.InstrIndex].Units[i].Disabled = val
|
||||
}
|
||||
}
|
||||
func (m *UnitDisabled) Enabled() bool {
|
||||
if m.d.InstrIndex < 0 || m.d.InstrIndex >= len(m.d.Song.Patch) {
|
||||
return false
|
||||
}
|
||||
if len(m.d.Song.Patch[m.d.InstrIndex].Units) == 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gioui.org/font"
|
||||
"gioui.org/io/clipboard"
|
||||
"gioui.org/io/key"
|
||||
"gioui.org/layout"
|
||||
@ -343,6 +344,7 @@ func (ie *InstrumentEditor) layoutUnitList(gtx C, t *Tracker) D {
|
||||
}
|
||||
u := units[i]
|
||||
var color color.NRGBA = white
|
||||
f := labelDefaultFont
|
||||
|
||||
var stackText string
|
||||
stackText = strconv.FormatInt(int64(u.StackAfter), 10)
|
||||
@ -353,6 +355,10 @@ func (ie *InstrumentEditor) layoutUnitList(gtx C, t *Tracker) D {
|
||||
color = warningColor
|
||||
(*tracker.Alerts)(t.Model).AddNamed("InstrumentLeavesSignals", fmt.Sprintf("Instrument leaves %v signal(s) on the stack", u.StackAfter), tracker.Warning)
|
||||
}
|
||||
if u.Disabled {
|
||||
color = disabledTextColor
|
||||
f.Style = font.Italic
|
||||
}
|
||||
|
||||
stackLabel := LabelStyle{Text: stackText, ShadeColor: black, Color: mediumEmphasisTextColor, Font: labelDefaultFont, FontSize: unit.Sp(12), Shaper: t.Theme.Shaper}
|
||||
rightMargin := layout.Inset{Right: unit.Dp(10)}
|
||||
@ -381,7 +387,7 @@ func (ie *InstrumentEditor) layoutUnitList(gtx C, t *Tracker) D {
|
||||
editor.Color = color
|
||||
editor.HintColor = instrumentNameHintColor
|
||||
editor.TextSize = unit.Sp(12)
|
||||
editor.Font = labelDefaultFont
|
||||
editor.Font = f
|
||||
|
||||
defer clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Push(gtx.Ops).Pop()
|
||||
key.InputOp{Tag: &ie.searchEditor, Keys: globalKeys}.Add(gtx.Ops)
|
||||
@ -399,7 +405,7 @@ func (ie *InstrumentEditor) layoutUnitList(gtx C, t *Tracker) D {
|
||||
}
|
||||
return ret
|
||||
} else {
|
||||
unitNameLabel := LabelStyle{Text: u.Type, ShadeColor: black, Color: color, Font: labelDefaultFont, FontSize: unit.Sp(12), Shaper: t.Theme.Shaper}
|
||||
unitNameLabel := LabelStyle{Text: u.Type, ShadeColor: black, Color: color, Font: f, FontSize: unit.Sp(12), Shaper: t.Theme.Shaper}
|
||||
if unitNameLabel.Text == "" {
|
||||
unitNameLabel.Text = "---"
|
||||
}
|
||||
|
||||
@ -64,6 +64,11 @@ func (t *Tracker) KeyEvent(e key.Event, o *op.Ops) {
|
||||
t.Model.Redo().Do()
|
||||
return
|
||||
}
|
||||
case "D":
|
||||
if e.Modifiers.Contain(key.ModShortcut) {
|
||||
t.Model.UnitDisabled().Bool().Toggle()
|
||||
return
|
||||
}
|
||||
case "N":
|
||||
if e.Modifiers.Contain(key.ModShortcut) {
|
||||
t.NewSong().Do()
|
||||
|
||||
@ -21,25 +21,27 @@ import (
|
||||
)
|
||||
|
||||
type UnitEditor struct {
|
||||
sliderList *DragList
|
||||
searchList *DragList
|
||||
Parameters []*ParameterWidget
|
||||
DeleteUnitBtn *ActionClickable
|
||||
CopyUnitBtn *TipClickable
|
||||
ClearUnitBtn *ActionClickable
|
||||
SelectTypeBtn *widget.Clickable
|
||||
tag bool
|
||||
caser cases.Caser
|
||||
sliderList *DragList
|
||||
searchList *DragList
|
||||
Parameters []*ParameterWidget
|
||||
DeleteUnitBtn *ActionClickable
|
||||
CopyUnitBtn *TipClickable
|
||||
ClearUnitBtn *ActionClickable
|
||||
DisableUnitBtn *BoolClickable
|
||||
SelectTypeBtn *widget.Clickable
|
||||
tag bool
|
||||
caser cases.Caser
|
||||
}
|
||||
|
||||
func NewUnitEditor(m *tracker.Model) *UnitEditor {
|
||||
ret := &UnitEditor{
|
||||
DeleteUnitBtn: NewActionClickable(m.DeleteUnit()),
|
||||
ClearUnitBtn: NewActionClickable(m.ClearUnit()),
|
||||
CopyUnitBtn: new(TipClickable),
|
||||
SelectTypeBtn: new(widget.Clickable),
|
||||
sliderList: NewDragList(m.Params().List(), layout.Vertical),
|
||||
searchList: NewDragList(m.SearchResults().List(), layout.Vertical),
|
||||
DeleteUnitBtn: NewActionClickable(m.DeleteUnit()),
|
||||
ClearUnitBtn: NewActionClickable(m.ClearUnit()),
|
||||
DisableUnitBtn: NewBoolClickable(m.UnitDisabled().Bool()),
|
||||
CopyUnitBtn: new(TipClickable),
|
||||
SelectTypeBtn: new(widget.Clickable),
|
||||
sliderList: NewDragList(m.Params().List(), layout.Vertical),
|
||||
searchList: NewDragList(m.SearchResults().List(), layout.Vertical),
|
||||
}
|
||||
ret.caser = cases.Title(language.English)
|
||||
return ret
|
||||
@ -114,6 +116,7 @@ func (pe *UnitEditor) layoutFooter(gtx C, t *Tracker) D {
|
||||
}
|
||||
copyUnitBtnStyle := TipIcon(t.Theme, pe.CopyUnitBtn, icons.ContentContentCopy, "Copy unit (Ctrl+C)")
|
||||
deleteUnitBtnStyle := ActionIcon(t.Theme, pe.DeleteUnitBtn, icons.ActionDelete, "Delete unit (Ctrl+Backspace)")
|
||||
disableUnitBtnStyle := ToggleIcon(t.Theme, pe.DisableUnitBtn, icons.AVVolumeUp, icons.AVVolumeOff, "Disable unit (Ctrl-D)", "Enable unit (Ctrl-D)")
|
||||
text := t.Units().SelectedType()
|
||||
if text == "" {
|
||||
text = "Choose unit type"
|
||||
@ -124,6 +127,7 @@ func (pe *UnitEditor) layoutFooter(gtx C, t *Tracker) D {
|
||||
return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
|
||||
layout.Rigid(deleteUnitBtnStyle.Layout),
|
||||
layout.Rigid(copyUnitBtnStyle.Layout),
|
||||
layout.Rigid(disableUnitBtnStyle.Layout),
|
||||
layout.Rigid(func(gtx C) D {
|
||||
var dims D
|
||||
if t.Units().SelectedType() != "" {
|
||||
|
||||
@ -34,6 +34,7 @@ type (
|
||||
|
||||
UnitListItem struct {
|
||||
Type string
|
||||
Disabled bool
|
||||
StackNeed, StackBefore, StackAfter int
|
||||
}
|
||||
|
||||
@ -323,7 +324,13 @@ func (v *Units) Iterate(yield UnitYieldFunc) {
|
||||
stackBefore := 0
|
||||
for _, unit := range v.d.Song.Patch[v.d.InstrIndex].Units {
|
||||
stackAfter := stackBefore + unit.StackChange()
|
||||
if !yield(UnitListItem{unit.Type, unit.StackNeed(), stackBefore, stackAfter}) {
|
||||
if !yield(UnitListItem{
|
||||
Type: unit.Type,
|
||||
Disabled: unit.Disabled,
|
||||
StackNeed: unit.StackNeed(),
|
||||
StackBefore: stackBefore,
|
||||
StackAfter: stackAfter,
|
||||
}) {
|
||||
break
|
||||
}
|
||||
stackBefore = stackAfter
|
||||
|
||||
Reference in New Issue
Block a user