2 #include "system/stacktrace.h"
7 #include "sdl/renderer.h"
8 #include "system/nth_alloc.h"
9 #include "system/log.h"
19 SDL_Renderer *renderer;
23 static Vec effective_ratio(const SDL_Rect *view_port);
24 static Vec effective_scale(const SDL_Rect *view_port);
25 static Triangle camera_triangle(const Camera *camera,
28 Camera *create_camera(SDL_Renderer *renderer,
31 trace_assert(renderer);
34 Camera *camera = nth_calloc(1, sizeof(Camera));
40 camera->position = vec(0.0f, 0.0f);
42 camera->debug_mode = 0;
43 camera->blackwhite_mode = 0;
44 camera->renderer = renderer;
50 void destroy_camera(Camera *camera)
57 int camera_fill_rect(Camera *camera,
63 const SDL_Rect sdl_rect = rect_for_sdl(
64 camera_rect(camera, rect));
66 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
68 if (camera->debug_mode) {
69 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
70 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
74 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
75 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
80 if (SDL_RenderFillRect(camera->renderer, &sdl_rect) < 0) {
81 log_fail("SDL_RenderFillRect: %s\n", SDL_GetError());
88 int camera_draw_rect(Camera *camera,
94 const SDL_Rect sdl_rect = rect_for_sdl(
95 camera_rect(camera, rect));
97 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
99 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
100 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
104 if (SDL_RenderDrawRect(camera->renderer, &sdl_rect) < 0) {
105 log_fail("SDL_RenderDrawRect: %s\n", SDL_GetError());
112 int camera_draw_rect_screen(Camera *camera,
116 trace_assert(camera);
118 const SDL_Rect sdl_rect = rect_for_sdl(rect);
119 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
121 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
122 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
126 if (SDL_RenderDrawRect(camera->renderer, &sdl_rect) < 0) {
127 log_fail("SDL_RenderDrawRect: %s\n", SDL_GetError());
134 int camera_draw_triangle(Camera *camera,
138 trace_assert(camera);
140 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
142 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
143 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
147 if (draw_triangle(camera->renderer, camera_triangle(camera, t)) < 0) {
154 int camera_fill_triangle(Camera *camera,
158 trace_assert(camera);
160 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
162 if (camera->debug_mode) {
163 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
164 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
168 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
169 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
174 if (fill_triangle(camera->renderer, camera_triangle(camera, t)) < 0) {
181 int camera_render_text(Camera *camera,
188 SDL_RenderGetViewport(camera->renderer, &view_port);
190 const Vec scale = effective_scale(&view_port);
191 const Vec screen_position = camera_point(camera, position);
193 if (sprite_font_render_text(
197 vec(size.x * scale.x * camera->scale, size.y * scale.y * camera->scale),
198 camera->blackwhite_mode ? color_desaturate(c) : c,
206 int camera_render_debug_text(Camera *camera,
210 trace_assert(camera);
213 if (!camera->debug_mode) {
217 if (camera_render_text(
221 rgba(0.0f, 0.0f, 0.0f, 1.0f),
229 int camera_clear_background(Camera *camera,
232 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
234 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
235 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
239 if (SDL_RenderClear(camera->renderer) < 0) {
240 log_fail("SDL_RenderClear: %s\n", SDL_GetError());
247 void camera_center_at(Camera *camera, Point position)
249 trace_assert(camera);
250 camera->position = position;
253 void camera_scale(Camera *camera, float scale)
255 trace_assert(camera);
256 camera->scale = fmaxf(0.1f, scale);
259 void camera_toggle_debug_mode(Camera *camera)
261 trace_assert(camera);
262 camera->debug_mode = !camera->debug_mode;
265 void camera_disable_debug_mode(Camera *camera)
267 trace_assert(camera);
268 camera->debug_mode = 0;
271 void camera_toggle_blackwhite_mode(Camera *camera)
273 trace_assert(camera);
274 camera->blackwhite_mode = !camera->blackwhite_mode;
277 int camera_is_point_visible(const Camera *camera, Point p)
280 SDL_RenderGetViewport(camera->renderer, &view_port);
282 return rect_contains_point(
283 rect_from_sdl(&view_port),
284 camera_point(camera, p));
287 Rect camera_view_port(const Camera *camera)
289 trace_assert(camera);
292 SDL_RenderGetViewport(camera->renderer, &view_port);
294 const Vec s = effective_scale(&view_port);
295 const float w = (float) view_port.w * s.x;
296 const float h = (float) view_port.h * s.y;
298 return rect(camera->position.x - w * 0.5f,
299 camera->position.y - h * 0.5f,
303 Rect camera_view_port_screen(const Camera *camera)
305 trace_assert(camera);
308 SDL_RenderGetViewport(camera->renderer, &view_port);
310 return rect_from_sdl(&view_port);
313 int camera_is_text_visible(const Camera *camera,
318 trace_assert(camera);
322 SDL_RenderGetViewport(camera->renderer, &view_port);
324 return rects_overlap(
327 sprite_font_boundary_box(
332 rect_from_sdl(&view_port));
335 /* ---------- Private Function ---------- */
337 static Vec effective_ratio(const SDL_Rect *view_port)
339 if ((float) view_port->w / RATIO_X > (float) view_port->h / RATIO_Y) {
340 return vec(RATIO_X, (float) view_port->h / ((float) view_port->w / RATIO_X));
342 return vec((float) view_port->w / ((float) view_port->h / RATIO_Y), RATIO_Y);
346 static Vec effective_scale(const SDL_Rect *view_port)
348 return vec_entry_div(
349 vec((float) view_port->w, (float) view_port->h),
350 vec_scala_mult(effective_ratio(view_port), 50.0f));
353 Vec camera_point(const Camera *camera, const Vec p)
356 SDL_RenderGetViewport(camera->renderer, &view_port);
361 vec_sum(p, vec_neg(camera->position)),
362 effective_scale(&view_port)),
364 vec((float) view_port.w * 0.5f,
365 (float) view_port.h * 0.5f));
368 static Triangle camera_triangle(const Camera *camera,
372 camera_point(camera, t.p1),
373 camera_point(camera, t.p2),
374 camera_point(camera, t.p3));
377 Rect camera_rect(const Camera *camera, const Rect rect)
379 return rect_from_points(
382 vec(rect.x, rect.y)),
385 vec(rect.x + rect.w, rect.y + rect.h)));
388 int camera_render_debug_rect(Camera *camera,
392 trace_assert(camera);
394 if (!camera->debug_mode) {
398 if (camera_fill_rect(camera, rect, c) < 0) {
405 Vec camera_map_screen(const Camera *camera,
408 trace_assert(camera);
411 SDL_RenderGetViewport(camera->renderer, &view_port);
413 Vec es = effective_scale(&view_port);
417 const Vec p = vec((float) x, (float) y);
424 vec((float) view_port.w * -0.5f,
425 (float) view_port.h * -0.5f)),
426 1.0f / camera->scale),
431 int camera_fill_rect_screen(Camera *camera,
435 trace_assert(camera);
437 const SDL_Rect sdl_rect = rect_for_sdl(rect);
438 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
440 if (camera->debug_mode) {
441 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
442 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
446 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
447 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
452 if (SDL_RenderFillRect(camera->renderer, &sdl_rect) < 0) {
453 log_fail("SDL_RenderFillRect: %s\n", SDL_GetError());
461 int camera_render_text_screen(Camera *camera,
467 trace_assert(camera);
470 return sprite_font_render_text(
479 int camera_draw_thicc_rect_screen(Camera *camera,
484 trace_assert(camera);
487 if (camera_fill_rect_screen(
489 horizontal_thicc_line(
499 if (camera_fill_rect_screen(
501 horizontal_thicc_line(
511 if (camera_fill_rect_screen(
523 if (camera_fill_rect_screen(
537 const Sprite_font *camera_font(const Camera *camera)