13 #include "gmath/gmath.h"
19 static IconRenderer *iconrend;
21 static std::map<std::string, FSNode*> node_cache;
22 static FSNode *cur_node;
23 static int start_child;
25 static dtx_font *fat_font;
26 #define FAT_FONT_SZ 32
27 static unsigned int font_sdr;
30 bool init_fs(const char *path)
32 iconrend = new ShapesIcons;
33 if(!iconrend->init()) {
37 if(!(fat_font = dtx_open_font_glyphmap("data/fat.glyphmap")) ||
38 dtx_get_glyphmap_ptsize(dtx_get_glyphmap(fat_font, 0)) != FAT_FONT_SZ) {
40 dtx_set(DTX_PADDING, 64);
42 if(!(fat_font = dtx_open_font("data/fat.font", 0))) {
43 fprintf(stderr, "failed to open font file data/fat.font\n");
46 dtx_prepare_range(fat_font, FAT_FONT_SZ * 8, 32, 127);
47 dtx_calc_font_distfield(fat_font, 1, 8);
48 dtx_save_glyphmap("data/fat.glyphmap", dtx_get_glyphmap(fat_font, 0));
49 dtx_use_font(fat_font, FAT_FONT_SZ);
52 if(!(font_sdr = create_program_load("sdr/dfont.v.glsl", "sdr/dfont.p.glsl"))) {
55 set_uniform_float(font_sdr, "smoothness", 0.01);
57 if(!(cur_node = get_fsnode(path))) {
66 std::map<std::string, FSNode*>::iterator it = node_cache.begin();
67 while(it != node_cache.end()) {
68 FSNode *node = it++->second;
72 dtx_close_font(fat_font);
76 static Vec3 icon_pos(int row, int col, int ncols, float row_spacing, float radius)
78 float angle = 2.0 * M_PI * (float)col / (float)ncols;
79 float x = sin(angle) * radius;
80 float z = -cos(angle) * radius;
81 float y = (float)row * row_spacing;
85 static float icon_angle(int col, int ncols, float max_angle = 0.0f)
88 return max_angle * ((float)col / (float)(ncols - 1) - 0.5);
90 return 2.0 * M_PI * (float)col / (float)ncols;
95 static const float row_spacing = 0.25;
96 static const float radius = 0.6;
97 static const float umax = 0.42;
98 static const float max_icon_angle = M_PI * 2.0 * umax;
100 int max_ncols = std::max<int>(1, umax * 12);
103 base_xform.rotate(time_sec, 0, 0);
104 base_xform.rotate(0, 0, time_sec * 0.5);
105 base_xform.translate(0, 1.65, 0);
107 glDisable(GL_TEXTURE_2D);
109 int nchildren = (int)cur_node->children.size();
110 int ncols = std::min(cur_node->nfiles, max_ncols);
112 int first = start_child % ncols;
113 int col = 0, row = 0;
115 for(int i=0; i<nchildren; i++) {
116 int idx = (i + first) % nchildren;
117 FSNode *node = cur_node->children[idx];
119 if(node->type == FSTYPE_DIR) {
125 float angle = icon_angle(col, ncols, max_icon_angle);
127 Mat4 xform = base_xform;
128 xform.translate(0, row * row_spacing, -radius);
129 xform.rotate_y(angle);
132 glMultMatrixf(xform[0]);
133 iconrend->draw(node);
137 xform = Mat4::identity;
138 xform.translate(-dtx_string_width(node->path.get_name()) / 2.0, 0, 0);
140 xform.translate(0, 1.54 + row * row_spacing, -radius);
141 xform.rotate_y(angle);
142 glMultMatrixf(xform[0]);
144 glUseProgram(font_sdr);
145 dtx_string(node->path.get_name());
155 FSNode *get_fsnode(const char *path)
157 char *abspath = make_abs_path(path);
159 FSNode *node = node_cache[abspath];
165 if(stat(node->path, &st) == -1) {
166 fprintf(stderr, "failed to stat: %s\n", node->path.get_path());
170 node->size = st.st_size;
172 switch(st.st_mode & S_IFMT) {
174 node->type = FSTYPE_FILE;
178 node->type = FSTYPE_DIR;
183 node->type = FSTYPE_DEV;
187 node->type = FSTYPE_UNKNOWN;
189 node_cache[abspath] = node;
195 FSNode *get_fsnode(const char *dir, const char *name)
198 return get_fsnode(name);
200 if(!name || *name == '/') {
204 int len = strlen(dir) + 1 + strlen(name);
205 char *buf = new char[len + 1];
206 sprintf(buf, "%s/%s", dir, name);
207 FSNode *res = get_fsnode(buf);
212 // ---- FSNode implementation ----
215 type = FSTYPE_UNKNOWN;
221 bool FSNode::expand()
223 if(type != FSTYPE_DIR) {
227 DIR *dir = opendir(path);
229 fprintf(stderr, "failed to open dir: %s: %s\n", path.get_path(), strerror(errno));
234 while((dent = readdir(dir))) {
235 if(strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) {
239 FSNode *node = get_fsnode(path, dent->d_name);
242 children.push_back(node);
253 printf("expanded %d children\n", (int)children.size());
255 parent = get_fsnode(path.get_parent());