a0babe4f7a8329feb9114acac3992586fa383f72
[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         Vec3 color;
18         Message *next;
19 };
20 static Message *msglist;
21
22 struct Text {
23         char *str;
24         Vec2 pos;
25         Vec3 color;
26         Text *next;
27 };
28 static Text *txlist;
29
30 static long timeout = 2000;
31 static long trans_time = 250;
32 static dtx_font *font;
33
34 void set_message_timeout(long tm)
35 {
36         timeout = tm;
37 }
38
39 void show_message(const char *fmt, ...)
40 {
41         va_list ap;
42         va_start(ap, fmt);
43         show_messagev(timeout, Vec3(1, 1, 1), fmt, ap);
44         va_end(ap);
45 }
46
47 void show_message(long timeout, const Vec3 &color, const char *fmt, ...)
48 {
49         va_list ap;
50         va_start(ap, fmt);
51         show_messagev(timeout, color, fmt, ap);
52         va_end(ap);
53 }
54
55 void show_messagev(long timeout, const Vec3 &color, const char *fmt, va_list ap)
56 {
57         char buf[512];
58
59         init();
60
61         vsnprintf(buf, sizeof buf, fmt, ap);
62
63         Message *msg = new Message;
64         int len = strlen(buf);
65         msg->str = new char[len + 1];
66         memcpy(msg->str, buf, len + 1);
67         msg->start_time = time_msec;
68         msg->show_until = time_msec + timeout;
69         msg->color = color;
70
71         Message dummy;
72         dummy.next = msglist;
73         Message *prev = &dummy;
74         while(prev->next && prev->next->show_until < msg->show_until) {
75                 prev = prev->next;
76         }
77         msg->next = prev->next;
78         prev->next = msg;
79         msglist = dummy.next;
80 }
81
82 void print_text(const Vec2 &pos, const Vec3 &color, const char *fmt, ...)
83 {
84         va_list ap;
85         va_start(ap, fmt);
86         print_textv(pos, color, fmt, ap);
87         va_end(ap);
88 }
89
90 void print_textv(const Vec2 &pos, const Vec3 &color, const char *fmt, va_list ap)
91 {
92         char buf[512];
93
94         init();
95
96         vsnprintf(buf, sizeof buf, fmt, ap);
97
98         Text *tx = new Text;
99         int len = strlen(buf);
100         tx->str = new char[len + 1];
101         memcpy(tx->str, buf, len + 1);
102         tx->color = color;
103         tx->pos = Vec2(pos.x, -pos.y);
104
105         tx->next = txlist;
106         txlist = tx;
107 }
108
109 void draw_ui()
110 {
111         if(!font) return;
112
113         while(msglist && msglist->show_until <= time_msec) {
114                 Message *msg = msglist;
115                 msglist = msg->next;
116                 delete [] msg->str;
117                 delete msg;
118         }
119
120         dtx_use_font(font, FONTSZ);
121
122         glMatrixMode(GL_PROJECTION);
123         glPushMatrix();
124         glLoadIdentity();
125         glOrtho(0, win_width, -win_height, 0, -1, 1);
126         glMatrixMode(GL_MODELVIEW);
127         glPushMatrix();
128         glLoadIdentity();
129
130         glPushAttrib(GL_ENABLE_BIT);
131         glDisable(GL_LIGHTING);
132         glDisable(GL_DEPTH_TEST);
133         glEnable(GL_BLEND);
134         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
135         glUseProgram(0);
136
137         Message *msg = msglist;
138         while(msg) {
139                 long t = time_msec - msg->start_time;
140                 long dur = msg->show_until - msg->start_time;
141                 float alpha = smoothstep(0, trans_time, t) *
142                         (1.0 - smoothstep(dur - trans_time, dur, t));
143                 glColor4f(msg->color.x, msg->color.y, msg->color.z, alpha);
144                 glTranslatef(0, -dtx_line_height(), 0);
145                 dtx_string(msg->str);
146                 msg = msg->next;
147         }
148
149         while(txlist) {
150                 Text *tx = txlist;
151                 txlist = txlist->next;
152
153                 glMatrixMode(GL_MODELVIEW);
154                 glLoadIdentity();
155                 glTranslatef(tx->pos.x, tx->pos.y, 0);
156
157                 glColor3f(tx->color.x, tx->color.y, tx->color.z);
158                 dtx_string(tx->str);
159
160                 delete [] tx->str;
161                 delete tx;
162         }
163
164         glPopAttrib();
165
166         glMatrixMode(GL_PROJECTION);
167         glPopMatrix();
168         glMatrixMode(GL_MODELVIEW);
169         glPopMatrix();
170 }
171
172 static bool init()
173 {
174         static bool done_init;
175         if(done_init) return true;
176
177         done_init = true;
178
179         if(!(font = dtx_open_font("data/ui.font", 0))) {
180                 fprintf(stderr, "failed to open font: data/ui.font\n");
181                 return false;
182         }
183         dtx_prepare_range(font, FONTSZ, 32, 127);
184         return true;
185 }