diff options
Diffstat (limited to 'src/painter.c')
-rw-r--r-- | src/painter.c | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/src/painter.c b/src/painter.c new file mode 100644 index 0000000..9f6b911 --- /dev/null +++ b/src/painter.c @@ -0,0 +1,274 @@ +#include <SFML/Graphics/RenderWindow.h> +#include <SFML/Graphics/RectangleShape.h> +#include <SFML/Graphics/Font.h> +#include <SFML/Graphics/Text.h> +#include <stdlib.h> +#include <stdio.h> + +#include "tet_conf.h" +#include "vector.h" +#include "text.h" +#include "field.h" +#include "painter.h" + +#include "idlist.h" + +static sfColor shape_color_map[] = { + UIBGCOLOR, + LCOLOR, + RLCOLOR, + ZCOLOR, + SCOLOR, + BCOLOR, + ICOLOR, + TCOLOR, +}; + +enum t { + TYPE_U, + TYPE_FIELD, + TYPE_TEXT +}; + +struct drawable { + enum t t; +}; + +struct field_drawable { + struct drawable; + + sfRectangleShape ***p; + struct vector2ui size; + unsigned int attr; +}; + +struct text_drawable { + struct drawable; + + sfText *text; + unsigned long attr; +}; + +static sfRenderWindow *window; +static sfFont *font; + +static struct idlist *drawables = NULL; + +void painter_set_window(sfRenderWindow *w) +{ + window = w; +} + +void painter_load_font(char *filename) +{ + font = sfFont_createFromFile(filename); + if (!font) { + printf("%s font load failed", filename); + exit(EXIT_FAILURE); + } +} + +void painter_destroy_font() +{ + sfFont_destroy(font); +} + +unsigned long painter_register_field(struct field *fld) +{ + struct idlist *last; + if (!drawables) + last = drawables = list_new(); + else + last = list_append(drawables); + + struct field_drawable *f = calloc(1, sizeof(struct field_drawable)); + f->t = TYPE_FIELD; + f->size = fld->size; + f->p = calloc(f->size.y, sizeof(sfRectangleShape **)); + for (unsigned int j = 0; j < f->size.y; j++) { + f->p[j] = calloc(f->size.x, sizeof(sfRectangleShape *)); + for (unsigned int i = 0; i < f->size.x; i++) { + f->p[j][i] = sfRectangleShape_create(); + sfVector2f cell_pos; + cell_pos.x = fld->pos.x + (i * (CELL_SIZE.x + 2 * OUT_THICK)); + cell_pos.y = fld->pos.y - (j * (CELL_SIZE.y + 2 * OUT_THICK)); + sfRectangleShape_setPosition(f->p[j][i], cell_pos); + sfRectangleShape_setFillColor(f->p[j][i], (sfColor)UIBGCOLOR); + sfRectangleShape_setSize(f->p[j][i], CELL_SIZE); + sfRectangleShape_setOutlineColor(f->p[j][i], (sfColor)UIFGACTIVECOLOR); + sfRectangleShape_setOutlineThickness(f->p[j][i], OUT_THICK); + } + } + + last->obj = f; + return last->id; +} + +void painter_update_field(unsigned long id, struct field *fld) +{ + struct idlist *node = list_get(drawables, id); + if (!node) + return; + struct field_drawable *f = node->obj; + f->attr = fld->attr; + for (unsigned int j = 0; j < fld->size.y; j++) { + for (unsigned int i = 0; i < fld->size.x; i++) { + sfVector2f cell_pos; + cell_pos.x = fld->pos.x + (i * (CELL_SIZE.x + 2 * OUT_THICK)); + cell_pos.y = fld->pos.y - (j * (CELL_SIZE.y + 2 * OUT_THICK)); + sfRectangleShape_setPosition(f->p[j][i], cell_pos); + if (fld->c[j][i].a) { + sfRectangleShape_setFillColor(f->p[j][i], shape_color_map[fld->c[j][i].color]); + sfRectangleShape_setOutlineColor(f->p[j][i], (sfColor)UIFGACTIVECOLOR); + } else if (f->attr & FLD_ATTR_TRANSPARENT) { + sfRectangleShape_setFillColor(f->p[j][i], (sfColor)UITRANSPARENT); + sfRectangleShape_setOutlineColor(f->p[j][i], (sfColor)UITRANSPARENT); + } else { + sfRectangleShape_setFillColor(f->p[j][i], (sfColor)UIBGCOLOR); + sfRectangleShape_setOutlineColor(f->p[j][i], (sfColor)UIFGINACTIVECOLOR); + } + } + } + for (unsigned int s = 0; s < fld->shape_cnt; ++s) + for (int j = 0; j < 4; j++) + for (int i = 0; i < 4; i++) + if (fld->shape[s].c[j][i] && j + fld->shape[s].y < (int)fld->size.y) { + sfRectangleShape_setFillColor( + f->p[j + fld->shape[s].y][i + fld->shape[s].x], + shape_color_map[fld->shape[s].color]); + sfRectangleShape_setOutlineColor( + f->p[j + fld->shape[s].y][i + fld->shape[s].x], + (sfColor)UIFGACTIVECOLOR); + } +} + +static void draw_field_drawable(struct drawable *d) +{ + struct field_drawable *f = (void *)d; + if (!(f->attr & FLD_ATTR_INVISIBLE)) + for (unsigned int j = 0; j < f->size.y; j++) + for (unsigned int i = 0; i < f->size.x; i++) + sfRenderWindow_drawRectangleShape(window, f->p[j][i], NULL); +} + +static void destroy_field_drawable(struct drawable *d) +{ + struct field_drawable *f = (void *)d; + for (unsigned int j = 0; j < f->size.y; j++) { + for (unsigned int i = 0; i < f->size.x; i++) + sfRectangleShape_destroy(f->p[j][i]); + free(f->p[j]); + } + free(f->p); + free(f); +} + +unsigned long painter_register_text(struct text *txt) +{ + struct idlist *last; + if (!drawables) + last = drawables = list_new(); + else + last = list_append(drawables); + + struct text_drawable *t = calloc(1, sizeof(struct text_drawable)); + t->t = TYPE_TEXT; + t->text = sfText_create(); + sfText_setFont(t->text, font); + sfText_setCharacterSize(t->text, txt->size); + sfVector2f pos = (sfVector2f){.x = txt->pos.x, .y = txt->pos.y}; + sfText_setPosition(t->text, pos); + sfText_setString(t->text, txt->text); + + last->obj = t; + return last->id; +} + +void painter_update_text(unsigned long id, struct text *txt) +{ + struct idlist *node = list_get(drawables, id); + if (!node) + return; + struct text_drawable *t = node->obj; + t->attr = txt->attr; + sfText_setCharacterSize(t->text, txt->size); + sfVector2f pos = (sfVector2f){.x = txt->pos.x, .y = txt->pos.y}; + sfText_setPosition(t->text, pos); + sfText_setString(t->text, txt->text); +} + +static void draw_text_drawable(struct drawable *d) +{ + struct text_drawable *t = (struct text_drawable *)d; + if (!(t->attr & TXT_ATTR_INVISIBLE)) + sfRenderWindow_drawText(window, t->text, NULL); +} + +static void destroy_text_drawable(struct drawable *d) +{ + struct text_drawable *t = (struct text_drawable *)d; + sfText_destroy(t->text); + free(t); +} + +static void draw_drawable(void *obj) +{ + struct drawable *d = obj; + switch (d->t) { + case TYPE_FIELD: + draw_field_drawable(d); + break; + case TYPE_TEXT: + draw_text_drawable(d); + break; + case TYPE_U: + fprintf(stderr, "ERROR: Unknown type of drawable\n"); + exit(EXIT_FAILURE); + break; + } +} + +void painter_draw() +{ + sfRenderWindow_clear(window, (sfColor)UIBGCOLOR); + list_foreach(drawables, draw_drawable); + sfRenderWindow_display(window); +} + +static void destroy_drawable(void *obj) +{ + struct drawable *d = obj; + switch (d->t) { + case TYPE_FIELD: + destroy_field_drawable(d); + break; + case TYPE_TEXT: + destroy_text_drawable(d); + break; + case TYPE_U: + fprintf(stderr, "ERROR: Unknown type of drawable\n"); + exit(EXIT_FAILURE); + break; + } +} + +void painter_destroy_drawable(unsigned long id) +{ + struct idlist *node = list_get(drawables, id); + destroy_drawable(node->obj); + list_rm_node(node); +} + +void painter_destroy_drawables() +{ + list_foreach(drawables, destroy_drawable); + list_destroy(drawables); + drawables = 0; +} + +void painter_destroy_all() +{ + painter_destroy_drawables(); + painter_destroy_font(); + window = 0; +} |