Unified handling of SDL_MOUSEBUTTONUP, SDL_MOUSEBUTTONDOWN, and SDL_MOUSEMOTION in...
[xuni.git] / src / menu.c
blob4a6cc8279f15f24e8467a38581ec7a8e5842f014
1 /*! \file menu.c
3 */
5 #include "SDL_image.h"
6 #include "SDL_rotozoom.h"
7 #include "font.h"
8 #include "graphics.h"
9 #include "gui.h"
10 #include "loop.h"
11 #include "menu.h"
12 #include "xuni.h"
14 static void resize_menu_images(struct menu_data_t *data,
15 struct smode_t *smode, struct font_t *font, struct gui_t *gui);
16 static void free_resize_menu(struct menu_data_t *data, struct gui_t *gui);
18 void init_menu(struct menu_data_t *data, struct smode_t *smode,
19 struct font_t *font, struct gui_t *gui) {
21 size_t x;
22 /* gui/default/menuhover/X.png\0 */
23 char fn[GUI_PATH_LEN + /*7 + 1*/ + 9 + 1 + 1+1+3 + 1]
24 = GUI_PATH /*"default/"*/"menuhover/";
26 /*data->text.title = TTF_RenderText_Blended(font->sans, VERSION, white);*/
27 load_resize_image(&data->title, GUI_PATH "title.png");
29 data->frame_based = smode->main_menu_quality;
31 for(x = 0; x < sizeof(data->gui.hover)/sizeof(*data->gui.hover); x ++) {
32 sprintf(fn + GUI_PATH_LEN + /*7 + 1*/ + 9 + 1, "%i.png", (int)x);
33 load_resize_image(&data->gui.hover[x], fn);
36 load_resize_image(&data->gui.hoverback, GUI_PATH /*"default/"*/"menuhover/back.png");
38 data->back0.image = load_image(GUI_PATH "back0.png");
39 data->back1.image = load_image(GUI_PATH "back1.png");
41 data->quality.x0 = 300.0;
42 data->quality.y0 = 500.0;
43 data->quality.x1 = 600.0;
44 data->quality.y1 = 200.0;
46 add_allocate_widget(gui->panel[PANEL_MAIN_MENU], 0, WIDGET_BUTTON);
47 add_allocate_widget(gui->panel[PANEL_MAIN_MENU], 1, WIDGET_BUTTON);
48 add_allocate_widget(gui->panel[PANEL_MAIN_MENU], 2, WIDGET_BUTTON);
50 add_allocate_widget(gui->panel[PANEL_MAIN_MENU], 3, WIDGET_BUTTON);
51 add_allocate_widget(gui->panel[PANEL_MAIN_MENU], 4, WIDGET_BUTTON);
52 add_allocate_widget(gui->panel[PANEL_MAIN_MENU], 5, WIDGET_BUTTON);
54 data->loaded = 0;
55 resize_menu_images(data, smode, font, gui);
56 data->loaded = 1;
59 static void resize_menu_images(struct menu_data_t *data,
60 struct smode_t *smode, struct font_t *font, struct gui_t *gui) {
62 size_t x;
64 if(data->loaded) free_resize_menu(data, gui);
66 /*data->text.loadgame.text = TTF_RenderText_Blended(font->sans,
67 "Load existing game", white);*/
69 /*data->gui.lastid = (size_t)-1;*/
71 set_button(gui->panel[PANEL_MAIN_MENU]->widget[0],
72 font->sans, "Create new game",
73 smode->width / 16, smode->height * .7,
74 smode->width / 3, smode->height / 15);
75 set_button(gui->panel[PANEL_MAIN_MENU]->widget[1],
76 font->sans, "Join multi-player game",
77 smode->width / 16, smode->height * .7 + smode->height / 12,
78 smode->width / 3, smode->height / 15);
79 set_button(gui->panel[PANEL_MAIN_MENU]->widget[2],
80 font->sans, "Load saved game",
81 smode->width / 16, smode->height * .7 + smode->height / 12 * 2,
82 smode->width / 3, smode->height / 15);
84 /*data->gui.widget[1].enabled = 0; !!! disable multiplayer button */
86 set_button(gui->panel[PANEL_MAIN_MENU]->widget[3],
87 font->sans, "Options and preferences",
88 smode->width - smode->width / 3 - smode->width / 16,
89 smode->height * .7, smode->width / 3, smode->height / 15);
90 set_button(gui->panel[PANEL_MAIN_MENU]->widget[4],
91 font->sans, "Help and information",
92 smode->width - smode->width / 3 - smode->width / 16,
93 smode->height * .7 + smode->height / 12,
94 smode->width / 3, smode->height / 15);
95 set_button(gui->panel[PANEL_MAIN_MENU]->widget[5],
96 font->sans, "Quit",
97 smode->width - smode->width / 3 - smode->width / 16,
98 smode->height * .7 + smode->height / 12 * 2,
99 smode->width / 3, smode->height / 15);
101 if(data->title.original) {
102 data->title.image = zoomSurface(data->title.original,
103 smode->width / 1.5 / data->title.original->w,
104 smode->height / 1.5 / data->title.original->h, SMOOTHING_ON);
107 for(x = 0; x < sizeof(data->gui.hover)/sizeof(*data->gui.hover); x ++) {
108 if(data->gui.hover[x].original) {
109 data->gui.hover[x].image
110 = zoomSurface(data->gui.hover[x].original,
111 smode->width / 5.0 / data->gui.hover[x].original->w,
112 smode->height / 3.75 / data->gui.hover[x].original->h,
113 SMOOTHING_ON);
117 if(data->gui.hoverback.original) {
118 data->gui.hoverback.image
119 = zoomSurface(data->gui.hoverback.original,
120 smode->width / 5.0 / data->gui.hoverback.original->w,
121 smode->height / 3.75 / data->gui.hoverback.original->h,
122 SMOOTHING_ON);
126 void start_menu(struct menu_data_t *data) {
127 set_caption("Main menu");
130 int menu_event(enum loop_mode_t *mode, SDL_Event *event,
131 struct menu_data_t *data, struct smode_t *smode, struct font_t *font,
132 struct theme_t *theme, struct gui_t *gui) {
134 int repaint = 0;
135 /*struct widget_sel_t sel;*/
137 switch(event->type) {
138 case SDL_KEYDOWN:
139 break;
140 case SDL_KEYUP:
141 switch(event->key.keysym.sym) {
142 case SDLK_ESCAPE:
143 case SDLK_q:
144 *mode = MODE_QUIT;
145 break;
146 case SDLK_n:
147 *mode = MODE_GAME;
148 break;
149 case SDLK_o:
150 *mode = MODE_OPTIONS;
151 break;
152 case SDLK_F4:
153 if(event->key.keysym.mod & KMOD_ALT) *mode = MODE_QUIT;
154 break;
155 default: break;
157 break;
158 #if 0
159 case SDL_MOUSEBUTTONDOWN:
160 if(event->button.button != 1) break;
162 repaint = set_menu_widget_sel(event->button.x, event->button.y, 1,
163 data, smode, theme, gui);
164 break;
165 case SDL_MOUSEBUTTONUP:
166 if(event->button.button != 1) break;
168 if(gui->sel.p.widget
169 && in_sdl_rect(event->button.x, event->button.y,
170 &gui->sel.p.widget->pos)) {
172 if(gui->sel.clickin) {
173 menu_perform_click(gui->sel.p.widget->id, mode);
174 gui->sel.clickin = 0;
177 gui->sel.wasin = 1;
178 repaint = 1;
180 if(gui->sel.p.widget
181 && widget_can_be_active(gui->sel.p.widget->type)) {
183 gui->active = gui->sel.p;
184 activate_widget(gui->sel.p.widget);
185 enable_unicode(gui->active.widget->type);
188 else {
189 repaint = set_menu_widget_sel(event->button.x, event->button.y, 0,
190 data, smode, theme, gui);
192 if(gui->active.widget) {
193 repaint = 1;
195 deactivate_widget(gui->active.widget);
197 clear_active(&gui->active);
201 break;
202 case SDL_MOUSEMOTION:
203 repaint = set_menu_widget_sel(event->button.x, event->button.y,
204 gui->sel.clickin, data, smode, theme, gui);
205 break;
206 #endif
207 case SDL_QUIT:
208 *mode = MODE_QUIT;
209 break;
210 case SDL_VIDEORESIZE:
211 resize_menu_images(data, smode, font, gui);
212 repaint = 1;
213 break;
214 default:
215 repaint = 1;
216 break;
219 return repaint;
222 int set_menu_widget_sel(int xp, int yp, int click, struct menu_data_t *data,
223 struct smode_t *smode, struct theme_t *theme, struct gui_t *gui) {
225 if(set_widget_sel_repaint(&gui->sel, xp, yp, click,
226 gui->panel[PANEL_MAIN_MENU]->widget,
227 gui->panel[PANEL_MAIN_MENU]->widgets)) {
229 return 1;
232 return 0;
235 void menu_perform_click(int id, enum loop_mode_t *mode) {
236 switch(id) {
237 case 0:
238 *mode = MODE_GAME;
239 break;
240 case 3:
241 *mode = MODE_OPTIONS;
242 break;
243 case 5:
244 *mode = MODE_QUIT;
245 break;
246 default:
247 break;
251 void paint_menu(struct menu_data_t *data, struct smode_t *smode,
252 struct font_t *font, struct theme_t *theme, struct gui_t *gui) {
254 size_t x;
256 lock_screen(smode->screen);
257 SDL_FillRect(smode->screen, NULL,
258 SDL_MapRGB(smode->screen->format, 0, 0, 0));
259 unlock_screen(smode->screen);
261 if(data->back0.image) {
262 if(data->frame_based) {
263 blit_surface_fill_from(smode->screen, data->back0.image, 0, 0,
264 smode->width, smode->height, data->back0.x, data->back0.y);
266 data->back0.x += smode->width / data->quality.x0;
267 data->back0.y += smode->height / data->quality.y0;
269 if(data->back0.x >= data->back0.image->w) {
270 data->back0.x = 0;
272 if(data->back0.y >= data->back0.image->h) {
273 data->back0.y = 0;
276 else {
277 blit_surface_repeat(smode->screen, data->back0.image,
278 0, 0, smode->width, smode->height);
282 if(data->frame_based >= 2 && data->back1.image) {
283 blit_surface_fill_from(smode->screen, data->back1.image,
284 0, 0, smode->width, smode->height, data->back1.x, data->back1.y);
286 data->back1.x += smode->width / data->quality.x1;
287 data->back1.y += smode->height / data->quality.y1;
289 if(data->back1.x >= data->back1.image->w) {
290 data->back1.x = 0;
292 if(data->back1.y >= data->back1.image->h) {
293 data->back1.y = 0;
297 if(data->title.image) {
298 blit_surface(smode->screen, data->title.image,
299 (smode->width - data->title.image->w) / 2, 0);
302 if(data->gui.hoverback.image) {
303 blit_surface(smode->screen, data->gui.hoverback.image,
304 (smode->width - data->gui.hoverback.image->w) / 2,
305 smode->height * .69);
308 for(x = 0; x < gui->panel[PANEL_MAIN_MENU]->widgets; x ++) {
309 switch(paint_widget(smode, font, theme, gui,
310 gui->panel[PANEL_MAIN_MENU]->widget[x])) {
312 case BOX_OUT_HOVER:
313 case BOX_IN_ACTIVE:
314 if(data->gui.hover[x].image) {
315 blit_surface(smode->screen, data->gui.hover[x].image,
316 (smode->width - data->gui.hover[x].image->w) / 2,
317 smode->height * .69);
320 break;
321 default:
322 break;
326 paint_menu_fps(smode->screen, font);
328 /*SDL_GetMouseState(&xp, &yp);
329 pixelRGBA(screen, xp, yp, 255, 255, 255, 255);*/
331 SDL_UpdateRect(smode->screen, 0, 0, 0, 0);
334 void paint_menu_fps(SDL_Surface *screen, struct font_t *font) {
335 static unsigned long count = 0, total = 0, lastfps = 0;
336 static Uint32 lasttick = 0;
337 Uint32 tick = SDL_GetTicks();
338 char buffer[BUFSIZ];
339 SDL_Surface *text;
341 if(tick >= lasttick + 1000) {
342 lasttick = tick;
343 lastfps = count;
344 count = 0;
347 count ++;
348 total ++;
350 sprintf(buffer, "%3lu FPS | %lu (+%3lu) frames | %lu.%03lu seconds",
351 lastfps, total, count, (unsigned long)tick / 1000,
352 (unsigned long)tick % 1000);
353 text = render_white_text(font->mono, buffer);
355 blit_surface(screen, text, 10, 10);
357 SDL_FreeSurface(text);
360 static void free_resize_menu(struct menu_data_t *data, struct gui_t *gui) {
361 size_t x;
363 SDL_FreeSurface(data->title.image);
365 /*free_panel(gui->panel[PANEL_MAIN_MENU]);*/
367 for(x = 0; x < sizeof(data->gui.hover)/sizeof(*data->gui.hover); x ++) {
368 SDL_FreeSurface(data->gui.hover[x].image);
371 SDL_FreeSurface(data->gui.hoverback.image);
374 void free_menu(struct menu_data_t *data, struct gui_t *gui) {
375 size_t x;
377 free_resize_menu(data, gui);
379 SDL_FreeSurface(data->title.original);
381 SDL_FreeSurface(data->back0.image);
382 SDL_FreeSurface(data->back1.image);
384 for(x = 0; x < sizeof(data->gui.hover)/sizeof(*data->gui.hover); x ++) {
385 SDL_FreeSurface(data->gui.hover[x].original);
388 SDL_FreeSurface(data->gui.hoverback.original);