2 #include "system/stacktrace.h"
8 #include "sdl/renderer.h"
9 #include "system/nth_alloc.h"
10 #include "system/log.h"
20 SDL_Renderer *renderer;
24 static Vec effective_ratio(const SDL_Rect *view_port);
25 static Vec effective_scale(const SDL_Rect *view_port);
26 static Triangle camera_triangle(const Camera *camera,
29 Camera *create_camera(SDL_Renderer *renderer,
32 trace_assert(renderer);
35 Camera *camera = nth_calloc(1, sizeof(Camera));
41 camera->position = vec(0.0f, 0.0f);
43 camera->debug_mode = 0;
44 camera->blackwhite_mode = 0;
45 camera->renderer = renderer;
51 void destroy_camera(Camera *camera)
58 int camera_fill_rect(Camera *camera,
64 const SDL_Rect sdl_rect = rect_for_sdl(
65 camera_rect(camera, rect));
67 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
69 if (camera->debug_mode) {
70 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
71 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
75 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
76 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
81 if (SDL_RenderFillRect(camera->renderer, &sdl_rect) < 0) {
82 log_fail("SDL_RenderFillRect: %s\n", SDL_GetError());
89 int camera_draw_rect(Camera *camera,
95 const SDL_Rect sdl_rect = rect_for_sdl(
96 camera_rect(camera, rect));
98 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
100 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
101 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
105 if (SDL_RenderDrawRect(camera->renderer, &sdl_rect) < 0) {
106 log_fail("SDL_RenderDrawRect: %s\n", SDL_GetError());
113 int camera_draw_rect_screen(Camera *camera,
117 trace_assert(camera);
119 const SDL_Rect sdl_rect = rect_for_sdl(rect);
120 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
122 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
123 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
127 if (SDL_RenderDrawRect(camera->renderer, &sdl_rect) < 0) {
128 log_fail("SDL_RenderDrawRect: %s\n", SDL_GetError());
135 int camera_draw_triangle(Camera *camera,
139 trace_assert(camera);
141 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
143 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
144 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
148 if (draw_triangle(camera->renderer, camera_triangle(camera, t)) < 0) {
155 int camera_fill_triangle(Camera *camera,
159 trace_assert(camera);
161 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
163 if (camera->debug_mode) {
164 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
165 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
169 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
170 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
175 if (fill_triangle(camera->renderer, camera_triangle(camera, t)) < 0) {
182 int camera_render_text(Camera *camera,
189 SDL_RenderGetViewport(camera->renderer, &view_port);
191 const Vec scale = effective_scale(&view_port);
192 const Vec screen_position = camera_point(camera, position);
194 if (sprite_font_render_text(
198 vec(size.x * scale.x * camera->scale, size.y * scale.y * camera->scale),
199 camera->blackwhite_mode ? color_desaturate(c) : c,
207 int camera_render_debug_text(Camera *camera,
211 trace_assert(camera);
214 if (!camera->debug_mode) {
218 if (camera_render_text(
222 rgba(0.0f, 0.0f, 0.0f, 1.0f),
230 int camera_clear_background(Camera *camera,
233 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
235 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
236 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
240 if (SDL_RenderClear(camera->renderer) < 0) {
241 log_fail("SDL_RenderClear: %s\n", SDL_GetError());
248 void camera_center_at(Camera *camera, Point position)
250 trace_assert(camera);
251 camera->position = position;
254 void camera_scale(Camera *camera, float scale)
256 trace_assert(camera);
257 camera->scale = fmaxf(0.1f, scale);
260 void camera_toggle_debug_mode(Camera *camera)
262 trace_assert(camera);
263 camera->debug_mode = !camera->debug_mode;
266 void camera_disable_debug_mode(Camera *camera)
268 trace_assert(camera);
269 camera->debug_mode = 0;
272 void camera_toggle_blackwhite_mode(Camera *camera)
274 trace_assert(camera);
275 camera->blackwhite_mode = !camera->blackwhite_mode;
278 int camera_is_point_visible(const Camera *camera, Point p)
281 SDL_RenderGetViewport(camera->renderer, &view_port);
283 return rect_contains_point(
284 rect_from_sdl(&view_port),
285 camera_point(camera, p));
288 Rect camera_view_port(const Camera *camera)
290 trace_assert(camera);
293 SDL_RenderGetViewport(camera->renderer, &view_port);
295 const Vec s = effective_scale(&view_port);
296 const float w = (float) view_port.w * s.x;
297 const float h = (float) view_port.h * s.y;
299 return rect(camera->position.x - w * 0.5f,
300 camera->position.y - h * 0.5f,
304 Rect camera_view_port_screen(const Camera *camera)
306 trace_assert(camera);
309 SDL_RenderGetViewport(camera->renderer, &view_port);
311 return rect_from_sdl(&view_port);
314 int camera_is_text_visible(const Camera *camera,
319 trace_assert(camera);
323 SDL_RenderGetViewport(camera->renderer, &view_port);
325 return rects_overlap(
328 sprite_font_boundary_box(
333 rect_from_sdl(&view_port));
336 /* ---------- Private Function ---------- */
338 static Vec effective_ratio(const SDL_Rect *view_port)
340 if ((float) view_port->w / RATIO_X > (float) view_port->h / RATIO_Y) {
341 return vec(RATIO_X, (float) view_port->h / ((float) view_port->w / RATIO_X));
343 return vec((float) view_port->w / ((float) view_port->h / RATIO_Y), RATIO_Y);
347 static Vec effective_scale(const SDL_Rect *view_port)
349 return vec_entry_div(
350 vec((float) view_port->w, (float) view_port->h),
351 vec_scala_mult(effective_ratio(view_port), 50.0f));
354 Vec camera_point(const Camera *camera, const Vec p)
357 SDL_RenderGetViewport(camera->renderer, &view_port);
362 vec_sum(p, vec_neg(camera->position)),
363 effective_scale(&view_port)),
365 vec((float) view_port.w * 0.5f,
366 (float) view_port.h * 0.5f));
369 static Triangle camera_triangle(const Camera *camera,
373 camera_point(camera, t.p1),
374 camera_point(camera, t.p2),
375 camera_point(camera, t.p3));
378 Rect camera_rect(const Camera *camera, const Rect rect)
380 return rect_from_points(
383 vec(rect.x, rect.y)),
386 vec(rect.x + rect.w, rect.y + rect.h)));
389 int camera_render_debug_rect(Camera *camera,
393 trace_assert(camera);
395 if (!camera->debug_mode) {
399 if (camera_fill_rect(camera, rect, c) < 0) {
406 Vec camera_map_screen(const Camera *camera,
409 trace_assert(camera);
412 SDL_RenderGetViewport(camera->renderer, &view_port);
414 Vec es = effective_scale(&view_port);
418 const Vec p = vec((float) x, (float) y);
425 vec((float) view_port.w * -0.5f,
426 (float) view_port.h * -0.5f)),
427 1.0f / camera->scale),
432 int camera_fill_rect_screen(Camera *camera,
436 trace_assert(camera);
438 const SDL_Rect sdl_rect = rect_for_sdl(rect);
439 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
441 if (camera->debug_mode) {
442 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
443 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
447 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
448 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
453 if (SDL_RenderFillRect(camera->renderer, &sdl_rect) < 0) {
454 log_fail("SDL_RenderFillRect: %s\n", SDL_GetError());
462 int camera_render_text_screen(Camera *camera,
468 trace_assert(camera);
471 return sprite_font_render_text(
480 int camera_draw_thicc_rect_screen(Camera *camera,
485 trace_assert(camera);
488 if (camera_fill_rect_screen(
490 horizontal_thicc_line(
500 if (camera_fill_rect_screen(
502 horizontal_thicc_line(
512 if (camera_fill_rect_screen(
524 if (camera_fill_rect_screen(
538 const Sprite_font *camera_font(const Camera *camera)
543 Rect camera_text_boundary_box(const Camera *camera,
548 trace_assert(camera);
551 return sprite_font_boundary_box(
552 camera->font, position, scale, text);