@@ -76,30 +76,48 @@ export class TimeManager {
7676
7777 advancePage ( numPages : number , updateSource : UpdateSource ) {
7878 console . log ( "advancePage" , numPages ) ;
79- const currentPage = bar_to_page [ this . scoreTime . act - 1 ] [ this . scoreTime . bar ] . page - 1
80- + act_starting_pages [ this . scoreTime . act - 1 ] ;
81- let targetPage = currentPage + numPages ;
82- if ( targetPage < act_starting_pages [ 0 ] ) {
83- targetPage = act_starting_pages [ 0 ] ;
84- } else if ( targetPage >= 486 ) {
85- targetPage = 486 ;
86- }
8779
88- for ( let act = 0 ; act < bar_to_page . length ; ++ act ) {
89- if ( targetPage >= act_starting_pages [ act ] && targetPage < act_starting_pages [ act + 1 ] ) {
90- targetPage -= act_starting_pages [ act ] ;
91- targetPage += 1 ;
92- for ( const bar in bar_to_page [ act ] ) {
93- if ( bar_to_page [ act ] [ bar ] . page === targetPage ) {
94- this . goToTime ( act + 1 , Number ( bar ) , this . scoreTime . beat , updateSource ) ;
95- return ;
96- }
80+ const firstPage = act_starting_pages [ 0 ] ;
81+ const lastPage = 486 ;
82+
83+ // Compute current absolute page (act-relative page is 1-based, so subtract 1 before adding act offset)
84+ const currentActIndex = this . scoreTime . act - 1 ;
85+ const currentWithinActPage = bar_to_page [ currentActIndex ] [ this . scoreTime . bar ] . page ;
86+ const currentAbsolutePage = currentWithinActPage - 1 + act_starting_pages [ currentActIndex ] ;
87+
88+ const targetAbsolutePage = Math . max ( firstPage , Math . min ( lastPage , currentAbsolutePage + numPages ) ) ;
89+
90+ // Search outward from targetAbsolutePage in the direction of travel until we find a
91+ // page that has at least one bar starting on it. This handles pages that fall in
92+ // the middle of a bar (no bar starts there) without silently doing nothing.
93+ const direction = numPages >= 0 ? 1 : - 1 ;
94+
95+ for ( let page = targetAbsolutePage ; page >= firstPage && page <= lastPage ; page += direction ) {
96+ // Determine which act this absolute page belongs to (last act whose start ≤ page)
97+ let actIndex = - 1 ;
98+ for ( let a = act_starting_pages . length - 1 ; a >= 0 ; a -- ) {
99+ if ( page >= act_starting_pages [ a ] ) {
100+ actIndex = a ;
101+ break ;
102+ }
103+ }
104+ if ( actIndex === - 1 ) continue ;
105+
106+ const withinActPage = page - act_starting_pages [ actIndex ] + 1 ;
107+
108+ // Numeric keys in JS objects iterate in ascending order, so the first match is
109+ // the lowest-numbered (i.e. first) bar that starts on this page.
110+ for ( const barStr in bar_to_page [ actIndex ] ) {
111+ if ( bar_to_page [ actIndex ] [ barStr ] . page === withinActPage ) {
112+ this . goToTime ( actIndex + 1 , Number ( barStr ) , this . scoreTime . beat , updateSource ) ;
113+ return ;
97114 }
98115 }
99116 }
100117 }
101118
102119 notifyListeners ( updateSource : UpdateSource ) {
120+ console . log ( "updateSource" , updateSource , "time" , this . scoreTime ) ;
103121 for ( const listener of this . listeners ) {
104122 listener . timeUpdated ( this . scoreTime , updateSource ) ;
105123 }
0 commit comments