--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <alloca.h>
+#include "fs.h"
+
+char *path_dir(const char *path, char *buf)
+{
+ char *sep;
+
+ if(!buf) buf = (char*)path;
+ if(path != buf) {
+ strcpy(buf, path);
+ }
+
+ if((sep = strrchr(buf, '/')) && sep > buf) {
+ *sep = 0;
+ }
+ return buf;
+}
+
+char *path_file(const char *path, char *buf)
+{
+ int len;
+ char *sep;
+
+ if(!buf) buf = (char*)path;
+ if(path != buf) {
+ strcpy(buf, path);
+ }
+
+ if((sep = strrchr(buf, '/'))) {
+ len = strlen(sep + 1);
+ memmove(buf, sep + 1, len + 1);
+ }
+ return buf;
+}
+
+char *combine_path(const char *dirname, const char *fname, char *buf)
+{
+ char *dest;
+
+ if(!buf) return 0;
+
+ if(!dirname || !*dirname) {
+ strcpy(buf, fname);
+ return buf;
+ }
+
+ dest = buf;
+ while(*dirname) *dest++ = *dirname++;
+
+ if(dest[-1] != '/') *dest++ = '/';
+
+ strcpy(dest, fname);
+ return buf;
+}
+
+FILE *fopenat(const char *dirname, const char *fname, const char *attr)
+{
+ char *buf;
+
+ if(!dirname || !*dirname) {
+ return fopen(fname, attr);
+ }
+
+ buf = alloca(strlen(dirname) + strlen(fname) + 2);
+ combine_path(dirname, fname, buf);
+ return fopen(buf, attr);
+}
--- /dev/null
+#ifndef FS_H_
+#define FS_H_
+
+#include <stdio.h>
+
+/* buf should be at least as large as strlen(path) + 1
+ * if buf is null, or buf points to path, will do in-place replacement
+ * only UNIX-style path separators are supported
+ * returns buf
+ */
+char *path_dir(const char *path, char *buf);
+char *path_file(const char *path, char *buf);
+
+/* buf should be at least strlen(dirname) + strlen(fname) + 2
+ * returns buf
+ */
+char *combine_path(const char *dirname, const char *fname, char *buf);
+
+/* if dirname is null or empty, this is equivalent to fopen(fname, attr) */
+FILE *fopenat(const char *dirname, const char *fname, const char *attr);
+
+#endif /* FS_H_ */
glLoadMatrixf(proj_matrix);
cgm_midentity(view_matrix);
- cgm_mpretranslate(view_matrix, 0, 0, -cam_dist);
+ cgm_mpretranslate(view_matrix, 0, 1.5, -cam_dist);
cgm_mprerotate(view_matrix, cam_phi, 1, 0, 0);
cgm_mprerotate(view_matrix, cam_theta, 0, 1, 0);
glMatrixMode(GL_MODELVIEW);
#include <errno.h>
#include <treestore.h>
#include "level.h"
+#include "fs.h"
+
+static int load_tileset(struct level *lvl, struct ts_node *tsn);
int init_level(struct level *lvl, int xsz, int ysz)
{
{
if(!lvl) return;
free(lvl->cells);
+ free(lvl->fname);
+ free(lvl->dirname);
}
int load_level(struct level *lvl, const char *fname)
{
- FILE *fp;
struct ts_node *ts, *node, *iter;
int sz, cx, cy;
struct cell *cell;
- if(!(fp = fopen(fname, "rb"))) {
- return -1;
+ lvl->fname = strdup(fname);
+ if((lvl->dirname = malloc(strlen(fname) + 1))) {
+ path_dir(lvl->fname, lvl->dirname);
}
if(!(ts = ts_load(fname))) {
node = iter;
iter = iter->next;
- if(strcmp(node->name, "cell") == 0) {
+ if(strcmp(node->name, "tileset") == 0) {
+ load_tileset(lvl, node);
+
+ } else if(strcmp(node->name, "cell") == 0) {
cx = ts_get_attr_int(node, "x", -1);
cy = ts_get_attr_int(node, "y", -1);
if(cx < 0 || cy < 0 || cx >= sz || cy >= sz) {
return 0;
}
+/* TODO: save tileset info */
int save_level(struct level *lvl, const char *fname)
{
int i, j;
ts_free_tree(root);
return -1;
}
+
+static int load_tileset(struct level *lvl, struct ts_node *tsn)
+{
+ static const char *tile_types[] = {"straight", "corner", "door", 0};
+
+ int i;
+ char *path;
+ const char *str;
+ struct ts_node *node;
+ struct tile *tile;
+
+ node = tsn->child_list;
+ while(node) {
+ if(strcmp(node->name, "tile") == 0) {
+ if(!(tile = calloc(1, sizeof *tile))) {
+ fprintf(stderr, "failed to allocate tile\n");
+ return -1;
+ }
+ if((str = ts_get_attr_str(node, "name", 0))) {
+ tile->name = strdup(str);
+ }
+ if((str = ts_get_attr_str(node, "type", 0))) {
+ for(i=0; tile_types[i]; i++) {
+ if(strcmp(str, tile_types[i]) == 0) {
+ tile->type = i;
+ break;
+ }
+ }
+ }
+ if((str = ts_get_attr_str(node, "scene", 0))) {
+ if(lvl->dirname) {
+ path = alloca(strlen(lvl->dirname) + strlen(str) + 2);
+ combine_path(lvl->dirname, str, path);
+ } else {
+ path = (char*)str;
+ }
+ load_scenefile(&tile->scn, path);
+ }
+
+ if(tile->name && tile->scn.meshlist) { /* valid tile */
+ tile->next = lvl->tiles;
+ lvl->tiles = tile;
+ } else {
+ fprintf(stderr, "load_tileset: skipping invalid tile: %s\n",
+ tile->name ? tile->name : "missing tile name");
+ free(tile);
+ }
+ }
+ node = node->next;
+ }
+
+ return 0;
+}
#ifndef LEVEL_H_
#define LEVEL_H_
+#include "scenefile.h"
+
+enum {
+ TILE_STRAIGHT,
+ TILE_CORNER,
+ TILE_DOOR
+};
+
enum {
CELL_SOLID,
CELL_WALK,
CELL_BLOCKED
};
+struct tile {
+ char *name;
+ int type;
+ struct scenefile scn;
+ struct tile *next;
+};
+
struct cell {
int type;
int wall[4];
int floor, ceil;
+
+ struct meshgroup mgrp;
};
struct level {
+ char *fname, *dirname;
+
int width, height;
struct cell *cells;
+
+ struct tile *tiles;
};
int load_level(struct level *lvl, const char *fname);
int save_level(struct level *lvl, const char *fname);
+int gen_level_geom(struct level *lvl);
+
#endif /* LEVEL_H_ */
char *sep;
struct rbtree *rbtree = 0;
+ memset(scn, 0, sizeof *scn);
varr_size = varr_max = narr_size = narr_max = tarr_size = tarr_max = 0;
varr = narr = 0;
if(!(rbtree = rb_create(cmp_facevert))) {
fprintf(stderr, "load_scenefile: failed to create facevertex search tree\n");
- fclose(fp);
- return -1;
+ goto fail;
}
rb_set_delete_func(rbtree, free_rbnode_key, 0);
path_prefix = alloca(strlen(buf) + 1);
strcpy(path_prefix, buf);
+ if(sep) {
+ sep = (char*)fname + (sep - buf);
+ }
+ if(!(scn->fname = strdup(sep ? sep + 1 : fname))) {
+ fprintf(stderr, "failed to allocate scenefile name buffer\n");
+ goto fail;
+ }
+
if(!(mesh = malloc(sizeof *mesh))) {
fprintf(stderr, "failed to allocate mesh\n");
fclose(fp);
}
mesh = 0;
- printf("load_scenefile: loaded %d meshes, %d vertices\n", scn->num_meshes,
- varr_size);
+ printf("load_scenefile %s: loaded %d meshes, %d vertices\n", scn->fname,
+ scn->num_meshes, varr_size);
res = 0;
+ if(0) {
fail:
+ free(scn->fname);
+ }
+
fclose(fp);
free(mesh);
free(varr);
#include "mesh.h"
struct scenefile {
+ char *fname;
+
struct mesh *meshlist;
int num_meshes;