X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=share%2Fgui.c;h=e7d58aa51358423aeaca27930291bf77e5164694;hb=c02ae9f8fce350c74e6ac7d281f03857c44964a7;hp=23c2a46d479feb4a892982be8ee5c3fe764a5c53;hpb=a090ae2fdc4919d9b91bb9fd17f78801d84f3e00;p=neverball diff --git a/share/gui.c b/share/gui.c index 23c2a46..e7d58aa 100644 --- a/share/gui.c +++ b/share/gui.c @@ -20,6 +20,7 @@ #include "glext.h" #include "image.h" #include "vec3.h" +#include "text.h" #include "gui.h" /*---------------------------------------------------------------------------*/ @@ -40,7 +41,6 @@ #define GUI_COUNT 16 #define GUI_CLOCK 18 #define GUI_SPACE 20 -#define GUI_PAUSE 22 struct widget { @@ -81,15 +81,12 @@ static struct widget widget[MAXWIDGET]; static int active; static int radius; static TTF_Font *font[3] = { NULL, NULL, NULL }; -static int scale[3] = { 1, 1, 1 }; static GLuint digit_text[3][11]; static GLuint digit_list[3][11]; static int digit_w[3][11]; static int digit_h[3][11]; -static int pause_id; - /*---------------------------------------------------------------------------*/ static int gui_hot(int id) @@ -112,14 +109,17 @@ static GLuint gui_list(int x, int y, GLfloat s0, t0; GLfloat s1, t1; - int W, H, d = h / 16; + int W, H, ww, hh, d = h / 16; /* Assume the applied texture size is rect size rounded to power-of-two. */ image_size(&W, &H, w, h); - s0 = 0.5f * (W - w) / W; - t0 = 0.5f * (H - h) / H; + ww = ((W - w) % 2) ? w + 1 : w; + hh = ((H - h) % 2) ? h + 1 : h; + + s0 = 0.5f * (W - ww) / W; + t0 = 0.5f * (H - hh) / H; s1 = 1.0f - s0; t1 = 1.0f - t0; @@ -128,18 +128,18 @@ static GLuint gui_list(int x, int y, glBegin(GL_QUADS); { glColor4f(0.0f, 0.0f, 0.0f, 0.5f); - glTexCoord2f(s0, t1); glVertex2i(x + d, y - d); - glTexCoord2f(s1, t1); glVertex2i(x + w + d, y - d); - glTexCoord2f(s1, t0); glVertex2i(x + w + d, y + h - d); - glTexCoord2f(s0, t0); glVertex2i(x + d, y + h - d); + glTexCoord2f(s0, t1); glVertex2i(x + d, y - d); + glTexCoord2f(s1, t1); glVertex2i(x + ww + d, y - d); + glTexCoord2f(s1, t0); glVertex2i(x + ww + d, y + hh - d); + glTexCoord2f(s0, t0); glVertex2i(x + d, y + hh - d); glColor4fv(c0); - glTexCoord2f(s0, t1); glVertex2i(x, y); - glTexCoord2f(s1, t1); glVertex2i(x + w, y); + glTexCoord2f(s0, t1); glVertex2i(x, y); + glTexCoord2f(s1, t1); glVertex2i(x + ww, y); glColor4fv(c1); - glTexCoord2f(s1, t0); glVertex2i(x + w, y + h); - glTexCoord2f(s0, t0); glVertex2i(x, y + h); + glTexCoord2f(s1, t0); glVertex2i(x + ww, y + hh); + glTexCoord2f(s0, t0); glVertex2i(x, y + hh); } glEnd(); } @@ -228,19 +228,6 @@ void gui_init(void) int s0 = s / 26; int s1 = s / 13; int s2 = s / 7; - int m; - - /* Make sure text size doesn't exceed the maximum texture size. */ - - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m); - - scale[0] = 1; - scale[1] = 1; - scale[2] = 1; - - while (s0 > m) { s0 /= 2; scale[0] *= 2; } - while (s1 > m) { s1 /= 2; scale[1] *= 2; } - while (s2 > m) { s2 /= 2; scale[2] *= 2; } memset(widget, 0, sizeof (struct widget) * MAXWIDGET); @@ -251,11 +238,6 @@ void gui_init(void) font[GUI_LRG] = TTF_OpenFont(config_data(GUI_FACE), s2); radius = s / 60; - /* Initialize the global pause GUI. */ - - if ((pause_id = gui_pause(0))) - gui_layout(pause_id, 0, 0); - /* Initialize digit glyphs and lists for counters and clocks. */ for (i = 0; i < 3; i++) @@ -272,7 +254,7 @@ void gui_init(void) digit_text[i][j] = make_image_from_font(NULL, NULL, &digit_w[i][j], &digit_h[i][j], - text, font[i], scale[i]); + text, font[i]); digit_list[i][j] = gui_list(-digit_w[i][j] / 2, -digit_h[i][j] / 2, +digit_w[i][j], @@ -284,7 +266,7 @@ void gui_init(void) digit_text[i][j] = make_image_from_font(NULL, NULL, &digit_w[i][10], &digit_h[i][10], - ":", font[i], scale[i]); + ":", font[i]); digit_list[i][j] = gui_list(-digit_w[i][10] / 2, -digit_h[i][10] / 2, +digit_w[i][10], @@ -384,7 +366,7 @@ static int gui_widget(int pd, int type) return id; } - fprintf(stderr, _("Out of widget IDs\n")); + fprintf(stderr, "Out of widget IDs\n"); return 0; } @@ -402,7 +384,7 @@ void gui_set_image(int id, const char *file) if (glIsTexture(widget[id].text_img)) glDeleteTextures(1, &widget[id].text_img); - widget[id].text_img = make_image_from_file(NULL, NULL, NULL, NULL, file); + widget[id].text_img = make_image_from_file(file); } void gui_set_label(int id, const char *text) @@ -415,8 +397,7 @@ void gui_set_label(int id, const char *text) glDeleteLists(widget[id].text_obj, 1); widget[id].text_img = make_image_from_font(NULL, NULL, &w, &h, - text, font[widget[id].size], - scale[widget[id].size]); + text, font[widget[id].size]); widget[id].text_obj = gui_list(-w / 2, -h / 2, w, h, widget[id].color0, widget[id].color1); } @@ -471,10 +452,9 @@ int gui_image(int pd, const char *file, int w, int h) if ((id = gui_widget(pd, GUI_IMAGE))) { - widget[id].text_img = make_image_from_file(NULL, NULL, - NULL, NULL, file); - widget[id].w = w; - widget[id].h = h; + widget[id].text_img = make_image_from_file(file); + widget[id].w = w; + widget[id].h = h; } return id; } @@ -498,8 +478,7 @@ int gui_state(int pd, const char *text, int size, int token, int value) widget[id].text_img = make_image_from_font(NULL, NULL, &widget[id].w, &widget[id].h, - text, font[size], - scale[size]); + text, font[size]); widget[id].size = size; widget[id].token = token; widget[id].value = value; @@ -517,8 +496,7 @@ int gui_label(int pd, const char *text, int size, int rect, const float *c0, widget[id].text_img = make_image_from_font(NULL, NULL, &widget[id].w, &widget[id].h, - text, font[size], - scale[size]); + text, font[size]); widget[id].size = size; widget[id].color0 = c0 ? c0 : gui_yel; widget[id].color1 = c1 ? c1 : gui_red; @@ -575,27 +553,6 @@ int gui_space(int pd) return id; } -int gui_pause(int pd) -{ - const char *text = _("Paused"); - int id; - - if ((id = gui_widget(pd, GUI_PAUSE))) - { - widget[id].text_img = make_image_from_font(NULL, NULL, - &widget[id].w, - &widget[id].h, - text, font[GUI_LRG], - scale[GUI_LRG]); - widget[id].color0 = gui_wht; - widget[id].color1 = gui_wht; - widget[id].value = 0; - widget[id].size = GUI_LRG; - widget[id].rect = GUI_ALL; - } - return id; -} - /*---------------------------------------------------------------------------*/ /* * Create a multi-line text box using a vertical array of labels. @@ -735,19 +692,6 @@ static void gui_vstack_up(int id) } } -static void gui_paused_up(int id) -{ - /* Store width and height for later use in text rendering. */ - - widget[id].x = widget[id].w; - widget[id].y = widget[id].h; - - /* The pause widget fills the screen. */ - - widget[id].w = config_get_d(CONFIG_WIDTH); - widget[id].h = config_get_d(CONFIG_HEIGHT); -} - static void gui_button_up(int id) { /* Store width and height for later use in text rendering. */ @@ -776,7 +720,6 @@ static void gui_widget_up(int id) case GUI_VARRAY: gui_varray_up(id); break; case GUI_HSTACK: gui_hstack_up(id); break; case GUI_VSTACK: gui_vstack_up(id); break; - case GUI_PAUSE: gui_paused_up(id); break; default: gui_button_up(id); break; } } @@ -919,7 +862,6 @@ static void gui_button_dn(int id, int x, int y, int w, int h) int W = widget[id].x; int H = widget[id].y; int R = widget[id].rect; - int r = ((widget[id].type & GUI_TYPE) == GUI_PAUSE ? radius * 4 : radius); const float *c0 = widget[id].color0; const float *c1 = widget[id].color1; @@ -932,7 +874,7 @@ static void gui_button_dn(int id, int x, int y, int w, int h) /* Create display lists for the text area and rounded rectangle. */ widget[id].text_obj = gui_list(-W / 2, -H / 2, W, H, c0, c1); - widget[id].rect_obj = gui_rect(-w / 2, -h / 2, w, h, R, r); + widget[id].rect_obj = gui_rect(-w / 2, -h / 2, w, h, R, radius); } static void gui_widget_dn(int id, int x, int y, int w, int h) @@ -982,7 +924,7 @@ void gui_layout(int id, int xd, int yd) /* Hilite the widget under the cursor, if any. */ - /* gui_point(id, -1, -1); */ + gui_point(id, -1, -1); } int gui_search(int id, int x, int y) @@ -1342,11 +1284,6 @@ void gui_paint(int id) } } -void gui_blank(void) -{ - gui_paint(pause_id); -} - /*---------------------------------------------------------------------------*/ void gui_dump(int id, int d) @@ -1460,122 +1397,174 @@ void gui_toggle(int id) /*---------------------------------------------------------------------------*/ -static int gui_vert_test(int id, int jd) +static int gui_vert_offset(int id, int jd) { - /* Determine whether widget id is in vertical contact with widget jd. */ + /* Vertical offset between bottom of id and top of jd */ - if (id && gui_hot(id) && jd && gui_hot(jd)) - { - int i0 = widget[id].x; - int i1 = widget[id].x + widget[id].w; - int j0 = widget[jd].x; - int j1 = widget[jd].x + widget[jd].w; - - /* Is widget id's top edge is in contact with jd's bottom edge? */ + return widget[id].y - (widget[jd].y + widget[jd].h); +} - if (widget[id].y + widget[id].h == widget[jd].y) - { - /* Do widgets id and jd overlap horizontally? */ +static int gui_horz_offset(int id, int jd) +{ + /* Horizontal offset between left of id and right of jd */ - if (j0 <= i0 && i0 < j1) return 1; - if (j0 < i1 && i1 <= j1) return 1; - if (i0 <= j0 && j0 < i1) return 1; - if (i0 < j1 && j1 <= i1) return 1; - } - } - return 0; + return widget[id].x - (widget[jd].x + widget[jd].w); } -static int gui_horz_test(int id, int jd) +static int gui_vert_dist(int id, int jd) { - /* Determine whether widget id is in horizontal contact with widget jd. */ - - if (id && gui_hot(id) && jd && gui_hot(jd)) - { - int i0 = widget[id].y; - int i1 = widget[id].y + widget[id].h; - int j0 = widget[jd].y; - int j1 = widget[jd].y + widget[jd].h; + /* Vertical distance between the tops of id and jd */ - /* Is widget id's right edge in contact with jd's left edge? */ + return abs((widget[id].y + widget[id].h) - (widget[jd].y + widget[jd].h)); +} - if (widget[id].x + widget[id].w == widget[jd].x) - { - /* Do widgets id and jd overlap vertically? */ +static int gui_horz_dist(int id, int jd) +{ + /* Horizontal distance between the left sides of id and jd */ - if (j0 <= i0 && i0 < j1) return 1; - if (j0 < i1 && i1 <= j1) return 1; - if (i0 <= j0 && j0 < i1) return 1; - if (i0 < j1 && j1 <= i1) return 1; - } - } - return 0; + return abs(widget[id].x - widget[jd].x); } /*---------------------------------------------------------------------------*/ static int gui_stick_L(int id, int dd) { - int jd, kd; + int jd, kd, hd; + int o, omin, d, dmin; - /* Find a widget to the left of widget dd. */ + /* Find the closest "hot" widget to the left of dd (and inside id) */ - if (gui_horz_test(id, dd)) + if (id && gui_hot(id)) return id; + hd = 0; + omin = widget[dd].x - widget[id].x + 1; + dmin = widget[dd].y + widget[dd].h + widget[id].y + widget[id].h; + for (jd = widget[id].car; jd; jd = widget[jd].cdr) - if ((kd = gui_stick_L(jd, dd))) - return kd; + { + kd = gui_stick_L(jd, dd); - return 0; + if (kd && kd != dd) + { + o = gui_horz_offset(dd, kd); + d = gui_vert_dist(dd, kd); + + if (0 <= o && o <= omin && d <= dmin) + { + hd = kd; + omin = o; + dmin = d; + } + } + } + + return hd; } static int gui_stick_R(int id, int dd) { - int jd, kd; + int jd, kd, hd; + int o, omin, d, dmin; - /* Find a widget to the right of widget dd. */ + /* Find the closest "hot" widget to the right of dd (and inside id) */ - if (gui_horz_test(dd, id)) + if (id && gui_hot(id)) return id; + hd = 0; + omin = (widget[id].x + widget[id].w) - (widget[dd].x + widget[dd].w) + 1; + dmin = widget[dd].y + widget[dd].h + widget[id].y + widget[id].h; + for (jd = widget[id].car; jd; jd = widget[jd].cdr) - if ((kd = gui_stick_R(jd, dd))) - return kd; + { + kd = gui_stick_R(jd, dd); - return 0; + if (kd && kd != dd) + { + o = gui_horz_offset(kd, dd); + d = gui_vert_dist(dd, kd); + + if (0 <= o && o <= omin && d <= dmin) + { + hd = kd; + omin = o; + dmin = d; + } + } + } + + return hd; } static int gui_stick_D(int id, int dd) { - int jd, kd; + int jd, kd, hd; + int o, omin, d, dmin; - /* Find a widget below widget dd. */ + /* Find the closest "hot" widget below dd (and inside id) */ - if (gui_vert_test(id, dd)) + if (id && gui_hot(id)) return id; + hd = 0; + omin = widget[dd].y - widget[id].y + 1; + dmin = widget[dd].x + widget[dd].w + widget[id].x + widget[id].w; + for (jd = widget[id].car; jd; jd = widget[jd].cdr) - if ((kd = gui_stick_D(jd, dd))) - return kd; + { + kd = gui_stick_D(jd, dd); - return 0; + if (kd && kd != dd) + { + o = gui_vert_offset(dd, kd); + d = gui_horz_dist(dd, kd); + + if (0 <= o && o <= omin && d <= dmin) + { + hd = kd; + omin = o; + dmin = d; + } + } + } + + return hd; } static int gui_stick_U(int id, int dd) { - int jd, kd; + int jd, kd, hd; + int o, omin, d, dmin; - /* Find a widget above widget dd. */ + /* Find the closest "hot" widget above dd (and inside id) */ - if (gui_vert_test(dd, id)) + if (id && gui_hot(id)) return id; + hd = 0; + omin = (widget[id].y + widget[id].h) - (widget[dd].y + widget[dd].h) + 1; + dmin = widget[dd].x + widget[dd].w + widget[id].x + widget[id].w; + for (jd = widget[id].car; jd; jd = widget[jd].cdr) - if ((kd = gui_stick_U(jd, dd))) - return kd; + { + kd = gui_stick_U(jd, dd); - return 0; + if (kd && kd != dd) + { + o = gui_vert_offset(kd, dd); + d = gui_horz_dist(dd, kd); + + if (0 <= o && o <= omin && d <= dmin) + { + hd = kd; + omin = o; + dmin = d; + } + } + } + + return hd; } /*---------------------------------------------------------------------------*/ @@ -1626,13 +1615,21 @@ static int gui_wrap_D(int id, int dd) /*---------------------------------------------------------------------------*/ -int gui_stick(int id, int x, int y) +/* Flag the axes to prevent uncontrolled scrolling. */ + +static int xflag = 1; +static int yflag = 1; + +void gui_stuck() { - /* Flag the axes to prevent uncontrolled scrolling. */ + /* Force the user to recenter the joystick before the next GUI action. */ - static int xflag = 1; - static int yflag = 1; + xflag = 0; + yflag = 0; +} +int gui_stick(int id, int x, int y) +{ int jd = 0; /* Find a new active widget in the direction of joystick motion. */