summaryrefslogtreecommitdiff
path: root/src/painter.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/painter.c')
-rw-r--r--src/painter.c274
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;
+}