#include "glext.h"
#include "image.h"
#include "vec3.h"
+#include "text.h"
#include "gui.h"
/*---------------------------------------------------------------------------*/
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];
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);
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],
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],
return id;
}
- fprintf(stderr, _("Out of widget IDs\n"));
+ fprintf(stderr, "Out of widget IDs\n");
return 0;
}
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)
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);
}
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;
}
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;
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;
if (widget[id].w < widget[id].h && widget[id].w > 0)
widget[id].w = widget[id].h;
-
/* Padded text elements look a little nicer. */
if (widget[id].w < config_get_d(CONFIG_WIDTH))
widget[id].w += radius;
if (widget[id].h < config_get_d(CONFIG_HEIGHT))
widget[id].h += radius;
+
+ /* A button should be at least wide enough to accomodate the rounding. */
+
+ if (widget[id].w < 2 * radius)
+ widget[id].w = 2 * radius;
+ if (widget[id].h < 2 * radius)
+ widget[id].h = 2 * radius;
}
static void gui_widget_up(int id)
{
if (id)
{
- glPushAttrib(GL_LIGHTING_BIT |
- GL_COLOR_BUFFER_BIT |
- GL_DEPTH_BUFFER_BIT);
config_push_ortho();
{
- glEnable(GL_BLEND);
glEnable(GL_COLOR_MATERIAL);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
-
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glPushAttrib(GL_TEXTURE_BIT);
{
glDisable(GL_TEXTURE_2D);
gui_paint_rect(id, 0);
- }
- glPopAttrib();
- gui_paint_text(id);
+ glEnable(GL_TEXTURE_2D);
+ gui_paint_text(id);
+
+ glColor4fv(gui_wht);
+ }
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
}
config_pop_matrix();
- glPopAttrib();
}
}
/*---------------------------------------------------------------------------*/
-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. */
+ /* Vertical distance between the tops of id and 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;
-
- /* 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;
}
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
-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. */