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 Vec camera_point(const Camera *camera,
26 const SDL_Rect *view_port,
28 static Rect camera_rect(const Camera *camera,
29 const SDL_Rect *view_port,
31 static Triangle camera_triangle(const Camera *camera,
32 const SDL_Rect *view_port,
35 Camera *create_camera(SDL_Renderer *renderer,
38 trace_assert(renderer);
41 Camera *camera = nth_calloc(1, sizeof(Camera));
47 camera->position = vec(0.0f, 0.0f);
49 camera->debug_mode = 0;
50 camera->blackwhite_mode = 0;
51 camera->renderer = renderer;
57 void destroy_camera(Camera *camera)
64 int camera_fill_rect(Camera *camera,
71 SDL_RenderGetViewport(camera->renderer, &view_port);
73 const SDL_Rect sdl_rect = rect_for_sdl(
74 camera_rect(camera, &view_port, rect));
76 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
78 if (camera->debug_mode) {
79 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
80 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
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());
90 if (SDL_RenderFillRect(camera->renderer, &sdl_rect) < 0) {
91 log_fail("SDL_RenderFillRect: %s\n", SDL_GetError());
98 int camera_draw_rect(Camera * camera,
102 trace_assert(camera);
105 SDL_RenderGetViewport(camera->renderer, &view_port);
107 const SDL_Rect sdl_rect = rect_for_sdl(
108 camera_rect(camera, &view_port, rect));
110 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
112 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
113 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
117 if (SDL_RenderDrawRect(camera->renderer, &sdl_rect) < 0) {
118 log_fail("SDL_RenderDrawRect: %s\n", SDL_GetError());
125 int camera_draw_triangle(Camera *camera,
129 trace_assert(camera);
132 SDL_RenderGetViewport(camera->renderer, &view_port);
134 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
136 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
137 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
141 if (draw_triangle(camera->renderer, camera_triangle(camera, &view_port, t)) < 0) {
148 int camera_fill_triangle(Camera *camera,
152 trace_assert(camera);
155 SDL_RenderGetViewport(camera->renderer, &view_port);
157 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
160 if (camera->debug_mode) {
161 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
162 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
166 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
167 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
172 if (fill_triangle(camera->renderer, camera_triangle(camera, &view_port, t)) < 0) {
179 int camera_render_text(Camera *camera,
186 SDL_RenderGetViewport(camera->renderer, &view_port);
188 const Vec scale = effective_scale(&view_port);
189 const Vec screen_position = camera_point(camera, &view_port, position);
191 if (sprite_font_render_text(
195 vec(size.x * scale.x * camera->scale, size.y * scale.y * camera->scale),
196 camera->blackwhite_mode ? color_desaturate(c) : c,
204 int camera_render_debug_text(Camera *camera,
208 trace_assert(camera);
211 if (!camera->debug_mode) {
215 if (camera_render_text(
219 rgba(0.0f, 0.0f, 0.0f, 1.0f),
227 int camera_clear_background(Camera *camera,
230 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
232 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
233 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
237 if (SDL_RenderClear(camera->renderer) < 0) {
238 log_fail("SDL_RenderClear: %s\n", SDL_GetError());
245 void camera_center_at(Camera *camera, Point position)
247 trace_assert(camera);
248 camera->position = position;
251 void camera_scale(Camera *camera, float scale)
253 trace_assert(camera);
254 camera->scale = fmaxf(0.1f, scale);
257 void camera_toggle_debug_mode(Camera *camera)
259 trace_assert(camera);
260 camera->debug_mode = !camera->debug_mode;
263 void camera_disable_debug_mode(Camera *camera)
265 trace_assert(camera);
266 camera->debug_mode = 0;
269 void camera_toggle_blackwhite_mode(Camera *camera)
271 trace_assert(camera);
272 camera->blackwhite_mode = !camera->blackwhite_mode;
275 int camera_is_point_visible(const Camera *camera, Point p)
278 SDL_RenderGetViewport(camera->renderer, &view_port);
280 return rect_contains_point(
281 rect_from_sdl(&view_port),
282 camera_point(camera, &view_port, p));
285 Rect camera_view_port(const Camera *camera)
287 trace_assert(camera);
290 SDL_RenderGetViewport(camera->renderer, &view_port);
292 const Vec s = effective_scale(&view_port);
293 const float w = (float) view_port.w * s.x;
294 const float h = (float) view_port.h * s.y;
296 return rect(camera->position.x - w * 0.5f,
297 camera->position.y - h * 0.5f,
301 Rect camera_view_port_screen(const Camera *camera)
303 trace_assert(camera);
306 SDL_RenderGetViewport(camera->renderer, &view_port);
308 return rect_from_sdl(&view_port);
311 int camera_is_text_visible(const Camera *camera,
316 trace_assert(camera);
320 SDL_RenderGetViewport(camera->renderer, &view_port);
322 return rects_overlap(
326 sprite_font_boundary_box(
331 rect_from_sdl(&view_port));
334 /* ---------- Private Function ---------- */
336 static Vec effective_ratio(const SDL_Rect *view_port)
338 if ((float) view_port->w / RATIO_X > (float) view_port->h / RATIO_Y) {
339 return vec(RATIO_X, (float) view_port->h / ((float) view_port->w / RATIO_X));
341 return vec((float) view_port->w / ((float) view_port->h / RATIO_Y), RATIO_Y);
345 static Vec effective_scale(const SDL_Rect *view_port)
347 return vec_entry_div(
348 vec((float) view_port->w, (float) view_port->h),
349 vec_scala_mult(effective_ratio(view_port), 50.0f));
352 static Vec camera_point(const Camera *camera,
353 const SDL_Rect *view_port,
360 vec_sum(p, vec_neg(camera->position)),
361 effective_scale(view_port)),
363 vec((float) view_port->w * 0.5f,
364 (float) view_port->h * 0.5f));
367 static Triangle camera_triangle(const Camera *camera,
368 const SDL_Rect *view_port,
372 camera_point(camera, view_port, t.p1),
373 camera_point(camera, view_port, t.p2),
374 camera_point(camera, view_port, t.p3));
377 static Rect camera_rect(const Camera *camera,
378 const SDL_Rect *view_port,
381 return rect_from_points(
385 vec(rect.x, rect.y)),
389 vec(rect.x + rect.w, rect.y + rect.h)));
392 int camera_render_debug_rect(Camera *camera,
396 trace_assert(camera);
398 if (!camera->debug_mode) {
402 if (camera_fill_rect(camera, rect, c) < 0) {
409 Vec camera_map_screen(const Camera *camera,
412 trace_assert(camera);
415 SDL_RenderGetViewport(camera->renderer, &view_port);
417 Vec es = effective_scale(&view_port);
421 const Vec p = vec((float) x, (float) y);
428 vec((float) view_port.w * -0.5f,
429 (float) view_port.h * -0.5f)),
430 1.0f / camera->scale),
435 int camera_fill_rect_screen(Camera *camera,
439 trace_assert(camera);
441 const SDL_Rect sdl_rect = rect_for_sdl(rect);
442 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
444 if (camera->debug_mode) {
445 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
446 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
450 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
451 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
456 if (SDL_RenderFillRect(camera->renderer, &sdl_rect) < 0) {
457 log_fail("SDL_RenderFillRect: %s\n", SDL_GetError());
465 int camera_render_text_screen(Camera *camera,
471 trace_assert(camera);
474 return sprite_font_render_text(