From 08dcbb9edbd62f1f7635182635d716848bd013ec Mon Sep 17 00:00:00 2001 From: vsariola <5684185+vsariola@users.noreply.github.com> Date: Sun, 17 Jan 2021 17:13:42 +0200 Subject: [PATCH] feat(tracker): add semitone & octave up/down buttons --- tracker/layout.go | 44 ++++++++++++++++++++++++++++++++------ tracker/tracker.go | 53 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 87 insertions(+), 10 deletions(-) diff --git a/tracker/layout.go b/tracker/layout.go index e8ec6f7..156f2e6 100644 --- a/tracker/layout.go +++ b/tracker/layout.go @@ -139,7 +139,40 @@ func (t *Tracker) layoutTracks(gtx layout.Context) layout.Dimensions { }.Op()) return layout.Dimensions{Size: gtx.Constraints.Min} } + + for t.AddSemitoneBtn.Clicked() { + t.AdjustSelectionPitch(1) + } + + for t.SubtractSemitoneBtn.Clicked() { + t.AdjustSelectionPitch(-1) + } + + for t.AddOctaveBtn.Clicked() { + t.AdjustSelectionPitch(12) + } + + for t.SubtractOctaveBtn.Clicked() { + t.AdjustSelectionPitch(-12) + } + menu := func(gtx C) D { + addSemitoneBtnStyle := material.Button(t.Theme, t.AddSemitoneBtn, "+1") + addSemitoneBtnStyle.Color = primaryColor + addSemitoneBtnStyle.Background = transparent + addSemitoneBtnStyle.Inset = layout.UniformInset(unit.Dp(6)) + subtractSemitoneBtnStyle := material.Button(t.Theme, t.SubtractSemitoneBtn, "-1") + subtractSemitoneBtnStyle.Color = primaryColor + subtractSemitoneBtnStyle.Background = transparent + subtractSemitoneBtnStyle.Inset = layout.UniformInset(unit.Dp(6)) + addOctaveBtnStyle := material.Button(t.Theme, t.AddOctaveBtn, "+12") + addOctaveBtnStyle.Color = primaryColor + addOctaveBtnStyle.Background = transparent + addOctaveBtnStyle.Inset = layout.UniformInset(unit.Dp(6)) + subtractOctaveBtnStyle := material.Button(t.Theme, t.SubtractOctaveBtn, "-12") + subtractOctaveBtnStyle.Color = primaryColor + subtractOctaveBtnStyle.Background = transparent + subtractOctaveBtnStyle.Inset = layout.UniformInset(unit.Dp(6)) newTrackBtnStyle := material.IconButton(t.Theme, t.NewTrackBtn, addIcon) newTrackBtnStyle.Background = transparent newTrackBtnStyle.Inset = layout.UniformInset(unit.Dp(6)) @@ -158,6 +191,11 @@ func (t *Tracker) layoutTracks(gtx layout.Context) layout.Dimensions { return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, layout.Rigid(Label("OCT:", white)), layout.Rigid(octave), + layout.Rigid(Label(" PITCH:", white)), + layout.Rigid(addSemitoneBtnStyle.Layout), + layout.Rigid(subtractSemitoneBtnStyle.Layout), + layout.Rigid(addOctaveBtnStyle.Layout), + layout.Rigid(subtractOctaveBtnStyle.Layout), layout.Flexed(1, func(gtx C) D { return layout.Dimensions{Size: gtx.Constraints.Min} }), layout.Rigid(newTrackBtnStyle.Layout)) } @@ -191,12 +229,6 @@ func (t *Tracker) layoutTracks(gtx layout.Context) layout.Dimensions { func (t *Tracker) layoutControls(gtx layout.Context) layout.Dimensions { go func() { - /*for t.BPMUpBtn.Clicked() { - t.ChangeBPM(1) - } - for t.BPMDownBtn.Clicked() { - t.ChangeBPM(-1) - }*/ for t.NewInstrumentBtn.Clicked() { t.AddInstrument() } diff --git a/tracker/tracker.go b/tracker/tracker.go index d62cd97..0c24854 100644 --- a/tracker/tracker.go +++ b/tracker/tracker.go @@ -33,6 +33,10 @@ type Tracker struct { NewInstrumentBtn *widget.Clickable LoadSongFileBtn *widget.Clickable NewSongFileBtn *widget.Clickable + AddSemitoneBtn *widget.Clickable + SubtractSemitoneBtn *widget.Clickable + AddOctaveBtn *widget.Clickable + SubtractOctaveBtn *widget.Clickable SongLength *NumberInput SaveSongFileBtn *widget.Clickable ParameterSliders []*widget.Float @@ -256,8 +260,7 @@ func (t *Tracker) SetSongLength(value int) { } } -func (t *Tracker) DeleteSelection() { - t.SaveUndo() +func (t *Tracker) getSelectionRange() (int, int, int, int) { r1 := t.Cursor.Pattern*t.song.PatternRows() + t.Cursor.Row r2 := t.SelectionCorner.Pattern*t.song.PatternRows() + t.SelectionCorner.Row if r2 < r1 { @@ -268,10 +271,48 @@ func (t *Tracker) DeleteSelection() { if t2 < t1 { t1, t2 = t2, t1 } - for r := r1; r <= r2; r++ { - for c := t1; c <= t2; c++ { + return r1, r2, t1, t2 +} + +func (t *Tracker) AdjustSelectionPitch(delta int) { + t.SaveUndo() + r1, r2, t1, t2 := t.getSelectionRange() + for c := t1; c <= t2; c++ { + adjustedNotes := map[struct { + Pat byte + Row int + }]bool{} + for r := r1; r <= r2; r++ { s := SongRow{Row: r} s.Wrap(t.song) + p := t.song.Tracks[c].Sequence[s.Pattern] + noteIndex := struct { + Pat byte + Row int + }{p, s.Row} + if !adjustedNotes[noteIndex] { + if val := t.song.Tracks[c].Patterns[p][s.Row]; val > 1 { + newVal := int(val) + delta + if newVal < 2 { + newVal = 2 + } else if newVal > 255 { + newVal = 255 + } + t.song.Tracks[c].Patterns[p][s.Row] = byte(newVal) + } + adjustedNotes[noteIndex] = true + } + } + } +} + +func (t *Tracker) DeleteSelection() { + t.SaveUndo() + r1, r2, t1, t2 := t.getSelectionRange() + for r := r1; r <= r2; r++ { + s := SongRow{Row: r} + s.Wrap(t.song) + for c := t1; c <= t2; c++ { p := t.song.Tracks[c].Sequence[s.Pattern] t.song.Tracks[c].Patterns[p][s.Row] = 1 } @@ -291,6 +332,10 @@ func New(audioContext sointu.AudioContext) *Tracker { NewSongFileBtn: new(widget.Clickable), LoadSongFileBtn: new(widget.Clickable), SaveSongFileBtn: new(widget.Clickable), + AddSemitoneBtn: new(widget.Clickable), + SubtractSemitoneBtn: new(widget.Clickable), + AddOctaveBtn: new(widget.Clickable), + SubtractOctaveBtn: new(widget.Clickable), setPlaying: make(chan bool), rowJump: make(chan int), patternJump: make(chan int),