z_mirror/sdl-osu

git clone https://git.raiguard.me/z_mirror/sdl-osu

Caleb HeuerSync metadata version with version from meson.builddbd643c

trunk
6.2 KiB148 linesraw
1#include "graphics.h"
2#include "beatmapselector.h"
3#include "defines.h"
4#include "util.h"
5#include <SDL3/SDL.h>
6#include <SDL3_image/SDL_image.h>
7#include <SDL3_ttf/SDL_ttf.h>
8#include <stdio.h>
9#include <stdlib.h>
10
11struct Osu_Graphics* Osu_CreateGraphics(const char* dataPath) {
12    SDL_SAFECALL(SDL_Init, SDL_INIT_VIDEO);
13
14    struct Osu_Graphics* graphics = calloc(1, sizeof(struct Osu_Graphics));
15    SDL_SAFECALL(SDL_CreateWindowAndRenderer, "osu! " OSU_VERSION, 800, 600,
16                 SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_RESIZABLE | SDL_WINDOW_FULLSCREEN,
17                 &graphics->window, &graphics->renderer)
18
19    // TODO: Go through all calls and check which actually need to be fatal errors.
20    SDL_SAFECALL(SDL_SetRenderVSync, graphics->renderer, true);
21
22    SDL_SAFECALL(SDL_HideCursor);
23
24    char path[512];
25    snprintf(path, 512, "%s" OSU_PATHSEP "assets" OSU_PATHSEP "Inter-Medium.ttf", dataPath);
26    SDL_SAFECALL(TTF_Init);
27    SDL_SAFEASSN(graphics->font, TTF_OpenFont, path, 32);
28    SDL_SAFEASSN(graphics->debugFont, TTF_OpenFont, path, 16);
29    SDL_SAFEASSN(graphics->textEngine, TTF_CreateRendererTextEngine, graphics->renderer);
30
31    SDL_SAFEASSN(graphics->debugText, TTF_CreateText, graphics->textEngine, graphics->debugFont, "", 0);
32
33    // TODO: There is a lot of conditional logic regarding skins that we are outright skipping.
34    snprintf(path, 512, "%s" OSU_PATHSEP "skins" OSU_PATHSEP OSU_ACTIVE_SKIN OSU_PATHSEP "%s", dataPath, "menu-button-background@2x.png");
35    SDL_SAFEASSN(graphics->beatmapWedgeTexture, IMG_LoadTexture, graphics->renderer, path);
36    snprintf(path, 512, "%s" OSU_PATHSEP "skins" OSU_PATHSEP OSU_ACTIVE_SKIN OSU_PATHSEP "%s", dataPath, "cursor.png");
37    SDL_SAFEASSN(graphics->cursorTexture, IMG_LoadTexture, graphics->renderer, path);
38    snprintf(path, 512, "%s" OSU_PATHSEP "skins" OSU_PATHSEP OSU_ACTIVE_SKIN OSU_PATHSEP "%s", dataPath, "menu-background.png");
39    SDL_SAFEASSN(graphics->menuBackgroundTexture, IMG_LoadTexture, graphics->renderer, path);
40    snprintf(path, 512, "%s" OSU_PATHSEP "skins" OSU_PATHSEP OSU_ACTIVE_SKIN OSU_PATHSEP "%s", dataPath, "songselect-top.png");
41    SDL_SAFEASSN(graphics->songSelectTopTexture, IMG_LoadTexture, graphics->renderer, path);
42    snprintf(path, 512, "%s" OSU_PATHSEP "skins" OSU_PATHSEP OSU_ACTIVE_SKIN OSU_PATHSEP "%s", dataPath, "hitcircle.png");
43    SDL_SAFEASSN(graphics->hitCircleTexture, IMG_LoadTexture, graphics->renderer, path);
44    snprintf(path, 512, "%s" OSU_PATHSEP "skins" OSU_PATHSEP OSU_ACTIVE_SKIN OSU_PATHSEP "%s", dataPath, "hitcircleoverlay.png");
45    SDL_SAFEASSN(graphics->hitCircleOverlayTexture, IMG_LoadTexture, graphics->renderer, path);
46    snprintf(path, 512, "%s" OSU_PATHSEP "skins" OSU_PATHSEP OSU_ACTIVE_SKIN OSU_PATHSEP "%s", dataPath, "approachcircle.png");
47    SDL_SAFEASSN(graphics->approachCircleTexture, IMG_LoadTexture, graphics->renderer, path);
48
49    graphics->beatmapDimFactor = 255;
50
51    return graphics;
52}
53
54void Osu_DestroyGraphics(struct Osu_Graphics* graphics) {
55    if (graphics->selectedBeatmapWallpaper) {
56        SDL_DestroyTexture(graphics->selectedBeatmapWallpaper);
57    }
58
59    SDL_DestroyTexture(graphics->beatmapWedgeTexture);
60    SDL_DestroyTexture(graphics->cursorTexture);
61    SDL_DestroyTexture(graphics->menuBackgroundTexture);
62    SDL_DestroyTexture(graphics->songSelectTopTexture);
63    SDL_DestroyTexture(graphics->hitCircleTexture);
64    SDL_DestroyTexture(graphics->hitCircleOverlayTexture);
65    SDL_DestroyTexture(graphics->approachCircleTexture);
66
67    TTF_DestroyText(graphics->debugText);
68    graphics->debugText = NULL;
69
70    TTF_DestroyRendererTextEngine(graphics->textEngine);
71    TTF_CloseFont(graphics->debugFont);
72    TTF_CloseFont(graphics->font);
73    TTF_Quit();
74
75    SDL_DestroyRenderer(graphics->renderer);
76    SDL_DestroyWindow(graphics->window);
77
78    SDL_QuitSubSystem(SDL_INIT_VIDEO);
79
80    free(graphics);
81}
82
83void Osu_PrepareRender(struct Osu_Graphics* graphics) {
84    int screenW, screenH;
85    SDL_SAFECALL(SDL_GetWindowSizeInPixels, graphics->window, &screenW, &screenH);
86    graphics->screenRect.w = screenW;
87    graphics->screenRect.h = screenH;
88
89    SDL_SAFECALL(SDL_SetRenderDrawColor, graphics->renderer, 0, 0, 0, 255);
90    SDL_SAFECALL(SDL_RenderClear, graphics->renderer);
91}
92
93void Osu_RenderWallpaper(struct Osu_Graphics* graphics) {
94    struct SDL_Texture* wallpaper = graphics->menuBackgroundTexture;
95    if (graphics->selectedBeatmapWallpaper) {
96        wallpaper = graphics->selectedBeatmapWallpaper;
97    }
98    float texW, texH;
99    SDL_SAFECALL(SDL_GetTextureSize, wallpaper, &texW, &texH);
100    SDL_assert(texW > 0);
101    SDL_assert(texH > 0);
102    double texAspectRatio = texW / texH;
103    double screenAspectRatio = graphics->screenRect.w / graphics->screenRect.h;
104    double scalingFactor = 1.0;
105    if (screenAspectRatio > texAspectRatio) {
106        scalingFactor = graphics->screenRect.w / texW;
107    } else {
108        scalingFactor = graphics->screenRect.h / texH;
109    }
110    float adjustedTexW = texW * scalingFactor;
111    float adjustedTexH = texH * scalingFactor;
112    SDL_FRect destRect = {
113        .x = (graphics->screenRect.w / 2) - (adjustedTexW / 2),
114        .y = (graphics->screenRect.h / 2) - (adjustedTexH / 2),
115        .w = adjustedTexW,
116        .h = adjustedTexH,
117    };
118    SDL_SAFECALL(SDL_RenderTexture, graphics->renderer, wallpaper, NULL, &destRect);
119}
120
121void Osu_RenderCursor(struct Osu_Graphics* graphics) {
122    struct SDL_FRect texRect = Osu_GetTextureRect(graphics->cursorTexture);
123    texRect.w *= 1.25;
124    texRect.h *= 1.25;
125
126    float mouseX, mouseY;
127    SDL_GetMouseState(&mouseX, &mouseY);
128    float scale;
129    SDL_SAFEASSN(scale, SDL_GetWindowDisplayScale, graphics->window);
130    mouseX *= scale;
131    mouseY *= scale;
132
133    SDL_FRect destRect = {
134        .x = mouseX - (texRect.w / 2),
135        .y = mouseY - (texRect.h / 2),
136        .w = texRect.w,
137        .h = texRect.h,
138    };
139    SDL_SAFECALL(SDL_RenderTexture, graphics->renderer, graphics->cursorTexture, &texRect, &destRect);
140}
141
142void Osu_SetWallpaper(struct Osu_Graphics* graphics, const char* filePath) {
143    if (graphics->selectedBeatmapWallpaper) {
144        SDL_DestroyTexture(graphics->selectedBeatmapWallpaper);
145    }
146
147    SDL_SAFEASSN(graphics->selectedBeatmapWallpaper, IMG_LoadTexture, graphics->renderer, filePath);
148}