ENGINE_DEFINE_COMPONENT(engine_Camera)
ENGINE_DEFINE_COMPONENT(engine_DrawRectangle)
ENGINE_DEFINE_COMPONENT(engine_DrawCircle)
ENGINE_DEFINE_COMPONENT(engine_DrawText)
ENGINE_DEFINE_COMPONENT(engine_Sprite)
// ====================================================================================================================
static void _draw_sprite(const struct alias_LocalToWorld2D *t, const struct engine_Sprite *s) {
struct LoadedResource *res = _resource_from_image(s->image);
alias_R hw = res->image.width / 2, hh = res->image.height / 2, bl = -hw, br = hw, bt = -hh, bb = hh;
alias_pga2d_Point box[] = {alias_pga2d_point(br, bb), alias_pga2d_point(br, bt), alias_pga2d_point(bl, bt),
alias_pga2d_point(bl, bb)};
box[0] = alias_pga2d_sandwich_bm(box[0], t->motor);
box[1] = alias_pga2d_sandwich_bm(box[1], t->motor);
box[2] = alias_pga2d_sandwich_bm(box[2], t->motor);
box[3] = alias_pga2d_sandwich_bm(box[3], t->motor);
uint32_t *indexes;
struct ScreenVertex *vertexes;
_ScreenVertex_begin_draw(6, &indexes, 4, &vertexes);
vertexes[0] = (struct ScreenVertex){.xy = {alias_pga2d_point_x(box[0]), alias_pga2d_point_y(box[0])},
.rgba = {s->color.r, s->color.g, s->color.b, s->color.a},
.st = {s->s1, s->t1}};
vertexes[1] = (struct ScreenVertex){.xy = {alias_pga2d_point_x(box[1]), alias_pga2d_point_y(box[1])},
.rgba = {s->color.r, s->color.g, s->color.b, s->color.a},
.st = {s->s1, s->t0}};
vertexes[2] = (struct ScreenVertex){.xy = {alias_pga2d_point_x(box[2]), alias_pga2d_point_y(box[2])},
.rgba = {s->color.r, s->color.g, s->color.b, s->color.a},
.st = {s->s0, s->t0}};
vertexes[3] = (struct ScreenVertex){.xy = {alias_pga2d_point_x(box[3]), alias_pga2d_point_y(box[3])},
.rgba = {s->color.r, s->color.g, s->color.b, s->color.a},
.st = {s->s0, s->t1}};
indexes[0] = 0;
indexes[1] = 1;
indexes[2] = 2;
indexes[3] = 0;
indexes[4] = 2;
indexes[5] = 3;
_ScreenVertex_draw(&res->image, 0, 6);
_ScreenVertex_end_draw();
}
ENGINE_QUERY(_draw_sprites
, read(alias_LocalToWorld2D, t)
, read(engine_Sprite, s)
, action(
(void)state;
_draw_sprite(t, s);
)
)
// ====================================================================================================================
static void _draw_rectangle_action(const struct alias_LocalToWorld2D *t, const struct engine_DrawRectangle *r) {
alias_R
hw = r->width / 2
, hh = r->height / 2
, bl = -hw
, br = hw
, bt = -hh
, bb = hh
;
alias_pga2d_Point box[] = {
alias_pga2d_point(br, bb)
, alias_pga2d_point(br, bt)
, alias_pga2d_point(bl, bt)
, alias_pga2d_point(bl, bb)
};
box[0] = alias_pga2d_sandwich_bm(box[0], t->motor);
box[1] = alias_pga2d_sandwich_bm(box[1], t->motor);
box[2] = alias_pga2d_sandwich_bm(box[2], t->motor);
box[3] = alias_pga2d_sandwich_bm(box[3], t->motor);
uint32_t * indexes;
struct ScreenVertex * vertexes;
_ScreenVertex_begin_draw(6, &indexes, 4, &vertexes);
vertexes[0] = (struct ScreenVertex) { .xy[0] = alias_pga2d_point_x(box[0]), .xy[1] = alias_pga2d_point_y(box[0]), .rgba = { r->color.r, r->color.g, r->color.b, r->color.a } };
vertexes[1] = (struct ScreenVertex) { .xy[0] = alias_pga2d_point_x(box[1]), .xy[1] = alias_pga2d_point_y(box[1]), .rgba = { r->color.r, r->color.g, r->color.b, r->color.a } };
vertexes[2] = (struct ScreenVertex) { .xy[0] = alias_pga2d_point_x(box[2]), .xy[1] = alias_pga2d_point_y(box[2]), .rgba = { r->color.r, r->color.g, r->color.b, r->color.a } };
vertexes[3] = (struct ScreenVertex) { .xy[0] = alias_pga2d_point_x(box[3]), .xy[1] = alias_pga2d_point_y(box[3]), .rgba = { r->color.r, r->color.g, r->color.b, r->color.a } };
indexes[0] = 0;
indexes[1] = 1;
indexes[2] = 2;
indexes[3] = 0;
indexes[4] = 2;
indexes[5] = 3;
_ScreenVertex_draw(NULL, 0, 6);
_ScreenVertex_end_draw();
}
ENGINE_QUERY(_draw_rectangles
, read(alias_LocalToWorld2D, t)
, read(engine_DrawRectangle, r)
, action(
(void)state;
_draw_rectangle_action(t, r);
)
)
// ====================================================================================================================
static void _draw_circle(float x, float y, float radius, alias_Color color) {
#define NUM_CIRCLE_SEGMENTS 32
struct ScreenVertex * vertexes;
uint32_t * indexes;
_ScreenVertex_begin_draw(3 * (NUM_CIRCLE_SEGMENTS - 2), &indexes, NUM_CIRCLE_SEGMENTS, &vertexes);
for(uint32_t i = 0; i < NUM_CIRCLE_SEGMENTS; i++) {
alias_R angle = (alias_R)i / NUM_CIRCLE_SEGMENTS * alias_R_PI * 2;
alias_R s = alias_R_sin(angle);
alias_R c = alias_R_cos(angle);
vertexes[i].xy[0] = x + s * radius;
vertexes[i].xy[1] = y + c * radius;
vertexes[i].rgba[0] = color.r;
vertexes[i].rgba[1] = color.g;
vertexes[i].rgba[2] = color.b;
vertexes[i].rgba[3] = color.a;
vertexes[i].st[0] = 0;
vertexes[i].st[1] = 0;
if(i >= 2) {
indexes[(i - 2) * 3 + 0] = 0;
indexes[(i - 2) * 3 + 1] = i - 1;
indexes[(i - 2) * 3 + 2] = i - 0;
}
}
_ScreenVertex_draw(NULL, 0, 3 * (NUM_CIRCLE_SEGMENTS - 2));
_ScreenVertex_end_draw();
#undef NUM_CIRCLE_SEGMENTS
}
ENGINE_QUERY(_draw_circles
, read(alias_LocalToWorld2D, transform)
, read(engine_DrawCircle, c)
, action(
(void)state;
_draw_circle(alias_pga2d_point_x(transform->position), alias_pga2d_point_y(transform->position), c->radius, c->color);
)
)
// ====================================================================================================================
ENGINE_QUERY(_draw_text
, read(alias_LocalToWorld2D, w)
, read(engine_DrawText, t)
, action(
(void)state;
_font_draw(&BreeSerif, t->text, alias_pga2d_point_x(w->position), alias_pga2d_point_y(w->position), t->size, 1.0, t->color);
)
)
// ====================================================================================================================
static void _draw_frame_action(const struct alias_LocalToWorld2D * transform, const struct engine_Camera * camera) {
int x = alias_pga2d_point_x(camera->viewport_min) * _r_width;
int y = alias_pga2d_point_y(camera->viewport_min) * _r_height;
int width = (alias_pga2d_point_x(camera->viewport_max) * _r_width) - x;
int height = (alias_pga2d_point_y(camera->viewport_max) * _r_height) - y;
alias_pga2d_Point center = alias_pga2d_sandwich_bm(alias_pga2d_point(0, 0), transform->motor);
float offset_x = width / 2.0f;
float offset_y = height / 2.0f;
float target_x = alias_pga2d_point_x(center);
float target_y = alias_pga2d_point_y(center);
float rotation = 0;
alias_matrix_ortho(0, width, height, 0, -99999, 99999, engine_r_projection_matrix.uniform.data.mat);
{
float origin_m[16], rotation_m[16], scale_m[16], translation_m[16], transform_m[16];
alias_matrix_translation(-target_x, -target_y, 0, origin_m);
alias_matrix_rotation_z(rotation * alias_R_PI / 180.0f, rotation_m);
alias_matrix_scale(camera->zoom, camera->zoom, 1, scale_m);
alias_matrix_translation(offset_x, offset_y, 0, translation_m);
alias_matrix_multiply(scale_m, rotation_m, transform_m);
alias_matrix_multiply(origin_m, transform_m, transform_m);
alias_matrix_multiply(transform_m, translation_m, engine_r_view_matrix.uniform.data.mat);
}
alias_matrix_identity(engine_r_model_matrix.uniform.data.mat);
glViewport(x, y, width, height);
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
_draw_sprites();
_draw_rectangles();
_draw_circles();
_draw_text();
}
ENGINE_QUERY(_draw_frame
, read(alias_LocalToWorld2D, transform)
, read(engine_Camera, camera)
, pre(
int w, h;
glfwGetFramebufferSize(_r_window, &w, &h);
_r_width = w;
_r_height = h;
glViewport(0, 0, _r_width, _r_height);
glClearColor(0.9, 0.9, 0.9, 1);
glClear(GL_COLOR_BUFFER_BIT);
alias_gl_resetTemporaryBuffers();
)
, action(
(void)state;
_draw_frame_action(transform, camera);
)
, post(
alias_matrix_ortho(0, _r_width, _r_height, 0, -99999, 99999, engine_r_projection_matrix.uniform.data.mat);
alias_matrix_identity(engine_r_view_matrix.uniform.data.mat);
glViewport(0, 0, _r_width, _r_height);
_ui_frame();
glfwSwapBuffers(_r_window);
)
)