ui notifications
[laserbrain_demo] / src / ui.cc
diff --git a/src/ui.cc b/src/ui.cc
new file mode 100644 (file)
index 0000000..33fbccf
--- /dev/null
+++ b/src/ui.cc
@@ -0,0 +1,120 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <gmath/gmath.h>
+#include <drawtext.h>
+#include "opengl.h"
+#include "ui.h"
+#include "app.h"
+
+#define FONTSZ 16
+
+static bool init();
+
+struct Message {
+       long start_time, show_until;
+       char *str;
+       Message *next;
+};
+static Message *msglist;
+
+static long timeout = 2000;
+static long trans_time = 250;
+static dtx_font *font;
+
+void set_message_timeout(long tm)
+{
+       timeout = tm;
+}
+
+void show_message(const char *fmt, ...)
+{
+       va_list ap;
+       char buf[512];
+
+       init();
+
+       va_start(ap, fmt);
+       vsnprintf(buf, sizeof buf, fmt, ap);
+       va_end(ap);
+
+       Message *msg = new Message;
+       int len = strlen(buf);
+       msg->str = new char[len + 1];
+       memcpy(msg->str, buf, len + 1);
+       msg->start_time = time_msec;
+       msg->show_until = time_msec + timeout;
+
+       Message dummy;
+       dummy.next = msglist;
+       Message *prev = &dummy;
+       while(prev->next && prev->next->show_until < msg->show_until) {
+               prev = prev->next;
+       }
+       msg->next = prev->next;
+       prev->next = msg;
+       msglist = dummy.next;
+}
+
+void draw_ui()
+{
+       if(!font) return;
+
+       while(msglist && msglist->show_until <= time_msec) {
+               Message *msg = msglist;
+               msglist = msg->next;
+               delete [] msg->str;
+               delete msg;
+       }
+
+       dtx_use_font(font, FONTSZ);
+
+       glMatrixMode(GL_PROJECTION);
+       glPushMatrix();
+       glLoadIdentity();
+       glOrtho(0, win_width, -win_height, 0, -1, 1);
+       glMatrixMode(GL_MODELVIEW);
+       glPushMatrix();
+       glLoadIdentity();
+
+       glPushAttrib(GL_ENABLE_BIT);
+       glDisable(GL_LIGHTING);
+       glDisable(GL_DEPTH_TEST);
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       glUseProgram(0);
+
+       Message *msg = msglist;
+       while(msg) {
+               long t = time_msec - msg->start_time;
+               long dur = msg->show_until - msg->start_time;
+               float alpha = smoothstep(0, trans_time, t) *
+                       (1.0 - smoothstep(dur - trans_time, dur, t));
+               glColor4f(1.0, 0.5, 0.1, alpha);
+               glTranslatef(0, -dtx_line_height(), 0);
+               dtx_string(msg->str);
+               msg = msg->next;
+       }
+
+       glPopAttrib();
+
+       glMatrixMode(GL_PROJECTION);
+       glPopMatrix();
+       glMatrixMode(GL_MODELVIEW);
+       glPopMatrix();
+}
+
+static bool init()
+{
+       static bool done_init;
+       if(done_init) return true;
+
+       done_init = true;
+
+       if(!(font = dtx_open_font("data/ui.font", 0))) {
+               fprintf(stderr, "failed to open font: data/ui.font\n");
+               return false;
+       }
+       dtx_prepare_range(font, FONTSZ, 32, 127);
+       return true;
+}