- shaders for both lightmapped objects with or without albedo maps
[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 static long timeout = 2000;
23 static long trans_time = 250;
24 static dtx_font *font;
25
26 void set_message_timeout(long tm)
27 {
28         timeout = tm;
29 }
30
31 void show_message(const char *fmt, ...)
32 {
33         va_list ap;
34         va_start(ap, fmt);
35         show_messagev(timeout, Vec3(1, 1, 1), fmt, ap);
36         va_end(ap);
37 }
38
39 void show_message(long timeout, const Vec3 &color, const char *fmt, ...)
40 {
41         va_list ap;
42         va_start(ap, fmt);
43         show_messagev(timeout, color, fmt, ap);
44         va_end(ap);
45 }
46
47 void show_messagev(long timeout, const Vec3 &color, const char *fmt, va_list ap)
48 {
49         char buf[512];
50
51         init();
52
53         vsnprintf(buf, sizeof buf, fmt, ap);
54
55         Message *msg = new Message;
56         int len = strlen(buf);
57         msg->str = new char[len + 1];
58         memcpy(msg->str, buf, len + 1);
59         msg->start_time = time_msec;
60         msg->show_until = time_msec + timeout;
61         msg->color = color;
62
63         Message dummy;
64         dummy.next = msglist;
65         Message *prev = &dummy;
66         while(prev->next && prev->next->show_until < msg->show_until) {
67                 prev = prev->next;
68         }
69         msg->next = prev->next;
70         prev->next = msg;
71         msglist = dummy.next;
72 }
73
74 void draw_ui()
75 {
76         if(!font) return;
77
78         while(msglist && msglist->show_until <= time_msec) {
79                 Message *msg = msglist;
80                 msglist = msg->next;
81                 delete [] msg->str;
82                 delete msg;
83         }
84
85         dtx_use_font(font, FONTSZ);
86
87         glMatrixMode(GL_PROJECTION);
88         glPushMatrix();
89         glLoadIdentity();
90         glOrtho(0, win_width, -win_height, 0, -1, 1);
91         glMatrixMode(GL_MODELVIEW);
92         glPushMatrix();
93         glLoadIdentity();
94
95         glPushAttrib(GL_ENABLE_BIT);
96         glDisable(GL_LIGHTING);
97         glDisable(GL_DEPTH_TEST);
98         glEnable(GL_BLEND);
99         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
100         glUseProgram(0);
101
102         Message *msg = msglist;
103         while(msg) {
104                 long t = time_msec - msg->start_time;
105                 long dur = msg->show_until - msg->start_time;
106                 float alpha = smoothstep(0, trans_time, t) *
107                         (1.0 - smoothstep(dur - trans_time, dur, t));
108                 glColor4f(msg->color.x, msg->color.y, msg->color.z, alpha);
109                 glTranslatef(0, -dtx_line_height(), 0);
110                 dtx_string(msg->str);
111                 msg = msg->next;
112         }
113
114         glPopAttrib();
115
116         glMatrixMode(GL_PROJECTION);
117         glPopMatrix();
118         glMatrixMode(GL_MODELVIEW);
119         glPopMatrix();
120 }
121
122 static bool init()
123 {
124         static bool done_init;
125         if(done_init) return true;
126
127         done_init = true;
128
129         if(!(font = dtx_open_font("data/ui.font", 0))) {
130                 fprintf(stderr, "failed to open font: data/ui.font\n");
131                 return false;
132         }
133         dtx_prepare_range(font, FONTSZ, 32, 127);
134         return true;
135 }