8#include "DrawUtils.hpp"
9#include "RootDisplay.hpp"
13char* musicData = NULL;
15bool CST_DrawInit(RootDisplay* root)
17 int sdl2Flags = SDL_INIT_GAMECONTROLLER;
19 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | sdl2Flags) < 0)
21 printf(
"Failed to initialize SDL2 drawing library: %s\n", SDL_GetError());
25 CST_SetQualityHint(
"linear");
28 printf(
"Failed to initialize TTF font library: %s\n", SDL_GetError());
35 SDLFlags |= SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC;
36 windowFlags |= SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
38 root->window = SDL_CreateWindow(
39 NULL, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
40 SCREEN_WIDTH, SCREEN_HEIGHT, windowFlags);
41 root->renderer = SDL_CreateRenderer(root->window, -1, SDLFlags);
43 SDL_SetRenderTarget(root->renderer, NULL);
45 if (root->renderer == NULL || root->window == NULL)
51 RootDisplay::mainDisplay = root;
53 for (
int i = 0; i < SDL_NumJoysticks(); i++)
55 if (SDL_JoystickOpen(i) == NULL)
57 printf(
"SDL_JoystickOpen: %s\n", SDL_GetError());
64 root->needsRender.type = SDL_USEREVENT;
74 SDL_DestroyWindow(RootDisplay::mainDisplay->window);
75 SDL_QuitSubSystem(SDL_INIT_VIDEO);
78 auto root = RootDisplay::mainDisplay;
79 if (root->music != NULL)
81 Mix_FreeMusic(root->music);
84 if (musicData != NULL)
94void CST_MixerInit(RootDisplay* root)
96#if !defined(SIMPLE_SDL2)
97 Mix_Init(MIX_INIT_MP3);
98 if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 4096) != 0) {
99 printf(
"Failed to initialize SDL2 mixer: %s\n", Mix_GetError());
104 const char* filename =
"background.mp3";
105 FILE* f = fopen(filename,
"rb");
109 fseek(f, 0, SEEK_END);
110 long fsize = ftell(f);
116 fseek(f, 0, SEEK_SET);
118 musicData = (
char*)(malloc(fsize + 1));
119 fread(musicData, fsize, 1, f);
122 musicData[fsize] = 0;
124 root->music = Mix_LoadMUS_RW(SDL_RWFromMem(musicData, fsize), 1);
129void CST_GetRGBA(Uint32 pixel, SDL_PixelFormat* format, CST_Color* cstColor)
131 SDL_GetRGBA(pixel, format, &cstColor->r, &cstColor->g, &cstColor->b, &cstColor->a);
135bool CST_SavePNG(CST_Texture* texture,
const char* file_name)
137 auto renderer = RootDisplay::mainDisplay->renderer;
138 SDL_Texture* target = SDL_GetRenderTarget(renderer);
139 SDL_SetRenderTarget(renderer, texture);
140 printf(
"Error: %s\n", SDL_GetError());
142 SDL_QueryTexture(texture, NULL, NULL, &width, &height);
143 SDL_Surface* surface = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0);
144 SDL_RenderReadPixels(renderer, NULL, surface->format->format, surface->pixels, surface->pitch);
145 IMG_SavePNG(surface, file_name);
146 SDL_FreeSurface(surface);
147 SDL_SetRenderTarget(renderer, target);
151void CST_FadeInMusic(RootDisplay* root)
153#if !defined(SIMPLE_SDL2)
156 Mix_VolumeMusic(0.85 * MIX_MAX_VOLUME);
157 Mix_PlayMusic(root->music, -1);
158 Mix_VolumeMusic(0.85 * MIX_MAX_VOLUME);
163void CST_RenderPresent(CST_Renderer* renderer)
167 CST_SetDrawColorRGBA(renderer, 0, 0, 0, 255);
168 CST_Rect rect = { 0, 240, 40, 240 };
169 CST_FillRect(renderer, &rect);
170 CST_Rect rect2 = { 360, 240, 40, 240 };
171 CST_FillRect(renderer, &rect2);
172 CST_Rect rect3 = { 0, 240, 400, 240 };
173 CST_DrawRect(renderer, &rect3);
176 SDL_RenderPresent(renderer);
179void CST_FreeSurface(CST_Surface* surface)
181 SDL_FreeSurface(surface);
184void CST_RenderCopy(CST_Renderer* dest, CST_Texture* src, CST_Rect* src_rect, CST_Rect* dest_rect)
186 SDL_RenderCopy(dest, src, src_rect, dest_rect);
189void CST_RenderCopyRotate(CST_Renderer* dest, CST_Texture* src, CST_Rect* src_rect, CST_Rect* dest_rect,
int angle)
191 SDL_RenderCopyEx(dest, src, src_rect, dest_rect, angle, NULL, SDL_FLIP_NONE);
194void CST_SetDrawColor(CST_Renderer* renderer, CST_Color c)
196 CST_SetDrawColorRGBA(renderer, c.r, c.g, c.b, c.a);
199void CST_SetDrawColorRGBA(CST_Renderer* renderer, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
201 SDL_SetRenderDrawColor(renderer, r, g, b, a);
204void CST_FillRect(CST_Renderer* renderer, CST_Rect* dimens)
206 SDL_RenderFillRect(renderer, dimens);
209void CST_DrawRect(CST_Renderer* renderer, CST_Rect* dimens)
211 SDL_RenderDrawRect(renderer, dimens);
214void CST_DrawLine(CST_Renderer* renderer,
int x,
int y,
int w,
int h)
216 SDL_RenderDrawLine(renderer, x, y, w, h);
219void CST_SetDrawBlend(CST_Renderer* renderer,
bool enabled)
221 SDL_BlendMode mode = enabled ? SDL_BLENDMODE_BLEND : SDL_BLENDMODE_NONE;
222 SDL_SetRenderDrawBlendMode(renderer, mode);
225void CST_QueryTexture(CST_Texture* texture,
int* w,
int* h)
227 SDL_QueryTexture(texture,
nullptr,
nullptr, w, h);
230CST_Texture* CST_CreateTextureFromSurface(CST_Renderer* renderer, CST_Surface* surface,
bool)
232 return SDL_CreateTextureFromSurface(renderer, surface);
235void CST_SetQualityHint(
const char* quality)
237 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, quality);
240void CST_filledCircleRGBA(CST_Renderer* renderer, uint32_t x, uint32_t y, uint32_t radius, uint32_t r, uint32_t g, uint32_t b, uint32_t a)
242 #if !defined(SIMPLE_SDL2)
244 filledCircleRGBA(renderer, x, y, radius, r, g, b, a);
248void CST_SetWindowSize(CST_Window* window,
int w,
int h)
251 SDL_SetWindowSize(window, w, h);
255void CST_Delay(
int time)
262 return SDL_GetTicks();
265void CST_LowRumble(InputEvents* event,
int)
267 auto joystick = SDL_JoystickFromInstanceID(event->event.jdevice.which);
268 if (joystick && SDL_JoystickGetAttached(joystick)) {
269 SDL_JoystickRumble(joystick, 0x400, 0x400, 200);
273void CST_SetCursor(
int cursor)
275 if (cursor == CST_CURSOR_NONE) {
276 SDL_ShowCursor(SDL_DISABLE);
280 SDL_ShowCursor(SDL_ENABLE);
281 auto sdlCursor = SDL_SYSTEM_CURSOR_ARROW;
282 if (cursor == CST_CURSOR_HAND) {
283 sdlCursor = SDL_SYSTEM_CURSOR_HAND;
284 }
else if (cursor == CST_CURSOR_TEXT) {
285 sdlCursor = SDL_SYSTEM_CURSOR_IBEAM;
286 }
else if (cursor == CST_CURSOR_SPINNER) {
287 sdlCursor = SDL_SYSTEM_CURSOR_WAIT;
290 SDL_SetCursor(SDL_CreateSystemCursor(sdlCursor));
293bool CST_isRectOffscreen(CST_Rect* rect)
296 if (rect->x > SCREEN_WIDTH + 10 || rect->y > SCREEN_HEIGHT + 10)
301 if (rect->x + rect->w < -10 || rect->y + rect->h < -10)
308float CST_GetDpiScale()
311 SDL_GetWindowSize(RootDisplay::window, &w, &h);
313 SDL_GL_GetDrawableSize(RootDisplay::window, &dw, &dh);
314 return (dw / (
float) w);
317void CST_SetWindowTitle(
const char* title)
319 SDL_SetWindowTitle(RootDisplay::mainDisplay->window, title);
322void CST_roundedBoxRGBA (
323 CST_Renderer *renderer,
324 Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
325 Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a
327 #if !defined(SIMPLE_SDL2)
329 roundedBoxRGBA(renderer, x1, y1, x2, y2, rad, r, g, b, a);
333void CST_roundedRectangleRGBA (
334 CST_Renderer *renderer,
335 Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
336 Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a
338 #if !defined(SIMPLE_SDL2)
340 roundedRectangleRGBA(renderer, x1, y1, x2, y2, rad, r, g, b, a);
344void CST_rectangleRGBA (
345 CST_Renderer *renderer,
346 Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
347 Uint8 r, Uint8 g, Uint8 b, Uint8 a
349 #if !defined(SIMPLE_SDL2)
351 rectangleRGBA(renderer, x1, y1, x2, y2, r, g, b, a);
358std::vector<std::string> CST_GetMusicInfo(CST_Music*) {
359 std::vector<std::string> info;
368 auto m = mpg123_new(NULL, NULL);
369 mpg123_open(m,
"./background.mp3");
370 mpg123_seek(m, 0, SEEK_SET);
371 auto meta = mpg123_meta_check(m);
376 if (meta == MPG123_ID3 && mpg123_id3(m, &v1, &v2) == MPG123_OK) {
379 info.push_back(v2->title && v2->title->p ? v2->title->p :
"");
380 info.push_back(v2->artist && v2->artist->p ? v2->artist->p :
"");
381 info.push_back(v2->album && v2->album->p ? v2->album->p :
"");
387 info.push_back(v1->title[0] ? v1->title :
"");
388 info.push_back(v1->artist[0] ? v1->artist :
"");
389 info.push_back(v1->album[0] ? v1->album :
"");
406void chdirForPlatform()
408 auto basePath = SDL_GetBasePath();
409 if (basePath != NULL) {
415std::string replaceAll(std::string str,
const std::string& from,
const std::string& to) {
416 size_t start_pos = 0;
417 while((start_pos = str.find(from, start_pos)) != std::string::npos) {
418 str.replace(start_pos, from.length(), to);
419 start_pos += to.length();
424CST_Color toCST(rgb color)
427 cstColor.r = (uint8_t)(color.r * 255);
428 cstColor.g = (uint8_t)(color.g * 255);
429 cstColor.b = (uint8_t)(color.b * 255);
434rgb fromCST(CST_Color color)
436 return (rgb){ color.r / 255.0, color.g / 255.0, color.b / 255.0 };