9 #include "sdl/renderer.h"
10 #include "system/nth_alloc.h"
11 #include "system/log.h"
12 #include "system/stacktrace.h"
17 static Vec2f effective_ratio(const SDL_Rect *view_port);
18 static Vec2f effective_scale(const SDL_Rect *view_port);
19 static Triangle camera_triangle(const Camera *camera,
22 static SDL_Color camera_sdl_color(const Camera *camera, Color color)
24 return color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
27 Camera create_camera(SDL_Renderer *renderer,
30 trace_assert(renderer);
42 int camera_fill_rect(const Camera *camera,
48 const SDL_Rect sdl_rect = rect_for_sdl(
49 camera_rect(camera, rect));
51 const SDL_Color sdl_color = camera_sdl_color(camera, color);
53 if (camera->debug_mode) {
54 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
55 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
59 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
60 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
65 if (SDL_RenderFillRect(camera->renderer, &sdl_rect) < 0) {
66 log_fail("SDL_RenderFillRect: %s\n", SDL_GetError());
73 int camera_draw_rect(const Camera *camera,
79 const SDL_Rect sdl_rect = rect_for_sdl(
80 camera_rect(camera, rect));
82 const SDL_Color sdl_color = camera_sdl_color(camera, color);
84 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
85 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
89 if (SDL_RenderDrawRect(camera->renderer, &sdl_rect) < 0) {
90 log_fail("SDL_RenderDrawRect: %s\n", SDL_GetError());
97 int camera_draw_rect_screen(const Camera *camera,
101 trace_assert(camera);
103 const SDL_Rect sdl_rect = rect_for_sdl(rect);
104 const SDL_Color sdl_color = camera_sdl_color(camera, color);
106 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
107 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
111 if (SDL_RenderDrawRect(camera->renderer, &sdl_rect) < 0) {
112 log_fail("SDL_RenderDrawRect: %s\n", SDL_GetError());
119 int camera_draw_triangle(Camera *camera,
123 trace_assert(camera);
125 const SDL_Color sdl_color = camera_sdl_color(camera, color);
127 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
128 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
132 if (draw_triangle(camera->renderer, camera_triangle(camera, t)) < 0) {
139 int camera_fill_triangle(const Camera *camera,
143 trace_assert(camera);
145 const SDL_Color sdl_color = camera_sdl_color(camera, color);
147 if (camera->debug_mode) {
148 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
149 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
153 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
154 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
159 if (fill_triangle(camera->renderer, camera_triangle(camera, t)) < 0) {
166 int camera_render_text(const Camera *camera,
173 SDL_RenderGetViewport(camera->renderer, &view_port);
175 const Vec2f scale = effective_scale(&view_port);
176 const Vec2f screen_position = camera_point(camera, position);
178 if (sprite_font_render_text(
182 vec(size.x * scale.x * camera->scale, size.y * scale.y * camera->scale),
183 camera->blackwhite_mode ? color_desaturate(c) : c,
191 int camera_render_debug_text(const Camera *camera,
195 trace_assert(camera);
198 if (!camera->debug_mode) {
202 if (camera_render_text(
206 rgba(0.0f, 0.0f, 0.0f, 1.0f),
214 int camera_clear_background(const Camera *camera,
217 const SDL_Color sdl_color = camera_sdl_color(camera, color);
219 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
220 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
224 if (SDL_RenderClear(camera->renderer) < 0) {
225 log_fail("SDL_RenderClear: %s\n", SDL_GetError());
232 void camera_center_at(Camera *camera, Vec2f position)
234 trace_assert(camera);
235 camera->position = position;
238 void camera_scale(Camera *camera, float scale)
240 trace_assert(camera);
241 camera->scale = fmaxf(0.1f, scale);
244 void camera_toggle_debug_mode(Camera *camera)
246 trace_assert(camera);
247 camera->debug_mode = !camera->debug_mode;
250 void camera_disable_debug_mode(Camera *camera)
252 trace_assert(camera);
253 camera->debug_mode = 0;
256 int camera_is_point_visible(const Camera *camera, Vec2f p)
259 SDL_RenderGetViewport(camera->renderer, &view_port);
261 return rect_contains_point(
262 rect_from_sdl(&view_port),
263 camera_point(camera, p));
266 Rect camera_view_port(const Camera *camera)
268 trace_assert(camera);
271 SDL_RenderGetViewport(camera->renderer, &view_port);
273 Vec2f p1 = camera_map_screen(
277 Vec2f p2 = camera_map_screen(
279 view_port.x + view_port.w,
280 view_port.y + view_port.h);
282 return rect_from_points(p1, p2);
285 Rect camera_view_port_screen(const Camera *camera)
287 trace_assert(camera);
290 SDL_RenderGetViewport(camera->renderer, &view_port);
292 return rect_from_sdl(&view_port);
295 int camera_is_text_visible(const Camera *camera,
300 trace_assert(camera);
304 SDL_RenderGetViewport(camera->renderer, &view_port);
306 return rects_overlap(
309 sprite_font_boundary_box(position, size, strlen(text))),
310 rect_from_sdl(&view_port));
313 /* ---------- Private Function ---------- */
315 static Vec2f effective_ratio(const SDL_Rect *view_port)
317 if ((float) view_port->w / RATIO_X > (float) view_port->h / RATIO_Y) {
318 return vec(RATIO_X, (float) view_port->h / ((float) view_port->w / RATIO_X));
320 return vec((float) view_port->w / ((float) view_port->h / RATIO_Y), RATIO_Y);
324 static Vec2f effective_scale(const SDL_Rect *view_port)
326 return vec_entry_div(
327 vec((float) view_port->w, (float) view_port->h),
328 vec_scala_mult(effective_ratio(view_port), 50.0f));
331 Vec2f camera_point(const Camera *camera, const Vec2f p)
334 SDL_RenderGetViewport(camera->renderer, &view_port);
339 vec_sum(p, vec_neg(camera->position)),
340 effective_scale(&view_port)),
342 vec((float) view_port.w * 0.5f,
343 (float) view_port.h * 0.5f));
346 static Triangle camera_triangle(const Camera *camera,
350 camera_point(camera, t.p1),
351 camera_point(camera, t.p2),
352 camera_point(camera, t.p3));
355 Rect camera_rect(const Camera *camera, const Rect rect)
357 return rect_from_points(
360 vec(rect.x, rect.y)),
363 vec(rect.x + rect.w, rect.y + rect.h)));
366 int camera_render_debug_rect(const Camera *camera,
370 trace_assert(camera);
372 if (!camera->debug_mode) {
376 if (camera_fill_rect(camera, rect, c) < 0) {
383 Vec2f camera_map_screen(const Camera *camera,
386 trace_assert(camera);
389 SDL_RenderGetViewport(camera->renderer, &view_port);
391 Vec2f es = effective_scale(&view_port);
395 const Vec2f p = vec((float) x, (float) y);
402 vec((float) view_port.w * -0.5f,
403 (float) view_port.h * -0.5f)),
404 1.0f / camera->scale),
409 int camera_fill_rect_screen(const Camera *camera,
413 trace_assert(camera);
415 const SDL_Rect sdl_rect = rect_for_sdl(rect);
416 const SDL_Color sdl_color = camera_sdl_color(camera, color);
418 if (camera->debug_mode) {
419 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
420 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
424 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
425 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
430 if (SDL_RenderFillRect(camera->renderer, &sdl_rect) < 0) {
431 log_fail("SDL_RenderFillRect: %s\n", SDL_GetError());
439 int camera_render_text_screen(const Camera *camera,
445 trace_assert(camera);
448 return sprite_font_render_text(
457 int camera_draw_thicc_rect_screen(const Camera *camera,
462 trace_assert(camera);
465 if (camera_fill_rect_screen(
467 horizontal_thicc_line(
477 if (camera_fill_rect_screen(
479 horizontal_thicc_line(
489 if (camera_fill_rect_screen(
501 if (camera_fill_rect_screen(
515 const Sprite_font *camera_font(const Camera *camera)
520 int camera_draw_line(const Camera *camera,
521 Vec2f begin, Vec2f end,
524 trace_assert(camera);
526 const Vec2f camera_begin = camera_point(camera, begin);
527 const Vec2f camera_end = camera_point(camera, end);
529 const SDL_Color sdl_color = camera_sdl_color(camera, color);
531 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
532 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
536 if (SDL_RenderDrawLine(
538 (int)roundf(camera_begin.x),
539 (int)roundf(camera_begin.y),
540 (int)roundf(camera_end.x),
541 (int)roundf(camera_end.y)) < 0) {
542 log_fail("SDL_RenderDrawRect: %s\n", SDL_GetError());