#include <SDL2/SDL.h>
-#include <assert.h>
+#include "system/stacktrace.h"
#include <math.h>
+#include <stdbool.h>
#include "camera.h"
#include "sdl/renderer.h"
-#include "system/error.h"
+#include "system/nth_alloc.h"
+#include "system/log.h"
#define RATIO_X 16.0f
#define RATIO_Y 9.0f
-struct camera_t {
- int debug_mode;
- int blackwhite_mode;
- point_t position;
+struct Camera {
+ bool debug_mode;
+ bool blackwhite_mode;
+ Point position;
SDL_Renderer *renderer;
+ Sprite_font *font;
};
-static vec_t effective_ratio(const SDL_Rect *view_port);
-static vec_t effective_scale(const SDL_Rect *view_port);
-static vec_t camera_point(const camera_t *camera,
- const SDL_Rect *view_port,
- const vec_t p);
-static rect_t camera_rect(const camera_t *camera,
- const SDL_Rect *view_port,
- const rect_t rect);
-static triangle_t camera_triangle(const camera_t *camera,
+static Vec effective_ratio(const SDL_Rect *view_port);
+static Vec effective_scale(const SDL_Rect *view_port);
+static Vec camera_point(const Camera *camera,
+ const SDL_Rect *view_port,
+ const Vec p);
+static Rect camera_rect(const Camera *camera,
+ const SDL_Rect *view_port,
+ const Rect rect);
+static Triangle camera_triangle(const Camera *camera,
const SDL_Rect *view_port,
- const triangle_t t);
+ const Triangle t);
-camera_t *create_camera_from_renderer(SDL_Renderer *renderer)
+Camera *create_camera(SDL_Renderer *renderer,
+ Sprite_font *font)
{
- camera_t *camera = malloc(sizeof(camera_t));
+ trace_assert(renderer);
+ trace_assert(font);
+
+ Camera *camera = nth_alloc(sizeof(Camera));
if (camera == NULL) {
- throw_error(ERROR_TYPE_LIBC);
return NULL;
}
camera->debug_mode = 0;
camera->blackwhite_mode = 0;
camera->renderer = renderer;
+ camera->font = font;
return camera;
}
-void destroy_camera(camera_t *camera)
+void destroy_camera(Camera *camera)
{
- assert(camera);
+ trace_assert(camera);
free(camera);
}
-
-int camera_fill_rect(camera_t *camera,
- rect_t rect,
- color_t color)
+int camera_fill_rect(Camera *camera,
+ Rect rect,
+ Color color)
{
- assert(camera);
+ trace_assert(camera);
SDL_Rect view_port;
SDL_RenderGetViewport(camera->renderer, &view_port);
if (camera->debug_mode) {
if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
- throw_error(ERROR_TYPE_SDL2);
+ log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
return -1;
}
} else {
if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
- throw_error(ERROR_TYPE_SDL2);
+ log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
return -1;
}
}
if (SDL_RenderFillRect(camera->renderer, &sdl_rect) < 0) {
- throw_error(ERROR_TYPE_SDL2);
+ log_fail("SDL_RenderFillRect: %s\n", SDL_GetError());
return -1;
}
return 0;
}
-int camera_draw_rect(camera_t * camera,
- rect_t rect,
- color_t color)
+int camera_draw_rect(Camera * camera,
+ Rect rect,
+ Color color)
{
- assert(camera);
+ trace_assert(camera);
SDL_Rect view_port;
SDL_RenderGetViewport(camera->renderer, &view_port);
const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
- throw_error(ERROR_TYPE_SDL2);
+ log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
return -1;
}
if (SDL_RenderDrawRect(camera->renderer, &sdl_rect) < 0) {
- throw_error(ERROR_TYPE_SDL2);
+ log_fail("SDL_RenderDrawRect: %s\n", SDL_GetError());
return -1;
}
return 0;
}
-int camera_draw_triangle(camera_t *camera,
- triangle_t t,
- color_t color)
+int camera_draw_triangle(Camera *camera,
+ Triangle t,
+ Color color)
{
- assert(camera);
+ trace_assert(camera);
SDL_Rect view_port;
SDL_RenderGetViewport(camera->renderer, &view_port);
const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
- throw_error(ERROR_TYPE_SDL2);
+ log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
return -1;
}
return 0;
}
-int camera_fill_triangle(camera_t *camera,
- triangle_t t,
- color_t color)
+int camera_fill_triangle(Camera *camera,
+ Triangle t,
+ Color color)
{
- assert(camera);
+ trace_assert(camera);
SDL_Rect view_port;
SDL_RenderGetViewport(camera->renderer, &view_port);
const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
-
if (camera->debug_mode) {
if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a / 2) < 0) {
- throw_error(ERROR_TYPE_SDL2);
+ log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
return -1;
}
} else {
if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
- throw_error(ERROR_TYPE_SDL2);
+ log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
return -1;
}
}
return 0;
}
-int camera_clear_background(camera_t *camera,
- color_t color)
+int camera_render_text(Camera *camera,
+ const char *text,
+ Vec size,
+ Color c,
+ Vec position)
+{
+ SDL_Rect view_port;
+ SDL_RenderGetViewport(camera->renderer, &view_port);
+
+ const Vec scale = effective_scale(&view_port);
+ const Vec screen_position = camera_point(camera, &view_port, position);
+
+ if (sprite_font_render_text(
+ camera->font,
+ camera->renderer,
+ screen_position,
+ vec(size.x * scale.x, size.y * scale.y),
+ camera->blackwhite_mode ? color_desaturate(c) : c,
+ text) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int camera_render_debug_text(Camera *camera,
+ const char *text,
+ Vec position)
+{
+ trace_assert(camera);
+ trace_assert(text);
+
+ if (!camera->debug_mode) {
+ return 0;
+ }
+
+ if (camera_render_text(
+ camera,
+ text,
+ vec(2.0f, 2.0f),
+ rgba(0.0f, 0.0f, 0.0f, 1.0f),
+ position) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int camera_clear_background(Camera *camera,
+ Color color)
{
const SDL_Color sdl_color = color_for_sdl(camera->blackwhite_mode ? color_desaturate(color) : color);
if (SDL_SetRenderDrawColor(camera->renderer, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) {
- throw_error(ERROR_TYPE_SDL2);
+ log_fail("SDL_SetRenderDrawColor: %s\n", SDL_GetError());
return -1;
}
if (SDL_RenderClear(camera->renderer) < 0) {
- throw_error(ERROR_TYPE_SDL2);
+ log_fail("SDL_RenderClear: %s\n", SDL_GetError());
return -1;
}
return 0;
}
-void camera_center_at(camera_t *camera, point_t position)
+void camera_center_at(Camera *camera, Point position)
{
- assert(camera);
+ trace_assert(camera);
camera->position = position;
}
-void camera_toggle_debug_mode(camera_t *camera)
+void camera_toggle_debug_mode(Camera *camera)
{
- assert(camera);
+ trace_assert(camera);
camera->debug_mode = !camera->debug_mode;
}
-void camera_disable_debug_mode(camera_t *camera)
+void camera_disable_debug_mode(Camera *camera)
{
- assert(camera);
+ trace_assert(camera);
camera->debug_mode = 0;
}
-void camera_toggle_blackwhite_mode(camera_t *camera)
+void camera_toggle_blackwhite_mode(Camera *camera)
{
- assert(camera);
+ trace_assert(camera);
camera->blackwhite_mode = !camera->blackwhite_mode;
}
-int camera_is_point_visible(const camera_t *camera, point_t p)
+int camera_is_point_visible(const Camera *camera, Point p)
{
SDL_Rect view_port;
SDL_RenderGetViewport(camera->renderer, &view_port);
camera_point(camera, &view_port, p));
}
-rect_t camera_view_port(const camera_t *camera)
+Rect camera_view_port(const Camera *camera)
{
- assert(camera);
+ trace_assert(camera);
SDL_Rect view_port;
SDL_RenderGetViewport(camera->renderer, &view_port);
- const vec_t s = effective_scale(&view_port);
+ const Vec s = effective_scale(&view_port);
const float w = (float) view_port.w * s.x;
const float h = (float) view_port.h * s.y;
w, h);
}
+int camera_is_text_visible(const Camera *camera,
+ Vec size,
+ Vec position,
+ const char *text)
+{
+ trace_assert(camera);
+ trace_assert(text);
+
+ SDL_Rect view_port;
+ SDL_RenderGetViewport(camera->renderer, &view_port);
+
+ return rects_overlap(
+ camera_rect(
+ camera,
+ &view_port,
+ sprite_font_boundary_box(
+ camera->font,
+ position,
+ size,
+ text)),
+ rect_from_sdl(&view_port));
+}
/* ---------- Private Function ---------- */
-static vec_t effective_ratio(const SDL_Rect *view_port)
+static Vec effective_ratio(const SDL_Rect *view_port)
{
if ((float) view_port->w / RATIO_X > (float) view_port->h / RATIO_Y) {
return vec(RATIO_X, (float) view_port->h / ((float) view_port->w / RATIO_X));
}
}
-static vec_t effective_scale(const SDL_Rect *view_port)
+static Vec effective_scale(const SDL_Rect *view_port)
{
return vec_entry_div(
vec((float) view_port->w, (float) view_port->h),
vec_scala_mult(effective_ratio(view_port), 50.0f));
}
-static vec_t camera_point(const camera_t *camera,
+static Vec camera_point(const Camera *camera,
const SDL_Rect *view_port,
- const vec_t p)
+ const Vec p)
{
return vec_sum(
(float) view_port->h * 0.5f));
}
-static triangle_t camera_triangle(const camera_t *camera,
+static Triangle camera_triangle(const Camera *camera,
const SDL_Rect *view_port,
- const triangle_t t)
+ const Triangle t)
{
return triangle(
camera_point(camera, view_port, t.p1),
camera_point(camera, view_port, t.p3));
}
-static rect_t camera_rect(const camera_t *camera,
+static Rect camera_rect(const Camera *camera,
const SDL_Rect *view_port,
- const rect_t rect)
+ const Rect rect)
{
return rect_from_vecs(
camera_point(
effective_scale(view_port),
vec(rect.w, rect.h)));
}
+
+int camera_render_debug_rect(Camera *camera,
+ Rect rect,
+ Color c)
+{
+ trace_assert(camera);
+
+ if (!camera->debug_mode) {
+ return 0;
+ }
+
+ if (camera_fill_rect(camera, rect, c) < 0) {
+ return -1;
+ }
+
+ return 0;
+}