2 #include "system/stacktrace.h"
8 #include "sdl/renderer.h"
9 #include "system/nth_alloc.h"
10 #include "system/log.h"
15 static Vec2f effective_ratio(const SDL_Rect *view_port);
16 static Vec2f effective_scale(const SDL_Rect *view_port);
17 static Triangle camera_triangle(const Camera *camera,
20 static SDL_Color camera_sdl_color(const Camera *camera, Color color)
22 return color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
25 Camera create_camera(SDL_Renderer *renderer,
28 trace_assert(renderer);
40 int camera_fill_rect(const Camera *camera,
46 const SDL_Rect sdl_rect = rect_for_sdl(
47 camera_rect(camera, rect));
49 const SDL_Color sdl_color = camera_sdl_color(camera, color);
51 if (camera->debug_mode) {
52 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
53 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
57 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
58 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
63 if (SDL_RenderFillRect(camera->renderer, &sdl_rect) < 0) {
64 log_fail("SDL_RenderFillRect: %s\n", SDL_GetError());
71 int camera_draw_rect(const Camera *camera,
77 const SDL_Rect sdl_rect = rect_for_sdl(
78 camera_rect(camera, rect));
80 const SDL_Color sdl_color = camera_sdl_color(camera, color);
82 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
83 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
87 if (SDL_RenderDrawRect(camera->renderer, &sdl_rect) < 0) {
88 log_fail("SDL_RenderDrawRect: %s\n", SDL_GetError());
95 int camera_draw_rect_screen(const Camera *camera,
101 const SDL_Rect sdl_rect = rect_for_sdl(rect);
102 const SDL_Color sdl_color = camera_sdl_color(camera, color);
104 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
105 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
109 if (SDL_RenderDrawRect(camera->renderer, &sdl_rect) < 0) {
110 log_fail("SDL_RenderDrawRect: %s\n", SDL_GetError());
117 int camera_draw_triangle(Camera *camera,
121 trace_assert(camera);
123 const SDL_Color sdl_color = camera_sdl_color(camera, color);
125 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
126 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
130 if (draw_triangle(camera->renderer, camera_triangle(camera, t)) < 0) {
137 int camera_fill_triangle(const Camera *camera,
141 trace_assert(camera);
143 const SDL_Color sdl_color = camera_sdl_color(camera, color);
145 if (camera->debug_mode) {
146 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
147 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
151 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
152 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
157 if (fill_triangle(camera->renderer, camera_triangle(camera, t)) < 0) {
164 int camera_render_text(const Camera *camera,
171 SDL_RenderGetViewport(camera->renderer, &view_port);
173 const Vec2f scale = effective_scale(&view_port);
174 const Vec2f screen_position = camera_point(camera, position);
176 if (sprite_font_render_text(
180 vec(size.x * scale.x * camera->scale, size.y * scale.y * camera->scale),
181 camera->blackwhite_mode ? color_desaturate(c) : c,
189 int camera_render_debug_text(const Camera *camera,
193 trace_assert(camera);
196 if (!camera->debug_mode) {
200 if (camera_render_text(
204 rgba(0.0f, 0.0f, 0.0f, 1.0f),
212 int camera_clear_background(const Camera *camera,
215 const SDL_Color sdl_color = camera_sdl_color(camera, color);
217 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
218 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
222 if (SDL_RenderClear(camera->renderer) < 0) {
223 log_fail("SDL_RenderClear: %s\n", SDL_GetError());
230 void camera_center_at(Camera *camera, Vec2f position)
232 trace_assert(camera);
233 camera->position = position;
236 void camera_scale(Camera *camera, float scale)
238 trace_assert(camera);
239 camera->scale = fmaxf(0.1f, scale);
242 void camera_toggle_debug_mode(Camera *camera)
244 trace_assert(camera);
245 camera->debug_mode = !camera->debug_mode;
248 void camera_disable_debug_mode(Camera *camera)
250 trace_assert(camera);
251 camera->debug_mode = 0;
254 int camera_is_point_visible(const Camera *camera, Vec2f p)
257 SDL_RenderGetViewport(camera->renderer, &view_port);
259 return rect_contains_point(
260 rect_from_sdl(&view_port),
261 camera_point(camera, p));
264 Rect camera_view_port(const Camera *camera)
266 trace_assert(camera);
269 SDL_RenderGetViewport(camera->renderer, &view_port);
271 Vec2f p1 = camera_map_screen(
275 Vec2f p2 = camera_map_screen(
277 view_port.x + view_port.w,
278 view_port.y + view_port.h);
280 return rect_from_points(p1, p2);
283 Rect camera_view_port_screen(const Camera *camera)
285 trace_assert(camera);
288 SDL_RenderGetViewport(camera->renderer, &view_port);
290 return rect_from_sdl(&view_port);
293 int camera_is_text_visible(const Camera *camera,
298 trace_assert(camera);
302 SDL_RenderGetViewport(camera->renderer, &view_port);
304 return rects_overlap(
307 sprite_font_boundary_box(
312 rect_from_sdl(&view_port));
315 /* ---------- Private Function ---------- */
317 static Vec2f effective_ratio(const SDL_Rect *view_port)
319 if ((float) view_port->w / RATIO_X > (float) view_port->h / RATIO_Y) {
320 return vec(RATIO_X, (float) view_port->h / ((float) view_port->w / RATIO_X));
322 return vec((float) view_port->w / ((float) view_port->h / RATIO_Y), RATIO_Y);
326 static Vec2f effective_scale(const SDL_Rect *view_port)
328 return vec_entry_div(
329 vec((float) view_port->w, (float) view_port->h),
330 vec_scala_mult(effective_ratio(view_port), 50.0f));
333 Vec2f camera_point(const Camera *camera, const Vec2f p)
336 SDL_RenderGetViewport(camera->renderer, &view_port);
341 vec_sum(p, vec_neg(camera->position)),
342 effective_scale(&view_port)),
344 vec((float) view_port.w * 0.5f,
345 (float) view_port.h * 0.5f));
348 static Triangle camera_triangle(const Camera *camera,
352 camera_point(camera, t.p1),
353 camera_point(camera, t.p2),
354 camera_point(camera, t.p3));
357 Rect camera_rect(const Camera *camera, const Rect rect)
359 return rect_from_points(
362 vec(rect.x, rect.y)),
365 vec(rect.x + rect.w, rect.y + rect.h)));
368 int camera_render_debug_rect(const Camera *camera,
372 trace_assert(camera);
374 if (!camera->debug_mode) {
378 if (camera_fill_rect(camera, rect, c) < 0) {
385 Vec2f camera_map_screen(const Camera *camera,
388 trace_assert(camera);
391 SDL_RenderGetViewport(camera->renderer, &view_port);
393 Vec2f es = effective_scale(&view_port);
397 const Vec2f p = vec((float) x, (float) y);
404 vec((float) view_port.w * -0.5f,
405 (float) view_port.h * -0.5f)),
406 1.0f / camera->scale),
411 int camera_fill_rect_screen(const Camera *camera,
415 trace_assert(camera);
417 const SDL_Rect sdl_rect = rect_for_sdl(rect);
418 const SDL_Color sdl_color = camera_sdl_color(camera, color);
420 if (camera->debug_mode) {
421 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
422 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
426 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
427 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
432 if (SDL_RenderFillRect(camera->renderer, &sdl_rect) < 0) {
433 log_fail("SDL_RenderFillRect: %s\n", SDL_GetError());
441 int camera_render_text_screen(const Camera *camera,
447 trace_assert(camera);
450 return sprite_font_render_text(
459 int camera_draw_thicc_rect_screen(const Camera *camera,
464 trace_assert(camera);
467 if (camera_fill_rect_screen(
469 horizontal_thicc_line(
479 if (camera_fill_rect_screen(
481 horizontal_thicc_line(
491 if (camera_fill_rect_screen(
503 if (camera_fill_rect_screen(
517 const Sprite_font *camera_font(const Camera *camera)
522 Rect camera_text_boundary_box(const Camera *camera,
527 trace_assert(camera);
530 return sprite_font_boundary_box(
531 camera->font, position, scale, text);
534 int camera_draw_line(const Camera *camera,
535 Vec2f begin, Vec2f end,
538 trace_assert(camera);
540 const Vec2f camera_begin = camera_point(camera, begin);
541 const Vec2f camera_end = camera_point(camera, end);
543 const SDL_Color sdl_color = camera_sdl_color(camera, color);
545 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
546 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
550 if (SDL_RenderDrawLine(
552 (int)roundf(camera_begin.x),
553 (int)roundf(camera_begin.y),
554 (int)roundf(camera_end.x),
555 (int)roundf(camera_end.y)) < 0) {
556 log_fail("SDL_RenderDrawRect: %s\n", SDL_GetError());