- added libdrawtext
[demo_prior] / src / osd.c
diff --git a/src/osd.c b/src/osd.c
new file mode 100644 (file)
index 0000000..415cb86
--- /dev/null
+++ b/src/osd.c
@@ -0,0 +1,184 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <drawtext.h>
+#include "cgmath/cgmath.h"
+#include "opengl.h"
+#include "osd.h"
+#include "demo.h"
+
+
+struct message {
+       long start_time, show_until;
+       char *str;
+       cgm_vec3 color;
+       struct message *next;
+};
+static struct message *msglist;
+
+struct text {
+       char *str;
+       cgm_vec2 pos;
+       cgm_vec3 color;
+       struct text *next;
+};
+static struct text *txlist;
+
+static long timeout = 2000;
+static long trans_time = 250;
+
+
+void set_message_timeout(long tm)
+{
+       timeout = tm;
+}
+
+void osd_printf(const char *fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       show_messagev(timeout, 1, 1, 1, fmt, ap);
+       va_end(ap);
+}
+
+void show_message(long timeout, float r, float g, float b, const char *fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       show_messagev(timeout, r, g, b, fmt, ap);
+       va_end(ap);
+}
+
+void show_messagev(long timeout, float r, float g, float b, const char *fmt, va_list ap)
+{
+       char buf[512];
+       struct message *msg;
+       struct message dummy;
+       int len;
+
+       vsnprintf(buf, sizeof buf, fmt, ap);
+
+       if(!(msg = malloc(sizeof *msg))) {
+               perror("failed to allocate memory");
+               abort();
+       }
+       len = strlen(buf);
+       if(!(msg->str = malloc(len + 1))) {
+               perror("failed to allocate memory");
+               abort();
+       }
+       memcpy(msg->str, buf, len + 1);
+       msg->start_time = time_msec;
+       msg->show_until = time_msec + timeout;
+       msg->color.x = r;
+       msg->color.y = g;
+       msg->color.z = b;
+
+       dummy.next = msglist;
+       struct 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 print_text(float x, float y, float r, float g, float b, const char *fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       print_textv(x, y, r, g, b, fmt, ap);
+       va_end(ap);
+}
+
+void print_textv(float x, float y, float r, float g, float b, const char *fmt, va_list ap)
+{
+       char buf[512];
+       int len;
+       struct text *tx;
+
+       vsnprintf(buf, sizeof buf, fmt, ap);
+
+       if(!(tx = malloc(sizeof *tx))) {
+               perror("failed to allocate memory");
+               abort();
+       }
+       len = strlen(buf);
+       if(!(tx->str = malloc(len + 1))) {
+               perror("failed to allocate memory");
+               abort();
+       }
+       memcpy(tx->str, buf, len + 1);
+       tx->color.x = r;
+       tx->color.y = g;
+       tx->color.z = b;
+       tx->pos.x = x;
+       tx->pos.y = -y;
+
+       tx->next = txlist;
+       txlist = tx;
+}
+
+void draw_osd(void)
+{
+       if(!fnt_ui) return;
+
+       while(msglist && msglist->show_until <= time_msec) {
+               struct message *msg = msglist;
+               msglist = msg->next;
+               free(msg->str);
+               free(msg);
+       }
+
+       dtx_use_font(fnt_ui, fnt_ui_size);
+
+       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);
+
+       struct message *msg = msglist;
+       while(msg) {
+               long t = time_msec - msg->start_time;
+               long dur = msg->show_until - msg->start_time;
+               float alpha = cgm_smoothstep(0, trans_time, t) *
+                       (1.0 - cgm_smoothstep(dur - trans_time, dur, t));
+               glColor4f(msg->color.x, msg->color.y, msg->color.z, alpha);
+               glTranslatef(0, -dtx_line_height(), 0);
+               dtx_string(msg->str);
+               msg = msg->next;
+       }
+
+       while(txlist) {
+               struct text *tx = txlist;
+               txlist = txlist->next;
+
+               glMatrixMode(GL_MODELVIEW);
+               glLoadIdentity();
+               glTranslatef(tx->pos.x, tx->pos.y, 0);
+
+               glColor3f(tx->color.x, tx->color.y, tx->color.z);
+               dtx_string(tx->str);
+
+               free(tx->str);
+               free(tx);
+       }
+
+       glPopAttrib();
+
+       glMatrixMode(GL_PROJECTION);
+       glPopMatrix();
+       glMatrixMode(GL_MODELVIEW);
+       glPopMatrix();
+}