2 #include "ui_exhibit.h"
13 static void draw_frame(const Rect &rect);
14 static void draw_titlebar(const Rect &rect);
15 static void draw_tabs(const Rect &rect);
16 static void draw_text(const Rect &rect);
17 static void layout_text(const char *text);
20 static int ui_width, ui_height;
22 static RenderTarget *rtarg;
23 static const SceneNode *parent;
26 static int text_padding;
27 static float text_scale = 1.0f;//0.05f;
31 static std::vector<const char*> text_lines;
32 static AudioStream *voice;
34 enum {COL_BG, COL_FG, COL_FRM};
35 static float color[][3] = {
36 {0.09, 0.14, 0.2}, // COL_BG
37 {0.31, 0.58, 0.9}, // COL_FG
38 {0.19, 0.23, 0.46} // COL_FRM
46 text_padding = ui_width / 100;
48 aspect = size.x / size.y;
50 ui_width = ui_height * aspect;
52 rtarg = new RenderTarget;
53 if(!rtarg->create(ui_width, ui_height, GL_RGBA)) {
54 error_log("failed to create exui render target\n");
66 void exui_setnode(const SceneNode *node)
71 void exui_change_tab(int dir)
75 void exui_scroll(float delta)
79 bool exui_raycast(const Ray &ray)
84 void exui_update(float dt)
86 if(exsel_active.ex != ex) {
91 if(voice) voice->stop();
94 int num_data = ex->data.size();
95 for(int i=0; i<num_data; i++) {
96 if(ex->data[i].type == EXDATA_INFO) {
97 layout_text(ex->data[i].text.c_str());
98 voice = ex->data[i].voice;
103 voice->play(AUDIO_PLAYMODE_ONCE);
111 static void draw_2d_ui()
113 dtx_use_font(ui_font, ui_font_size);
114 float rowspc = dtx_line_height() * text_scale;
116 glMatrixMode(GL_PROJECTION);
119 glTranslatef(-1, 1, 0);
120 glScalef(2.0 / ui_width, -2.0 / ui_height, 1);
122 glMatrixMode(GL_MODELVIEW);
128 glPushAttrib(GL_ENABLE_BIT);
129 glDisable(GL_TEXTURE_2D);
130 glDisable(GL_LIGHTING);
131 glDisable(GL_DEPTH_TEST);
133 Rect rect = {0, 0, (float)ui_width, (float)ui_height};
135 Rect tbar_rect = {rect.x, rect.y, rect.w, rowspc};
136 draw_titlebar(tbar_rect);
137 Rect tabs_rect = {tbar_rect.x, tbar_rect.y + rowspc, tbar_rect.w, tbar_rect.h};
138 draw_tabs(tabs_rect);
139 Rect text_rect = {rect.x, tabs_rect.y + rowspc, rect.w, rect.h - tabs_rect.y - rowspc};
140 draw_text(text_rect);
144 glMatrixMode(GL_PROJECTION);
146 glMatrixMode(GL_MODELVIEW);
152 if(!exsel_active) return;
155 // render the 2D UI in a texture
156 push_render_target(rtarg);
157 glClearColor(0, 1, 0, 0);
158 glClear(GL_COLOR_BUFFER_BIT);
162 // place UI image into the scene
163 glMatrixMode(GL_MODELVIEW);
167 glGetFloatv(GL_MODELVIEW_MATRIX, mvmat[0]);
171 glMultMatrixf(parent->get_matrix()[0]);
173 glTranslatef(pos.x, pos.y, pos.z);
176 mvmat = parent->get_matrix() * mvmat;
178 mvmat.translate(pos.x, pos.y, pos.z);
180 mvmat[0][0] = mvmat[1][1] = mvmat[2][2] = 1.0f;
181 mvmat[0][1] = mvmat[0][2] = mvmat[1][0] = mvmat[2][0] = mvmat[1][2] = mvmat[2][1] = 0.0f;
183 glLoadMatrixf(mvmat[0]);
185 glPushAttrib(GL_ENABLE_BIT);
187 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
188 glEnable(GL_TEXTURE_2D);
192 bind_texture(rtarg->texture());
194 glMatrixMode(GL_TEXTURE);
195 glLoadMatrixf(rtarg->texture_matrix()[0]);
199 glTexCoord2f(0, 0); glVertex2f(-size.x / 2, -size.y / 2);
200 glTexCoord2f(1, 0); glVertex2f(size.x / 2, -size.y / 2);
201 glTexCoord2f(1, 1); glVertex2f(size.x / 2, size.y / 2);
202 glTexCoord2f(0, 1); glVertex2f(-size.x / 2, size.y / 2);
210 glMatrixMode(GL_MODELVIEW);
214 static inline float *vrect(const Rect &rect, int i)
217 v[0] = ((i + 1) & 2) ? rect.x + rect.w : rect.x;
218 v[1] = (i & 2) ? rect.y : rect.y + rect.h;
222 static inline void draw_rect(const Rect &rect, int col)
225 glColor3fv(color[col]);
226 for(int i=0; i<4; i++)
227 glVertex2fv(vrect(rect, i));
231 static void draw_frame(const Rect &rect)
233 draw_rect(rect, COL_BG);
235 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
236 draw_rect(rect, COL_FRM);
237 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
240 static void draw_titlebar(const Rect &rect)
242 draw_rect(rect, COL_FRM);
244 const char *title = ex->get_name();
247 glTranslatef(rect.x + text_padding, rect.y + rect.h - text_padding, 0);
248 glScalef(text_scale, -text_scale, text_scale);
250 glColor3fv(color[COL_BG]);
251 dtx_string(ex->get_name());
256 static void draw_tabs(const Rect &rect)
260 static void draw_text(const Rect &rect)
264 static void layout_text(const char *text)
270 dtx_use_font(ui_font, ui_font_size);
272 float pos = text_padding;
273 text_lines.push_back(text);
274 const char *last_break = 0;
277 if(*text == '\n') { // paragraph break
278 text_lines.push_back(text);
279 text_lines.push_back(++text);
285 int code = dtx_utf8_char_code(text);
286 const char *next = dtx_utf8_next_char((char*)text);
287 pos += dtx_glyph_width(code) * text_scale;
289 if(code < 256 && isspace(code)) {
293 if(pos >= ui_width - text_padding) {
294 if(text == text_lines.back()) {
295 // not even a single character fits on a line... abort
296 warning_log("text layout failed. glyph %d doesn't fit in line (%d)\n", code, ui_width - 2 * text_padding);
301 text_lines.push_back(last_break + 1);
304 // no good point to break, just break here
305 text_lines.push_back(text);
311 text_lines.push_back(0);
314 debug_log("text layout:\n");
315 for(size_t i=0; i<text_lines.size() - 1; i++) {
316 const char *p = text_lines[i];
317 while(*p && p != text_lines[i + 1]) {