nasty bug in Texture::create
[laserbrain_demo] / src / ui_exhibit.cc
index eda39c6..dd09678 100644 (file)
@@ -4,6 +4,7 @@
 #include "app.h"
 #include "snode.h"
 #include "shader.h"
+#include "rtarg.h"
 
 struct Rect {
        float x, y, w, h;
@@ -15,11 +16,15 @@ static void draw_tabs(const Rect &rect);
 static void draw_text(const Rect &rect);
 static void layout_text(const char *text);
 
+static float aspect;
+static int ui_width, ui_height;
+
+static RenderTarget *rtarg;
 static const SceneNode *parent;
 static Vec3 pos;
 static Vec2 size;
-static float text_padding;
-static float text_scale = 0.05f;
+static int text_padding;
+static float text_scale = 1.0f;//0.05f;
 static Exhibit *ex;
 static int vis_tab;
 static float scroll;
@@ -38,13 +43,24 @@ bool exui_init()
 {
        size.x = 15;
        size.y = 18;
-       text_padding = size.x * 0.01;
+       text_padding = ui_width / 100;
+
+       aspect = size.x / size.y;
+       ui_height = 512;
+       ui_width = ui_height * aspect;
+
+       rtarg = new RenderTarget;
+       if(!rtarg->create(ui_width, ui_height, GL_RGB)) {
+               error_log("failed to create exui render target\n");
+               return false;
+       }
 
        return true;
 }
 
 void exui_shutdown()
 {
+       delete rtarg;
 }
 
 void exui_setnode(const SceneNode *node)
@@ -92,33 +108,28 @@ void exui_update(float dt)
        }
 }
 
-void exui_draw()
+static void draw_2d_ui()
 {
-       if(!exsel_active) return;
-       if(!ui_font) return;
-
        dtx_use_font(ui_font, ui_font_size);
        float rowspc = dtx_line_height() * text_scale;
 
-       Rect rect = {-size.x / 2.0f, -size.y / 2.0f, size.x, size.y};
+       glMatrixMode(GL_PROJECTION);
+       glPushMatrix();
+       glLoadIdentity();
+       glOrtho(0, ui_width, 0, ui_height, -1, 1);
 
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
-       if(parent) {
-               glMultMatrixf(parent->get_matrix()[0]);
-       }
-       glTranslatef(pos.x, pos.y, pos.z);
-       glScalef(1, -1, 1);
+       glLoadIdentity();
 
        bind_shader(0);
 
        glPushAttrib(GL_ENABLE_BIT);
        glDisable(GL_TEXTURE_2D);
        glDisable(GL_LIGHTING);
-       glEnable(GL_BLEND);
-       glBlendFunc(GL_SRC_ALPHA, GL_ONE);
-       glDepthMask(0);
+       glDisable(GL_DEPTH_TEST);
 
+       Rect rect = {0, 0, (float)ui_width, (float)ui_height};
        draw_frame(rect);
        Rect tbar_rect = {rect.x, rect.y, rect.w, rowspc};
        draw_titlebar(tbar_rect);
@@ -127,9 +138,60 @@ void exui_draw()
        Rect text_rect = {rect.x, tabs_rect.y + rowspc, rect.w, rect.h - tabs_rect.y - rowspc};
        draw_text(text_rect);
 
+       glPopAttrib();
+
+       glMatrixMode(GL_PROJECTION);
+       glPopMatrix();
+       glMatrixMode(GL_MODELVIEW);
+       glPopMatrix();
+}
+
+void exui_draw()
+{
+       if(!exsel_active) return;
+       if(!ui_font) return;
+
+       // render the 2D UI in a texture
+       push_render_target(rtarg);
+       glClearColor(0, 1, 0, 0);
+       glClear(GL_COLOR_BUFFER_BIT);
+       draw_2d_ui();
+       pop_render_target();
+
+       // place UI image into the scene
+       glMatrixMode(GL_MODELVIEW);
+       glPushMatrix();
+       if(parent) {
+               glMultMatrixf(parent->get_matrix()[0]);
+       }
+       glTranslatef(pos.x, pos.y, pos.z);
+
+       glPushAttrib(GL_ENABLE_BIT);
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+       glEnable(GL_TEXTURE_2D);
+       glDepthMask(0);
+
+       bind_shader(0);
+       bind_texture(rtarg->texture());
+
+       glMatrixMode(GL_TEXTURE);
+       glLoadMatrixf(rtarg->texture_matrix()[0]);
+
+       glBegin(GL_QUADS);
+       glColor3f(1, 1, 1);
+       glTexCoord2f(0, 0); glVertex2f(-size.x / 2, -size.y / 2);
+       glTexCoord2f(1, 0); glVertex2f(size.x / 2, -size.y / 2);
+       glTexCoord2f(1, 1); glVertex2f(size.x / 2, size.y / 2);
+       glTexCoord2f(0, 1); glVertex2f(-size.x / 2, size.y / 2);
+       glEnd();
+
+       glLoadIdentity();
+
        glDepthMask(1);
        glPopAttrib();
 
+       glMatrixMode(GL_MODELVIEW);
        glPopMatrix();
 }
 
@@ -212,10 +274,10 @@ static void layout_text(const char *text)
                        last_break = text;
                }
 
-               if(pos >= size.x - text_padding) {
+               if(pos >= ui_width - text_padding) {
                        if(text == text_lines.back()) {
                                // not even a single character fits on a line... abort
-                               warning_log("text layout failed. glyph %d doesn't fit in line (%g)\n", code, size.x - 2.0 * text_padding);
+                               warning_log("text layout failed. glyph %d doesn't fit in line (%d)\n", code, ui_width - 2 * text_padding);
                                text_lines.clear();
                                return;
                        }