JacksEscape/render_bundle_file.c

150 lines
3.9 KiB
C
Raw Permalink Normal View History

2024-03-28 14:04:43 +08:00
#include "render_bundle.h"
2024-03-30 18:55:43 +08:00
#include "render_util.h"
2024-03-28 14:04:43 +08:00
#include "util/vector.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
2024-03-30 18:55:43 +08:00
#define RGB(r, g, b) ((r) | ((g) << 8) | ((b) << 16))
2024-03-28 14:04:43 +08:00
vector_Vector *render_Bundles;
static render_Bundle *_tmpb;
static render_Primitive *_tmpp;
// Subsequent tokens can be read by strtok(NULL, " ")
static void _render_BundleCommand(char *cmd) {
// convert CMD to upper case
for (int i = 0; i < strlen(cmd); i++)
cmd[i] = toupper(cmd[i]);
#define CMD(str) (strcmp(cmd, str) == 0)
// Find the command
if (CMD("BUNDLE")) {
// Start a bundle
if (_tmpb != NULL) {
2024-04-28 19:12:25 +08:00
WARN("_tmpb!=0, you forgot to use ENDBUNDLE for the last bundle, discarding");
2024-03-28 14:04:43 +08:00
free(_tmpb);
}
_tmpb = render_NewBundle(strtok(NULL, " "));
} else if (CMD("ENDBUNDLE")) {
// commit the bundle
if (_tmpb) {
fprintf(stderr, "[_render_BundleCommand] Commiting bundle %s with %d primitives\n", _tmpb->name, vector_Size(_tmpb->prims));
vector_Push(render_Bundles, &_tmpb);
_tmpb = NULL;
} else
2024-04-28 19:12:25 +08:00
WARN("_tmpb==0, ENDBUNDLE without BUNDLE first");
2024-03-28 14:04:43 +08:00
} else if (CMD("PRIM")) {
// start a primitive
if (_tmpp != NULL) {
2024-04-28 19:12:25 +08:00
WARN("_tmpp!=0, you forgot to ENDPRIM for the last primitive, discarding");
2024-03-28 14:04:43 +08:00
if (_tmpp->points)
vector_Destroy(_tmpp->points);
free(_tmpp);
}
_tmpp = malloc(sizeof(render_Primitive));
_tmpp->points = vector_Create(sizeof(Vec2));
2024-03-30 18:55:43 +08:00
_tmpp->mode = render_ModeDefault;
2024-03-28 14:04:43 +08:00
// parse the type
char *type = strtok(NULL, " ");
2024-03-30 18:55:43 +08:00
if (strcmp(type, "LINES") == 0)
2024-03-28 14:04:43 +08:00
_tmpp->type = render_Lines;
2024-03-30 18:55:43 +08:00
else if (strcmp(type, "LINESTRIP") == 0)
2024-03-28 14:04:43 +08:00
_tmpp->type = render_LineStrip;
2024-03-30 18:55:43 +08:00
else if (strcmp(type, "POLY") == 0)
2024-03-28 14:04:43 +08:00
_tmpp->type = render_Polygon;
} else if (CMD("ENDPRIM")) {
// commit the primitive
if (_tmpb && _tmpp) {
fprintf(stderr, "[_render_BundleCommand] Commiting primitive type %d with %d points\n", _tmpp->type, vector_Size(_tmpp->points));
vector_Push(_tmpb->prims, _tmpp);
free(_tmpp);
_tmpp = NULL;
} else
WARN("tmpb=%x, tmpp=%x, ENDPRIM when one of them is NULL", _tmpb, _tmpp);
} else if (CMD("P")) {
// Add a Vec2
if (_tmpp) {
2024-03-30 18:55:43 +08:00
double x = strtod(strtok(NULL, " "), NULL);
double y = strtod(strtok(NULL, " "), NULL);
Vec2 v = vec2(x, y);
2024-03-28 14:04:43 +08:00
vector_Push(_tmpp->points, &v);
} else
2024-04-28 19:12:25 +08:00
WARN("P without PRIM first");
2024-03-30 18:55:43 +08:00
} else if (CMD("FG")) {
// Set Foreground color
if (_tmpp) {
int r = atoi(strtok(NULL, " "));
int g = atoi(strtok(NULL, " "));
int b = atoi(strtok(NULL, " "));
_tmpp->mode.fg = RGB(r, g, b);
2024-03-30 18:55:43 +08:00
} else
2024-04-28 19:12:25 +08:00
WARN("FG without PRIM first");
2024-03-30 18:55:43 +08:00
} else if (CMD("BG")) {
// Set Background color
if (_tmpp) {
int r = atoi(strtok(NULL, " "));
int g = atoi(strtok(NULL, " "));
int b = atoi(strtok(NULL, " "));
_tmpp->mode.bg = RGB(r, g, b);
2024-03-30 18:55:43 +08:00
} else
2024-04-28 19:12:25 +08:00
WARN("BG without PRIM first");
2024-03-28 14:04:43 +08:00
} else {
WARN("unknown command %s", cmd);
}
#undef CMD
}
void render_LoadBundle(const char *filename) {
if (!render_Bundles)
render_Bundles = vector_Create(sizeof(render_Bundle *));
FILE *f = fopen(filename, "r");
if (!f) {
WARN("failed to open file\"%s\"", filename);
return;
}
2024-04-28 19:12:25 +08:00
char linebuf[512];
2024-05-05 13:36:53 +08:00
memset(linebuf, 0, sizeof(linebuf));
while (!feof(f) && fgets(linebuf, sizeof(linebuf) - 1, f)) {
while (linebuf[0] !='\0' && linebuf[strlen(linebuf) - 1] == '\n')
2024-03-28 14:04:43 +08:00
linebuf[strlen(linebuf) - 1] = '\0';
char *cmd = strtok(linebuf, " ");
if (cmd == NULL)
continue;
_render_BundleCommand(cmd);
}
}
render_Bundle *render_FindBundle(const char *name) {
if (!render_Bundles) {
WARN("called with render_Bundles=NULL (name=%s)", name);
return NULL;
}
// brute force search. could be slow
for (int i = 0; i < vector_Size(render_Bundles); i++) {
render_Bundle *b = *(render_Bundle **)vector_At(render_Bundles, i);
if (strcmp(name, b->name) == 0)
return b;
}
WARN("bundle \"%s\" not found", name);
return NULL;
}