@@ -42,9 +42,9 @@ export class Editor
42
42
. upsertMeterChange ( new MeterChange ( new Rational ( 0 , 4 ) , 4 , 4 ) )
43
43
. upsertMeterChange ( new MeterChange ( new Rational ( 11 , 4 ) , 5 , 4 ) )
44
44
45
- . upsertKeyChange ( new KeyChange ( new Rational ( 0 , 4 ) , new Key ( 0 , 0 , scales . major . pitches ) ) )
46
- . upsertKeyChange ( new KeyChange ( new Rational ( 7 , 4 ) , new Key ( 5 , 1 , scales . minor . pitches ) ) )
47
- . upsertKeyChange ( new KeyChange ( new Rational ( 9 , 4 ) , new Key ( 7 , - 1 , scales . doubleHarmonic . pitches ) ) )
45
+ . upsertKeyChange ( new KeyChange ( new Rational ( 0 , 4 ) , new Key ( 0 , 0 , scales [ 0 ] . pitches ) ) )
46
+ . upsertKeyChange ( new KeyChange ( new Rational ( 7 , 4 ) , new Key ( 5 , 1 , scales [ 5 ] . pitches ) ) )
47
+ . upsertKeyChange ( new KeyChange ( new Rational ( 9 , 4 ) , new Key ( 7 , - 1 , scales [ 7 ] . pitches ) ) )
48
48
49
49
this . timeScale = 200
50
50
this . timeScroll = 0
@@ -60,10 +60,14 @@ export class Editor
60
60
this . refreshLayout ( )
61
61
62
62
this . cursorTime = new Range ( new Rational ( 0 ) , new Rational ( 0 ) )
63
- this . cursorTrack = { start : 0 , end : 0 }
63
+ this . cursorTrack = { start : 1 , end : 1 }
64
64
this . cursorShow = true
65
65
this . insertionDuration = new Rational ( 1 , 4 )
66
66
67
+ this . playing = false
68
+ this . playbackTime = 0
69
+ this . playbackTimeRational = new Rational ( 0 )
70
+
67
71
this . mouseDown = false
68
72
this . mouseDownDate = new Date ( )
69
73
this . mouseDownData = { pos : { x : - 1 , y : - 1 } , time : new Rational ( 0 ) }
@@ -120,6 +124,43 @@ export class Editor
120
124
setSong ( song )
121
125
{
122
126
this . song = song
127
+ this . toolboxRefreshFn ( )
128
+ this . draw ( )
129
+ }
130
+
131
+
132
+ setPlayback ( playing )
133
+ {
134
+ this . playing = playing
135
+ this . playbackTime = this . cursorTime . min ( ) . asFloat ( )
136
+ this . scrollTimeIntoView ( this . cursorTime . min ( ) )
137
+
138
+ this . toolboxRefreshFn ( )
139
+ this . draw ( )
140
+
141
+ this . onPlaybackToggle ( this . playing )
142
+ }
143
+
144
+
145
+ rewind ( )
146
+ {
147
+ this . selectionClear ( )
148
+
149
+ this . cursorTime = new Range ( new Rational ( 0 ) , new Rational ( 0 ) )
150
+ this . cursorShow = true
151
+ this . playbackTime = 0
152
+ this . playbackTimeRational = new Rational ( 0 )
153
+
154
+ if ( this . playing )
155
+ {
156
+ this . setPlayback ( false )
157
+ this . setPlayback ( true )
158
+ }
159
+ else
160
+ this . scrollTimeIntoView ( this . cursorTime . start )
161
+
162
+ this . toolboxRefreshFn ( )
163
+ this . draw ( )
123
164
}
124
165
125
166
@@ -183,6 +224,18 @@ export class Editor
183
224
}
184
225
185
226
227
+ scrollPlaybackIntoView ( time )
228
+ {
229
+ const margin = this . timeSnap . multiply ( new Rational ( 16 ) )
230
+
231
+ if ( time . compare ( this . screenRange . end . subtract ( margin ) ) > 0 )
232
+ this . timeScroll = time . subtract ( margin ) . asFloat ( )
233
+
234
+ else if ( time . compare ( this . screenRange . start . add ( margin ) ) < 0 )
235
+ this . timeScroll = time . subtract ( margin ) . asFloat ( )
236
+ }
237
+
238
+
186
239
* enumerateTracksUnderCursor ( )
187
240
{
188
241
const trackMin = Math . min ( this . cursorTrack . start , this . cursorTrack . end )
@@ -368,6 +421,14 @@ export class Editor
368
421
this . mouseTime = this . getTimeAtPos ( this . mousePos )
369
422
this . mouseTrack = this . tracks . findIndex ( track => track . area . contains ( this . mousePos ) )
370
423
424
+ const edgeAutoScroll = ( ) =>
425
+ {
426
+ if ( this . mousePos . x > this . width - this . mouseEdgeScrollThreshold ) // && this.mousePos.x > mousePosPrev.x)
427
+ this . timeScroll += this . timeSnap . asFloat ( ) * this . mouseEdgeScrollSpeed
428
+ else if ( this . mousePos . x < this . mouseEdgeScrollThreshold ) // && this.mousePos.x < mousePosPrev.x)
429
+ this . timeScroll -= this . timeSnap . asFloat ( ) * this . mouseEdgeScrollSpeed
430
+ }
431
+
371
432
if ( this . mouseDown )
372
433
{
373
434
if ( this . mouseDownAction == Editor . ACTION_PAN )
@@ -384,17 +445,15 @@ export class Editor
384
445
this . cursorTrack = { ...this . cursorTrack , end : this . mouseTrack }
385
446
386
447
this . selectUnderCursor ( )
387
-
388
- if ( this . mousePos . x > this . width - this . mouseEdgeScrollThreshold ) // && this.mousePos.x > mousePosPrev.x)
389
- this . timeScroll += this . timeSnap . asFloat ( ) * this . mouseEdgeScrollSpeed
390
- else if ( this . mousePos . x < this . mouseEdgeScrollThreshold ) // && this.mousePos.x < mousePosPrev.x)
391
- this . timeScroll -= this . timeSnap . asFloat ( ) * this . mouseEdgeScrollSpeed
448
+ edgeAutoScroll ( )
392
449
}
393
450
else
394
451
{
395
452
this . curSanitizationMode = "mouse"
396
453
for ( const track of this . tracks )
397
454
track . onDrag ( { x : this . mousePos . x - track . area . x , y : this . mousePos . y - track . area . y } )
455
+
456
+ edgeAutoScroll ( )
398
457
}
399
458
}
400
459
else
@@ -548,6 +607,12 @@ export class Editor
548
607
}
549
608
break
550
609
}
610
+ case " " :
611
+ {
612
+ this . setPlayback ( ! this . playing )
613
+ handled = true
614
+ break
615
+ }
551
616
case "enter" :
552
617
case "escape" :
553
618
{
@@ -661,6 +726,7 @@ export class Editor
661
726
this . ctx . fillRect ( 0 , 0 , this . width , this . height )
662
727
663
728
this . screenRange = new Range ( this . getTimeAtPos ( { x : 0 , y : 0 } ) , this . getTimeAtPos ( { x : this . width , y : 0 } ) . add ( this . timeSnap ) )
729
+ this . playbackTimeRational = Rational . fromFloat ( this . playbackTime , new Rational ( 1 , 64 ) )
664
730
665
731
for ( const [ curMeter , nextMeter ] of this . song . meterChanges . enumerateAffectingRangePairwise ( this . screenRange ) )
666
732
{
@@ -702,7 +768,7 @@ export class Editor
702
768
}
703
769
}
704
770
705
- if ( this . cursorShow )
771
+ if ( this . cursorShow && ! this . playing )
706
772
this . drawCursorRect ( )
707
773
708
774
for ( const keyChange of this . song . keyChanges . enumerateOverlappingRange ( this . screenRange ) )
@@ -741,12 +807,15 @@ export class Editor
741
807
this . ctx . restore ( )
742
808
}
743
809
744
- if ( this . cursorShow )
810
+ if ( this . cursorShow && ! this . playing )
745
811
{
746
812
this . drawCursorBeam ( this . cursorTime . min ( ) , true )
747
813
this . drawCursorBeam ( this . cursorTime . max ( ) , false )
748
814
}
749
815
816
+ if ( this . playing )
817
+ this . drawPlaybackBeam ( this . playbackTime )
818
+
750
819
this . ctx . restore ( )
751
820
}
752
821
@@ -807,4 +876,27 @@ export class Editor
807
876
808
877
this . ctx . restore ( )
809
878
}
879
+
880
+
881
+ drawPlaybackBeam ( time )
882
+ {
883
+ const trackMin = 0
884
+ const trackMax = this . tracks . length - 1
885
+
886
+ this . ctx . save ( )
887
+
888
+ const offset = time - this . timeScroll
889
+ const x = offset * this . timeScale
890
+
891
+ this . ctx . strokeStyle = "#f00"
892
+ this . ctx . lineCap = "round"
893
+ this . ctx . lineWidth = 3
894
+
895
+ this . ctx . beginPath ( )
896
+ this . ctx . moveTo ( this . tracks [ trackMin ] . area . x + x , this . tracks [ trackMin ] . area . y )
897
+ this . ctx . lineTo ( this . tracks [ trackMax ] . area . x + x , this . tracks [ trackMax ] . area . y + this . tracks [ trackMax ] . area . h )
898
+ this . ctx . stroke ( )
899
+
900
+ this . ctx . restore ( )
901
+ }
810
902
}
0 commit comments