nuclear@7: #include nuclear@7: #include nuclear@7: #include "goatkit/goatkit.h" nuclear@7: #include "opengl.h" nuclear@9: #include "sanegl.h" nuclear@7: #include "drawtext.h" nuclear@7: #include "sdr.h" nuclear@7: nuclear@15: #define BEVEL 1.5 nuclear@7: #define VIS_THRES 0.005 nuclear@7: nuclear@7: using namespace goatkit; nuclear@7: nuclear@14: struct Color { nuclear@14: float r, g, b, a; nuclear@14: nuclear@14: Color() : r(1), g(1), b(1), a(1) {} nuclear@14: Color(float r, float g, float b, float a = 1.0f) nuclear@14: { nuclear@14: this->r = r; nuclear@14: this->g = g; nuclear@14: this->b = b; nuclear@14: this->a = a; nuclear@14: } nuclear@14: }; nuclear@14: nuclear@14: enum { nuclear@14: TEXT_COLOR, nuclear@14: TOP_COLOR, nuclear@14: BOTTOM_COLOR, nuclear@15: TOP_ON_COLOR, nuclear@15: BOTTOM_ON_COLOR, nuclear@15: TOP_OFF_COLOR, nuclear@15: BOTTOM_OFF_COLOR, nuclear@14: BEVEL_LIT_COLOR, nuclear@14: BEVEL_SHAD_COLOR, nuclear@14: CURSOR_COLOR, nuclear@14: SELECTION_COLOR, nuclear@14: CHECK_COLOR nuclear@14: }; nuclear@14: nuclear@14: static Color colors[] = { nuclear@14: Color(0.0, 0.0, 0.0, 1.0), /* text color */ nuclear@14: Color(0.75, 0.75, 0.75, 1.0), /* top color */ nuclear@14: Color(0.56, 0.56, 0.56, 1.0), /* bot color */ nuclear@15: Color(0.4, 0.5, 0.8, 1.0), /* top on color */ nuclear@15: Color(0.15, 0.2, 0.4, 1.0), /* bottom on color */ nuclear@15: Color(0.8, 0.5, 0.4, 1.0), /* top off color */ nuclear@15: Color(0.4, 0.2, 0.15, 1.0), /* bottom off color */ nuclear@14: Color(0.8, 0.8, 0.8, 1.0), /* lit bevel */ nuclear@15: Color(0.35, 0.35, 0.35, 1.0), /* shadowed bevel */ nuclear@14: Color(0.8, 0.25, 0.18, 1.0), /* cursor color */ nuclear@14: Color(0.68, 0.85, 1.3, 1.0), /* selection color */ nuclear@14: Color(0.75, 0.1, 0.095, 1.0) /* check color */ nuclear@14: }; nuclear@14: nuclear@14: nuclear@14: #define JLEFT -1.0f nuclear@14: #define JCENTER 0.0f nuclear@14: #define JRIGHT 1.0f nuclear@14: nuclear@14: enum { FRAME_INSET, FRAME_OUTSET }; nuclear@14: nuclear@7: extern int view_xsz, view_ysz; nuclear@13: extern float view_aspect; nuclear@13: extern unsigned int prog_ui, prog_font, prog_color; nuclear@7: extern struct dtx_font *font; nuclear@7: nuclear@7: static void draw_label(const Widget *w); nuclear@13: static void draw_button(const Widget *w); nuclear@15: static void draw_checkbox(const Widget *w); nuclear@15: static void draw_slider(const Widget *w); nuclear@15: static void draw_rect(const Widget *w, const Vec2 &pos, const Vec2 &sz, const Color &color); nuclear@15: static void draw_rect(const Widget *w, const Vec2 &pos, const Vec2 &sz, const Color &ctop, const Color &cbot); nuclear@15: static void draw_shadow_text(const Widget *w, float justify, float x, float y, const Color &col, const char *text, float press = 0.0); nuclear@15: static void draw_shadow_text(const Widget *w, float justify, float x, float y, const char *text, float press = 0.0); nuclear@15: static void draw_text(const Widget *w, float justify, float x, float y, const char *text); nuclear@15: static void draw_frame(const Widget *w, const Vec2 &pos, const Vec2 &sz, float inset); nuclear@15: static float lerp(float a, float b, float t); nuclear@14: static Color lerp(const Color &a, const Color &b, float t); nuclear@7: nuclear@7: static struct { nuclear@7: const char *name; nuclear@7: WidgetDrawFunc func; nuclear@7: } widget_funcs[] = { nuclear@7: { "label", draw_label }, nuclear@13: { "button", draw_button }, nuclear@15: { "checkbox", draw_checkbox }, nuclear@15: { "slider", draw_slider }, nuclear@7: {0, 0} nuclear@7: }; nuclear@7: nuclear@7: static std::map funcmap; nuclear@7: nuclear@9: nuclear@10: extern "C" __attribute__ ((used)) nuclear@9: WidgetDrawFunc get_widget_func(const char *name) nuclear@7: { nuclear@7: static bool initialized; nuclear@7: nuclear@7: if(!initialized) { nuclear@7: for(int i=0; widget_funcs[i].func; i++) { nuclear@7: funcmap[widget_funcs[i].name] = widget_funcs[i].func; nuclear@7: } nuclear@7: initialized = true; nuclear@7: } nuclear@7: return funcmap[name]; nuclear@7: } nuclear@7: nuclear@11: // register ourselves as a built-in theme nuclear@11: GOATKIT_BUILTIN_THEME("istereo", get_widget_func); nuclear@11: nuclear@7: static void begin_drawing(const Widget *w) nuclear@7: { nuclear@14: //Vec2 pos = w->get_position(); nuclear@7: nuclear@7: glEnable(GL_BLEND); nuclear@7: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); nuclear@7: nuclear@7: gl_matrix_mode(GL_MODELVIEW); nuclear@7: gl_push_matrix(); nuclear@7: gl_load_identity(); nuclear@14: //gl_translatef(pos.x, pos.y, 0); nuclear@7: } nuclear@7: nuclear@7: static void end_drawing(const Widget *w) nuclear@7: { nuclear@7: gl_matrix_mode(GL_MODELVIEW); nuclear@7: gl_pop_matrix(); nuclear@7: } nuclear@7: nuclear@7: static void draw_label(const Widget *w) nuclear@7: { nuclear@7: Vec2 pos = w->get_position(); nuclear@15: Vec2 sz = w->get_size(); nuclear@7: float vis = w->get_visibility(); nuclear@7: if(vis < VIS_THRES) return; nuclear@7: nuclear@7: begin_drawing(w); nuclear@15: draw_shadow_text(w, JLEFT, pos.x, pos.y + sz.y / 2.0, w->get_text()); nuclear@7: end_drawing(w); nuclear@7: } nuclear@7: nuclear@13: static void draw_button(const Widget *w) nuclear@13: { nuclear@15: float vis = w->get_visibility(); nuclear@15: if(vis < VIS_THRES) return; nuclear@15: nuclear@13: Vec2 pos = w->get_position(); nuclear@13: Vec2 sz = w->get_size(); nuclear@14: float press = w->get_pressed(); nuclear@13: nuclear@14: Color tcol = lerp(colors[TOP_COLOR], colors[BOTTOM_COLOR], press); nuclear@14: Color bcol = lerp(colors[BOTTOM_COLOR], colors[TOP_COLOR], press); nuclear@14: nuclear@13: begin_drawing(w); nuclear@13: nuclear@15: draw_frame(w, pos, sz, press); nuclear@15: draw_rect(w, pos, sz, tcol, bcol); nuclear@15: //draw_rect(w, Vec2(pos.x + sz.x / 2.0 - 2.0, pos.y), Vec2(4.0, sz.y), nuclear@14: // Color(0.4, 0.5, 1.0)); nuclear@15: draw_shadow_text(w, JCENTER, pos.x + sz.x / 2.0, pos.y + sz.y / 2.0, w->get_text(), press); nuclear@13: nuclear@13: end_drawing(w); nuclear@13: } nuclear@13: nuclear@15: static void draw_checkbox(const Widget *w) nuclear@14: { nuclear@15: float vis = w->get_visibility(); nuclear@15: if(vis < VIS_THRES) return; nuclear@15: nuclear@15: Vec2 pos = w->get_position(); nuclear@15: Vec2 sz = w->get_size(); nuclear@15: Vec2 boxsz = Vec2(sz.y * 3.0, sz.y); nuclear@15: Vec2 boxpos = Vec2(pos.x + sz.x - boxsz.x, pos.y); nuclear@15: nuclear@15: float checked = ((CheckBox*)w)->get_checked(); nuclear@15: nuclear@15: float vcenter = boxpos.y + boxsz.y / 2.0; nuclear@15: nuclear@15: begin_drawing(w); nuclear@15: nuclear@15: draw_frame(w, boxpos, boxsz, 1.0); nuclear@15: Color tcol = lerp(colors[TOP_OFF_COLOR], colors[TOP_ON_COLOR], checked); nuclear@15: Color bcol = lerp(colors[BOTTOM_OFF_COLOR], colors[BOTTOM_ON_COLOR], checked); nuclear@15: draw_rect(w, boxpos, boxsz, bcol, tcol); nuclear@15: nuclear@15: draw_shadow_text(w, JLEFT, boxpos.x + 2, vcenter, "ON", 0.0); nuclear@15: draw_shadow_text(w, JRIGHT, boxpos.x + boxsz.x - 3, vcenter, "OFF", 0.0); nuclear@15: nuclear@15: Vec2 knobpos = Vec2(0, boxpos.y + 1.0); nuclear@15: Vec2 knobsz = Vec2(boxsz.x / 2.0, boxsz.y - 2.0); nuclear@15: nuclear@15: knobpos.x = lerp(boxpos.x + 1.0, boxpos.x + boxsz.x / 2.0, checked); nuclear@15: nuclear@15: draw_frame(w, knobpos, knobsz, 0.0); nuclear@15: draw_rect(w, knobpos, knobsz, colors[TOP_COLOR], colors[BOTTOM_COLOR]); nuclear@15: nuclear@15: draw_shadow_text(w, JRIGHT, boxpos.x - 2.0, vcenter, w->get_text(), 0.0); nuclear@15: nuclear@15: end_drawing(w); nuclear@14: } nuclear@14: nuclear@15: static void draw_slider(const Widget *w) nuclear@13: { nuclear@15: float vis = w->get_visibility(); nuclear@15: if(vis < VIS_THRES) return; nuclear@15: nuclear@15: float nval = ((Slider*)w)->get_value_norm(); nuclear@15: nuclear@15: Vec2 pos = w->get_position(); nuclear@15: Vec2 sz = w->get_size(); nuclear@15: Vec2 tsz = Vec2(sz.y * 0.5, sz.y); nuclear@15: Vec2 tpos = Vec2(pos.x + sz.x * nval - tsz.x / 2.0, pos.y); nuclear@15: nuclear@15: // modify original pos/size to correspond to the trough geometry nuclear@15: sz.y /= 5.0; nuclear@15: pos.y += sz.y * 2.0; nuclear@15: nuclear@15: begin_drawing(w); nuclear@15: nuclear@15: // draw trough nuclear@15: draw_frame(w, pos, sz, 1.0); nuclear@15: draw_rect(w, pos, sz, colors[BOTTOM_COLOR], colors[TOP_COLOR]); nuclear@15: nuclear@15: // draw thumb nuclear@15: draw_frame(w, tpos, tsz, 0.0); nuclear@15: draw_rect(w, tpos, tsz, colors[TOP_COLOR], colors[BOTTOM_COLOR]); nuclear@15: nuclear@15: end_drawing(w); nuclear@15: } nuclear@15: nuclear@15: static void draw_rect(const Widget *w, const Vec2 &pos, const Vec2 &sz, const Color &color) nuclear@15: { nuclear@15: draw_rect(w, pos, sz, color, color); nuclear@15: } nuclear@15: nuclear@15: static void draw_rect(const Widget *w, const Vec2 &pos, const Vec2 &sz, const Color &ctop, const Color &cbot) nuclear@15: { nuclear@15: float vis = w ? w->get_visibility() : 1.0; nuclear@15: float act = w ? w->get_active() : 1.0; nuclear@13: float aspect = sz.x / sz.y; nuclear@13: nuclear@15: float alpha = vis * (act * 0.5 + 0.5); nuclear@15: nuclear@13: bind_program(prog_color); nuclear@13: nuclear@13: gl_begin(GL_QUADS); nuclear@15: gl_color4f(cbot.r, cbot.g, cbot.b, cbot.a * alpha); nuclear@13: gl_texcoord2f(0, 1); nuclear@14: gl_vertex3f(pos.x, pos.y, 0); nuclear@13: gl_texcoord2f(aspect, 1); nuclear@14: gl_vertex3f(pos.x + sz.x, pos.y, 0); nuclear@15: gl_color4f(ctop.r, ctop.g, ctop.b, ctop.a * alpha); nuclear@13: gl_texcoord2f(aspect, 0); nuclear@14: gl_vertex3f(pos.x + sz.x, pos.y + sz.y, 0); nuclear@13: gl_texcoord2f(0, 0); nuclear@14: gl_vertex3f(pos.x, pos.y + sz.y, 0); nuclear@13: gl_end(); nuclear@13: } nuclear@13: nuclear@15: static void draw_shadow_text(const Widget *w, float justify, float x, float y, const Color &col, const char *text, float press) nuclear@15: { nuclear@15: static const Color cshad = Color(0.1, 0.1, 0.1, 1.0); nuclear@15: nuclear@15: float xoffs = 1.0 - press; nuclear@15: float yoffs = 1.0 - press; nuclear@15: nuclear@15: Color orig = colors[TEXT_COLOR]; nuclear@15: colors[TEXT_COLOR] = cshad; nuclear@15: colors[TEXT_COLOR].a = (1.0 - press); nuclear@15: draw_text(w, justify, x + xoffs, y - yoffs, text); nuclear@15: colors[TEXT_COLOR] = col; nuclear@15: draw_text(w, justify, x, y, text); nuclear@15: colors[TEXT_COLOR] = orig; nuclear@15: } nuclear@15: nuclear@15: static void draw_shadow_text(const Widget *w, float justify, float x, float y, const char *text, float press) nuclear@15: { nuclear@15: draw_shadow_text(w, justify, x, y, Color(1.0, 1.0, 1.0, 1.0), text, press); nuclear@15: } nuclear@15: nuclear@15: static void draw_text(const Widget *w, float justify, float x, float y, const char *text) nuclear@7: { nuclear@7: struct dtx_glyphmap *gmap = dtx_get_font_glyphmap_idx(font, 0); nuclear@7: dtx_use_font(font, dtx_get_glyphmap_ptsize(gmap)); nuclear@7: nuclear@15: float vis = w ? w->get_visibility() : 1.0; nuclear@15: float act = w ? w->get_active() : 1.0; nuclear@15: nuclear@14: float twidth = dtx_string_width(text); nuclear@14: float thalf = twidth / 2.0; nuclear@15: float theight = dtx_line_height(); nuclear@7: nuclear@7: gl_matrix_mode(GL_MODELVIEW); nuclear@7: gl_push_matrix(); nuclear@7: gl_load_identity(); nuclear@15: gl_translatef(x - thalf - justify * thalf, y - theight * 0.25, 0); nuclear@7: nuclear@7: bind_program(prog_font); nuclear@15: const Color &tcol = colors[TEXT_COLOR]; nuclear@15: set_uniform_float4(prog_font, "ucolor", tcol.r, tcol.g, tcol.b, tcol.a * vis * (act * 0.5 + 0.5)); nuclear@14: gl_apply_xform(prog_font); nuclear@7: nuclear@7: dtx_string(text); nuclear@7: nuclear@7: gl_matrix_mode(GL_MODELVIEW); nuclear@7: gl_pop_matrix(); nuclear@9: } nuclear@14: nuclear@15: static void draw_frame(const Widget *widget, const Vec2 &pos, const Vec2 &sz, float inset) nuclear@14: { nuclear@15: float vis = widget ? widget->get_visibility() : 1.0; nuclear@15: float act = widget ? widget->get_active() : 1.0; nuclear@15: float offs = 300.0 * (1.0 - vis); nuclear@15: nuclear@15: float alpha = vis * (act * 0.5 + 0.5); nuclear@15: nuclear@14: float x = pos.x - BEVEL; nuclear@14: float y = pos.y - BEVEL; nuclear@14: float w = sz.x + BEVEL * 2.0; nuclear@14: float h = sz.y + BEVEL * 2.0; nuclear@14: float b = BEVEL; nuclear@14: nuclear@14: Color tcol = lerp(colors[BEVEL_LIT_COLOR], colors[BEVEL_SHAD_COLOR], inset); nuclear@14: Color bcol = lerp(colors[BEVEL_SHAD_COLOR], colors[BEVEL_LIT_COLOR], inset); nuclear@14: nuclear@14: bind_program(prog_color); nuclear@14: nuclear@14: gl_begin(GL_QUADS); nuclear@15: gl_color4f(tcol.r, tcol.g, tcol.b, tcol.a * alpha); nuclear@15: gl_vertex2f(x + b + offs, y + h - b); nuclear@15: gl_vertex2f(x + w - b + offs, y + h - b); nuclear@15: gl_vertex2f(x + w + offs, y + h); nuclear@15: gl_vertex2f(x + offs, y + h); nuclear@14: nuclear@15: gl_vertex2f(x + b, y + b + offs); nuclear@15: gl_vertex2f(x, y + offs); nuclear@15: gl_vertex2f(x, y + h + offs); nuclear@15: gl_vertex2f(x + b, y + h - b + offs); nuclear@14: nuclear@15: gl_color4f(bcol.r, bcol.g, bcol.b, bcol.a * alpha); nuclear@15: gl_vertex2f(x - offs, y); nuclear@15: gl_vertex2f(x + b - offs, y + b); nuclear@15: gl_vertex2f(x + w - b - offs, y + b); nuclear@15: gl_vertex2f(x + w - offs, y); nuclear@14: nuclear@15: gl_vertex2f(x + w - b, y + b - offs); nuclear@15: gl_vertex2f(x + w, y - offs); nuclear@15: gl_vertex2f(x + w, y + h - offs); nuclear@15: gl_vertex2f(x + w - b, y + h - b - offs); nuclear@14: gl_end(); nuclear@14: } nuclear@14: nuclear@15: static float lerp(float a, float b, float t) nuclear@15: { nuclear@15: return a + (b - a) * t; nuclear@15: } nuclear@15: nuclear@14: static Color lerp(const Color &a, const Color &b, float t) nuclear@14: { nuclear@14: Color res; nuclear@14: res.r = a.r + (b.r - a.r) * t; nuclear@14: res.g = a.g + (b.g - a.g) * t; nuclear@14: res.b = a.b + (b.b - a.b) * t; nuclear@14: return res; nuclear@14: }