Song select: the decided genre board stays up while its songs load #22

Merged
Yonokid merged 4 commits from GanYiZhong/YataiDONNijiiro:folder-open-leg into main 2026-09-10 19:32:36 +02:00
3 changed files with 377 additions and 253 deletions

No files matched your search

+235 -229
View File
@@ -1,12 +1,14 @@
-- GENERATED by scratchpad/anim_export.py -- DO NOT EDIT BY HAND.
-- Re-export: python anim_export.py enso_normal/song_select/song_select_main_genre.nulm #19 --range 27,150 --fields tx,ty --out wheel_decide.lua
-- Source: enso_normal/song_select/song_select_main_genre.nulm clip #19 frames 27..150 @ 60 fps
-- Rows are {frame, tx, ty}; every field is LINEAR between two rows.
-- GENERATED from the cabinet clip with lumen_anim_dump -- DO NOT EDIT BY HAND.
-- Re-export: lumen_anim_dump.exe enso_normal/song_select/song_select_main_genre.nulm --sprite 19 --all --range 27,255
-- Source: enso_normal/song_select/song_select_main_genre.nulm clip #19 frames 27..255 @ 60 fps
-- Rows are {frame, tx, ty}; every field is LINEAR between two rows. f27..150 is the
-- folder OPEN leg (genre_deceide f45, return f150), f150..255 the CLOSE leg (return
-- f150 .. genre_deceide2 f255); at f255 the clip re-bases for a second decide.
return {
movie = "enso_normal/song_select/song_select_main_genre.nulm",
clip = "#19",
fps = 60,
range = { 27, 150 },
range = { 27, 255 },
fields = { "tx", "ty" },
labels = {
["init"] = 0,
@@ -21,13 +23,36 @@ return {
tracks = {
["kanban_genre_1"] = {
{ 27, 5.55, 28.35 },
{ 28, 11.1, 56.65 },
{ 30, 22.2, 113.35 },
{ 31, 27.8, 141.65 },
{ 33, 38.9, 198.35 },
{ 34, 44.45, 226.65 },
{ 35, 50, 255 },
{ 36, 44.45, 226.65 },
{ 37, 38.9, 198.35 },
{ 39, 27.8, 141.65 },
{ 40, 22.2, 113.35 },
{ 42, 11.1, 56.65 },
{ 43, 5.55, 28.35 },
{ 44, 0, 0 },
{ 150, 0, 0 },
{ 254, 0, 0 },
{ 255, 50, 255 },
},
["kanban_genre_2"] = {
{ 27, -44.45, -226.65 },
{ 28, -38.9, -198.35 },
{ 30, -27.8, -141.65 },
{ 31, -22.2, -113.35 },
{ 33, -11.1, -56.65 },
{ 34, -5.55, -28.35 },
{ 35, 0, 0 },
{ 36, -5.55, -28.35 },
{ 37, -11.1, -56.65 },
{ 39, -22.2, -113.35 },
{ 40, -27.8, -141.65 },
{ 42, -38.9, -198.35 },
{ 43, -44.45, -226.65 },
{ 44, -50, -255 },
{ 86, -50, -255 },
{ 87, -50.7, -257.4 },
@@ -57,11 +82,44 @@ return {
{ 139, -52.85, -264.6 },
{ 140, -50.7, -257.4 },
{ 141, -50, -255 },
{ 150, -50, -255 },
{ 191, -50, -255 },
{ 192, -50.7, -257.4 },
{ 193, -52.85, -264.6 },
{ 194, -56.4, -276.55 },
{ 195, -61.35, -293.35 },
{ 196, -67.75, -314.9 },
{ 197, -75.55, -341.25 },
{ 198, -84.8, -372.45 },
{ 199, -95.45, -408.4 },
{ 200, -107.5, -449.1 },
{ 201, -121, -494.65 },
{ 202, -135.9, -544.95 },
{ 203, -152.25, -600.1 },
{ 204, -170, -660 },
{ 233, -170, -660 },
{ 234, -152.25, -600.1 },
{ 235, -135.9, -545 },
{ 236, -121, -494.65 },
{ 237, -107.5, -449.1 },
{ 238, -95.45, -408.4 },
{ 239, -84.8, -372.45 },
{ 240, -75.55, -341.25 },
{ 241, -67.75, -314.9 },
{ 242, -61.35, -293.35 },
{ 243, -56.4, -276.55 },
{ 244, -52.85, -264.6 },
{ 245, -50.7, -257.4 },
{ 246, -50, -255 },
{ 254, -50, -255 },
{ 255, 0, 0 },
},
["kanban_genre_3"] = {
{ 27, 54.45, 270 },
{ 30, 67.8, 315 },
{ 31, 72.2, 330 },
{ 35, 90, 390 },
{ 39, 72.2, 330 },
{ 40, 67.8, 315 },
{ 44, 50, 255 },
{ 86, 50, 255 },
{ 87, 50.7, 257.4 },
@@ -91,11 +149,44 @@ return {
{ 139, 52.85, 264.6 },
{ 140, 50.7, 257.4 },
{ 141, 50, 255 },
{ 150, 50, 255 },
{ 191, 50, 255 },
{ 192, 50.7, 257.4 },
{ 193, 52.85, 264.6 },
{ 194, 56.4, 276.55 },
{ 195, 61.35, 293.35 },
{ 196, 67.75, 314.9 },
{ 197, 75.55, 341.25 },
{ 198, 84.8, 372.45 },
{ 199, 95.45, 408.4 },
{ 200, 107.5, 449.1 },
{ 201, 121, 494.65 },
{ 202, 135.9, 544.95 },
{ 203, 152.25, 600.1 },
{ 204, 170, 660 },
{ 233, 170, 660 },
{ 234, 152.25, 600.1 },
{ 235, 135.9, 545 },
{ 236, 121, 494.65 },
{ 237, 107.5, 449.1 },
{ 238, 95.45, 408.4 },
{ 239, 84.8, 372.45 },
{ 240, 75.55, 341.25 },
{ 241, 67.75, 314.9 },
{ 242, 61.35, 293.35 },
{ 243, 56.4, 276.55 },
{ 244, 52.85, 264.6 },
{ 245, 50.7, 257.4 },
{ 246, 50, 255 },
{ 254, 50, 255 },
{ 255, 90, 390 },
},
["kanban_genre_4"] = {
{ 27, -85.55, -375 },
{ 30, -72.2, -330 },
{ 31, -67.8, -315 },
{ 35, -50, -255 },
{ 39, -67.8, -315 },
{ 40, -72.2, -330 },
{ 44, -90, -390 },
{ 82, -90, -390 },
{ 83, -90.7, -392.4 },
@@ -125,11 +216,44 @@ return {
{ 143, -92.85, -399.6 },
{ 144, -90.7, -392.4 },
{ 145, -90, -390 },
{ 150, -90, -390 },
{ 187, -90, -390 },
{ 188, -90.7, -392.4 },
{ 189, -92.85, -399.6 },
{ 190, -96.4, -411.55 },
{ 191, -101.35, -428.35 },
{ 192, -107.75, -449.9 },
{ 193, -115.55, -476.25 },
{ 194, -124.8, -507.45 },
{ 195, -135.45, -543.4 },
{ 196, -147.5, -584.1 },
{ 197, -161, -629.65 },
{ 198, -175.9, -679.95 },
{ 199, -192.25, -735.1 },
{ 200, -210, -795 },
{ 237, -210, -795 },
{ 238, -192.25, -735.1 },
{ 239, -175.9, -680 },
{ 240, -161, -629.65 },
{ 241, -147.5, -584.1 },
{ 242, -135.45, -543.4 },
{ 243, -124.8, -507.45 },
{ 244, -115.55, -476.25 },
{ 245, -107.75, -449.9 },
{ 246, -101.35, -428.35 },
{ 247, -96.4, -411.55 },
{ 248, -92.85, -399.6 },
{ 249, -90.7, -392.4 },
{ 250, -90, -390 },
{ 254, -90, -390 },
{ 255, -50, -255 },
},
["kanban_genre_5"] = {
{ 27, 94.45, 405 },
{ 30, 107.8, 450 },
{ 31, 112.2, 465 },
{ 35, 130, 525 },
{ 39, 112.2, 465 },
{ 40, 107.8, 450 },
{ 44, 90, 390 },
{ 82, 90, 390 },
{ 83, 90.7, 392.4 },
@@ -159,11 +283,44 @@ return {
{ 143, 92.85, 399.6 },
{ 144, 90.7, 392.4 },
{ 145, 90, 390 },
{ 150, 90, 390 },
{ 187, 90, 390 },
{ 188, 90.7, 392.4 },
{ 189, 92.85, 399.6 },
{ 190, 96.4, 411.55 },
{ 191, 101.35, 428.35 },
{ 192, 107.75, 449.9 },
{ 193, 115.55, 476.25 },
{ 194, 124.8, 507.45 },
{ 195, 135.45, 543.4 },
{ 196, 147.5, 584.1 },
{ 197, 161, 629.65 },
{ 198, 175.9, 679.95 },
{ 199, 192.25, 735.1 },
{ 200, 210, 795 },
{ 237, 210, 795 },
{ 238, 192.25, 735.1 },
{ 239, 175.9, 680 },
{ 240, 161, 629.65 },
{ 241, 147.5, 584.1 },
{ 242, 135.45, 543.4 },
{ 243, 124.8, 507.45 },
{ 244, 115.55, 476.25 },
{ 245, 107.75, 449.9 },
{ 246, 101.35, 428.35 },
{ 247, 96.4, 411.55 },
{ 248, 92.85, 399.6 },
{ 249, 90.7, 392.4 },
{ 250, 90, 390 },
{ 254, 90, 390 },
{ 255, 130, 525 },
},
["kanban_genre_6"] = {
{ 27, -125.55, -510 },
{ 30, -112.2, -465 },
{ 31, -107.8, -450 },
{ 35, -90, -390 },
{ 39, -107.8, -450 },
{ 40, -112.2, -465 },
{ 44, -130, -525 },
{ 78, -130, -525 },
{ 79, -130.7, -527.4 },
@@ -193,11 +350,43 @@ return {
{ 147, -132.85, -534.6 },
{ 148, -130.7, -527.4 },
{ 149, -130, -525 },
{ 150, -130, -525 },
{ 183, -130, -525 },
{ 184, -130.7, -527.4 },
{ 185, -132.85, -534.6 },
{ 186, -136.4, -546.55 },
{ 187, -141.35, -563.35 },
{ 188, -147.75, -584.9 },
{ 189, -155.55, -611.25 },
{ 190, -164.8, -642.45 },
{ 191, -175.45, -678.4 },
{ 192, -187.5, -719.1 },
{ 193, -201, -764.65 },
{ 194, -215.9, -814.95 },
{ 195, -232.25, -870.1 },
{ 196, -250, -930 },
{ 241, -250, -930 },
{ 242, -232.25, -870.1 },
{ 243, -215.9, -815 },
{ 244, -201, -764.65 },
{ 245, -187.5, -719.1 },
{ 246, -175.45, -678.4 },
{ 247, -164.8, -642.45 },
{ 248, -155.55, -611.25 },
{ 249, -147.75, -584.9 },
{ 250, -141.35, -563.35 },
{ 251, -136.4, -546.55 },
{ 252, -132.85, -534.6 },
{ 253, -130.7, -527.4 },
{ 254, -130, -525 },
{ 255, -90, -390 },
},
["kanban_genre_7"] = {
{ 27, 134.45, 540 },
{ 30, 147.8, 585 },
{ 31, 152.2, 600 },
{ 35, 170, 660 },
{ 39, 152.2, 600 },
{ 40, 147.8, 585 },
{ 44, 130, 525 },
{ 78, 130, 525 },
{ 79, 130.7, 527.4 },
@@ -227,229 +416,46 @@ return {
{ 147, 132.85, 534.6 },
{ 148, 130.7, 527.4 },
{ 149, 130, 525 },
{ 150, 130, 525 },
{ 183, 130, 525 },
{ 184, 130.7, 527.4 },
{ 185, 132.85, 534.6 },
{ 186, 136.4, 546.55 },
{ 187, 141.35, 563.35 },
{ 188, 147.75, 584.9 },
{ 189, 155.55, 611.25 },
{ 190, 164.8, 642.45 },
{ 191, 175.45, 678.4 },
{ 192, 187.5, 719.1 },
{ 193, 201, 764.65 },
{ 194, 215.9, 814.95 },
{ 195, 232.25, 870.1 },
{ 196, 250, 930 },
{ 241, 250, 930 },
{ 242, 232.25, 870.1 },
{ 243, 215.9, 815 },
{ 244, 201, 764.65 },
{ 245, 187.5, 719.1 },
{ 246, 175.45, 678.4 },
{ 247, 164.8, 642.45 },
{ 248, 155.55, 611.25 },
{ 249, 147.75, 584.9 },
{ 250, 141.35, 563.35 },
{ 251, 136.4, 546.55 },
{ 252, 132.85, 534.6 },
{ 253, 130.7, 527.4 },
{ 254, 130, 525 },
{ 255, 170, 660 },
},
["kanban_genre_8"] = {
{ 27, -165.55, -645 },
{ 30, -152.2, -600 },
{ 31, -147.8, -585 },
{ 35, -130, -525 },
{ 39, -147.8, -585 },
{ 40, -152.2, -600 },
{ 44, -170, -660 },
{ 150, -170, -660 },
},
["kanban_song_1"] = {
{ 27, 5.55, 28.35 },
{ 35, 50, 255 },
{ 44, 0, 0 },
{ 150, 0, 0 },
},
["kanban_song_2"] = {
{ 27, -44.45, -226.65 },
{ 35, 0, 0 },
{ 44, -50, -255 },
{ 86, -50, -255 },
{ 87, -50.7, -257.4 },
{ 88, -52.85, -264.6 },
{ 89, -56.4, -276.55 },
{ 90, -61.35, -293.35 },
{ 91, -67.75, -314.9 },
{ 92, -75.55, -341.25 },
{ 93, -84.8, -372.45 },
{ 94, -95.45, -408.4 },
{ 95, -107.5, -449.1 },
{ 96, -121, -494.65 },
{ 97, -135.9, -544.95 },
{ 98, -152.25, -600.1 },
{ 99, -170, -660 },
{ 128, -170, -660 },
{ 129, -152.25, -600.1 },
{ 130, -135.9, -545 },
{ 131, -121, -494.65 },
{ 132, -107.5, -449.1 },
{ 133, -95.45, -408.4 },
{ 134, -84.8, -372.45 },
{ 135, -75.55, -341.25 },
{ 136, -67.75, -314.9 },
{ 137, -61.35, -293.35 },
{ 138, -56.4, -276.55 },
{ 139, -52.85, -264.6 },
{ 140, -50.7, -257.4 },
{ 141, -50, -255 },
{ 150, -50, -255 },
},
["kanban_song_3"] = {
{ 27, 54.45, 270 },
{ 35, 90, 390 },
{ 44, 50, 255 },
{ 86, 50, 255 },
{ 87, 50.7, 257.4 },
{ 88, 52.85, 264.6 },
{ 89, 56.4, 276.55 },
{ 90, 61.35, 293.35 },
{ 91, 67.75, 314.9 },
{ 92, 75.55, 341.25 },
{ 93, 84.8, 372.45 },
{ 94, 95.45, 408.4 },
{ 95, 107.5, 449.1 },
{ 96, 121, 494.65 },
{ 97, 135.9, 544.95 },
{ 98, 152.25, 600.1 },
{ 99, 170, 660 },
{ 128, 170, 660 },
{ 129, 152.25, 600.1 },
{ 130, 135.9, 545 },
{ 131, 121, 494.65 },
{ 132, 107.5, 449.1 },
{ 133, 95.45, 408.4 },
{ 134, 84.8, 372.45 },
{ 135, 75.55, 341.25 },
{ 136, 67.75, 314.9 },
{ 137, 61.35, 293.35 },
{ 138, 56.4, 276.55 },
{ 139, 52.85, 264.6 },
{ 140, 50.7, 257.4 },
{ 141, 50, 255 },
{ 150, 50, 255 },
},
["kanban_song_4"] = {
{ 27, -85.55, -375 },
{ 35, -50, -255 },
{ 44, -90, -390 },
{ 82, -90, -390 },
{ 83, -90.7, -392.4 },
{ 84, -92.85, -399.6 },
{ 85, -96.4, -411.55 },
{ 86, -101.35, -428.35 },
{ 87, -107.75, -449.9 },
{ 88, -115.55, -476.25 },
{ 89, -124.8, -507.45 },
{ 90, -135.45, -543.4 },
{ 91, -147.5, -584.1 },
{ 92, -161, -629.65 },
{ 93, -175.9, -679.95 },
{ 94, -192.25, -735.1 },
{ 95, -210, -795 },
{ 132, -210, -795 },
{ 133, -192.25, -735.1 },
{ 134, -175.9, -680 },
{ 135, -161, -629.65 },
{ 136, -147.5, -584.1 },
{ 137, -135.45, -543.4 },
{ 138, -124.8, -507.45 },
{ 139, -115.55, -476.25 },
{ 140, -107.75, -449.9 },
{ 141, -101.35, -428.35 },
{ 142, -96.4, -411.55 },
{ 143, -92.85, -399.6 },
{ 144, -90.7, -392.4 },
{ 145, -90, -390 },
{ 150, -90, -390 },
},
["kanban_song_5"] = {
{ 27, 94.45, 405 },
{ 35, 130, 525 },
{ 44, 90, 390 },
{ 82, 90, 390 },
{ 83, 90.7, 392.4 },
{ 84, 92.85, 399.6 },
{ 85, 96.4, 411.55 },
{ 86, 101.35, 428.35 },
{ 87, 107.75, 449.9 },
{ 88, 115.55, 476.25 },
{ 89, 124.8, 507.45 },
{ 90, 135.45, 543.4 },
{ 91, 147.5, 584.1 },
{ 92, 161, 629.65 },
{ 93, 175.9, 679.95 },
{ 94, 192.25, 735.1 },
{ 95, 210, 795 },
{ 132, 210, 795 },
{ 133, 192.25, 735.1 },
{ 134, 175.9, 680 },
{ 135, 161, 629.65 },
{ 136, 147.5, 584.1 },
{ 137, 135.45, 543.4 },
{ 138, 124.8, 507.45 },
{ 139, 115.55, 476.25 },
{ 140, 107.75, 449.9 },
{ 141, 101.35, 428.35 },
{ 142, 96.4, 411.55 },
{ 143, 92.85, 399.6 },
{ 144, 90.7, 392.4 },
{ 145, 90, 390 },
{ 150, 90, 390 },
},
["kanban_song_6"] = {
{ 27, -125.55, -510 },
{ 35, -90, -390 },
{ 44, -130, -525 },
{ 78, -130, -525 },
{ 79, -130.7, -527.4 },
{ 80, -132.85, -534.6 },
{ 81, -136.4, -546.55 },
{ 82, -141.35, -563.35 },
{ 83, -147.75, -584.9 },
{ 84, -155.55, -611.25 },
{ 85, -164.8, -642.45 },
{ 86, -175.45, -678.4 },
{ 87, -187.5, -719.1 },
{ 88, -201, -764.65 },
{ 89, -215.9, -814.95 },
{ 90, -232.25, -870.1 },
{ 91, -250, -930 },
{ 136, -250, -930 },
{ 137, -232.25, -870.1 },
{ 138, -215.9, -815 },
{ 139, -201, -764.65 },
{ 140, -187.5, -719.1 },
{ 141, -175.45, -678.4 },
{ 142, -164.8, -642.45 },
{ 143, -155.55, -611.25 },
{ 144, -147.75, -584.9 },
{ 145, -141.35, -563.35 },
{ 146, -136.4, -546.55 },
{ 147, -132.85, -534.6 },
{ 148, -130.7, -527.4 },
{ 149, -130, -525 },
{ 150, -130, -525 },
},
["kanban_song_7"] = {
{ 27, 134.45, 540 },
{ 35, 170, 660 },
{ 44, 130, 525 },
{ 78, 130, 525 },
{ 79, 130.7, 527.4 },
{ 80, 132.85, 534.6 },
{ 81, 136.4, 546.55 },
{ 82, 141.35, 563.35 },
{ 83, 147.75, 584.9 },
{ 84, 155.55, 611.25 },
{ 85, 164.8, 642.45 },
{ 86, 175.45, 678.4 },
{ 87, 187.5, 719.1 },
{ 88, 201, 764.65 },
{ 89, 215.9, 814.95 },
{ 90, 232.25, 870.1 },
{ 91, 250, 930 },
{ 136, 250, 930 },
{ 137, 232.25, 870.1 },
{ 138, 215.9, 815 },
{ 139, 201, 764.65 },
{ 140, 187.5, 719.1 },
{ 141, 175.45, 678.4 },
{ 142, 164.8, 642.45 },
{ 143, 155.55, 611.25 },
{ 144, 147.75, 584.9 },
{ 145, 141.35, 563.35 },
{ 146, 136.4, 546.55 },
{ 147, 132.85, 534.6 },
{ 148, 130.7, 527.4 },
{ 149, 130, 525 },
{ 150, 130, 525 },
},
["kanban_song_8"] = {
{ 27, -165.55, -645 },
{ 35, -130, -525 },
{ 44, -170, -660 },
{ 150, -170, -660 },
{ 254, -170, -660 },
{ 255, -130, -525 },
},
},
}
+140 -22
View File
@@ -361,6 +361,7 @@ function SongSelect:draw_top(dan_progress)
end
function SongSelect:draw_overlays(state)
self:draw_decided_bridge() -- decided genre board while its songs load (defined below)
if _dd_ok then dan_doors.arm(state == STATE_DAN_SELECTED) end
-- number_of_songs plate: arcade song_of_number_instance at stage (1754,270), 280x72 centred.
-- The engine draws its own song_num_bg (made transparent in this skin) and the "N曲目" text
@@ -678,6 +679,7 @@ end
-- Scrolling genre backdrop (enso_normal/song_select/song_select_bg, 2880x1080 per genre)
--------------------------------------------------------------------------------
function SongSelect:draw_background(nav)
self._frame_no = (self._frame_no or 0) + 1
self:refresh_folder_context(nav)
local info = tex.get_texture_info("box", "background")
local width = info.width
@@ -710,13 +712,17 @@ end
-- width -- exactly how the existing `y2 = h - 352` calls already drive the height. So a
-- horizontal scale is `x2 = BOARD_W * (sx - 1)` plus a re-centred x, with no engine
-- change. sx = nil/1 leaves every pre-r61 call byte-identical.
-- A furled board (sx < 1) is not a squashed copy of the 960-wide texture: squashing
-- averages the outline away and makes the GPU pick a small mip level (the LOD follows
-- the larger axis), which blurs every row. The cabinet scales a vector shape, so its
-- edges stay sharp at any width. Five columns get the same result from the bitmap:
-- the two rounded corners at 1:1 (40 px), and the coloured band / inner panel / band
-- between them scaled in proportion, each drawn from an 8 px flat slice of itself and
-- MAGNIFIED to its width. Column layout of every bar_genre frame and the back board:
-- corner 0..40 | band 40..83 | panel 83..877 | band 877..920 | corner 920..960.
local function draw_board(bar_id, frame, bx, by, cen_h, fade, crop_center, sx)
local w = BOARD_W
local x2 = nil
if sx and sx ~= 1.0 then
w = BOARD_W * sx
x2 = w - BOARD_W
end
if sx and sx ~= 1.0 then w = math.max(2, math.floor(BOARD_W * sx + 0.5)) end
local x = math.floor(bx - w / 2 + 0.5)
local top = math.floor(by - cen_h / 2 + 0.5) - CAP_H
local src_y, src_h = CAP_H, CEN_SRC_H
@@ -725,12 +731,53 @@ local function draw_board(bar_id, frame, bx, by, cen_h, fade, crop_center, sx)
src_y = CAP_H + math.floor((CEN_SRC_H - src_h) / 2)
cen_h = src_h
end
tex.draw_texture(bar_id, { frame = frame, x = x, y = top, y2 = CAP_H - 352, x2 = x2, fade = fade,
src = { x = 0, y = 0, width = BOARD_W, height = CAP_H } })
tex.draw_texture(bar_id, { frame = frame, x = x, y = top + CAP_H, y2 = cen_h - 352, x2 = x2, fade = fade,
src = { x = 0, y = src_y, width = BOARD_W, height = src_h } })
tex.draw_texture(bar_id, { frame = frame, x = x, y = top + CAP_H + cen_h, y2 = CAP_H - 352, x2 = x2, fade = fade,
src = { x = 0, y = CAP_H + CEN_SRC_H, width = BOARD_W, height = CAP_H } })
-- the three horizontal bands (top cap / centre / bottom cap) as {y, src_y, src_h, dst_h}
local bands = { { top, 0, CAP_H, CAP_H }, { top + CAP_H, src_y, src_h, cen_h },
{ top + CAP_H + cen_h, CAP_H + CEN_SRC_H, CAP_H, CAP_H } }
if w == BOARD_W then
for _, b in ipairs(bands) do
tex.draw_texture(bar_id, { frame = frame, x = x, y = b[1], y2 = b[4] - 352, fade = fade,
src = { x = 0, y = b[2], width = BOARD_W, height = b[3] } })
end
return
end
local CORNER, BAND, PANEL = 40, 43, 794 -- source widths; 40+43+794+43+40 = 960
local cols
if w >= 2 * CORNER then
local corner = CORNER
local inner = w - 2 * corner
local band = math.floor(inner * BAND / (2 * BAND + PANEL) + 0.5)
local panel = inner - 2 * band
-- columns: {src_x, src_w, dst_x, dst_w}
cols = {
{ 0, CORNER, x, corner },
{ CORNER + BAND / 2 - 4, 8, x + corner, band },
{ BOARD_W / 2 - 4, 8, x + corner + band, panel },
{ BOARD_W - CORNER - BAND / 2 - 4, 8, x + corner + band + panel, band },
{ BOARD_W - CORNER, CORNER, x + w - corner, corner },
}
else
-- narrower than both corners (the last frames of a furl / first of an unfurl): the
-- cabinet's vector shape is a solid bar with its outline all round, so draw the
-- two outline columns (texture x 13..20 / 940..947) at a few px each and fill the
-- rest from the flat centre slice -- squeezing the rounded corners instead left
-- two hollow strokes with nothing between them.
local ol = math.max(2, math.min(8, math.floor(w / 6)))
local mid = math.max(0, w - 2 * ol)
cols = {
{ 13, 8, x, ol },
{ BOARD_W / 2 - 4, 8, x + ol, mid },
{ 940, 8, x + ol + mid, ol },
}
end
for _, b in ipairs(bands) do
for _, c in ipairs(cols) do
if c[4] > 0 then
tex.draw_texture(bar_id, { frame = frame, x = c[3], y = b[1], x2 = c[4] - BOARD_W, y2 = b[4] - 352,
fade = fade, src = { x = c[1], y = b[2], width = c[2], height = b[3] } })
end
end
end
end
-- Yellow cursor glow around the board (arcade cursor_top/center/bottom): the glow's caps
@@ -979,6 +1026,7 @@ local R61 = {
-- clip landmarks (overwritten from the generated table)
open_f0 = 45, open_swap = 114, open_end = 145,
close_f0 = 150, close_swap = 219, close_end = 250,
open_furl = 100, -- first frame the decided genre board furls shut (genre_board_sx < 1)
-- event bookkeeping
seq = nil, -- last Navigator.wheel_event_seq we saw
have_events = false, -- engine actually exposes the r85 channel
@@ -993,6 +1041,12 @@ do
"close_f0", "close_swap", "close_end" }) do
if t[k] then R61[k] = t[k] end
end
local rows = t.tracks and t.tracks.genre_board_sx
if rows then
for i = 1, #rows do
if rows[i][2] < 0.999 then R61.open_furl = rows[i][1]; break end
end
end
end
end
-- Linear sampler over the generated {frame, v1, v2...} rows. Fail-soft: an absent table
@@ -1044,8 +1098,14 @@ local function leg_f()
if R61.disabled or not R61.clip or not R61.t0 then return nil end
local f = R61.f0 + (tex.get_current_ms() - R61.t0) * 0.06
if not R61.swapped then
-- hold one frame short of the swap until the engine says it happened
local hold = (R61.kind == "close") and (R61.close_swap - 1) or (R61.open_swap - 1)
-- hold until the engine says the swap happened. The close leg holds one frame
-- short of its swap; the OPEN leg holds one frame short of the FURL (f99): the
-- cabinet loads a folder inside its 69-frame decide, this engine can take a
-- couple of seconds, and parking on f113 (board already furled away, boxes
-- flown out) left the screen empty for all of that time. Parked on f99 the
-- decided board stays up as the loading state and the furl -> unfurl pair
-- plays back to back once the swap lands (see leg_event).
local hold = (R61.kind == "close") and (R61.close_swap - 1) or (R61.open_furl - 1)
if f > hold then f = hold end
return f
end
@@ -1054,6 +1114,15 @@ local function leg_f()
return f
end
-- The engine's own box fade, except during the pre-swap half of the CLOSE leg: there the
-- engine fades the song boxes and the back board out in 166 ms, while the cabinet keeps
-- them solid until they fly out (f184..204) / the board furls (f205..217) -- those come
-- from the clip channels, so the engine fade is ignored until the swap.
local function box_fade(box)
if R61.kind == "close" and R61.t0 and not R61.swapped then return 1.0 end
return box.fade.attribute
end
-- Start / advance the leg. `begin` puts the clock on the label frame; `swap` re-anchors
-- it on the cabinet's content-swap frame so the post-swap half is phase-exact no matter
-- how long the loader took.
@@ -1061,8 +1130,16 @@ local function leg_event(id)
local now = tex.get_current_ms()
if id == 3 then -- OPEN_BEGIN
R61.t0, R61.f0, R61.kind, R61.swapped = now, R61.open_f0, "open", false
R61.dec_id, R61.dec_box = R61.last_open_id, R61.last_open_box -- the decided board
elseif id == 4 then -- OPEN_SWAP
R61.t0, R61.f0, R61.kind, R61.swapped = now, R61.open_swap, "open", true
-- the clock was parked on open_furl - 1 while the loader ran: resume from the
-- furl so furl (f100..113) and unfurl (f114..) play back to back. A swap that
-- lands before the park point (tiny folder) just lets the clock keep running.
local f = (R61.kind == "open" and R61.t0) and (R61.f0 + (now - R61.t0) * 0.06) or nil
if not f or f >= R61.open_furl - 1 then
R61.t0, R61.f0 = now, R61.open_furl
end
R61.kind, R61.swapped = "open", true
R61.snap_once, R61.snap_ms = true, now -- OpenFolderState ends GotoAndPlay("on")
elseif id == 5 then -- CLOSE_BEGIN
R61.t0, R61.f0, R61.kind, R61.swapped = now, R61.close_f0, "close", false
@@ -1091,8 +1168,17 @@ local _fly_dbg = read_env("YATAIDON_R56_DEBUG") ~= nil -- log sampled offsets (
local function fly_offset(box)
if R56_DISABLED then return 0.0, 0.0 end
local f = leg_f()
if not f or not R61.swapped or R61.kind ~= "open" then return 0.0, 0.0 end
if f >= FLY_END_F then return 0.0, 0.0 end
if not f then return 0.0, 0.0 end
if R61.kind == "open" then
if f >= FLY_END_F then return 0.0, 0.0 end
elseif R61.kind == "close" then
-- the CLOSE leg is the clip's `return` half: the song boxes fly out f184..204,
-- wait off screen across the swap (f219) and the genre boxes fly back in
-- f234..254; f255 (`genre_deceide2`) re-bases the clip, so stop just before it
if f >= (WHEEL_FLY:label("genre_deceide2") or 255) - 1 then return 0.0, 0.0 end
else
return 0.0, 0.0
end
local st = box:draw_state()
if st == "open" or st == "diff_select" then return 0.0, 0.0 end -- the decided board stays
local d = box:box_y() - FLY_CENTER_Y
@@ -1109,6 +1195,25 @@ local function fly_offset(box)
return x - rx, y - ry
end
-- The decided genre board while the loader owns it (see draw_folder_open): drawn here,
-- after the wheel, whenever draw_box did not get to it this frame, until it has furled.
function SongSelect:draw_decided_bridge()
if not R61.dec_box then return end
local lf = (R61.kind == "open") and leg_f() or nil
if lf and lf < R61.open_swap - 1 then
if self._dec_frame ~= self._frame_no then
pcall(self.draw_folder_open, self, R61.dec_box)
end
else
R61.dec_id, R61.dec_box = nil, nil
end
end
-- true while `box` is the genre board the player just decided on (open leg running)
local function is_decided(box)
return R61.kind == "open" and R61.t0 ~= nil and R61.dec_id ~= nil and box_id(box) == R61.dec_id
end
-- ROUND 51: how a FRESH open animation starts is not one-size-fits-all. From the real
-- the reference build song_select_song_main.lua state machine (scratchpad dec/, verified this round):
-- * cursor move Scroll -> Main -> ProcKanbanWaitCountToSelectOn (61-tick hold,
@@ -1348,7 +1453,7 @@ end
function SongSelect:draw_song_board(box, pb, ia, ic)
local bx, by = box:box_x(), box:box_y()
local fdx, fdy = fly_offset(box); bx, by = bx + fdx, by + fdy -- r56 wheel fly-in
local fade = math.min(1.0, box.fade.attribute)
local fade = math.min(1.0, box_fade(box))
-- ROUND 61: the folder-ENTER unfurl. On the frames the cabinet is playing
-- genre_deceide f113..f145 the incoming song board is NOT growing vertically from
@@ -1375,6 +1480,9 @@ function SongSelect:draw_song_board(box, pb, ia, ic)
tostring(box:draw_state()), tostring(box.text_name)))
end)
end
if gof and R61.kind == "open" and gof < R61.open_swap - 1 and box:draw_state() == "open" then
return -- the new content's board does not exist until the swap frame
end
if gof and box:draw_state() == "open" then
local sx, ba = go_get("song_board_sx", gof, 1), go_get("song_board_sx", gof, 2)
if sx and ba then
@@ -2077,7 +2185,7 @@ function SongSelect:draw_folder_board(box, pb, ch_alpha, ch_off, ta, glow_a)
local bx, by = box:box_x(), box:box_y()
local fdx, fdy = fly_offset(box); bx, by = bx + fdx, by + fdy -- r56 wheel fly-in
local cen_h = CEN_CLOSED_H + (CEN_OPEN_H - CEN_CLOSED_H) * pb
local fade = box.fade.attribute
local fade = box_fade(box)
local frame, has_pattern = folder_frame(box)
-- ROUND 85 ---------------------------------------------------------------
@@ -2094,7 +2202,7 @@ function SongSelect:draw_folder_board(box, pb, ch_alpha, ch_off, ta, glow_a)
-- pointing at.
local ltitle = 1.0
if not R61.disabled then
local lf = (box:draw_state() == "open") and leg_f() or nil
local lf = (box:draw_state() == "open" or is_decided(box)) and leg_f() or nil
if lf then
local sx, ba = go_get("genre_board_sx", lf, 1), go_get("genre_board_sx", lf, 2)
if sx and ba then
@@ -2223,6 +2331,15 @@ function SongSelect:draw_folder_closed(box)
end
function SongSelect:draw_folder_open(box)
-- remember the decided board: the engine removes the folder box from the wheel
-- while its songs load, and draw_overlays keeps drawing it from here until it
-- has furled away (the C++ box outlives the wheel slot, so the handle stays valid)
R61.last_open_id, R61.last_open_box = box_id(box), box
if is_decided(box) then
self._dec_frame = self._frame_no
self:draw_folder_board(box, 1.0, 1.0, 440.0, 1.0, 1.0)
return
end
local key = "f\0" .. box_id(box) -- r63: per-BOX, not per-title (see box_id)
local t = wheel_open_t(key)
if t == nil then -- cabinet 508 ms pre-growth hold: fully closed
@@ -2273,7 +2390,7 @@ function SongSelect:draw_back_board(box, p)
local bx, by = box:box_x(), box:box_y()
local fdx, fdy = fly_offset(box); bx, by = bx + fdx, by + fdy -- r56 wheel fly-in
local cen_h = CEN_CLOSED_H + (CEN_OPEN_H - CEN_CLOSED_H) * p
local fade = math.min(1.0, box.fade.attribute)
local fade = math.min(1.0, box_fade(box))
-- ROUND 85: on the cabinet the panel that unfurls across the swap is the
-- newly-focused one (`GetSongKanbanMc(kSelectNumber + openOffset)`). In THIS
@@ -2286,6 +2403,7 @@ function SongSelect:draw_back_board(box, p)
local lta = 1.0
if not R61.disabled then
local lf = (box:draw_state() == "open") and leg_f() or nil
if lf and R61.kind == "open" and lf < R61.open_swap - 1 then return end -- not yet
if lf then
local sx, ba = go_get("song_board_sx", lf, 1), go_get("song_board_sx", lf, 2)
if sx and ba then
@@ -2644,7 +2762,7 @@ function SongSelect:draw_box(box)
elseif state == "open" then self:draw_song_open(box)
else self:draw_song_closed(box) end
elseif kind == "folder" then
if state == "open" then self:draw_folder_open(box)
if state == "open" or is_decided(box) then self:draw_folder_open(box)
else self:draw_folder_closed(box) end
elseif kind == "back" then
if state == "open" then self:draw_back_open(box)
@@ -2665,7 +2783,7 @@ function SongSelect:draw_box(box)
p = e and (folder_close_timeline(e)) or 0.0
end
local cen_h = CEN_CLOSED_H + (CEN_OPEN_H - CEN_CLOSED_H) * p
local fade = math.min(1.0, box.fade.attribute)
local fade = math.min(1.0, box_fade(box))
if p > 0 then self:draw_glow(bx, by, cen_h, fade * p * glow_pulse()) end
draw_board((p > 0) and self._id_bar_folder or self._id_bar_genre, 10, bx, by, cen_h, fade, p <= 0 or p >= 1) -- ROUND 5: closed = full pale panel
if p > 0 and p < 1 then draw_board(self._id_bar_genre, 10, bx, by, cen_h, fade * (1.0 - p)) end
+2 -2
View File
@@ -3171,7 +3171,7 @@ e08f82230e9e8f8c00deed9a7d0d0eaba6933021b9960b782a8b77eca3200b06 *./Scripts/anim
eb2bb15e87cc83d66b320e0e4cbcbd2d5385881f36eca27fe73740439055ef6c *./Scripts/anim/sort_cursor.lua
5789c13c7958010f2878f9a0b119a50af4f362e754dc06ca3683ce742d507d25 *./Scripts/anim/title_idle.lua
24e7afe3e93935774c14aebce3e635970ec045952224ea5246633ff05b37e3af *./Scripts/anim/title_idle_map.lua
a340f195886e0e372da2cca847c1a243ed56d76239597c01f6ccdf11d1779759 *./Scripts/anim/wheel_decide.lua
2a160f3c8902d329effb39fb342087b6f7dca56b15c13d1b605b7cf3ca275b1c *./Scripts/anim/wheel_decide.lua
4e61d41a6f50228b0d320290a99c7f6658843936448c61aff89c5a1e86891121 *./Scripts/background/background.lua
1d35116ef8edb2c9acf9ccc26024e1e788cf3cb010b87a930f1f76108d3c6b69 *./Scripts/background/bg_collabs/a3.lua
784052aa0ba1881415d1468174453cbee33b2cc58c6283b0a53758759a750668 *./Scripts/background/bg_collabs/animal.lua
@@ -3277,7 +3277,7 @@ bae62b0f451139b880d57d4b214156a8deaadedb2aacc1f7421d4e21189a810d *./Scripts/resu
fe5bc0a6cff271012d0de9ec7fc5cc7a94b3f1268ea1aa4a18e72c38b1a0e6c3 *./Scripts/result/result_fade_in.lua
9447dea62976348429b38b22104c68708b21cfbbf61f5d37a5a8d082d69f7a1c *./Scripts/result/result_player.lua
1033652c20bd62a07f645c94961227dfe73fb49df9bc581c460739c96c109c08 *./Scripts/song_select/dan_doors.lua
d3af610009783a9cf6e044dfcee396ea7f0ee90cd059fc44feb98e6935a5afff *./Scripts/song_select/song_select.lua
698d1ba46c4be558b59624e339a5e1971d12bff5119daed2bc22bdeb5b305286 *./Scripts/song_select/song_select.lua
89047ab5b642696922ca2c6e098ca288580a9c0bb3e197a08f17b821a31fc519 *./.skin-repo
40c378cdcaea2e2c9ec3da4c7fa72911d13a849a5b51e9645300f9571a7e12c8 *./Sounds/dan_result/achieve_tamashii.ogg
606f2d3558badc06e54b2c59a36f0580f4954774918d69a712ad6de45518cba0 *./Sounds/dan_result/advance_intro.ogg