2 #include "system/stacktrace.h"
7 #include "sdl/renderer.h"
8 #include "system/nth_alloc.h"
9 #include "system/log.h"
18 SDL_Renderer *renderer;
22 static Vec effective_ratio(const SDL_Rect *view_port);
23 static Vec effective_scale(const SDL_Rect *view_port);
24 static Vec camera_point(const Camera *camera,
25 const SDL_Rect *view_port,
27 static Rect camera_rect(const Camera *camera,
28 const SDL_Rect *view_port,
30 static Triangle camera_triangle(const Camera *camera,
31 const SDL_Rect *view_port,
34 Camera *create_camera(SDL_Renderer *renderer,
37 trace_assert(renderer);
40 Camera *camera = nth_alloc(sizeof(Camera));
46 camera->position = vec(0.0f, 0.0f);
47 camera->debug_mode = 0;
48 camera->blackwhite_mode = 0;
49 camera->renderer = renderer;
55 void destroy_camera(Camera *camera)
62 int camera_fill_rect(Camera *camera,
69 SDL_RenderGetViewport(camera->renderer, &view_port);
71 const SDL_Rect sdl_rect = rect_for_sdl(
72 camera_rect(camera, &view_port, rect));
74 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
76 if (camera->debug_mode) {
77 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
78 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
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());
88 if (SDL_RenderFillRect(camera->renderer, &sdl_rect) < 0) {
89 log_fail("SDL_RenderFillRect: %s\n", SDL_GetError());
96 int camera_draw_rect(Camera * camera,
100 trace_assert(camera);
103 SDL_RenderGetViewport(camera->renderer, &view_port);
105 const SDL_Rect sdl_rect = rect_for_sdl(
106 camera_rect(camera, &view_port, rect));
108 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
110 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
111 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
115 if (SDL_RenderDrawRect(camera->renderer, &sdl_rect) < 0) {
116 log_fail("SDL_RenderDrawRect: %s\n", SDL_GetError());
123 int camera_draw_triangle(Camera *camera,
127 trace_assert(camera);
130 SDL_RenderGetViewport(camera->renderer, &view_port);
132 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
134 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
135 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
139 if (draw_triangle(camera->renderer, camera_triangle(camera, &view_port, t)) < 0) {
146 int camera_fill_triangle(Camera *camera,
150 trace_assert(camera);
153 SDL_RenderGetViewport(camera->renderer, &view_port);
155 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
158 if (camera->debug_mode) {
159 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
160 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
164 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
165 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
170 if (fill_triangle(camera->renderer, camera_triangle(camera, &view_port, t)) < 0) {
177 int camera_render_text(Camera *camera,
184 SDL_RenderGetViewport(camera->renderer, &view_port);
186 const Vec scale = effective_scale(&view_port);
187 const Vec screen_position = camera_point(camera, &view_port, position);
189 if (sprite_font_render_text(
193 vec(size.x * scale.x, size.y * scale.y),
194 camera->blackwhite_mode ? color_desaturate(c) : c,
202 int camera_render_debug_text(Camera *camera,
206 trace_assert(camera);
209 if (!camera->debug_mode) {
213 if (camera_render_text(
217 rgba(0.0f, 0.0f, 0.0f, 1.0f),
225 int camera_clear_background(Camera *camera,
228 const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
230 if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
231 log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
235 if (SDL_RenderClear(camera->renderer) < 0) {
236 log_fail("SDL_RenderClear: %s\n", SDL_GetError());
243 void camera_center_at(Camera *camera, Point position)
245 trace_assert(camera);
246 camera->position = position;
249 void camera_toggle_debug_mode(Camera *camera)
251 trace_assert(camera);
252 camera->debug_mode = !camera->debug_mode;
255 void camera_disable_debug_mode(Camera *camera)
257 trace_assert(camera);
258 camera->debug_mode = 0;
261 void camera_toggle_blackwhite_mode(Camera *camera)
263 trace_assert(camera);
264 camera->blackwhite_mode = !camera->blackwhite_mode;
267 int camera_is_point_visible(const Camera *camera, Point p)
270 SDL_RenderGetViewport(camera->renderer, &view_port);
272 return rect_contains_point(
273 rect_from_sdl(&view_port),
274 camera_point(camera, &view_port, p));
277 Rect camera_view_port(const Camera *camera)
279 trace_assert(camera);
282 SDL_RenderGetViewport(camera->renderer, &view_port);
284 const Vec s = effective_scale(&view_port);
285 const float w = (float) view_port.w * s.x;
286 const float h = (float) view_port.h * s.y;
288 return rect(camera->position.x - w * 0.5f,
289 camera->position.y - h * 0.5f,
293 int camera_is_text_visible(const Camera *camera,
298 trace_assert(camera);
302 SDL_RenderGetViewport(camera->renderer, &view_port);
304 return rects_overlap(
308 sprite_font_boundary_box(
313 rect_from_sdl(&view_port));
316 /* ---------- Private Function ---------- */
318 static Vec effective_ratio(const SDL_Rect *view_port)
320 if ((float) view_port->w / RATIO_X > (float) view_port->h / RATIO_Y) {
321 return vec(RATIO_X, (float) view_port->h / ((float) view_port->w / RATIO_X));
323 return vec((float) view_port->w / ((float) view_port->h / RATIO_Y), RATIO_Y);
327 static Vec effective_scale(const SDL_Rect *view_port)
329 return vec_entry_div(
330 vec((float) view_port->w, (float) view_port->h),
331 vec_scala_mult(effective_ratio(view_port), 50.0f));
334 static Vec camera_point(const Camera *camera,
335 const SDL_Rect *view_port,
341 vec_sum(p, vec_neg(camera->position)),
342 effective_scale(view_port)),
343 vec((float) view_port->w * 0.5f,
344 (float) view_port->h * 0.5f));
347 static Triangle camera_triangle(const Camera *camera,
348 const SDL_Rect *view_port,
352 camera_point(camera, view_port, t.p1),
353 camera_point(camera, view_port, t.p2),
354 camera_point(camera, view_port, t.p3));
357 static Rect camera_rect(const Camera *camera,
358 const SDL_Rect *view_port,
361 return rect_from_vecs(
365 vec(rect.x, rect.y)),
367 effective_scale(view_port),
368 vec(rect.w, rect.h)));
371 int camera_render_debug_rect(Camera *camera,
375 trace_assert(camera);
377 if (!camera->debug_mode) {
381 if (camera_fill_rect(camera, rect, c) < 0) {