z_mirror/sdl-osu
git clone https://git.raiguard.me/z_mirror/sdl-osu
836a89c
trunk
1#include "beatmapselector.h" 2#include "beatmap.h" 3#include "beatmapstore.h" 4#include "game.h" 5#include "graphics.h" 6#include "util.h" 7#include <SDL3/SDL.h> 8#include <SDL3_ttf/SDL_ttf.h> 9#include <stdio.h> 10#include <stdlib.h> 11 12int Osu_SortBeatmapsByTitle (const void * userdata1 ,const void * userdata2 ) { 13const struct Osu_Beatmap * beatmap1 = * (struct Osu_Beatmap ** )userdata1 ; 14const struct Osu_Beatmap * beatmap2 = * (struct Osu_Beatmap ** )userdata2 ; 15 16SDL_assert (beatmap1 -> title ); 17SDL_assert (beatmap2 -> title ); 18 19return strcmp (beatmap1 -> title ,beatmap2 -> title ); 20} 21 22struct Osu_BeatmapSelector * Osu_CreateBeatmapSelector (struct Osu_Game * game ,struct Osu_BeatmapStore * beatmapStore ) { 23struct Osu_BeatmapSelector * selector = calloc (1 ,sizeof (struct Osu_BeatmapSelector )); 24selector -> beatmaps = calloc (beatmapStore -> beatmapsLen ,sizeof (struct Osu_BeatmapStore )); 25selector -> beatmapsLen = beatmapStore -> beatmapsLen ; 26memcpy (selector -> beatmaps ,beatmapStore -> beatmaps ,sizeof (struct Osu_Beatmap * )* selector -> beatmapsLen ); 27qsort (selector -> beatmaps ,selector -> beatmapsLen ,sizeof (struct Osu_Beatmap * ),Osu_SortBeatmapsByTitle ); 28 29selector -> beatmapTexts = calloc (selector -> beatmapsLen ,sizeof (struct SDL_Text * )); 30for (size_t i = 0 ;i < selector -> beatmapsLen ;i ++ ) { 31struct Osu_Beatmap * beatmap = selector -> beatmaps [i ]; 32char label [512 ]; 33snprintf (label ,512 ,"%s (%s)" ,beatmap -> title ,beatmap -> version ); 34selector -> beatmapTexts [i ]= TTF_CreateText (game -> graphics -> textEngine ,game -> graphics -> font ,label ,0 ); 35 } 36 37SDL_SAFECALL (SDL_StartTextInput ,game -> graphics -> window ); 38 39return selector ; 40} 41 42void Osu_DestroyBeatmapSelector (struct Osu_Game * game ,struct Osu_BeatmapSelector * selector ) { 43if (selector -> beatmapTexts ) { 44for (size_t i = 0 ;i < selector -> beatmapsLen ;i ++ ) { 45TTF_DestroyText (selector -> beatmapTexts [i ]); 46 } 47free (selector -> beatmapTexts ); 48selector -> beatmapTexts = NULL ; 49 } 50 51SDL_SAFECALL (SDL_StopTextInput ,game -> graphics -> window ); 52 53free (selector -> beatmaps );// Does not own the contained pointers. 54free (selector ); 55} 56 57void Osu_HandleBeatmapSelectorEvent (struct Osu_Game * game ,struct Osu_BeatmapSelector * selector ,union SDL_Event * event ) { 58if (event -> type == SDL_EVENT_MOUSE_WHEEL ) { 59selector -> beatmapYOffset += event -> wheel .y * 100 ; 60if (selector -> beatmapYOffset > 0 ) { 61selector -> beatmapYOffset = 0 ; 62 } 63 } 64 65if (event -> type == SDL_EVENT_KEY_UP && event -> key .key == SDLK_F2 ) { 66Osu_SetSelectedBeatmap (game ,game -> beatmaps -> beatmaps [Osu_Random (0 ,game -> beatmaps -> beatmapsLen - 1 )]); 67 } 68 69if (event -> type == SDL_EVENT_TEXT_INPUT ) { 70SDL_strlcat (selector -> searchText ,event -> text .text ,sizeof (selector -> searchText )); 71 }else if (event -> type == SDL_EVENT_KEY_DOWN && event -> key .key == SDLK_BACKSPACE ) { 72size_t len = SDL_strlen (selector -> searchText ); 73if (len > 0 ) { 74const char * cursor = selector -> searchText + len ; 75SDL_StepBackUTF8 (selector -> searchText ,& cursor ); 76selector -> searchText [cursor - selector -> searchText ]= 0 ; 77 } 78 }else if (event -> type == SDL_EVENT_KEY_UP && event -> key .key == SDLK_RETURN ) { 79Osu_EnterBeatmap (game ,selector -> selectedBeatmap ); 80 } 81// TODO: This is all very messy and hardcoded, bad! 82if (event -> type == SDL_EVENT_MOUSE_BUTTON_UP ) { 83int screenW ,screenH ; 84SDL_GetWindowSizeInPixels (game -> graphics -> window ,& screenW ,& screenH ); 85float backgroundW ,backgroundH ; 86SDL_GetTextureSize (game -> graphics -> beatmapWedgeTexture ,& backgroundW ,& backgroundH ); 87SDL_FRect backgroundRect = { 88 .x = screenW - ((backgroundW /5 )* 4 ), 89 .y = 0 , 90 .w = backgroundW , 91 .h = backgroundH , 92 }; 93SDL_FPoint mousePoint = { 94 .x = event -> button .x * SDL_GetWindowDisplayScale (game -> graphics -> window ), 95 .y = event -> button .y * SDL_GetWindowDisplayScale (game -> graphics -> window ), 96 }; 97size_t drawnIndex = 0 ; 98for (size_t i = 0 ;i < selector -> beatmapsLen ;i ++ ) { 99if (strlen (selector -> searchText )> 0 && !SDL_strstr (selector -> beatmaps [i ]-> title ,selector -> searchText )) { 100continue ; 101 } 102drawnIndex ++ ; 103int y = selector -> beatmapYOffset + drawnIndex * (backgroundH * 0.8 ); 104if (y + backgroundH < 0 ) { 105continue ; 106 } 107if (y > screenH ) { 108break ; 109 } 110backgroundRect .y = y ; 111if (SDL_PointInRectFloat (& mousePoint ,& backgroundRect )) { 112Osu_SetSelectedBeatmap (game ,selector -> beatmaps [i ]); 113break ; 114 } 115 } 116 } 117} 118 119void Osu_RenderBeatmapSelector (struct Osu_BeatmapSelector * selector ,struct Osu_Graphics * graphics ) { 120float wedgeW ,wedgeH ; 121SDL_GetTextureSize (graphics -> beatmapWedgeTexture ,& wedgeW ,& wedgeH ); 122struct SDL_FRect backgroundRect = { 123 .x = graphics -> screenRect .w - ((wedgeW /5 )* 4 ), 124 .y = 0 , 125 .w = wedgeW , 126 .h = wedgeH , 127 }; 128 129struct SDL_FPoint mousePoint ; 130SDL_GetMouseState (& mousePoint .x ,& mousePoint .y ); 131mousePoint .x *=SDL_GetWindowDisplayScale (graphics -> window ); 132mousePoint .y *=SDL_GetWindowDisplayScale (graphics -> window ); 133 134size_t drawnIndex = 0 ; 135for (size_t i = 0 ;i < selector -> beatmapsLen ;i ++ ) { 136if (strlen (selector -> searchText )> 0 && !SDL_strstr (selector -> beatmaps [i ]-> title ,selector -> searchText )) { 137continue ; 138 } 139drawnIndex ++ ; 140int y = selector -> beatmapYOffset + drawnIndex * (wedgeH * 0.8 ); 141if (y + wedgeH < 0 ) { 142continue ; 143 } 144if (y > graphics -> screenRect .h ) { 145break ; 146 } 147backgroundRect .y = y ; 148if (selector -> selectedBeatmap == selector -> beatmaps [i ]) { 149SDL_SetTextureColorMod (graphics -> beatmapWedgeTexture ,200 ,200 ,200 ); 150 }else if (SDL_PointInRectFloat (& mousePoint ,& backgroundRect )) { 151SDL_SetTextureColorMod (graphics -> beatmapWedgeTexture ,255 ,150 ,245 ); 152 }else { 153SDL_SetTextureColorMod (graphics -> beatmapWedgeTexture ,255 ,110 ,245 ); 154 } 155SDL_RenderTexture (graphics -> renderer ,graphics -> beatmapWedgeTexture ,NULL ,& backgroundRect ); 156TTF_DrawRendererText (selector -> beatmapTexts [i ],backgroundRect .x + 255 ,y + 30 ); 157 } 158 159struct SDL_FRect topTexRect = Osu_GetTextureRect (graphics -> songSelectTopTexture ); 160struct SDL_FRect destRect = { 161 .x = 0 , 162 .y = 0 , 163 .w = topTexRect .w * 2 , 164 .h = topTexRect .h * 2 , 165 }; 166SDL_RenderTexture (graphics -> renderer ,graphics -> songSelectTopTexture ,& topTexRect ,& destRect ); 167}