33fbccf60cc838aa507c775095a4c2ed7e75fdc7
[laserbrain_demo] / src / ui.cc
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdarg.h>
4 #include <gmath/gmath.h>
5 #include <drawtext.h>
6 #include "opengl.h"
7 #include "ui.h"
8 #include "app.h"
9
10 #define FONTSZ  16
11
12 static bool init();
13
14 struct Message {
15         long start_time, show_until;
16         char *str;
17         Message *next;
18 };
19 static Message *msglist;
20
21 static long timeout = 2000;
22 static long trans_time = 250;
23 static dtx_font *font;
24
25 void set_message_timeout(long tm)
26 {
27         timeout = tm;
28 }
29
30 void show_message(const char *fmt, ...)
31 {
32         va_list ap;
33         char buf[512];
34
35         init();
36
37         va_start(ap, fmt);
38         vsnprintf(buf, sizeof buf, fmt, ap);
39         va_end(ap);
40
41         Message *msg = new Message;
42         int len = strlen(buf);
43         msg->str = new char[len + 1];
44         memcpy(msg->str, buf, len + 1);
45         msg->start_time = time_msec;
46         msg->show_until = time_msec + timeout;
47
48         Message dummy;
49         dummy.next = msglist;
50         Message *prev = &dummy;
51         while(prev->next && prev->next->show_until < msg->show_until) {
52                 prev = prev->next;
53         }
54         msg->next = prev->next;
55         prev->next = msg;
56         msglist = dummy.next;
57 }
58
59 void draw_ui()
60 {
61         if(!font) return;
62
63         while(msglist && msglist->show_until <= time_msec) {
64                 Message *msg = msglist;
65                 msglist = msg->next;
66                 delete [] msg->str;
67                 delete msg;
68         }
69
70         dtx_use_font(font, FONTSZ);
71
72         glMatrixMode(GL_PROJECTION);
73         glPushMatrix();
74         glLoadIdentity();
75         glOrtho(0, win_width, -win_height, 0, -1, 1);
76         glMatrixMode(GL_MODELVIEW);
77         glPushMatrix();
78         glLoadIdentity();
79
80         glPushAttrib(GL_ENABLE_BIT);
81         glDisable(GL_LIGHTING);
82         glDisable(GL_DEPTH_TEST);
83         glEnable(GL_BLEND);
84         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
85         glUseProgram(0);
86
87         Message *msg = msglist;
88         while(msg) {
89                 long t = time_msec - msg->start_time;
90                 long dur = msg->show_until - msg->start_time;
91                 float alpha = smoothstep(0, trans_time, t) *
92                         (1.0 - smoothstep(dur - trans_time, dur, t));
93                 glColor4f(1.0, 0.5, 0.1, alpha);
94                 glTranslatef(0, -dtx_line_height(), 0);
95                 dtx_string(msg->str);
96                 msg = msg->next;
97         }
98
99         glPopAttrib();
100
101         glMatrixMode(GL_PROJECTION);
102         glPopMatrix();
103         glMatrixMode(GL_MODELVIEW);
104         glPopMatrix();
105 }
106
107 static bool init()
108 {
109         static bool done_init;
110         if(done_init) return true;
111
112         done_init = true;
113
114         if(!(font = dtx_open_font("data/ui.font", 0))) {
115                 fprintf(stderr, "failed to open font: data/ui.font\n");
116                 return false;
117         }
118         dtx_prepare_range(font, FONTSZ, 32, 127);
119         return true;
120 }