#include "opengl.h"
#include "app.h"
#include "drawtext.h"
+#include "sdr.h"
+
+static void draw_node_name(FSNode *node, float angle, float ypos, float dist, bool full);
static IconRenderer *iconrend;
static dtx_font *fat_font;
#define FAT_FONT_SZ 32
+static unsigned int font_sdr;
-bool init_fs()
+bool init_fs(const char *path)
{
iconrend = new ShapesIcons;
if(!iconrend->init()) {
return false;
}
- if(!(fat_font = dtx_open_font("data/fat.font", FAT_FONT_SZ))) {
- fprintf(stderr, "failed to open font file data/fat.font\n");
+ if(!(fat_font = dtx_open_font_glyphmap("data/fat.glyphmap")) ||
+ dtx_get_glyphmap_ptsize(dtx_get_glyphmap(fat_font, 0)) != FAT_FONT_SZ) {
+
+ dtx_set(DTX_PADDING, 64);
+
+ if(!(fat_font = dtx_open_font("data/fat.font", 0))) {
+ fprintf(stderr, "failed to open font file data/fat.font\n");
+ return false;
+ }
+ dtx_prepare_range(fat_font, FAT_FONT_SZ * 8, 32, 127);
+ dtx_calc_font_distfield(fat_font, 1, 8);
+ dtx_save_glyphmap("data/fat.glyphmap", dtx_get_glyphmap(fat_font, 0));
+ }
+ dtx_use_font(fat_font, FAT_FONT_SZ);
+
+ if(!(font_sdr = create_program_load("sdr/dfont.v.glsl", "sdr/dfont.p.glsl"))) {
return false;
}
+ set_uniform_float(font_sdr, "smoothness", 0.01);
- cur_node = get_fsnode(0);
+ if(!(cur_node = get_fsnode(path))) {
+ return false;
+ }
cur_node->expand();
return true;
}
delete node;
}
node_cache.clear();
+ dtx_close_font(fat_font);
delete iconrend;
}
-static Vec3 icon_pos(int row, int col, int ncols, float row_spacing, float radius)
-{
- float angle = 2.0 * M_PI * (float)col / (float)ncols;
- float x = sin(angle) * radius;
- float z = -cos(angle) * radius;
- float y = (float)row * row_spacing;
- return Vec3(x, y, z);
-}
-
static float icon_angle(int col, int ncols, float max_angle = 0.0f)
{
if(max_angle > 0) {
void draw_fs()
{
- static const float row_spacing = 2.0;
- static const float radius = 5;
+ static const float row_spacing = 0.25;
+ static const float radius = 0.6;
static const float umax = 0.42;
static const float max_icon_angle = M_PI * 2.0 * umax;
- int max_ncols = std::max<int>(1, umax * 16);
+ int max_ncols = std::max<int>(1, umax * 12);
- Mat4 base_xform;
- base_xform.rotate(time_sec, 0, 0);
- base_xform.rotate(0, 0, time_sec * 0.5);
- base_xform.translate(0, 2, 0);
+ glPushMatrix();
+ glTranslatef(0, cam_height, 0);
+
+ Mat4 rot_xform;
+ rot_xform.rotate(time_sec, 0, 0);
+ rot_xform.rotate(0, 0, time_sec * 0.5);
- glUseProgram(0);
glDisable(GL_TEXTURE_2D);
int nchildren = (int)cur_node->children.size();
int first = start_child % ncols;
int col = 0, row = 0;
+ int num_dirs = 0;
+
+ // count directories ...
+ for(int i=0; i<nchildren; i++) {
+ FSNode *node = cur_node->children[i];
+ if(node->type == FSTYPE_DIR) {
+ ++num_dirs;
+ }
+ }
+
+ // ... and draw them
+ glLineWidth(5.0);
+ for(int i=0; i<nchildren; i++) {
+ FSNode *node = cur_node->children[i];
+
+ if(node->type != FSTYPE_DIR) {
+ continue;
+ }
+
+ float angle = (float)col++ / (float)(num_dirs - 1) * max_icon_angle - max_icon_angle * 0.5;
+
+ Mat4 xform;
+ xform.rotate_y(angle);
+ xform.translate(0, -0.3, 0);
+
+ glUseProgram(0);
+ glPushMatrix();
+ glMultMatrixf(xform[0]);
+
+ glBegin(GL_LINES);
+ glColor3f(0.2, 0.3, 0.8);
+ glVertex3f(0, 0, -0.3);
+ glVertex3f(0, 0, -2);
+ glColor3f(1, 1, 1);
+ glEnd();
+ glPopMatrix();
+ draw_node_name(node, angle, -0.3, radius, false);
+ }
+ glLineWidth(1.0);
+
+ // then draw files
+ col = 0;
for(int i=0; i<nchildren; i++) {
int idx = (i + first) % nchildren;
FSNode *node = cur_node->children[idx];
if(node->type == FSTYPE_DIR) {
+ ++num_dirs;
continue;
}
+ glUseProgram(0);
+
float angle = icon_angle(col, ncols, max_icon_angle);
- Mat4 xform = base_xform;
+ Mat4 xform = rot_xform;
xform.translate(0, row * row_spacing, -radius);
xform.rotate_y(angle);
iconrend->draw(node);
glPopMatrix();
- glPushMatrix();
- xform = Mat4::identity;
- xform.translate(-dtx_string_width(node->path.get_name()) / 2.0, 0, 0);
- xform.scale(0.01);
- xform.translate(0, 1 + row * row_spacing, -radius);
- xform.rotate_y(angle);
- glMultMatrixf(xform[0]);
-
- dtx_string(node->path.get_name());
- glPopMatrix();
+ draw_node_name(node, angle, row * row_spacing - 0.1, radius, false);
if(++col >= ncols) {
col = 0;
++row;
}
}
+
+ glPopMatrix();
}
+static void draw_node_name(FSNode *node, float angle, float ypos, float dist, bool full)
+{
+ dtx_use_font(fat_font, FAT_FONT_SZ);
+ int line_height = dtx_line_height();
+
+ int nlines = full ? node->name_lines.size() : 1;
+ for(int i=0; i<nlines; i++) {
+ const char *name = full ? node->name_lines[i].c_str() : node->short_name.c_str();
+ glPushMatrix();
+ Mat4 xform;
+ xform.translate(-dtx_string_width(name) / 2.0, -line_height * i, 0);
+ if(node->type == FSTYPE_DIR) {
+ xform.rotate_z(deg_to_rad(90));
+ xform.rotate_x(deg_to_rad(-90));
+ xform.scale(0.0017);
+ } else {
+ xform.scale(0.0012);
+ }
+ xform.translate(0, ypos, -dist);
+ xform.rotate_y(angle);
+ glMultMatrixf(xform[0]);
+
+ glUseProgram(font_sdr);
+ set_uniform_float(font_sdr, "height", line_height);
+ dtx_string(name);
+ glPopMatrix();
+ }
+}
+
+#define MAX_NAME_SZ 16
+
FSNode *get_fsnode(const char *path)
{
char *abspath = make_abs_path(path);
node = new FSNode;
node->path = path;
+ const char *name = node->path.get_name();
+ if(name) {
+ const char *ptr = name;
+ while(*ptr) {
+ if(ptr - name >= MAX_NAME_SZ) {
+ int len = ptr - name;
+ std::string s = std::string(name, len);
+ if(node->short_name.empty()) {
+ node->short_name = s;
+ node->short_name[len - 1] = node->short_name[len - 2] = '.';
+ }
+ node->name_lines.push_back(s);
+ name = ptr;
+ }
+ ++ptr;
+ }
+ if(*name) {
+ if(node->short_name.empty()) {
+ node->short_name = name;
+ }
+ node->name_lines.push_back(name);
+ }
+ }
+
struct stat st;
if(stat(node->path, &st) == -1) {
fprintf(stderr, "failed to stat: %s\n", node->path.get_path());