register_widget_type() can now be called in any order.
[xuni.git] / src / test / menu.c
blob4b5078ce84a0a7f3182621da8bd2e11ba79e1346
1 /*! \file menu.c
3 */
5 #include <string.h>
7 #include "menu.h"
9 #include "error.h"
10 #include "graphics.h"
11 #include "gui.h"
12 #include "loop.h"
13 #include "memory.h"
14 #include "xuni.h"
15 #include "resource/resource.h"
17 #include "widget/widgets.h"
18 #include "widget/button.h"
19 #include "widget/image.h"
21 #include "main.h"
22 #include "version.h"
24 enum wid_t {
25 WID_ORION_BACKGROUND,
26 WID_MOON_BACKGROUND,
27 WID_PARALLAX_BACKGROUND_0,
28 WID_PARALLAX_BACKGROUND_1,
29 WID_PARALLAX_BACKGROUND_2,
30 WID_PARALLAX_BACKGROUND_3,
31 WID_VERSION_LABEL,
32 WID_NEWGAME,
33 WID_MULTIPLAYER,
34 WID_LOADGAME,
35 WID_OPTIONS,
36 WID_HELP,
37 WID_QUIT,
38 WID_NEWGAME_IMAGE,
39 WID_MULTIPLAYER_IMAGE,
40 WID_LOADGAME_IMAGE,
41 WID_OPTIONS_IMAGE,
42 WID_HELP_IMAGE,
43 WID_QUIT_IMAGE,
44 WIDS
47 struct string_index_t main_menu_background_names[MAIN_MENU_BACKGROUNDS] = {
48 {"Black", MAIN_MENU_BACKGROUND_BLACK},
49 {"Moon with parallax clouds",
50 MAIN_MENU_BACKGROUND_MOON_WITH_PARALLAX_CLOUDS},
51 {"Orion nebula", MAIN_MENU_BACKGROUND_ORION_NEBULA},
52 {"Orion nebula frame update", MAIN_MENU_BACKGROUND_ORION_NEBULA_FRAME},
53 {"Parallax clouds", MAIN_MENU_BACKGROUND_PARALLAX_CLOUDS}
56 static void set_hover_visible(struct gui_t *gui, struct widget_t *menu);
58 void switch_main_menu_background(struct widget_t *panel, const char *name) {
59 size_t index = string_to_index(main_menu_background_names,
60 sizeof(main_menu_background_names)
61 / sizeof(*main_menu_background_names), name);
62 static size_t wids[] = {
63 WID_ORION_BACKGROUND,
64 WID_MOON_BACKGROUND,
65 WID_PARALLAX_BACKGROUND_0,
66 WID_PARALLAX_BACKGROUND_1,
67 WID_PARALLAX_BACKGROUND_2,
68 WID_PARALLAX_BACKGROUND_3
70 static struct {
71 int frameupdate;
72 int enable[6];
73 } data[] = {
74 {1, {0, 1, 0, 1, 1, 1}},
75 {0, {1, 0, 0, 0, 0, 0}},
76 {1, {1, 0, 0, 0, 0, 0}},
77 {1, {0, 0, 1, 1, 0, 0}},
78 {0, {0, 0, 0, 0, 0, 0}}
80 size_t x;
82 if(index != (size_t)-1) {
83 panel->p.panel->frameupdate = data[index].frameupdate;
85 for(x = 0; x < sizeof(wids) / sizeof(*wids); x ++) {
86 set_widget_visibility(
87 widget_nameid_access(panel, wids[x]),
88 WIDGET_VISIBILITY_VISIBLE,
89 data[index].enable[x]);
94 int menu_init(struct xuni_t *xuni, struct panel_data_t *data) {
95 struct widget_t *panel = data->event[PANEL_EVENT_INIT].p.init.panel;
97 init_wid(xuni->gui->widget, xuni->gui->widget,
98 PANEL_MAIN_MENU, "main menu");
100 init_wid(xuni->gui->widget, panel, WID_ORION_BACKGROUND,
101 "main menu/orion background");
102 init_wid(xuni->gui->widget, panel, WID_MOON_BACKGROUND,
103 "main menu/moon background");
104 init_wid(xuni->gui->widget, panel, WID_PARALLAX_BACKGROUND_0,
105 "main menu/parallax background 0");
106 init_wid(xuni->gui->widget, panel, WID_PARALLAX_BACKGROUND_1,
107 "main menu/parallax background 1");
108 init_wid(xuni->gui->widget, panel, WID_PARALLAX_BACKGROUND_2,
109 "main menu/parallax background 2");
110 init_wid(xuni->gui->widget, panel, WID_PARALLAX_BACKGROUND_3,
111 "main menu/parallax background 3");
112 init_wid(xuni->gui->widget, panel, WID_VERSION_LABEL,
113 "main menu/version label");
114 init_wid(xuni->gui->widget, panel, WID_NEWGAME, "main menu/newgame");
115 init_wid(xuni->gui->widget, panel, WID_MULTIPLAYER,
116 "main menu/multiplayer");
117 init_wid(xuni->gui->widget, panel, WID_LOADGAME, "main menu/loadgame");
118 init_wid(xuni->gui->widget, panel, WID_OPTIONS, "main menu/options");
119 init_wid(xuni->gui->widget, panel, WID_HELP, "main menu/help");
120 init_wid(xuni->gui->widget, panel, WID_QUIT, "main menu/quit");
121 init_wid(xuni->gui->widget, panel, WID_NEWGAME_IMAGE,
122 "main menu/newgame image");
123 init_wid(xuni->gui->widget, panel, WID_MULTIPLAYER_IMAGE,
124 "main menu/multiplayer image");
125 init_wid(xuni->gui->widget, panel, WID_LOADGAME_IMAGE,
126 "main menu/loadgame image");
127 init_wid(xuni->gui->widget, panel, WID_OPTIONS_IMAGE,
128 "main menu/options image");
129 init_wid(xuni->gui->widget, panel, WID_HELP_IMAGE,
130 "main menu/help image");
131 init_wid(xuni->gui->widget, panel, WID_QUIT_IMAGE,
132 "main menu/quit image");
134 add_widget_accelerator(xuni, panel,
135 widget_nameid_access(panel, WID_NEWGAME), SDLK_n, KMOD_NONE);
136 add_widget_accelerator(xuni, panel,
137 widget_nameid_access(panel, WID_OPTIONS), SDLK_o, KMOD_NONE);
138 add_widget_accelerator(xuni, panel,
139 widget_nameid_access(panel, WID_HELP), SDLK_h, KMOD_NONE);
140 add_widget_accelerator(xuni, panel,
141 widget_nameid_access(panel, WID_QUIT), SDLK_q, KMOD_NONE);
143 xuni_memory_free((void *)
144 widget_nameid_access(panel, WID_VERSION_LABEL)->p.label->text);
145 widget_nameid_access(panel, WID_VERSION_LABEL)->p.label->text
146 = xuni_memory_duplicate_string(get_xuni_version_string());
148 widget_event(xuni, widget_nameid_access(panel, WID_VERSION_LABEL),
149 WIDGET_EVENT_RESCALE);
151 /*data->quality.x0 = 300.0;
152 data->quality.y0 = 500.0;
153 data->quality.x1 = 600.0;
154 data->quality.y1 = 200.0;*/
156 return 0;
159 int menu_start(struct xuni_t *xuni, struct panel_data_t *data) {
160 set_caption("Main menu");
162 return 0;
165 int menu_event(struct xuni_t *xuni, struct panel_data_t *data) {
166 panel_type_t *mode = data->event[PANEL_EVENT_EVENT].p.event.mode;
167 SDL_Event *event = data->event[PANEL_EVENT_EVENT].p.event.event;
168 int repaint = 0;
170 switch(event->type) {
171 case SDL_KEYDOWN:
172 switch(event->key.keysym.sym) {
173 case SDLK_F4:
174 if(event->key.keysym.mod & KMOD_ALT) *mode = PANEL_NONE;
175 break;
176 default: break;
178 break;
179 case SDL_QUIT:
180 *mode = PANEL_NONE;
181 break;
182 case SDL_KEYUP:
183 case SDL_MOUSEMOTION:
184 break;
185 default:
186 repaint = 1;
187 break;
190 return repaint;
193 int menu_click(struct xuni_t *xuni, struct panel_data_t *data) {
194 panel_type_t *mode = data->event[PANEL_EVENT_CLICK].p.click.mode;
195 struct widget_t *widget = data->event[PANEL_EVENT_CLICK].p.click.widget;
197 switch(widget->id) {
198 case WID_NEWGAME:
199 *mode = PANEL_GAME;
200 break;
201 case WID_OPTIONS:
202 *mode = PANEL_OPTIONS;
203 break;
204 case WID_HELP:
205 *mode = PANEL_HELP;
206 break;
207 case WID_QUIT:
208 *mode = PANEL_NONE;
209 break;
210 default:
211 break;
214 return 0; /* ignored */
217 static void set_hover_visible(struct gui_t *gui, struct widget_t *menu) {
218 size_t x;
220 for(x = WID_NEWGAME_IMAGE; x <= WID_QUIT_IMAGE; x ++) {
221 int set = (gui->sel.p.widget
222 && gui->sel.p.widget == widget_nameid_follow(menu,
223 x + (WID_NEWGAME - WID_NEWGAME_IMAGE), (size_t)-1));
225 set_widget_visibility(widget_nameid_access(menu, x),
226 WIDGET_VISIBILITY_VISIBLE, set);
230 int menu_paint(struct xuni_t *xuni, struct panel_data_t *data) {
231 struct widget_t *panel
232 = widget_nameid_access(xuni->gui->widget, PANEL_MAIN_MENU);
234 /*lock_screen(xuni->smode->screen);*/
235 clear_screen(xuni->smode->screen);
236 /*unlock_screen(xuni->smode->screen);*/
238 set_hover_visible(xuni->gui, panel);
240 widget_event(xuni, panel, WIDGET_EVENT_PAINT);
242 paint_menu_fps(xuni, THEME_FONT_MONO);
244 if(panel->p.panel->frameupdate) {
245 paint_cursor(xuni, get_theme_widget(xuni, THEME_DEFAULT_CURSOR));
248 update_screen(xuni);
250 return 0;
253 void paint_menu_fps(struct xuni_t *xuni, size_t font) {
254 static unsigned long count = 0, total = 0, lastfps = 0;
255 static Uint32 lasttick = 0;
256 Uint32 tick = SDL_GetTicks();
257 char buffer[BUFSIZ];
258 SDL_Surface *text;
260 if(tick >= lasttick + 1000) {
261 lasttick = tick;
262 lastfps = count;
263 count = 0;
266 count ++;
267 total ++;
269 sprintf(buffer, "%3lu FPS | %lu (+%3lu) frames | %lu.%03lu seconds",
270 lastfps, total, count, (unsigned long)tick / 1000,
271 (unsigned long)tick % 1000);
272 text = render_text(xuni, get_theme_widget(xuni, font), buffer,
273 255, 255, 255);
275 blit_surface(xuni->smode->screen, text, 10, 10);
277 free_surface(text);
280 int menu_free(struct xuni_t *xuni, struct panel_data_t *data) {
281 return 0;