127 lines
3.2 KiB
C
127 lines
3.2 KiB
C
|
|
||
|
#include "render_bundle.h"
|
||
|
#include "util/vector.h"
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <ctype.h>
|
||
|
|
||
|
|
||
|
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) {
|
||
|
WARN("_tmpb!=0, you forgot to use ENDBUNDLE for the last bundle, discarding", 0);
|
||
|
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
|
||
|
WARN("_tmpb==0, ENDBUNDLE without BUNDLE first", 0);
|
||
|
|
||
|
|
||
|
} else if (CMD("PRIM")) {
|
||
|
// start a primitive
|
||
|
if (_tmpp != NULL) {
|
||
|
WARN("_tmpp!=0, you forgot to ENDPRIM for the last primitive, discarding", 0);
|
||
|
if (_tmpp->points)
|
||
|
vector_Destroy(_tmpp->points);
|
||
|
free(_tmpp);
|
||
|
}
|
||
|
_tmpp = malloc(sizeof(render_Primitive));
|
||
|
_tmpp->points = vector_Create(sizeof(Vec2));
|
||
|
_tmpp->fg = 0xffffff;
|
||
|
_tmpp->bg = 0;
|
||
|
|
||
|
// parse the type
|
||
|
char *type = strtok(NULL, " ");
|
||
|
if (strcmp(type, "LINES"))
|
||
|
_tmpp->type = render_Lines;
|
||
|
else if (strcmp(type, "LINESTRIP"))
|
||
|
_tmpp->type = render_LineStrip;
|
||
|
else if (strcmp(type, "POLY"))
|
||
|
_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) {
|
||
|
Vec2 v = vec2(strtod(strtok(NULL, " "), NULL), strtod(strtok(NULL, " "), NULL));
|
||
|
vector_Push(_tmpp->points, &v);
|
||
|
} else
|
||
|
WARN("P without PRIM first", 0);
|
||
|
} else {
|
||
|
WARN("unknown command %s", cmd);
|
||
|
}
|
||
|
#undef CMD
|
||
|
}
|
||
|
|
||
|
|
||
|
static char linebuf[512];
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
while (!feof(f) && fgets(linebuf, sizeof(linebuf), f)) {
|
||
|
while (linebuf[strlen(linebuf) - 1] == '\n')
|
||
|
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;
|
||
|
}
|