mirror of
https://github.com/vsariola/sointu.git
synced 2025-07-22 23:14:59 -04:00
drafting
This commit is contained in:
parent
8415660416
commit
ec8c51b003
@ -2,6 +2,7 @@ package gioui
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"math"
|
||||
|
||||
"gioui.org/f32"
|
||||
@ -15,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
Oscilloscope struct {
|
||||
OscilloscopeState struct {
|
||||
onceBtn *BoolClickable
|
||||
wrapBtn *BoolClickable
|
||||
lengthInBeatsNumber *NumberInput
|
||||
@ -29,14 +30,21 @@ type (
|
||||
}
|
||||
|
||||
OscilloscopeStyle struct {
|
||||
Oscilloscope *Oscilloscope
|
||||
Wave tracker.RingBuffer[[2]float32]
|
||||
Theme *Theme
|
||||
CurveColors [2]color.NRGBA `yaml:",flow"`
|
||||
LimitColor color.NRGBA `yaml:",flow"`
|
||||
CursorColor color.NRGBA `yaml:",flow"`
|
||||
}
|
||||
|
||||
Oscilloscope struct {
|
||||
State *OscilloscopeState
|
||||
Wave tracker.RingBuffer[[2]float32]
|
||||
Theme *Theme
|
||||
OscilloscopeStyle
|
||||
}
|
||||
)
|
||||
|
||||
func NewOscilloscope(model *tracker.Model) *Oscilloscope {
|
||||
return &Oscilloscope{
|
||||
func NewOscilloscope(model *tracker.Model) *OscilloscopeState {
|
||||
return &OscilloscopeState{
|
||||
onceBtn: NewBoolClickable(model.SignalAnalyzer().Once().Bool()),
|
||||
wrapBtn: NewBoolClickable(model.SignalAnalyzer().Wrap().Bool()),
|
||||
lengthInBeatsNumber: NewNumberInput(model.SignalAnalyzer().LengthInBeats().Int()),
|
||||
@ -44,15 +52,15 @@ func NewOscilloscope(model *tracker.Model) *Oscilloscope {
|
||||
}
|
||||
}
|
||||
|
||||
func LineOscilloscope(s *Oscilloscope, wave tracker.RingBuffer[[2]float32], th *Theme) *OscilloscopeStyle {
|
||||
return &OscilloscopeStyle{Oscilloscope: s, Wave: wave, Theme: th}
|
||||
func Scope(s *OscilloscopeState, wave tracker.RingBuffer[[2]float32], th *Theme) *Oscilloscope {
|
||||
return &Oscilloscope{State: s, Wave: wave, Theme: th}
|
||||
}
|
||||
|
||||
func (s *OscilloscopeStyle) Layout(gtx C) D {
|
||||
wrapBtnStyle := ToggleButton(gtx, &s.Theme.Material, s.Oscilloscope.wrapBtn, "Wrap")
|
||||
onceBtnStyle := ToggleButton(gtx, &s.Theme.Material, s.Oscilloscope.onceBtn, "Once")
|
||||
triggerChannelStyle := NumericUpDown(&s.Theme.Material, s.Oscilloscope.triggerChannelNumber, "Trigger channel")
|
||||
lengthNumberStyle := NumericUpDown(&s.Theme.Material, s.Oscilloscope.lengthInBeatsNumber, "Buffer length in beats")
|
||||
func (s *Oscilloscope) Layout(gtx C) D {
|
||||
wrapBtnStyle := ToggleButton(gtx, s.Theme, s.State.wrapBtn, "Wrap")
|
||||
onceBtnStyle := ToggleButton(gtx, s.Theme, s.State.onceBtn, "Once")
|
||||
triggerChannelStyle := NumUpDown(s.Theme, s.State.triggerChannelNumber, "Trigger channel")
|
||||
lengthNumberStyle := NumUpDown(s.Theme, s.State.lengthInBeatsNumber, "Buffer length in beats")
|
||||
|
||||
leftSpacer := layout.Spacer{Width: unit.Dp(6), Height: unit.Dp(24)}.Layout
|
||||
rightSpacer := layout.Spacer{Width: unit.Dp(6)}.Layout
|
||||
@ -82,13 +90,13 @@ func (s *OscilloscopeStyle) Layout(gtx C) D {
|
||||
)
|
||||
}
|
||||
|
||||
func (s *OscilloscopeStyle) layoutWave(gtx C) D {
|
||||
func (s *Oscilloscope) layoutWave(gtx C) D {
|
||||
s.update(gtx)
|
||||
if gtx.Constraints.Max.X == 0 || gtx.Constraints.Max.Y == 0 {
|
||||
return D{}
|
||||
}
|
||||
defer clip.Rect(image.Rectangle{Max: gtx.Constraints.Max}).Push(gtx.Ops).Pop()
|
||||
event.Op(gtx.Ops, s.Oscilloscope)
|
||||
event.Op(gtx.Ops, s.State)
|
||||
paint.ColorOp{Color: s.Theme.Oscilloscope.CursorColor}.Add(gtx.Ops)
|
||||
cursorX := int(s.sampleToPx(gtx, float32(s.Wave.Cursor)))
|
||||
fillRect(gtx, clip.Rect{Min: image.Pt(cursorX, 0), Max: image.Pt(cursorX+1, gtx.Constraints.Max.Y)})
|
||||
@ -134,10 +142,10 @@ func fillRect(gtx C, rect clip.Rect) {
|
||||
stack.Pop()
|
||||
}
|
||||
|
||||
func (o *OscilloscopeStyle) update(gtx C) {
|
||||
func (o *Oscilloscope) update(gtx C) {
|
||||
for {
|
||||
ev, ok := gtx.Event(pointer.Filter{
|
||||
Target: o.Oscilloscope,
|
||||
Target: o.State,
|
||||
Kinds: pointer.Scroll | pointer.Press | pointer.Drag | pointer.Release | pointer.Cancel,
|
||||
ScrollY: pointer.ScrollRange{Min: -1e6, Max: 1e6},
|
||||
})
|
||||
@ -148,58 +156,58 @@ func (o *OscilloscopeStyle) update(gtx C) {
|
||||
switch e.Kind {
|
||||
case pointer.Scroll:
|
||||
s1 := o.pxToSample(gtx, e.Position.X)
|
||||
o.Oscilloscope.xScale += min(max(-1, int(e.Scroll.Y)), 1)
|
||||
o.State.xScale += min(max(-1, int(e.Scroll.Y)), 1)
|
||||
s2 := o.pxToSample(gtx, e.Position.X)
|
||||
o.Oscilloscope.xOffset -= s1 - s2
|
||||
o.State.xOffset -= s1 - s2
|
||||
case pointer.Press:
|
||||
if e.Buttons&pointer.ButtonSecondary != 0 {
|
||||
o.Oscilloscope.xOffset = 0
|
||||
o.Oscilloscope.xScale = 0
|
||||
o.Oscilloscope.yScale = 0
|
||||
o.State.xOffset = 0
|
||||
o.State.xScale = 0
|
||||
o.State.yScale = 0
|
||||
}
|
||||
if e.Buttons&pointer.ButtonPrimary != 0 {
|
||||
o.Oscilloscope.dragging = true
|
||||
o.Oscilloscope.dragId = e.PointerID
|
||||
o.Oscilloscope.dragStartPoint = e.Position
|
||||
o.State.dragging = true
|
||||
o.State.dragId = e.PointerID
|
||||
o.State.dragStartPoint = e.Position
|
||||
}
|
||||
case pointer.Drag:
|
||||
if e.Buttons&pointer.ButtonPrimary != 0 && o.Oscilloscope.dragging && e.PointerID == o.Oscilloscope.dragId {
|
||||
deltaX := o.pxToSample(gtx, e.Position.X) - o.pxToSample(gtx, o.Oscilloscope.dragStartPoint.X)
|
||||
o.Oscilloscope.xOffset += deltaX
|
||||
if e.Buttons&pointer.ButtonPrimary != 0 && o.State.dragging && e.PointerID == o.State.dragId {
|
||||
deltaX := o.pxToSample(gtx, e.Position.X) - o.pxToSample(gtx, o.State.dragStartPoint.X)
|
||||
o.State.xOffset += deltaX
|
||||
num := o.yToAmp(gtx, e.Position.Y)
|
||||
den := o.yToAmp(gtx, o.Oscilloscope.dragStartPoint.Y)
|
||||
den := o.yToAmp(gtx, o.State.dragStartPoint.Y)
|
||||
if l := math.Abs(float64(num / den)); l > 1e-3 && l < 1e3 {
|
||||
o.Oscilloscope.yScale += math.Log(l)
|
||||
o.Oscilloscope.yScale = min(max(o.Oscilloscope.yScale, -1e3), 1e3)
|
||||
o.State.yScale += math.Log(l)
|
||||
o.State.yScale = min(max(o.State.yScale, -1e3), 1e3)
|
||||
}
|
||||
o.Oscilloscope.dragStartPoint = e.Position
|
||||
o.State.dragStartPoint = e.Position
|
||||
|
||||
}
|
||||
case pointer.Release | pointer.Cancel:
|
||||
o.Oscilloscope.dragging = false
|
||||
o.State.dragging = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (o *OscilloscopeStyle) scaleFactor() float32 {
|
||||
return float32(math.Pow(1.1, float64(o.Oscilloscope.xScale)))
|
||||
func (o *Oscilloscope) scaleFactor() float32 {
|
||||
return float32(math.Pow(1.1, float64(o.State.xScale)))
|
||||
}
|
||||
|
||||
func (s *OscilloscopeStyle) pxToSample(gtx C, px float32) float32 {
|
||||
return px*s.scaleFactor()*float32(len(s.Wave.Buffer))/float32(gtx.Constraints.Max.X) - s.Oscilloscope.xOffset
|
||||
func (s *Oscilloscope) pxToSample(gtx C, px float32) float32 {
|
||||
return px*s.scaleFactor()*float32(len(s.Wave.Buffer))/float32(gtx.Constraints.Max.X) - s.State.xOffset
|
||||
}
|
||||
|
||||
func (s *OscilloscopeStyle) sampleToPx(gtx C, sample float32) float32 {
|
||||
return (sample + s.Oscilloscope.xOffset) * float32(gtx.Constraints.Max.X) / float32(len(s.Wave.Buffer)) / s.scaleFactor()
|
||||
func (s *Oscilloscope) sampleToPx(gtx C, sample float32) float32 {
|
||||
return (sample + s.State.xOffset) * float32(gtx.Constraints.Max.X) / float32(len(s.Wave.Buffer)) / s.scaleFactor()
|
||||
}
|
||||
|
||||
func (s *OscilloscopeStyle) ampToY(gtx C, amp float32) float32 {
|
||||
scale := float32(math.Exp(s.Oscilloscope.yScale))
|
||||
func (s *Oscilloscope) ampToY(gtx C, amp float32) float32 {
|
||||
scale := float32(math.Exp(s.State.yScale))
|
||||
return (1 - amp*scale) / 2 * float32(gtx.Constraints.Max.Y-1)
|
||||
}
|
||||
|
||||
func (s *OscilloscopeStyle) yToAmp(gtx C, y float32) float32 {
|
||||
scale := float32(math.Exp(s.Oscilloscope.yScale))
|
||||
func (s *Oscilloscope) yToAmp(gtx C, y float32) float32 {
|
||||
scale := float32(math.Exp(s.State.yScale))
|
||||
return (1 - y/float32(gtx.Constraints.Max.Y-1)*2) / scale
|
||||
}
|
||||
|
Reference in New Issue
Block a user