4 #include "goatkit/goatkit.h"
6 #if !defined(WIN32) && !defined(__WIN32__)
14 #define FONT GLUT_BITMAP_HELVETICA_18
16 using namespace goatkit;
18 typedef void (*DrawFunc)(const Widget*);
20 static void draw_button(const Widget *w);
21 static void draw_checkbox(const Widget *w);
22 static void draw_label(const Widget *w);
23 static void draw_slider(const Widget *w);
24 static void draw_textbox(const Widget *w);
25 static float calc_text_width(const char *text);
26 static void draw_text(float x, float y, const char *text);
27 static void draw_rect(const Widget *w, float x, float y, float xsz, float ysz);
29 static void get_fgcolor(const Widget *w, float *col);
30 static void get_bgcolor(const Widget *w, float *col);
36 { "button", draw_button },
37 { "checkbox", draw_checkbox },
38 { "label", draw_label },
39 { "slider", draw_slider },
40 { "textbox", draw_textbox },
44 static bool initialized;
45 static std::map<std::string, DrawFunc> funcmap;
48 static float fgcol[] = {0.4, 0.5, 0.8, 1.0};
49 static float fgcol_off[] = {0.5, 0.6, 0.65, 1.0};
50 static float fgcol_inact[] = {0.4, 0.4, 0.4, 1.0};
51 static float bgcol[] = {0.1, 0.1, 0.15, 1.0};
52 static float bgcol_off[] = {0.1, 0.1, 0.15, 1.0};
53 static float bgcol_inact[] = {0.1, 0.1, 0.15, 1.0};
56 extern "C" goatkit::WidgetDrawFunc get_widget_func(const char *name)
61 for(i=0; widget_funcs[i].func; i++) {
62 funcmap[widget_funcs[i].name] = widget_funcs[i].func;
70 // register ourselves as a built-in theme
71 GOATKIT_BUILTIN_THEME("simple", get_widget_func);
74 #define VIS_THRES 0.0001
76 static void begin_drawing(const Widget *w)
78 Vec2 pos = w->get_position();
80 glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
81 glDisable(GL_LIGHTING);
82 glDisable(GL_DEPTH_TEST);
84 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
86 glMatrixMode(GL_MODELVIEW);
88 glTranslatef(pos.x, pos.y, 0);
91 static void end_drawing(const Widget *w)
98 #define LERP(a, b, t) ((a) + ((b) - (a)) * t)
100 static void draw_button(const Widget *w)
102 Vec2 sz = w->get_size();
103 float bnaspect = sz.x / sz.y;
105 float pressed = w->get_pressed();
106 float vis = w->get_visibility();
108 if(vis < VIS_THRES) {
112 float tor_rad = sz.x * 0.5 * vis;
113 float scale = LERP(1.0, 0.85, pressed);
121 glTranslatef(sz.x / 2.0, sz.y / 2.0, 0.0);
122 glScalef(1, 1, 1.0 / sz.x);
123 glRotatef(90, 1, 0, 0);
126 glutSolidTorus(scale * sz.y / 2.0, scale * tor_rad / 2.0, 18, 16);
128 glScalef(1.0 - 0.1 / bnaspect, 1.0, 1.0 - 0.1);
130 glutSolidTorus(scale * sz.y / 2.0, scale * tor_rad / 2.0, 18, 16);
133 glTranslatef(-calc_text_width(w->get_text()) / 2.0, 0, -5);
135 draw_text(0, 0, w->get_text());
141 static void draw_checkbox(const Widget *w)
143 Vec2 sz = w->get_size();
144 float vis = w->get_visibility();
146 if(vis < VIS_THRES) {
153 goatkit::CheckBox *cbox = (goatkit::CheckBox*)w;
157 draw_rect(w, 0, 0, sz.y, sz.y);
159 float state = cbox->get_checked();
161 float bottom[2] = {sz.y / 2, sz.y - 1};
162 float left[2] = {-2, sz.y / 4};
163 float right[2] = {sz.y, -4};
167 glBegin(GL_TRIANGLES);
169 float t = state * 2.0 > 1.0 ? 1.0 : state * 2.0;
170 glVertex2f(left[0], left[1]);
171 glVertex2f(LERP(left[0], bottom[0], t), LERP(left[1], bottom[1], t));
172 glVertex2f(LERP(left[0], bottom[0], t), LERP(left[1], bottom[1] - sz.y / 3, t));
174 if((t = state * 2.0 - 1.0) > 0.0) {
175 glVertex2f(bottom[0], bottom[1]);
176 glVertex2f(LERP(bottom[0], right[0], t), LERP(bottom[1], right[1], t));
177 glVertex2f(bottom[0], bottom[1] - sz.y / 3);
182 glTranslatef(sz.y * 1.5, sz.y / 2.0 + 5, 0);
184 draw_text(0, 0, w->get_text());
189 static void draw_label(const Widget *w)
191 Vec2 sz = w->get_size();
192 float vis = w->get_visibility();
194 if(vis < VIS_THRES) {
203 glTranslatef((sz.x - calc_text_width(w->get_text())) / 2.0, sz.y / 2.0, 0);
205 draw_text(0, 0, w->get_text());
210 static void draw_slider(const Widget *w)
212 Vec2 sz = w->get_size();
213 float vis = w->get_visibility();
215 if(vis < VIS_THRES) {
223 Slider *slider = (Slider*)w;
224 float pad = slider->get_padding();
225 float handle_width = pad * 2.0;
227 float value = slider->get_value();
229 sprintf(valtext, "%g", value);
231 float trough_sz = sz.x - 2.0 * pad;
232 float x = pad + trough_sz * slider->get_value_norm();
234 float act_height = sz.y / 2.0;
238 float step = slider->get_step();
240 float beg = slider->get_range_min();
241 float end = slider->get_range_max();
242 int num_seg = (end - beg) / step;
243 int num_ticks = num_seg + 1;
245 float dx = trough_sz / num_seg;
250 for(int i=0; i<num_ticks; i++) {
251 glVertex2f(x + 0.5, sz.y / 3.0 + 0.5);
252 glVertex2f(x + 0.5, sz.y / 2.0 + 0.5);
258 draw_rect(w, 0, sz.y - act_height + act_height / 3, sz.x, act_height / 3);
259 draw_rect(w, x - handle_width / 2.0, sz.y - act_height, handle_width, act_height);
260 draw_text(x - calc_text_width(valtext) / 2.0, act_height / 2.0, valtext);
265 static void draw_textbox(const Widget *w)
267 if(!w->is_visible()) {
271 Vec2 sz = w->get_size();
276 TextBox *tbox = (TextBox*)w;
280 draw_rect(w, 0, 0, sz.x, sz.y);
282 const char *str = tbox->get_text();
283 char *buf = (char*)alloca(strlen(str) + 1);
285 // figure out how many characters fit in the textbox
287 const char *sptr = str;
290 float nsz = tsz + glutBitmapWidth(FONT, *sptr);
300 draw_text(2, 2.0 * sz.y / 3.0, buf);
303 int cursor = tbox->get_cursor();
307 memcpy(buf, str, cursor);
309 cx += calc_text_width(buf);
312 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
313 glColor4f(1.0 - fg[0], 1.0 - fg[1], 1.0 - fg[2], fg[3]);
314 draw_text(cx, 2.0 * sz.y / 3.0, "|");
315 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
320 static float calc_text_width(const char *text)
325 res += glutBitmapWidth(FONT, *text++);
330 static void draw_text(float x, float y, const char *text)
335 glutBitmapCharacter(FONT, *text++);
339 #define DISP(s, t) LERP((s) * 2.0, 0, (t))
340 static void draw_rect(const Widget *w, float x, float y, float xsz, float ysz)
343 float vis = w->get_visibility();
351 glVertex2f(x + xsz, y);
352 glVertex2f(x + xsz, y + ysz);
353 glVertex2f(x, y + ysz);
356 glLineWidth(w->get_focus() + 1.0);
359 glTranslatef(0.5, 0.5, 0);
365 glVertex2f(x - DISP(xsz, vis), y);
366 glVertex2f(x + xsz - DISP(xsz, vis), y);
369 glVertex2f(x + xsz, y - DISP(ysz, vis));
370 glVertex2f(x + xsz, y + ysz - DISP(ysz, vis));
373 glVertex2f(x + xsz + DISP(xsz, vis), y + ysz);
374 glVertex2f(x + DISP(xsz, vis), y + ysz);
377 glVertex2f(x, y + ysz + DISP(ysz, vis));
378 glVertex2f(x, y + DISP(ysz, vis));
387 static void get_fgcolor(const Widget *w, float *col)
389 float hover = w->get_under_mouse();
390 float act = w->get_active();
391 float vis = w->get_visibility();
393 for(int i=0; i<4; i++) {
394 float c = LERP(fgcol_off[i], fgcol[i], hover);
395 col[i] = LERP(fgcol_inact[i], c, act);
400 static void get_bgcolor(const Widget *w, float *col)
402 float hover = w->get_under_mouse();
403 float act = w->get_active();
404 float vis = w->get_visibility();
406 for(int i=0; i<4; i++) {
407 float c = LERP(bgcol_off[i], bgcol[i], hover);
408 col[i] = LERP(bgcol_inact[i], c, act);