diff --git a/PyTaiko.py b/PyTaiko.py index 42234be..3bf03c5 100644 --- a/PyTaiko.py +++ b/PyTaiko.py @@ -18,6 +18,7 @@ from libs.utils import ( global_data, load_all_textures_from_zip, ) +from scenes.devtest import DevScreen from scenes.entry import EntryScreen from scenes.game import GameScreen from scenes.result import ResultScreen @@ -33,6 +34,7 @@ class Screens: GAME = "GAME" RESULT = "RESULT" SETTINGS = "SETTINGS" + DEV_MENU = "DEV_MENU" def create_song_db(): with sqlite3.connect('scores.db') as con: @@ -84,24 +86,26 @@ def main(): if global_data.config["video"]["fullscreen"]: ray.maximize_window() - current_screen = Screens.TITLE + current_screen = Screens.DEV_MENU audio.init_audio_device() title_screen = TitleScreen(screen_width, screen_height) entry_screen = EntryScreen(screen_width, screen_height) - song_select_screen = SongSelectScreen(screen_width, screen_height) + #song_select_screen = SongSelectScreen(screen_width, screen_height) game_screen = GameScreen(screen_width, screen_height) result_screen = ResultScreen(screen_width, screen_height) settings_screen = SettingsScreen(screen_width, screen_height) + dev_screen = DevScreen(screen_width, screen_height) screen_mapping = { Screens.ENTRY: entry_screen, Screens.TITLE: title_screen, - Screens.SONG_SELECT: song_select_screen, + #Screens.SONG_SELECT: song_select_screen, Screens.GAME: game_screen, Screens.RESULT: result_screen, - Screens.SETTINGS: settings_screen + Screens.SETTINGS: settings_screen, + Screens.DEV_MENU: dev_screen } target = ray.load_render_texture(screen_width, screen_height) ray.set_texture_filter(target.texture, ray.TextureFilter.TEXTURE_FILTER_TRILINEAR) diff --git a/Songs/TRIPLE HELIX/TRIPLE HELIX.ogg b/Songs/TRIPLE HELIX/TRIPLE HELIX.ogg new file mode 100644 index 0000000..63f641c Binary files /dev/null and b/Songs/TRIPLE HELIX/TRIPLE HELIX.ogg differ diff --git a/Songs/TRIPLE HELIX/TRIPLE HELIX.tja b/Songs/TRIPLE HELIX/TRIPLE HELIX.tja new file mode 100644 index 0000000..956b1c2 --- /dev/null +++ b/Songs/TRIPLE HELIX/TRIPLE HELIX.tja @@ -0,0 +1,1945 @@ +TITLE:TRIPLE HELIX +SUBTITLE:--Yonokid +BPM:160 +WAVE:TRIPLE HELIX.ogg +OFFSET:-0.001 +DEMOSTART:120.001 +LYRICS:TRIPLE HELIX.vtt +PREIMAGE:Circulation.jpg +MAKER:Colin,Komi + +COURSE:Oni +LEVEL:9 +BALLOON:10,21,2 +NOTESDESIGNER3:Colin,Komi + +#START +#MEASURE 4/4 +10010012, +10010011, +10010012, +10010010, +1022102010201020, +1022102010201020, +1022101150008011, +2011225080100200, +1111, +12121212, +1020102010201120, + +#SCROLL 2 +50 +#SCROLL 1 +80220200221122, + +#GOGOSTART +1010102 +#SCROLL 1.5 +50 +#SCROLL 1 +8201020, +1120102010221122, +1020120 +#SCROLL 1.5 +50 +#SCROLL 1 +8201020, +1012102010221122, +1122120 +#SCROLL 1.5 +50 +#SCROLL 1 +8201020, +101200 +#SCROLL 1.5 +50 +#SCROLL 1 +80122122, +1020120 +#SCROLL 1.5 +50 +#SCROLL 1 +8201020, +102210 +#SCROLL 1.5 +50 +#SCROLL 1 +80221122, +1020112210201020, +101200 +#SCROLL 1.5 +50 +#SCROLL 1 +80221122, +1020112210201020, +101200 +#SCROLL 1.5 +50 +#SCROLL 1 +80221122, +1122120 +#SCROLL 1.5 +50 +#SCROLL 1 +8201020, +101210 +#SCROLL 1.5 +50 +#SCROLL 1 +80122122, +1010120 +#SCROLL 1.5 +50 +#SCROLL 1 +8201020, +101200 +#SCROLL 1.5 +50 +#SCROLL 1 +80221122, + +#GOGOEND +1022102210201020, +12121212, +1120112010201020, +1122112211221122, +1021102110201020, +12121212, +1120112010201020, +1122112211221122, +2000001120201020, +1000112020001020, +1120112011202211, +2010201202112211, +2000112020102010, +2000112020102010, +2211211202112011, +2111020202121212, +1020102210201020, +1022102010201022, +1012012001121222, +1202020201112110, +1022102010201020, +1022102010201010, +1012001012001212, +1222122210112010, + +#GOGOSTART +1110111022202220, +2222111122221222, +5000801210212111, +2012005000800011, +2001205080201020, +1202021010112110, +2102102121112111, +70000008, +5000000000008022, +1122112211225080, +1012012012012210, +1122112211225080, +1010120210201122, +1020120122020121, +2220111022201222, +1020220210221122, + +#GOGOEND +11022012, +11022012, +11022012, +11022012, +7, +0008, +0011221150008011, +2211225000801200, + +#SCROLL 8 +7800 +#SCROLL 1 +100010001000, +12121212, +12121212, +3000220200 +#SCROLL 1.04 +2 +#SCROLL 1.08 +2 +#SCROLL 1.12 +1 +#SCROLL 1.16 +1 +#SCROLL 1.2 +2 +#SCROLL 1.24 +2, + +#SCROLL 1.28 + +#GOGOSTART +1010102110201020, +1120102010221122, +1020120110201020, +1012112010221122, +1122120101201020, +1012012010122122, +1020120201201020, +1122101011221122, +1020112210201020, +1012012010221122, +1020112210201020, +1012112110221122, +1122120120201020, +1012102120122122, +1010120210201020, +100100100200100000100000101010200200100100200200, + +#GOGOEND +4, +#END + +COURSE:Hard +LEVEL:6 +BALLOON:23,21,23 +NOTESDESIGNER2:Colin,Komi + +#START +#MEASURE 4/4 +10101011, +10101011, +10101011, +1111, +5, +00000008, +0011101020202022, +2010202000100200, +1, +0, +0, +3, + +#GOGOSTART +5080201100201020, +1001005080111010, +1000220200201020, +1001005080111010, +1022020200101010, +3003005080111010, +2020220100101010, +3003006000800000, +5080201100201020, +1001005080111010, +1000220200201020, +1001005080111010, +1022020200101010, +3003005080111010, +2020220100101010, +3003006000800000, + +#GOGOEND +12121012, +10221012, +1000101010001110, +1020100020222020, +12121012, +10221012, +1000101010001110, +1020100020222020, +10020011, +10020011, +1110111022202020, +2221, +10020011, +10020011, +10121012, +10121012, +10121012, +1000200020002011, +12121010, +1020102010111010, +10201120, +10201120, +1011101011001110, +10202220, + +#GOGOSTART +7, +00000008, +7, +0008, +7, +00000008, +12121212, +5, +8000102010001011, +1011101010102000, +1011002022001011, +1020101110102020, +1020110100001010, +22221010, +58585080, +3000400400000000, + +#GOGOEND +10020011, +10020011, +10020011, +20020010, +1111, +1111, +5, +00000008, +1, +0, +0, +3, + +#GOGOSTART +5080201100201020, +1001005080111010, +1000220200201020, +1001005080111010, +1022020200101010, +3003005080111010, +2020220100101010, +3003006000800000, +5080201100201020, +1001005080111010, +1000220200201020, +1001005080111010, +1022020200101010, +3003005080111010, +2020220100101010, +3003006000800000, + +#GOGOEND +4, +#END + +COURSE:Normal +LEVEL:4 +SCOREINIT: +SCOREDIFF: +NOTESDESIGNER1:Colin + +#START +1110, +1110, +1110, +1110, +5, +0008, +05000000, +00000008, +, +, +, +3, +#GOGOSTART +1000100500800000, +5008, +1000000100000010, +1001005080000000, +1211, +10020000, +10111010, +50000008, +2120, +2120, +2120, +2120, +2120, +2120, +2120, +5008, +#GOGOEND +10111000, +10111000, +10111000, +10111000, +20222000, +20222000, +20222000, +20222000, +10020000, +10020000, +58585850, +0008, +1110, +1110, +10101110, +10101110, +1110, +1110, +1110, +1220, +2220, +2220, +2220, +2220, +#GOGOSTART +5, +0008, +5, +0008, +5, +0008, +5, +0008, +1210, +1210, +1210, +1210, +1110, +1110, +1220, +2220, +#GOGOEND +10020000, +10020000, +10020000, +10020000, +10020000, +10020000, +10020000, +10020000, +, +, +, +3, +#GOGOSTART +1000100500800000, +5008, +1000000100000010, +1001005080000000, +1211, +10020000, +10111010, +50000008, +2120, +2120, +2120, +2120, +2120, +2120, +2120, +5008, +#GOGOEND +4, +#END + +COURSE:Easy +LEVEL:2 +SCOREINIT: +SCOREDIFF: +NOTESDESIGNER0:Colin + +#START +1010, +1, +1010, +1, +5, +0008, +05000000, +00000008, +, +, +, +3, +#GOGOSTART +1000100500800000, +5008, +1000000100000000, +10058000, +1210, +10020000, +1101, +50000008, +2020, +2, +2020, +2, +2020, +2, +2020, +5008, +#GOGOEND +1110, +1, +1110, +1, +2220, +2, +2220, +2, +10020000, +10020000, +58585850, +0008, +1010, +1, +1110, +1010, +1, +1010, +1, +1020, +2, +2, +2, +2, +#GOGOSTART +5, +0008, +5, +0008, +5, +0008, +5, +0008, +1010, +1, +1010, +1, +1010, +1, +1020, +2, +#GOGOEND +10020000, +10020000, +10020000, +10020000, +10020000, +10020000, +10020000, +10020000, +, +, +, +3, +#GOGOSTART +1000100500800000, +5008, +1000000100000000, +10058000, +1010, +1, +1010, +50000008, +2020, +2020, +2020, +2020, +2020, +2020, +2020, +5008, +#GOGOEND +4, +#END + +COURSE:Edit +LEVEL:10.5 +BALLOON:30 +NOTESDESIGNER4:Colin,Komi + +#START +#MEASURE 4/4 +10010012, +10010011, +10010012, +10010010, +1022102210201120, +1022102011201120, +10001010202010101100110011001010, +2211225080201120, + +#SCROLL 0.500000 +11111000100000001000000010000000, + +#SCROLL 0.750000 +12121212, +12121212, + +#SCROLL 1.000000 +11111111202000200000202010102010, + +#GOGOSTART +#SCROLL 1+0i +2 +#SCROLL 1+0.05i +0 +#SCROLL 1+0.1i +1 +#SCROLL 1+0.15i +0 +#SCROLL 1+0.2i +1 +#SCROLL 1+0.25i +0 +#SCROLL 1+0.3i +2 +#SCROLL 1+0.35i +1 +#SCROLL 1+0.4i +0 +#SCROLL 1+0.45i +1 +#SCROLL 1+0.5i +2 +#SCROLL 1+0.55i +0 +#SCROLL 1+0.6i +1 +#SCROLL 1+0.65i +0 +#SCROLL 1+0.7i +2 +#SCROLL 1+0.75i +0, + +#SCROLL 1+0.8i +1 +#SCROLL 1+0.75i +1 +#SCROLL 1+0.7i +2 +#SCROLL 1+0.65i +0 +#SCROLL 1+0.6i +1 +#SCROLL 1+0.55i +0 +#SCROLL 1+0.5i +2 +#SCROLL 1+0.45i +0 +#SCROLL 1+0.4i +1 +#SCROLL 1+0.35i +0 +#SCROLL 1+0.3i +2 +#SCROLL 1+0.25i +2 +#SCROLL 1+0.2i +1 +#SCROLL 1+0.15i +1 +#SCROLL 1+0.1i +2 +#SCROLL 1+0.05i +2, + +#SCROLL 1+0.0i +1 +#SCROLL 1-0.05i +0 +#SCROLL 1-0.1i +2 +#SCROLL 1-0.15i +0 +#SCROLL 1-0.2i +1 +#SCROLL 1-0.25i +2 +#SCROLL 1-0.3i +0 +#SCROLL 1-0.35i +1 +#SCROLL 1-0.4i +1 +#SCROLL 1-0.45i +0 +#SCROLL 1-0.5i +2 +#SCROLL 1-0.55i +0 +#SCROLL 1-0.6i +1 +#SCROLL 1-0.65i +0 +#SCROLL 1-0.7i +2 +#SCROLL 1-0.75i +0, + +#SCROLL 1-0.8i +1 +#SCROLL 1-0.75i +0 +#SCROLL 1-0.7i +1 +#SCROLL 1-0.65i +2 +#SCROLL 1-0.6i +1 +#SCROLL 1-0.55i +0 +#SCROLL 1-0.5i +2 +#SCROLL 1-0.45i +0 +#SCROLL 1-0.4i +1 +#SCROLL 1-0.35i +0 +#SCROLL 1-0.3i +1 +#SCROLL 1-0.25i +2 +#SCROLL 1-0.2i +1 +#SCROLL 1-0.15i +1 +#SCROLL 1-0.1i +2 +#SCROLL 1-0.05i +2, + +#SCROLL 1+0.0i +1 +#SCROLL 1+0.05i +1 +#SCROLL 1+0.1i +1 +#SCROLL 1+0.15i +1 +#SCROLL 1+0.2i +2 +#SCROLL 1+0.25i +2 +#SCROLL 1+0.3i +1 +#SCROLL 1+0.35i +2 +#SCROLL 1+0.4i +1 +#SCROLL 1+0.45i +0 +#SCROLL 1+0.5i +2 +#SCROLL 1+0.55i +0 +#SCROLL 1+0.6i +1 +#SCROLL 1+0.65i +0 +#SCROLL 1+0.7i +2 +#SCROLL 1+0.75i +0, + +#SCROLL 1+0.8i +1 +#SCROLL 1+0.75i +0 +#SCROLL 1+0.7i +1 +#SCROLL 1+0.65i +2 +#SCROLL 1+0.6i +0 +#SCROLL 1+0.55i +1 +#SCROLL 1+0.5i +2 +#SCROLL 1+0.45i +0 +#SCROLL 1+0.4i +1 +#SCROLL 1+0.35i +1 +#SCROLL 1+0.3i +2 +#SCROLL 1+0.25i +2 +#SCROLL 1+0.2i +1 +#SCROLL 1+0.15i +1 +#SCROLL 1+0.1i +2 +#SCROLL 1+0.05i +2, + +#SCROLL 1+0.0i +1 +#SCROLL 1-0.05i +0 +#SCROLL 1-0.1i +2 +#SCROLL 1-0.15i +0 +#SCROLL 1-0.2i +1 +#SCROLL 1-0.25i +2 +#SCROLL 1-0.3i +0 +#SCROLL 1-0.35i +2 +#SCROLL 1-0.4i +1 +#SCROLL 1-0.45i +0 +#SCROLL 1-0.5i +2 +#SCROLL 1-0.55i +0 +#SCROLL 1-0.6i +1 +#SCROLL 1-0.65i +0 +#SCROLL 1-0.7i +2 +#SCROLL 1-0.75i +0, + +#SCROLL 1-0.8i +1 +#SCROLL 1-0.75i +0 +#SCROLL 1-0.7i +2 +#SCROLL 1-0.65i +2 +#SCROLL 1-0.6i +1 +#SCROLL 1-0.55i +0 +#SCROLL 1-0.5i +2 +#SCROLL 1-0.45i +0 +#SCROLL 1-0.4i +1 +#SCROLL 1-0.35i +0 +#SCROLL 1-0.3i +2 +#SCROLL 1-0.25i +2 +#SCROLL 1-0.2i +1 +#SCROLL 1-0.15i +1 +#SCROLL 1-0.1i +2 +#SCROLL 1-0.05i +2, + +#SCROLL 1+0.0i +1 +#SCROLL 1+0.05i +0 +#SCROLL 1+0.1i +2 +#SCROLL 1+0.15i +0 +#SCROLL 1+0.2i +1 +#SCROLL 1+0.25i +1 +#SCROLL 1+0.3i +2 +#SCROLL 1+0.35i +2 +#SCROLL 1+0.4i +1 +#SCROLL 1+0.45i +0 +#SCROLL 1+0.5i +2 +#SCROLL 1+0.55i +0 +#SCROLL 1+0.6i +1 +#SCROLL 1+0.65i +0 +#SCROLL 1+0.7i +2 +#SCROLL 1+0.75i +0, + +#SCROLL 1+0.8i +1 +#SCROLL 1+0.75i +1 +#SCROLL 1+0.7i +2 +#SCROLL 1+0.65i +2 +#SCROLL 1+0.6i +1 +#SCROLL 1+0.55i +0 +#SCROLL 1+0.5i +2 +#SCROLL 1+0.45i +0 +#SCROLL 1+0.4i +1 +#SCROLL 1+0.35i +0 +#SCROLL 1+0.3i +2 +#SCROLL 1+0.25i +2 +#SCROLL 1+0.2i +1 +#SCROLL 1+0.15i +1 +#SCROLL 1+0.1i +2 +#SCROLL 1+0.05i +2, + +#SCROLL 1+0.0i +1 +#SCROLL 1-0.05i +0 +#SCROLL 1-0.1i +2 +#SCROLL 1-0.15i +0 +#SCROLL 1-0.2i +1 +#SCROLL 1-0.25i +1 +#SCROLL 1-0.3i +2 +#SCROLL 1-0.35i +2 +#SCROLL 1-0.4i +1 +#SCROLL 1-0.45i +0 +#SCROLL 1-0.5i +2 +#SCROLL 1-0.55i +0 +#SCROLL 1-0.6i +1 +#SCROLL 1-0.65i +0 +#SCROLL 1-0.7i +2 +#SCROLL 1-0.75i +0, + +#SCROLL 1-0.8i +1 +#SCROLL 1-0.75i +1 +#SCROLL 1-0.7i +2 +#SCROLL 1-0.65i +1 +#SCROLL 1-0.6i +1 +#SCROLL 1-0.55i +0 +#SCROLL 1-0.5i +2 +#SCROLL 1-0.45i +0 +#SCROLL 1-0.4i +1 +#SCROLL 1-0.35i +0 +#SCROLL 1-0.3i +2 +#SCROLL 1-0.25i +2 +#SCROLL 1-0.2i +1 +#SCROLL 1-0.15i +1 +#SCROLL 1-0.1i +2 +#SCROLL 1-0.05i +2, + +#SCROLL 1+0.0i +1 +#SCROLL 1+0.05i +1 +#SCROLL 1+0.1i +2 +#SCROLL 1+0.15i +2 +#SCROLL 1+0.2i +1 +#SCROLL 1+0.25i +2 +#SCROLL 1+0.3i +0 +#SCROLL 1+0.35i +2 +#SCROLL 1+0.4i +1 +#SCROLL 1+0.45i +0 +#SCROLL 1+0.5i +2 +#SCROLL 1+0.55i +2 +#SCROLL 1+0.6i +1 +#SCROLL 1+0.65i +1 +#SCROLL 1+0.7i +2 +#SCROLL 1+0.75i +0, + +#SCROLL 1+0.8i +1 +#SCROLL 1+0.75i +0 +#SCROLL 1+0.7i +2 +#SCROLL 1+0.65i +1 +#SCROLL 1+0.6i +1 +#SCROLL 1+0.55i +0 +#SCROLL 1+0.5i +2 +#SCROLL 1+0.45i +0 +#SCROLL 1+0.4i +1 +#SCROLL 1+0.35i +0 +#SCROLL 1+0.3i +1 +#SCROLL 1+0.25i +1 +#SCROLL 1+0.2i +2 +#SCROLL 1+0.15i +1 +#SCROLL 1+0.1i +2 +#SCROLL 1+0.05i +2, + +#SCROLL 1+0.0i +1 +#SCROLL 1-0.05i +0 +#SCROLL 1-0.1i +1 +#SCROLL 1-0.15i +0 +#SCROLL 1-0.2i +2 +#SCROLL 1-0.25i +2 +#SCROLL 1-0.3i +1 +#SCROLL 1-0.35i +2 +#SCROLL 1-0.4i +1 +#SCROLL 1-0.45i +0 +#SCROLL 1-0.5i +2 +#SCROLL 1-0.55i +0 +#SCROLL 1-0.6i +1 +#SCROLL 1-0.65i +0 +#SCROLL 1-0.7i +2 +#SCROLL 1-0.75i +0, + +#SCROLL 1-0.8i +1 +#SCROLL 1-0.75i +1 +#SCROLL 1-0.7i +2 +#SCROLL 1-0.65i +1 +#SCROLL 1-0.6i +1 +#SCROLL 1-0.55i +0 +#SCROLL 1-0.5i +2 +#SCROLL 1-0.45i +0 +#SCROLL 1-0.4i +1 +#SCROLL 1-0.35i +0 +#SCROLL 1-0.3i +2 +#SCROLL 1-0.25i +2 +#SCROLL 1-0.2i +1 +#SCROLL 1-0.15i +1 +#SCROLL 1-0.1i +1 +#SCROLL 1-0.05i +1, + + +#GOGOEND + +#SCROLL 1 +1022102210201120, +1022102210201120, +1120102210221120, +1122112211221122, +1120112010201120, +1020112010221022, +1020112010221020, +1022102011221120, +2000001120221120, +1000001120221120, +1120112011202211, +2010201202112212, +1120221120201122, +1020221120201022, +1222121202121212, +1122120202221212, +1020112210201120, +1122102010221011, +1012112011121222, +1202020201111110, +1022112011201020, +1022112011201010, +1012102011201212, +100200200200100200200200100000101010200200100000, + +#GOGOSTART +2211221122112211, +2222111122221222, +5000802210221121, +100000200100200000100200101010200000100000200200, +1021102011201020, +1211121011221212, +1121121121112111, +211211211211211211211211, +5000000000008022, +100100200200200100200200100100200200102010100200, +100000100200100200200000100200100100200200102010, +100100200200100100200200100100200200102010100200, +1010121210201122, +1020212112121122, +1122112211221212, +11111111202000201000202010102010, + +#GOGOEND +11022012, +11022012, +11022012, +11022012, +7, +0008, +0022112210201012, +2122121010201120, +11111000100000001000000010000000, +12121212, +12121212, +11111111202000200000202010102010, + +#GOGOSTART +#SCROLL 1+0i +2 +#SCROLL 1+0.075i +0 +#SCROLL 1+0.15i +1 +#SCROLL 1+0.225i +0 +#SCROLL 1+0.3i +1 +#SCROLL 1+0.375i +0 +#SCROLL 1+0.45i +2 +#SCROLL 1+0.525i +1 +#SCROLL 1+0.6i +1 +#SCROLL 1+0.675i +1 +#SCROLL 1+0.75i +2 +#SCROLL 1+0.825i +0 +#SCROLL 1+0.9i +1 +#SCROLL 1+0.975i +0 +#SCROLL 1+1.05i +2 +#SCROLL 1+1.125i +0, + +#SCROLL 1+1.2i +1 +#SCROLL 1+1.125i +1 +#SCROLL 1+1.05i +2 +#SCROLL 1+0.975i +0 +#SCROLL 1+0.9i +1 +#SCROLL 1+0.825i +0 +#SCROLL 1+0.75i +2 +#SCROLL 1+0.675i +0 +#SCROLL 1+0.6i +1 +#SCROLL 1+0.525i +0 +#SCROLL 1+0.45i +2 +#SCROLL 1+0.375i +2 +#SCROLL 1+0.3i +1 +#SCROLL 1+0.225i +1 +#SCROLL 1+0.15i +2 +#SCROLL 1+0.075i +2, + +#SCROLL 1+0.0i +1 +#SCROLL 1-0.075i +0 +#SCROLL 1-0.15i +2 +#SCROLL 1-0.225i +0 +#SCROLL 1-0.3i +1 +#SCROLL 1-0.375i +2 +#SCROLL 1-0.45i +1 +#SCROLL 1-0.525i +1 +#SCROLL 1-0.6i +2 +#SCROLL 1-0.675i +0 +#SCROLL 1-0.75i +2 +#SCROLL 1-0.825i +0 +#SCROLL 1-0.9i +1 +#SCROLL 1-0.975i +0 +#SCROLL 1-1.05i +2 +#SCROLL 1-1.125i +0, + +#SCROLL 1-1.2i +1 +#SCROLL 1-1.175i +0 +#SCROLL 1-1.15i +0 +#SCROLL 1-1.125i +0 +#SCROLL 1-1.1i +0 +#SCROLL 1-1.075i +0 +#SCROLL 1-1.05i +2 +#SCROLL 1-1.025i +0 +#SCROLL 1-1.0i +2 +#SCROLL 1-0.975i +0 +#SCROLL 1-0.95i +2 +#SCROLL 1-0.925i +0 +#SCROLL 1-0.9i +1 +#SCROLL 1-0.875i +0 +#SCROLL 1-0.85i +0 +#SCROLL 1-0.825i +1 +#SCROLL 1-0.8i +0 +#SCROLL 1-0.775i +0 +#SCROLL 1-0.75i +2 +#SCROLL 1-0.725i +0 +#SCROLL 1-0.7i +0 +#SCROLL 1-0.675i +2 +#SCROLL 1-0.65i +0 +#SCROLL 1-0.625i +0 +#SCROLL 1-0.6i +1 +#SCROLL 1-0.575i +0 +#SCROLL 1-0.55i +0 +#SCROLL 1-0.525i +0 +#SCROLL 1-0.5i +0 +#SCROLL 1-0.475i +0 +#SCROLL 1-0.45i +1 +#SCROLL 1-0.425i +0 +#SCROLL 1-0.4i +0 +#SCROLL 1-0.375i +2 +#SCROLL 1-0.35i +0 +#SCROLL 1-0.325i +0 +#SCROLL 1-0.3i +1 +#SCROLL 1-0.275i +0 +#SCROLL 1-0.25i +0 +#SCROLL 1-0.225i +1 +#SCROLL 1-0.2i +0 +#SCROLL 1-0.175i +0 +#SCROLL 1-0.15i +2 +#SCROLL 1-0.125i +0 +#SCROLL 1-0.1i +2 +#SCROLL 1-0.075i +0 +#SCROLL 1-0.05i +2 +#SCROLL 1-0.025i +0, + +#SCROLL 1-0.0i +1 +#SCROLL 1+0.075i +1 +#SCROLL 1+0.15i +1 +#SCROLL 1+0.225i +1 +#SCROLL 1+0.3i +2 +#SCROLL 1+0.375i +2 +#SCROLL 1+0.45i +1 +#SCROLL 1+0.525i +2 +#SCROLL 1+0.6i +1 +#SCROLL 1+0.675i +0 +#SCROLL 1+0.75i +2 +#SCROLL 1+0.825i +0 +#SCROLL 1+0.9i +1 +#SCROLL 1+0.975i +0 +#SCROLL 1+1.05i +2 +#SCROLL 1+1.125i +0, + +#SCROLL 1+1.2i +1 +#SCROLL 1+1.125i +0 +#SCROLL 1+1.05i +1 +#SCROLL 1+0.975i +2 +#SCROLL 1+0.9i +1 +#SCROLL 1+0.825i +0 +#SCROLL 1+0.75i +2 +#SCROLL 1+0.675i +0 +#SCROLL 1+0.6i +1 +#SCROLL 1+0.525i +1 +#SCROLL 1+0.45i +1 +#SCROLL 1+0.375i +1 +#SCROLL 1+0.3i +2 +#SCROLL 1+0.225i +2 +#SCROLL 1+0.15i +2 +#SCROLL 1+0.075i +2, + +#SCROLL 1+0.0i +1 +#SCROLL 1-0.075i +0 +#SCROLL 1-0.15i +2 +#SCROLL 1-0.225i +0 +#SCROLL 1-0.3i +1 +#SCROLL 1-0.375i +2 +#SCROLL 1-0.45i +1 +#SCROLL 1-0.525i +2 +#SCROLL 1-0.6i +1 +#SCROLL 1-0.675i +0 +#SCROLL 1-0.75i +2 +#SCROLL 1-0.825i +0 +#SCROLL 1-0.9i +1 +#SCROLL 1-0.975i +0 +#SCROLL 1-1.05i +2 +#SCROLL 1-1.125i +0, + +#SCROLL 1-1.2i +1 +#SCROLL 1-1.175i +0 +#SCROLL 1-1.15i +0 +#SCROLL 1-1.125i +1 +#SCROLL 1-1.1i +0 +#SCROLL 1-1.075i +0 +#SCROLL 1-1.05i +0 +#SCROLL 1-1.025i +0 +#SCROLL 1-1.0i +0 +#SCROLL 1-0.975i +2 +#SCROLL 1-0.95i +0 +#SCROLL 1-0.925i +0 +#SCROLL 1-0.9i +1 +#SCROLL 1-0.875i +0 +#SCROLL 1-0.85i +0 +#SCROLL 1-0.825i +0 +#SCROLL 1-0.8i +0 +#SCROLL 1-0.775i +0 +#SCROLL 1-0.75i +2 +#SCROLL 1-0.725i +0 +#SCROLL 1-0.7i +0 +#SCROLL 1-0.675i +0 +#SCROLL 1-0.65i +0 +#SCROLL 1-0.625i +0 +#SCROLL 1-0.6i +1 +#SCROLL 1-0.575i +0 +#SCROLL 1-0.55i +1 +#SCROLL 1-0.525i +0 +#SCROLL 1-0.5i +1 +#SCROLL 1-0.475i +0 +#SCROLL 1-0.45i +2 +#SCROLL 1-0.425i +0 +#SCROLL 1-0.4i +0 +#SCROLL 1-0.375i +2 +#SCROLL 1-0.35i +0 +#SCROLL 1-0.325i +0 +#SCROLL 1-0.3i +1 +#SCROLL 1-0.275i +0 +#SCROLL 1-0.25i +0 +#SCROLL 1-0.225i +1 +#SCROLL 1-0.2i +0 +#SCROLL 1-0.175i +0 +#SCROLL 1-0.15i +2 +#SCROLL 1-0.125i +0 +#SCROLL 1-0.1i +0 +#SCROLL 1-0.075i +2 +#SCROLL 1-0.05i +0 +#SCROLL 1-0.025i +0, + +#SCROLL 1-0.0i +1 +#SCROLL 1+0.075i +0 +#SCROLL 1+0.15i +2 +#SCROLL 1+0.225i +0 +#SCROLL 1+0.3i +1 +#SCROLL 1+0.375i +1 +#SCROLL 1+0.45i +2 +#SCROLL 1+0.525i +2 +#SCROLL 1+0.6i +1 +#SCROLL 1+0.675i +0 +#SCROLL 1+0.75i +2 +#SCROLL 1+0.825i +0 +#SCROLL 1+0.9i +1 +#SCROLL 1+0.975i +0 +#SCROLL 1+1.05i +2 +#SCROLL 1+1.125i +0, + +#SCROLL 1+1.2i +1 +#SCROLL 1+1.125i +1 +#SCROLL 1+1.05i +2 +#SCROLL 1+0.975i +2 +#SCROLL 1+0.9i +1 +#SCROLL 1+0.825i +0 +#SCROLL 1+0.75i +2 +#SCROLL 1+0.675i +0 +#SCROLL 1+0.6i +1 +#SCROLL 1+0.525i +0 +#SCROLL 1+0.45i +2 +#SCROLL 1+0.375i +2 +#SCROLL 1+0.3i +1 +#SCROLL 1+0.225i +1 +#SCROLL 1+0.15i +2 +#SCROLL 1+0.075i +2, + +#SCROLL 1+0.0i +1 +#SCROLL 1-0.075i +0 +#SCROLL 1-0.15i +2 +#SCROLL 1-0.225i +0 +#SCROLL 1-0.3i +1 +#SCROLL 1-0.375i +1 +#SCROLL 1-0.45i +2 +#SCROLL 1-0.525i +2 +#SCROLL 1-0.6i +1 +#SCROLL 1-0.675i +0 +#SCROLL 1-0.75i +2 +#SCROLL 1-0.825i +0 +#SCROLL 1-0.9i +1 +#SCROLL 1-0.975i +0 +#SCROLL 1-1.05i +2 +#SCROLL 1-1.125i +0, + +#SCROLL 1-1.2i +1 +#SCROLL 1-1.175i +0 +#SCROLL 1-1.15i +0 +#SCROLL 1-1.125i +0 +#SCROLL 1-1.1i +0 +#SCROLL 1-1.075i +0 +#SCROLL 1-1.05i +2 +#SCROLL 1-1.025i +0 +#SCROLL 1-1.0i +2 +#SCROLL 1-0.975i +0 +#SCROLL 1-0.95i +2 +#SCROLL 1-0.925i +0 +#SCROLL 1-0.9i +1 +#SCROLL 1-0.875i +0 +#SCROLL 1-0.85i +0 +#SCROLL 1-0.825i +1 +#SCROLL 1-0.8i +0 +#SCROLL 1-0.775i +0 +#SCROLL 1-0.75i +2 +#SCROLL 1-0.725i +0 +#SCROLL 1-0.7i +0 +#SCROLL 1-0.675i +2 +#SCROLL 1-0.65i +0 +#SCROLL 1-0.625i +0 +#SCROLL 1-0.6i +1 +#SCROLL 1-0.575i +0 +#SCROLL 1-0.55i +0 +#SCROLL 1-0.525i +0 +#SCROLL 1-0.5i +0 +#SCROLL 1-0.475i +0 +#SCROLL 1-0.45i +2 +#SCROLL 1-0.425i +0 +#SCROLL 1-0.4i +0 +#SCROLL 1-0.375i +2 +#SCROLL 1-0.35i +0 +#SCROLL 1-0.325i +0 +#SCROLL 1-0.3i +1 +#SCROLL 1-0.275i +0 +#SCROLL 1-0.25i +0 +#SCROLL 1-0.225i +1 +#SCROLL 1-0.2i +0 +#SCROLL 1-0.175i +0 +#SCROLL 1-0.15i +2 +#SCROLL 1-0.125i +0 +#SCROLL 1-0.1i +0 +#SCROLL 1-0.075i +2 +#SCROLL 1-0.05i +0 +#SCROLL 1-0.025i +0, + +#SCROLL 1-0.0i +1 +#SCROLL 1+0.075i +1 +#SCROLL 1+0.15i +2 +#SCROLL 1+0.225i +2 +#SCROLL 1+0.3i +1 +#SCROLL 1+0.375i +2 +#SCROLL 1+0.45i +1 +#SCROLL 1+0.525i +2 +#SCROLL 1+0.6i +1 +#SCROLL 1+0.675i +0 +#SCROLL 1+0.75i +2 +#SCROLL 1+0.825i +0 +#SCROLL 1+0.9i +1 +#SCROLL 1+0.975i +0 +#SCROLL 1+1.05i +2 +#SCROLL 1+1.125i +0, + +#SCROLL 1+1.2i +1 +#SCROLL 1+1.125i +1 +#SCROLL 1+1.05i +2 +#SCROLL 1+0.975i +1 +#SCROLL 1+0.9i +1 +#SCROLL 1+0.825i +0 +#SCROLL 1+0.75i +2 +#SCROLL 1+0.675i +0 +#SCROLL 1+0.6i +1 +#SCROLL 1+0.525i +0 +#SCROLL 1+0.45i +1 +#SCROLL 1+0.375i +1 +#SCROLL 1+0.3i +2 +#SCROLL 1+0.225i +1 +#SCROLL 1+0.15i +2 +#SCROLL 1+0.075i +2, + +#SCROLL 1+0.0i +1 +#SCROLL 1-0.075i +0 +#SCROLL 1-0.15i +1 +#SCROLL 1-0.225i +0 +#SCROLL 1-0.3i +1 +#SCROLL 1-0.375i +2 +#SCROLL 1-0.45i +1 +#SCROLL 1-0.525i +2 +#SCROLL 1-0.6i +1 +#SCROLL 1-0.675i +0 +#SCROLL 1-0.75i +2 +#SCROLL 1-0.825i +0 +#SCROLL 1-0.9i +1 +#SCROLL 1-0.975i +0 +#SCROLL 1-1.05i +2 +#SCROLL 1-1.125i +0, + +#SCROLL 1-1.2i +1 +#SCROLL 1-1.175i +0 +#SCROLL 1-1.15i +0 +#SCROLL 1-1.125i +1 +#SCROLL 1-1.1i +0 +#SCROLL 1-1.075i +0 +#SCROLL 1-1.05i +0 +#SCROLL 1-1.025i +0 +#SCROLL 1-1.0i +0 +#SCROLL 1-0.975i +2 +#SCROLL 1-0.95i +0 +#SCROLL 1-0.925i +0 +#SCROLL 1-0.9i +1 +#SCROLL 1-0.875i +0 +#SCROLL 1-0.85i +0 +#SCROLL 1-0.825i +0 +#SCROLL 1-0.8i +0 +#SCROLL 1-0.775i +0 +#SCROLL 1-0.75i +2 +#SCROLL 1-0.725i +0 +#SCROLL 1-0.7i +2 +#SCROLL 1-0.675i +0 +#SCROLL 1-0.65i +2 +#SCROLL 1-0.625i +0 +#SCROLL 1-0.6i +1 +#SCROLL 1-0.575i +0 +#SCROLL 1-0.55i +0 +#SCROLL 1-0.525i +1 +#SCROLL 1-0.5i +0 +#SCROLL 1-0.475i +0 +#SCROLL 1-0.45i +2 +#SCROLL 1-0.425i +0 +#SCROLL 1-0.4i +0 +#SCROLL 1-0.375i +2 +#SCROLL 1-0.35i +0 +#SCROLL 1-0.325i +0 +#SCROLL 1-0.3i +1 +#SCROLL 1-0.275i +0 +#SCROLL 1-0.25i +0 +#SCROLL 1-0.225i +1 +#SCROLL 1-0.2i +0 +#SCROLL 1-0.175i +0 +#SCROLL 1-0.15i +1 +#SCROLL 1-0.125i +0 +#SCROLL 1-0.1i +0 +#SCROLL 1-0.075i +1 +#SCROLL 1-0.05i +0 +#SCROLL 1-0.025i +0, +#GOGOEND + +#SCROLL 13.954 +G, +#END diff --git a/libs/audio.py b/libs/audio.py index 7bf300a..1aa5585 100644 --- a/libs/audio.py +++ b/libs/audio.py @@ -727,6 +727,10 @@ class AudioEngine: self.running = False self.audio_device_ready = False + self.sounds = {} + self.music_streams = {} + self.sound_queue = queue.Queue() + self.music_queue = queue.Queue() print("Audio device closed") return diff --git a/libs/tja.py b/libs/tja.py index ff5f787..54b3d35 100644 --- a/libs/tja.py +++ b/libs/tja.py @@ -176,7 +176,6 @@ class TJAParser: DIFFS = {0: "easy", 1: "normal", 2: "hard", 3: "oni", 4: "edit", 5: "tower", 6: "dan"} def __init__(self, path: Path, start_delay: int = 0, distance: int = 866): self.file_path: Path = path - print(self.file_path) lines = self.file_path.read_text(encoding='utf-8-sig').splitlines() self.data = [cleaned for line in lines diff --git a/libs/utils.py b/libs/utils.py index c9363d5..1cce13d 100644 --- a/libs/utils.py +++ b/libs/utils.py @@ -7,10 +7,15 @@ import zipfile from dataclasses import dataclass, field from functools import lru_cache from pathlib import Path -from typing import Any +from typing import Any, Optional import pyray as ray import tomlkit +from raylib import ( + SHADER_UNIFORM_FLOAT, + SHADER_UNIFORM_VEC2, + SHADER_UNIFORM_VEC4, +) #TJA Format creator is unknown. I did not create the format, but I did write the parser though. @@ -231,600 +236,150 @@ class GlobalData: global_data = GlobalData() -rotation_cache = dict() -char_size_cache = dict() -horizontal_cache = dict() -text_cache = set() -if not Path('cache/image').exists(): - Path('cache').mkdir() - Path('cache/image').mkdir() -for file in Path('cache/image').iterdir(): - text_cache.add(file.stem) - -@dataclass class OutlinedText: - text: str - font_size: int - text_color: ray.Color - outline_color: ray.Color - font: ray.Font = ray.Font() - outline_thickness: int = 2 - vertical: bool = False - line_spacing: float = 1.0 # Line spacing for vertical text - horizontal_spacing: float = 1.0 # Character spacing for horizontal text - lowercase_spacing_factor: float = 0.85 # Adjust spacing for lowercase letters and whitespace - vertical_chars: set = field(default_factory=lambda: {'-', '‐', '|', '/', '\\', 'ー', '~', '~', '(', ')', '(', ')', - '「', '」', '[', ']', '[', ']', '【', '】', '…', '→', '→', ':', ':'}) - no_space_chars: set = field(default_factory=lambda: { - 'ぁ', 'ア','ぃ', 'イ','ぅ', 'ウ','ぇ', 'エ','ぉ', 'オ', - 'ゃ', 'ャ','ゅ', 'ュ','ょ', 'ョ','っ', 'ッ','ゎ', 'ヮ', - 'ヶ', 'ヵ','ㇰ','ㇱ','ㇲ','ㇳ','ㇴ','ㇵ','ㇶ','ㇷ','ㇸ', - 'ㇹ','ㇺ','ㇻ','ㇼ','ㇽ','ㇾ','ㇿ' - }) - # New field for horizontal exception strings - horizontal_exceptions: set = field(default_factory=lambda: {'!!!!', '!!!', '!!', '!!','!!!','!?', '!?', '??', '??', '†††', '(°∀°)', '(°∀°)'}) - # New field for adjacent punctuation characters - adjacent_punctuation: set = field(default_factory=lambda: {'.', ',', '。', '、', "'", '"', '´', '`'}) + def __init__(self, text: str, font_size: int, color: ray.Color, outline_color: ray.Color, outline_thickness=5.0, vertical=False): + self.font = self._load_font_for_text(text) + if vertical: + self.texture = self._create_text_vertical(text, font_size, color, ray.BLANK, self.font) + else: + self.texture = self._create_text_horizontal(text, font_size, color, ray.BLANK, self.font) + outline_size = ray.ffi.new('float*', outline_thickness) + if isinstance(outline_color, tuple): + outline_color_alloc = ray.ffi.new("float[4]", [ + outline_color[0] / 255.0, + outline_color[1] / 255.0, + outline_color[2] / 255.0, + outline_color[3] / 255.0 + ]) + else: + outline_color_alloc = ray.ffi.new("float[4]", [ + outline_color.r / 255.0, + outline_color.g / 255.0, + outline_color.b / 255.0, + outline_color.a / 255.0 + ]) + texture_size = ray.ffi.new("float[2]", [self.texture.width, self.texture.height]) - def __post_init__(self): - # Cache for rotated characters - self._rotation_cache = rotation_cache - # Cache for character measurements - self._char_size_cache = char_size_cache - # Cache for horizontal exception measurements - self._horizontal_cache = horizontal_cache - self.hash = self._get_hash() - self.texture = self._create_texture() + self.shader = ray.load_shader('', 'shader/outline.fs') + outline_size_loc = ray.get_shader_location(self.shader, "outlineSize") + outline_color_loc = ray.get_shader_location(self.shader, "outlineColor") + texture_size_loc = ray.get_shader_location(self.shader, "textureSize") + self.alpha_loc = ray.get_shader_location(self.shader, "alpha") + ray.set_shader_value(self.shader, outline_size_loc, outline_size, SHADER_UNIFORM_FLOAT) + ray.set_shader_value(self.shader, outline_color_loc, outline_color_alloc, SHADER_UNIFORM_VEC4) + ray.set_shader_value(self.shader, texture_size_loc, texture_size, SHADER_UNIFORM_VEC2) def _load_font_for_text(self, text: str) -> ray.Font: codepoint_count = ray.ffi.new('int *', 0) unique_codepoints = set(text) codepoints = ray.load_codepoints(''.join(unique_codepoints), codepoint_count) - return ray.load_font_ex(str(Path('Graphics/Modified-DFPKanteiryu-XB.ttf')), self.font_size, codepoints, 0) + return ray.load_font_ex(str(Path('Graphics/Modified-DFPKanteiryu-XB.ttf')), 40, codepoints, 0) - def _get_hash(self): - n = hashlib.sha256() - n.update(self.text.encode('utf-8')) - n.update(str(self.vertical).encode('utf-8')) - n.update(str(self.horizontal_spacing).encode('utf-8')) # Include horizontal spacing in hash - n.update(str(self.outline_color.a).encode('utf-8')) - n.update(str(self.outline_color.r).encode('utf-8')) - n.update(str(self.outline_color.g).encode('utf-8')) - n.update(str(self.outline_color.b).encode('utf-8')) - n.update(str(self.text_color.a).encode('utf-8')) - n.update(str(self.text_color.r).encode('utf-8')) - n.update(str(self.text_color.g).encode('utf-8')) - n.update(str(self.text_color.b).encode('utf-8')) - n.update(str(self.font_size).encode('utf-8')) - return n.hexdigest() + def _create_text_vertical(self, text: str, font_size: int, color: ray.Color, bg_color: ray.Color, font: Optional[ray.Font]=None, padding: int=10): + rotate_chars = {'-', '‐', '|', '/', '\\', 'ー', '~', '~', '(', ')', '(', ')', + '「', '」', '[', ']', '[', ']', '【', '】', '…', '→', '→', ':', ':'} + max_char_width = 0 + total_height = padding * 2 # Top and bottom padding - def _parse_text_segments(self): - """Parse text into segments, identifying horizontal exceptions""" - if not self.vertical: - return [{'text': self.text, 'is_horizontal': False}] - - segments = [] - i = 0 - current_segment = "" - - while i < len(self.text): - # Check if any horizontal exception starts at current position - found_exception = None - for exception in self.horizontal_exceptions: - if self.text[i:].startswith(exception): - found_exception = exception - break - - if found_exception: - # Save current segment if it exists - if current_segment: - segments.append({'text': current_segment, 'is_horizontal': False}) - current_segment = "" - - # Add horizontal exception as separate segment - segments.append({'text': found_exception, 'is_horizontal': True}) - i += len(found_exception) + for char in text: + if font: + char_size = ray.measure_text_ex(font, char, font_size, 0) else: - # Add character to current segment - current_segment += self.text[i] - i += 1 + char_width = ray.measure_text(char, font_size) + char_size = ray.Vector2(char_width, font_size) - # Add remaining segment - if current_segment: - segments.append({'text': current_segment, 'is_horizontal': False}) - - return segments - - def _group_characters_with_punctuation(self, text): - """Group characters with their adjacent punctuation""" - groups = [] - i = 0 - - while i < len(text): - current_char = text[i] - group = {'main_char': current_char, 'adjacent_punct': []} - - # Look ahead for adjacent punctuation - j = i + 1 - while j < len(text) and text[j] in self.adjacent_punctuation: - group['adjacent_punct'].append(text[j]) - j += 1 - - groups.append(group) - i = j # Move to next non-punctuation character - - return groups - - def _get_horizontal_exception_texture(self, text: str, color): - """Get or create a texture for horizontal exception text""" - cache_key = (text, color.r, color.g, color.b, color.a, 'horizontal') - - if cache_key in self._horizontal_cache: - return self._horizontal_cache[cache_key] - - # Measure the text - text_size = ray.measure_text_ex(self.font, text, self.font_size, 1.0) - padding = int(self.outline_thickness * 3) - - # Create image with proper dimensions - img_width = int(text_size.x + padding * 2) - img_height = int(text_size.y + padding * 2) - temp_image = ray.gen_image_color(img_width, img_height, ray.Color(0, 0, 0, 0)) - - # Draw the text centered - ray.image_draw_text_ex( - temp_image, - self.font, - text, - ray.Vector2(padding, padding), - self.font_size, - 1.0, - color - ) - - # Cache the image - self._horizontal_cache[cache_key] = temp_image - return temp_image - - def _get_char_size(self, char): - """Cache character size measurements""" - if char not in self._char_size_cache: - if char in self.vertical_chars: - # For vertical chars, width and height are swapped - self._char_size_cache[char] = ray.Vector2(self.font_size, self.font_size) + # If character should be rotated, swap width and height for measurements + if char in rotate_chars: + effective_width = char_size.y # Height becomes width when rotated 90° else: - self._char_size_cache[char] = ray.measure_text_ex(self.font, char, self.font_size, 1.0) - return self._char_size_cache[char] + effective_width = char_size.x - def _calculate_vertical_spacing(self, current_char, next_char=None): - """Calculate vertical spacing between characters""" - # Check if current char is lowercase, whitespace or a special character - is_spacing_char = (current_char.islower() or - current_char.isspace()) + max_char_width = max(max_char_width, effective_width) - # Additional check for capitalization transition - if next_char and ((current_char.isupper() and next_char.islower()) or - next_char in self.no_space_chars): - is_spacing_char = True + total_height += len(text) * font_size + width = int(max_char_width + (padding * 2)) # Add left and right padding + height = total_height + image = ray.gen_image_color(width, height, bg_color) - # Apply spacing factor if it's a spacing character - spacing = self.line_spacing * (self.lowercase_spacing_factor if is_spacing_char else 1.0) - return self.font_size * spacing + for i, char in enumerate(text): + char_y = i * ray.measure_text_ex(self.font, char, font_size, 0).y + char_y += padding - def _get_rotated_char(self, char: str, color): - """Get or create a rotated character texture from cache""" - cache_key = (char, color.r, color.g, color.b, color.a) - - if cache_key in self._rotation_cache: - return self._rotation_cache[cache_key] - - char_size = self._get_char_size(char) - padding = int(self.outline_thickness * 3) # Increased padding - temp_width = max(int(char_size.y) + padding, self.font_size + padding) - temp_height = max(int(char_size.x) + padding, self.font_size + padding) - temp_image = ray.gen_image_color(temp_width, temp_height, ray.Color(0, 0, 0, 0)) - - center_x = (temp_width - char_size.y) // 2 - center_y = (temp_height - char_size.x) // 2 - - ray.image_draw_text_ex( - temp_image, - self.font, - char, - ray.Vector2(center_x-5, center_y), # Centered placement with padding - self.font_size, - 1.0, - color - ) - - # Rotate the temporary image 90 degrees counterclockwise - rotated_image = ray.gen_image_color(temp_height, temp_width, ray.Color(0, 0, 0, 0)) - for x in range(temp_width): - for y in range(temp_height): - pixel = ray.get_image_color(temp_image, x, temp_height - y - 1) - ray.image_draw_pixel(rotated_image, y, x, pixel) - - # Unload temporary image - ray.unload_image(temp_image) - - # Cache the rotated image - self._rotation_cache[cache_key] = rotated_image - return rotated_image - - def _calculate_horizontal_text_width(self): - """Calculate the total width of horizontal text with custom spacing""" - if not self.text: - return 0 - - total_width = 0 - for i, char in enumerate(self.text): - char_size = ray.measure_text_ex(self.font, char, self.font_size, 1.0) - total_width += char_size.x - - # Add spacing between characters (except for the last character) - if i < len(self.text) - 1: - total_width += (char_size.x * (self.horizontal_spacing - 1.0)) - - return total_width - - def _calculate_dimensions(self): - padding = int(self.outline_thickness * 3) - - if not self.vertical: - if self.horizontal_spacing == 1.0: - # Use default raylib measurement for normal spacing - text_size = ray.measure_text_ex(self.font, self.text, self.font_size, 1.0) - return int(text_size.x + padding * 2), int(text_size.y + padding * 2) + if font: + char_size = ray.measure_text_ex(font, char, font_size, 0) + char_image = ray.image_text_ex(font, char, font_size, 0, color) else: - # Calculate custom spacing width - text_width = self._calculate_horizontal_text_width() - text_height = ray.measure_text_ex(self.font, "Ag", self.font_size, 1.0).y # Use sample chars for height - return int(text_width + padding * 2), int(text_height + padding * 2) + char_width = ray.measure_text(char, font_size) + char_size = ray.Vector2(char_width, font_size) + char_image = ray.image_text(char, font_size, color) + + # Rotate character if it's in the rotate_chars set + if char in rotate_chars: + rotated_image = ray.gen_image_color(char_image.height, char_image.width, ray.BLANK) + + # Manual 90-degree clockwise rotation + for y in range(char_image.height): + for x in range(char_image.width): + src_color = ray.get_image_color(char_image, x, y) + # 90° clockwise: new_x = old_y, new_y = width - 1 - old_x + new_x = y + new_y = char_image.width - 1 - x + ray.image_draw_pixel(rotated_image, new_x, new_y, src_color) + + ray.unload_image(char_image) + char_image = rotated_image + effective_width = char_size.y # Height becomes width when rotated + else: + effective_width = char_size.x + + # Center the character horizontally + char_x = width // 2 - effective_width // 2 + + ray.image_draw(image, char_image, + ray.Rectangle(0, 0, char_image.width, char_image.height), + ray.Rectangle(char_x, char_y, char_image.width, char_image.height), + ray.WHITE) + ray.unload_image(char_image) + + texture = ray.load_texture_from_image(image) + ray.unload_image(image) + return texture + + def _create_text_horizontal(self, text: str, font_size: int, color: ray.Color, bg_color: ray.Color, font: Optional[ray.Font]=None, padding: int=10): + if font: + text_size = ray.measure_text_ex(font, text, font_size, 0) + total_width = text_size.x + (padding * 2) + total_height = text_size.y + (padding * 2) else: - # Parse text into segments - segments = self._parse_text_segments() - - char_heights = [] - char_widths = [] - - for segment in segments: - if segment['is_horizontal']: - # For horizontal exceptions, add their height as spacing - text_size = ray.measure_text_ex(self.font, segment['text'], self.font_size, 1.0) - char_heights.append(text_size.y * self.line_spacing) - char_widths.append(text_size.x) - else: - # Process vertical text with character grouping - char_groups = self._group_characters_with_punctuation(segment['text']) - - for i, group in enumerate(char_groups): - main_char = group['main_char'] - adjacent_punct = group['adjacent_punct'] - - # Get next group's main character for spacing calculation - next_char = char_groups[i+1]['main_char'] if i+1 < len(char_groups) else None - char_heights.append(self._calculate_vertical_spacing(main_char, next_char)) - - # Calculate width considering main char + adjacent punctuation - main_char_size = self._get_char_size(main_char) - group_width = main_char_size.x - - # Add width for adjacent punctuation - for punct in adjacent_punct: - punct_size = self._get_char_size(punct) - group_width += punct_size.x - - # For vertical characters, consider rotated dimensions - if main_char in self.vertical_chars: - char_widths.append(group_width + padding) - else: - char_widths.append(group_width) - - max_char_width = max(char_widths) if char_widths else 0 - total_height = sum(char_heights) if char_heights else 0 - - width = int(max_char_width + padding * 2) # Padding on both sides - height = int(total_height + padding * 2) # Padding on top and bottom - - return width, height - - def _draw_horizontal_text(self, image): - if self.horizontal_spacing == 1.0: - # Use original method for normal spacing - text_size = ray.measure_text_ex(self.font, self.text, self.font_size, 1.0) - position = ray.Vector2((image.width - text_size.x) / 2, (image.height - text_size.y) / 2) - - for dx in range(-self.outline_thickness, self.outline_thickness + 1): - for dy in range(-self.outline_thickness, self.outline_thickness + 1): - # Skip the center position (will be drawn as main text) - if dx == 0 and dy == 0: - continue - - # Calculate outline distance - dist = (dx*dx + dy*dy) ** 0.5 - - # Only draw outline positions that are near the outline thickness - if dist <= self.outline_thickness + 0.5: - ray.image_draw_text_ex( - image, - self.font, - self.text, - ray.Vector2(position.x + dx, position.y + dy), - self.font_size, - 1.0, - self.outline_color - ) - - # Draw main text - ray.image_draw_text_ex( - image, - self.font, - self.text, - position, - self.font_size, - 1.0, - self.text_color - ) + total_width = ray.measure_text(text, font_size) + (padding * 2) + total_height = font_size + (padding * 2) + image = ray.gen_image_color(int(total_width), int(total_height), bg_color) + if font: + text_image = ray.image_text_ex(font, text, font_size, 0, color) else: - # Draw text with custom character spacing - text_width = self._calculate_horizontal_text_width() - text_height = ray.measure_text_ex(self.font, "Ag", self.font_size, 1.0).y + text_image = ray.image_text(text, font_size, color) + text_x = padding + text_y = padding + ray.image_draw(image, text_image, + ray.Rectangle(0, 0, text_image.width, text_image.height), + ray.Rectangle(text_x, text_y, text_image.width, text_image.height), + ray.WHITE) + ray.unload_image(text_image) - start_x = (image.width - text_width) / 2 - start_y = (image.height - text_height) / 2 - - # First draw all outlines - current_x = start_x - for i, char in enumerate(self.text): - char_size = ray.measure_text_ex(self.font, char, self.font_size, 1.0) - - for dx in range(-self.outline_thickness, self.outline_thickness + 1): - for dy in range(-self.outline_thickness, self.outline_thickness + 1): - if dx == 0 and dy == 0: - continue - - dist = (dx*dx + dy*dy) ** 0.5 - if dist <= self.outline_thickness + 0.5: - ray.image_draw_text_ex( - image, - self.font, - char, - ray.Vector2(current_x + dx, start_y + dy), - self.font_size, - 1.0, - self.outline_color - ) - - # Move to next character position - current_x += char_size.x - if i < len(self.text) - 1: # Add spacing except for last character - current_x += (char_size.x * (self.horizontal_spacing - 1.0)) - - # Then draw all main text - current_x = start_x - for i, char in enumerate(self.text): - char_size = ray.measure_text_ex(self.font, char, self.font_size, 1.0) - - ray.image_draw_text_ex( - image, - self.font, - char, - ray.Vector2(current_x, start_y), - self.font_size, - 1.0, - self.text_color - ) - - # Move to next character position - current_x += char_size.x - if i < len(self.text) - 1: # Add spacing except for last character - current_x += (char_size.x * (self.horizontal_spacing - 1.0)) - - def _draw_vertical_text(self, image, width): - padding = int(self.outline_thickness * 2) - segments = self._parse_text_segments() - - positions = [] - current_y = padding # Start with padding at the top - - for segment in segments: - if segment['is_horizontal']: - # Handle horizontal exception - text_size = ray.measure_text_ex(self.font, segment['text'], self.font_size, 1.0) - center_offset = (width - text_size.x) // 2 - char_height = text_size.y * self.line_spacing - - positions.append({ - 'type': 'horizontal', - 'text': segment['text'], - 'x': center_offset, - 'y': current_y, - 'height': char_height - }) - current_y += char_height - else: - # Handle vertical text with character grouping - char_groups = self._group_characters_with_punctuation(segment['text']) - - for i, group in enumerate(char_groups): - main_char = group['main_char'] - adjacent_punct = group['adjacent_punct'] - - # Get next group for spacing calculation - next_char = char_groups[i+1]['main_char'] if i+1 < len(char_groups) else None - char_height = self._calculate_vertical_spacing(main_char, next_char) - - # Calculate positioning for main character - main_char_size = self._get_char_size(main_char) - - if main_char in self.vertical_chars: - rotated_img = self._get_rotated_char(main_char, self.text_color) - main_char_width = rotated_img.width - center_offset = (width - main_char_width) // 2 - else: - main_char_width = main_char_size.x - center_offset = (width - main_char_width) // 2 - - # Add main character position - positions.append({ - 'type': 'vertical', - 'char': main_char, - 'x': center_offset, - 'y': current_y, - 'height': char_height, - 'is_vertical_char': main_char in self.vertical_chars - }) - - # Add adjacent punctuation positions - punct_x_offset = center_offset + main_char_width - for punct in adjacent_punct: - punct_size = self._get_char_size(punct) - - positions.append({ - 'type': 'vertical', - 'char': punct, - 'x': punct_x_offset, - 'y': current_y+5, - 'height': 0, # No additional height for punctuation - 'is_vertical_char': punct in self.vertical_chars, - 'is_adjacent': True - }) - - punct_x_offset += punct_size.x - - current_y += char_height - - # First draw all outlines - outline_thickness = int(self.outline_thickness) - - for pos in positions: - if pos['type'] == 'horizontal': - # Draw horizontal text outline - for dx in range(-outline_thickness, outline_thickness + 1): - for dy in range(-outline_thickness, outline_thickness + 1): - if dx == 0 and dy == 0: - continue - - dist = (dx*dx + dy*dy) ** 0.5 - if dist <= outline_thickness + 0.5: - ray.image_draw_text_ex( - image, - self.font, - pos['text'], - ray.Vector2(pos['x'] + dx, pos['y'] + dy), - self.font_size, - 1.0, - self.outline_color - ) - else: - # Draw vertical character outline - for dx in range(-outline_thickness, outline_thickness + 1): - for dy in range(-outline_thickness, outline_thickness + 1): - if dx == 0 and dy == 0: - continue - - dist = (dx*dx + dy*dy) ** 0.5 - if dist <= outline_thickness + 0.5: - if pos['is_vertical_char']: - rotated_img = self._get_rotated_char(pos['char'], self.outline_color) - ray.image_draw( - image, - rotated_img, - ray.Rectangle(0, 0, rotated_img.width, rotated_img.height), - ray.Rectangle( - int(pos['x'] + dx), - int(pos['y'] + dy), - rotated_img.width, - rotated_img.height - ), - ray.WHITE - ) - else: - ray.image_draw_text_ex( - image, - self.font, - pos['char'], - ray.Vector2(pos['x'] + dx, pos['y'] + dy), - self.font_size, - 1.0, - self.outline_color - ) - - # Then draw all main text - for pos in positions: - if pos['type'] == 'horizontal': - # Draw horizontal text - ray.image_draw_text_ex( - image, - self.font, - pos['text'], - ray.Vector2(pos['x'], pos['y']), - self.font_size, - 1.0, - self.text_color - ) - else: - # Draw vertical character - if pos['is_vertical_char']: - rotated_img = self._get_rotated_char(pos['char'], self.text_color) - ray.image_draw( - image, - rotated_img, - ray.Rectangle(0, 0, rotated_img.width, rotated_img.height), - ray.Rectangle( - int(pos['x']), - int(pos['y']), - rotated_img.width, - rotated_img.height - ), - ray.WHITE - ) - else: - ray.image_draw_text_ex( - image, - self.font, - pos['char'], - ray.Vector2(pos['x'], pos['y']), - self.font_size, - 1.0, - self.text_color - ) - - def _create_texture(self): - if self.hash in text_cache: - texture = ray.load_texture(f'cache/image/{self.hash}.png') - return texture - - self.font = self._load_font_for_text(self.text) - - width, height = self._calculate_dimensions() - - width += int(self.outline_thickness * 1.5) - height += int(self.outline_thickness * 1.5) - - image = ray.gen_image_color(width, height, ray.Color(0, 0, 0, 0)) - - if not self.vertical: - self._draw_horizontal_text(image) - else: - self._draw_vertical_text(image, width) - - ray.export_image(image, f'cache/image/{self.hash}.png') - text_cache.add(self.hash) texture = ray.load_texture_from_image(image) ray.unload_image(image) return texture def draw(self, src: ray.Rectangle, dest: ray.Rectangle, origin: ray.Vector2, rotation: float, color: ray.Color): + if isinstance(color, tuple): + alpha_value = ray.ffi.new('float*', color[3] / 255.0) + else: + alpha_value = ray.ffi.new('float*', color.a / 255.0) + ray.set_shader_value(self.shader, self.alpha_loc, alpha_value, SHADER_UNIFORM_FLOAT) + ray.begin_shader_mode(self.shader) ray.draw_texture_pro(self.texture, src, dest, origin, rotation, color) + ray.end_shader_mode() def unload(self): - for img in self._rotation_cache.values(): - ray.unload_image(img) - self._rotation_cache.clear() - - for img in self._horizontal_cache.values(): - ray.unload_image(img) - self._horizontal_cache.clear() - + ray.unload_shader(self.shader) ray.unload_texture(self.texture) diff --git a/scenes/devtest.py b/scenes/devtest.py new file mode 100644 index 0000000..a19fa1f --- /dev/null +++ b/scenes/devtest.py @@ -0,0 +1,32 @@ +import pyray as ray + +from libs.utils import OutlinedText, get_current_ms + + +class DevScreen: + def __init__(self, width: int, height: int): + self.width = width + self.height = height + self.screen_init = False + + self.time_now = get_current_ms() + self.test = OutlinedText('Triple Helix', 40, ray.Color(255, 255, 255, 255), ray.Color(101, 0, 82, 255), outline_thickness=4, vertical=True) + + def on_screen_start(self): + if not self.screen_init: + self.screen_init = True + + def on_screen_end(self, next_screen: str): + self.screen_init = False + return next_screen + + def update(self): + self.on_screen_start() + if ray.is_key_pressed(ray.KeyboardKey.KEY_ENTER): + return self.on_screen_end('TITLE') + + def draw(self): + ray.draw_rectangle(0, 0, self.width, self.height, ray.WHITE) + src = ray.Rectangle(0, 0, self.test.texture.width, self.test.texture.height) + dest = ray.Rectangle(self.width//2 - self.test.texture.width//2, self.height//2 - self.test.texture.height//2, self.test.texture.width, self.test.texture.height) + self.test.draw(src, dest, ray.Vector2(0, 0), 0, ray.WHITE) diff --git a/scenes/entry.py b/scenes/entry.py index 139118c..9b8f742 100644 --- a/scenes/entry.py +++ b/scenes/entry.py @@ -279,12 +279,12 @@ class EntryScreen: box_title = self.box_titles[i][1] src = ray.Rectangle(0, 0, box_title.texture.width, box_title.texture.height) - dest = ray.Rectangle(final_x + 12, y + 20, box_title.texture.width, box_title.texture.height) + dest = ray.Rectangle(final_x + 25, y + 20, box_title.texture.width, box_title.texture.height) box_title.draw(src, dest, ray.Vector2(0, 0), 0, color) else: box_title = self.box_titles[i][0] src = ray.Rectangle(0, 0, box_title.texture.width, box_title.texture.height) - dest = ray.Rectangle(final_x + 9, y + 20, box_title.texture.width, box_title.texture.height) + dest = ray.Rectangle(final_x + 20, y + 20, box_title.texture.width, box_title.texture.height) box_title.draw(src, dest, ray.Vector2(0, 0), 0, color) def draw(self): diff --git a/scenes/settings.py b/scenes/settings.py index d5a685e..04e0166 100644 --- a/scenes/settings.py +++ b/scenes/settings.py @@ -1,6 +1,7 @@ import pyray as ray import sounddevice as sd +from libs.audio import audio from libs.utils import ( global_data, is_l_don_pressed, @@ -34,6 +35,9 @@ class SettingsScreen: self.screen_init = False save_config(self.config) global_data.config = self.config + audio.close_audio_device() + audio.type = global_data.config["audio"]["device_type"] + audio.init_audio_device() return "ENTRY" def get_current_settings(self): diff --git a/scenes/song_select.py b/scenes/song_select.py index cce86fd..a944d3b 100644 --- a/scenes/song_select.py +++ b/scenes/song_select.py @@ -400,7 +400,7 @@ class SongBox: self.tja_count = tja_count self.tja_count_text = None if self.tja_count is not None and self.tja_count != 0: - self.tja_count_text = OutlinedText(str(self.tja_count), 35, ray.Color(255, 255, 255, 255), ray.Color(0, 0, 0, 255), outline_thickness=5, horizontal_spacing=1.2) + self.tja_count_text = OutlinedText(str(self.tja_count), 35, ray.Color(255, 255, 255, 255), ray.Color(0, 0, 0, 255), outline_thickness=5)#, horizontal_spacing=1.2) self.tja = tja self.hash = dict() self.update(False) @@ -1007,6 +1007,8 @@ class SongFile(FileSystemItem): def __init__(self, path: Path, name: str, texture_index: int, tja=None, name_texture_index: Optional[int]=None): super().__init__(path, name) self.is_recent = (datetime.now() - datetime.fromtimestamp(path.stat().st_mtime)) <= timedelta(days=7) + if self.is_recent: + print(name, (datetime.now() - datetime.fromtimestamp(path.stat().st_mtime))) self.tja = tja or TJAParser(path) if self.is_recent: self.tja.ex_data.new = True diff --git a/shader/outline.fs b/shader/outline.fs new file mode 100644 index 0000000..61708d1 --- /dev/null +++ b/shader/outline.fs @@ -0,0 +1,40 @@ +#version 330 +in vec2 fragTexCoord; +in vec4 fragColor; +uniform sampler2D texture0; +uniform vec4 colDiffuse; +uniform vec2 textureSize; +uniform float outlineSize; +uniform vec4 outlineColor; +uniform float alpha; +uniform float smoothness = 1.0; // Add this uniform for control (0.0-1.0) +out vec4 finalColor; + +void main() +{ + vec4 texel = texture(texture0, fragTexCoord); + vec2 texelScale = vec2(outlineSize/textureSize.x, outlineSize/textureSize.y); + + // Calculate outline + float outline = 0.0; + int ringSamples = 64; + int rings = 4; + for(int ring = 1; ring <= rings; ring++) { + float ringRadius = float(ring) / float(rings); + for(int i = 0; i < ringSamples; i++) { + float angle = 2.0 * 3.14159 * float(i) / float(ringSamples); + vec2 offset = vec2(cos(angle), sin(angle)) * texelScale * ringRadius; + outline += texture(texture0, fragTexCoord + offset).a / float(rings); + } + } + outline = min(outline, 1.0); + outline = smoothstep(0.1, 0.6, outline); + + float edgeStart = 0.5 - smoothness * 0.3; + float edgeEnd = 0.5 + smoothness * 0.3; + float textAlpha = smoothstep(edgeStart, edgeEnd, texel.a); + vec3 color = mix(outlineColor.rgb, texel.rgb, textAlpha); + float combinedAlpha = mix(outline * outlineColor.a, texel.a, textAlpha); + + finalColor = vec4(color, combinedAlpha * alpha); +}