Import from neverball-1.3.1.tar.gz
[neverball-archive.git] / share / menu.c
blob29e59c431a67c554b2fd1dde2b3fe62b08fff625
1 /*
2 * Copyright (C) 2003 Robert Kooima
4 * NEVERBALL is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
15 #include <SDL.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <math.h>
20 #include "glext.h"
21 #include "text.h"
22 #include "menu.h"
23 #include "image.h"
24 #include "config.h"
26 /*---------------------------------------------------------------------------*/
28 struct text
30 GLuint text;
31 GLuint list;
33 int x, y;
36 struct item
38 GLuint list;
40 int state;
42 int x0, y0;
43 int x1, y1;
45 int U, D;
46 int L, R;
49 struct menu
51 struct text *text;
52 struct item *item;
54 int ntext;
55 int nitem;
56 int value;
59 /*---------------------------------------------------------------------------*/
61 static struct menu menu;
63 /*---------------------------------------------------------------------------*/
65 void menu_init(int ntext, int nitem, int value)
67 menu.text = (struct text *) calloc(ntext, sizeof (struct text));
68 menu.item = (struct item *) calloc(nitem, sizeof (struct item));
70 menu.ntext = (menu.text) ? ntext : 0;
71 menu.nitem = (menu.item) ? nitem : 0;
73 if (value >= 0) menu.value = value;
76 void menu_free(void)
78 int i;
80 if (menu.text)
82 for (i = 0; i < menu.ntext; i++)
84 if (glIsList(menu.text[i].list))
85 glDeleteLists(menu.text[i].list, 1);
87 if (glIsTexture(menu.text[i].text))
88 glDeleteTextures(1, &menu.text[i].text);
90 free(menu.text);
93 if (menu.item)
95 for (i = 0; i < menu.nitem; i++)
97 if (glIsList(menu.item[i].list))
98 glDeleteLists(menu.item[i].list, 1);
100 free(menu.item);
104 void menu_item(int i, int x, int y, int w, int h)
106 if (menu.item)
108 menu.item[i].x0 = x + (config_get_d(CONFIG_WIDTH) - w) / 2;
109 menu.item[i].x1 = x + (config_get_d(CONFIG_WIDTH) + w) / 2;
110 menu.item[i].y0 = y + (config_get_d(CONFIG_HEIGHT) - h) / 2;
111 menu.item[i].y1 = y + (config_get_d(CONFIG_HEIGHT) + h) / 2;
113 menu.item[i].U = i;
114 menu.item[i].D = i;
115 menu.item[i].L = i;
116 menu.item[i].R = i;
118 menu.item[i].state = -1;
120 menu.item[i].list = make_rect(menu.item[i].x0,
121 menu.item[i].y0,
122 menu.item[i].x1,
123 menu.item[i].y1);
127 void menu_link(int i, int U, int D, int L, int R)
129 if (menu.item)
131 menu.item[i].U = U;
132 menu.item[i].D = D;
133 menu.item[i].L = L;
134 menu.item[i].R = R;
138 void menu_stat(int i, int state)
140 if (menu.item)
141 menu.item[i].state = state;
144 void menu_text(int i, int x, int y, const float *c0, const float *c1,
145 const char *text, int s)
147 if (glIsList(menu.text[i].list))
148 glDeleteLists(menu.text[i].list, 1);
150 if (glIsTexture(menu.text[i].text))
151 glDeleteTextures(1, &menu.text[i].text);
153 menu.text[i].list = 0;
154 menu.text[i].text = 0;
156 if (menu.text && text && strlen(text) >= 0)
158 int w, h;
160 text_size(text, s, &w, &h);
162 menu.text[i].text = make_text(text, s);
163 menu.text[i].list = make_list(text, s, c0, c1);
165 menu.text[i].x = x + (config_get_d(CONFIG_WIDTH) - w) / 2;
166 menu.text[i].y = y + (config_get_d(CONFIG_HEIGHT) - h) / 2;
170 /*---------------------------------------------------------------------------*/
172 static void menu_paint_item(struct item *item, int n, int value)
174 static const GLfloat back[5][4] = {
175 { 0.0f, 0.0f, 0.0f, 0.5f }, /* disabled */
176 { 0.1f, 0.1f, 0.1f, 0.5f }, /* normal */
177 { 0.3f, 0.3f, 0.3f, 0.5f }, /* selected */
178 { 0.7f, 0.3f, 0.0f, 0.5f }, /* hilited */
179 { 1.0f, 0.7f, 0.3f, 0.5f }, /* selected and hilited */
181 int i, j;
183 glDisable(GL_TEXTURE_2D);
185 for (i = 0; i < n; i++)
187 j = 0;
189 if (item[i].state >= 0) j = 1;
190 if (i == value) j = 2;
191 if (item[i].state > 0) j += 2;
193 glColor4fv(back[j]);
195 if (glIsList(item[i].list))
196 glCallList(item[i].list);
199 glEnable(GL_TEXTURE_2D);
202 static void menu_paint_text(struct text *text, int n)
204 int i;
206 for (i = 0; i < n; i++)
208 if (glIsTexture(text[i].text))
209 glBindTexture(GL_TEXTURE_2D, text[i].text);
211 glPushMatrix();
213 glTranslatef((GLfloat) text[i].x, (GLfloat) text[i].y, 0.0f);
215 if (glIsList(text[i].list))
216 glCallList(text[i].list);
218 glPopMatrix();
222 void menu_paint(void)
224 glPushAttrib(GL_LIGHTING_BIT |
225 GL_COLOR_BUFFER_BIT |
226 GL_DEPTH_BUFFER_BIT);
227 config_push_ortho();
229 glEnable(GL_BLEND);
230 glEnable(GL_COLOR_MATERIAL);
231 glDisable(GL_LIGHTING);
232 glDisable(GL_DEPTH_TEST);
234 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
236 if (menu.item)
237 menu_paint_item(menu.item, menu.nitem, menu.value);
239 if (menu.text)
240 menu_paint_text(menu.text, menu.ntext);
242 config_pop_matrix();
243 glPopAttrib();
246 /*---------------------------------------------------------------------------*/
248 int menu_point(int x, int y)
250 int i;
252 for (i = 0; i < menu.nitem; i++)
254 struct item *item = menu.item + i;
256 if (item->x0 < x && x < item->x1 &&
257 item->y0 < y && y < item->y1 && item->state >= 0)
259 menu.value = i;
260 break;
263 return menu.value;
266 int menu_stick(int a, int v)
268 static int xflag = 0;
269 static int yflag = 0;
271 if (menu.item)
273 if (config_tst_d(CONFIG_JOYSTICK_AXIS_X, a))
275 if (v < -JOY_MID && xflag == 0 && menu.item[menu.value].L >= 0)
277 menu.value = menu.item[menu.value].L;
278 xflag = 1;
280 if (v > +JOY_MID && xflag == 0 && menu.item[menu.value].R >= 0)
282 menu.value = menu.item[menu.value].R;
283 xflag = 1;
285 if (-JOY_MID < v && v < +JOY_MID)
286 xflag = 0;
289 if (config_tst_d(CONFIG_JOYSTICK_AXIS_Y, a))
291 if (v < -JOY_MID && yflag == 0 && menu.item[menu.value].U >= 0)
293 menu.value = menu.item[menu.value].U;
294 yflag = 1;
296 if (v > +JOY_MID && yflag == 0 && menu.item[menu.value].D >= 0)
298 menu.value = menu.item[menu.value].D;
299 yflag = 1;
301 if (-JOY_MID < v && v < +JOY_MID)
302 yflag = 0;
305 return menu.value;
308 int menu_click(void)
310 if (menu.value >= 0)
311 return menu.value;
313 return -1;
316 int menu_buttn(void)
318 if (menu.value >= 0)
319 return menu.value;
321 return -1;
324 /*---------------------------------------------------------------------------*/