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