2 #if defined(WIN32) || defined(__WIN32__)
8 #include "ui_exhibit.h"
19 static void draw_frame(const Rect &rect);
20 static void draw_titlebar(const Rect &rect);
21 static void draw_tabs(const Rect &rect);
22 static void draw_text(const Rect &rect);
23 static void layout_text(const char *text);
26 static int ui_width, ui_height;
28 static RenderTarget *rtarg;
29 static const SceneNode *parent;
32 static int text_padding;
33 static float text_scale = 1.0f;//0.05f;
37 static std::vector<const char*> text_lines;
38 static int max_line_size;
39 static AudioStream *voice;
41 enum {COL_BG, COL_FG, COL_FRM};
42 static float color[][3] = {
43 {0.014, 0.016, 0.04}, // COL_BG
44 {0.31, 0.58, 0.9}, // COL_FG
45 {0.19, 0.23, 0.46} // COL_FRM
55 aspect = size.x / size.y;
57 ui_width = ui_height * aspect;
59 rtarg = new RenderTarget;
60 if(!rtarg->create(ui_width, ui_height, GL_SRGB_ALPHA)) {
61 error_log("failed to create exui render target\n");
73 void exui_setnode(const SceneNode *node)
78 void exui_change_tab(int dir)
82 void exui_scroll(float delta)
86 bool exui_raycast(const Ray &ray)
91 void exui_update(float dt)
93 if(exsel_active.ex != ex) {
98 if(voice) voice->stop();
101 int num_data = ex->data.size();
102 for(int i=0; i<num_data; i++) {
103 if(ex->data[i].type == EXDATA_INFO) {
104 layout_text(ex->data[i].text.c_str());
105 voice = ex->data[i].voice;
110 voice->play(AUDIO_PLAYMODE_ONCE);
118 static void draw_2d_ui()
120 dtx_use_font(ui_font, ui_font_size);
121 float rowspc = dtx_line_height() * text_scale;
123 glMatrixMode(GL_PROJECTION);
126 glTranslatef(-1, 1, 0);
127 glScalef(2.0 / ui_width, -2.0 / ui_height, 1);
129 glMatrixMode(GL_MODELVIEW);
135 glPushAttrib(GL_ENABLE_BIT);
136 glDisable(GL_TEXTURE_2D);
137 glDisable(GL_LIGHTING);
138 glDisable(GL_DEPTH_TEST);
140 Rect rect = {0, 0, (float)ui_width, (float)ui_height};
142 Rect tbar_rect = {rect.x, rect.y, rect.w, rowspc + text_padding}; // half the padding
143 draw_titlebar(tbar_rect);
144 Rect tabs_rect = {tbar_rect.x, tbar_rect.y + tbar_rect.h, tbar_rect.w, tbar_rect.h};
145 draw_tabs(tabs_rect);
146 Rect text_rect = {rect.x, tabs_rect.y + tabs_rect.h, rect.w, rect.h - tabs_rect.y - tabs_rect.h};
147 draw_text(text_rect);
151 glMatrixMode(GL_PROJECTION);
153 glMatrixMode(GL_MODELVIEW);
159 if(!exsel_active) return;
162 // render the 2D UI in a texture
163 push_render_target(rtarg);
164 glClearColor(0, 1, 0, 0);
165 glClear(GL_COLOR_BUFFER_BIT);
169 // place UI image into the scene
170 glMatrixMode(GL_MODELVIEW);
174 glGetFloatv(GL_MODELVIEW_MATRIX, mvmat[0]);
178 glMultMatrixf(parent->get_matrix()[0]);
180 glTranslatef(pos.x, pos.y, pos.z);
183 mvmat = parent->get_matrix() * mvmat;
185 mvmat.translate(pos.x, pos.y, pos.z);
187 mvmat[0][0] = mvmat[1][1] = mvmat[2][2] = 1.0f;
188 mvmat[0][1] = mvmat[0][2] = mvmat[1][0] = mvmat[2][0] = mvmat[1][2] = mvmat[2][1] = 0.0f;
190 glLoadMatrixf(mvmat[0]);
192 glPushAttrib(GL_ENABLE_BIT);
194 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
195 glEnable(GL_TEXTURE_2D);
199 bind_texture(rtarg->texture());
201 glMatrixMode(GL_TEXTURE);
202 glLoadMatrixf(rtarg->texture_matrix()[0]);
206 glTexCoord2f(0, 0); glVertex2f(-size.x / 2, -size.y / 2);
207 glTexCoord2f(1, 0); glVertex2f(size.x / 2, -size.y / 2);
208 glTexCoord2f(1, 1); glVertex2f(size.x / 2, size.y / 2);
209 glTexCoord2f(0, 1); glVertex2f(-size.x / 2, size.y / 2);
217 glMatrixMode(GL_MODELVIEW);
221 static inline float *vrect(const Rect &rect, int i)
224 v[0] = ((i + 1) & 2) ? rect.x + rect.w : rect.x;
225 v[1] = (i & 2) ? rect.y : rect.y + rect.h;
229 static inline void draw_rect(const Rect &rect, int col)
232 glColor3fv(color[col]);
233 for(int i=0; i<4; i++)
234 glVertex2fv(vrect(rect, i));
238 static void draw_frame(const Rect &rect)
240 draw_rect(rect, COL_BG);
242 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
243 draw_rect(rect, COL_FRM);
244 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
247 static void draw_titlebar(const Rect &rect)
249 draw_rect(rect, COL_FRM);
251 const char *title = ex->get_name();
254 glTranslatef(rect.x + text_padding, rect.y + rect.h - text_padding, 0);
255 glScalef(text_scale, -text_scale, text_scale);
257 glColor3fv(color[COL_BG]);
258 dtx_string(ex->get_name());
263 static void draw_tabs(const Rect &rect)
267 static void draw_text(const Rect &rect)
269 char *buf = (char*)alloca(max_line_size + 1);
271 float dy = dtx_line_height() * text_scale;
273 glMatrixMode(GL_MODELVIEW);
275 glTranslatef(rect.x + text_padding, rect.y + dy + text_padding, 0);
276 glScalef(text_scale, -text_scale, text_scale);
278 glColor3fv(color[COL_FG]);
280 int nlines = text_lines.size() - 1;
281 for(int i=0; i<nlines; i++) {
283 int sz = text_lines[i + 1] - text_lines[i];
284 assert(sz <= max_line_size);
285 memcpy(buf, text_lines[i], sz);
288 buf = (char*)text_lines[i];
292 glTranslatef(0, -dy, 0);
298 static void layout_text(const char *text)
304 dtx_use_font(ui_font, ui_font_size);
306 int left_margin = text_padding;
307 int right_margin = ui_width - text_padding;
309 text_lines.push_back(text);
310 const char *last_break = 0;
314 if(*text == '\n') { // paragraph break
315 text_lines.push_back(text);
316 text_lines.push_back(++text);
321 int code = dtx_utf8_char_code(text);
322 const char *next = dtx_utf8_next_char((char*)text);
325 dtx_substring_box(text_lines.back(), 0, text - text_lines.back(), &box);
326 float pos = left_margin + (box.width + box.x) * text_scale;
328 if(code < 256 && isspace(code)) {
332 if(pos > right_margin) {
333 if(text == text_lines.back()) {
334 // not even a single character fits on a line... abort
335 warning_log("text layout failed. glyph %d doesn't fit in line (%d)\n", code, right_margin - left_margin);
340 text_lines.push_back(last_break + 1);
343 // no good point to break, just break here
344 text_lines.push_back(text);
347 int d = text_lines.back() - (text_lines[text_lines.size() - 2]);
348 if(d > max_line_size) max_line_size = d;
352 text_lines.push_back(0);
355 debug_log("text layout:\n");
356 for(size_t i=0; i<text_lines.size() - 1; i++) {
357 const char *p = text_lines[i];
358 while(*p && p != text_lines[i + 1]) {