Make a separate screen for video settings
[neverball] / ball / st_conf.c
1 /*
2  * Copyright (C) 2003 Robert Kooima
3  *
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.
8  *
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.
13  */
14
15 #include "gui.h"
16 #include "hud.h"
17 #include "back.h"
18 #include "geom.h"
19 #include "item.h"
20 #include "ball.h"
21 #include "part.h"
22 #include "audio.h"
23 #include "config.h"
24 #include "video.h"
25 #include "common.h"
26
27 #include "game_common.h"
28 #include "game_client.h"
29 #include "game_server.h"
30
31 #include "st_conf.h"
32 #include "st_title.h"
33 #include "st_resol.h"
34 #include "st_name.h"
35 #include "st_ball.h"
36 #include "st_shared.h"
37
38 extern const char TITLE[];
39 extern const char ICON[];
40
41 /*---------------------------------------------------------------------------*/
42
43 static void conf_slider(int id, const char *text,
44                         int token, int value,
45                         int *ids, int num)
46 {
47     int jd, kd, i;
48
49     if ((jd = gui_harray(id)) && (kd = gui_harray(jd)))
50     {
51         /* A series of empty buttons forms a "slider". */
52
53         for (i = num - 1; i >= 0; i--)
54             ids[i] = gui_state(kd, NULL, GUI_SML, token + i, (i == value));
55
56         gui_label(jd, text, GUI_SML, GUI_ALL, 0, 0);
57     }
58 }
59
60 static int conf_state(int id, const char *label, const char *text, int token)
61 {
62     int jd, kd, rd = 0;
63
64     if ((jd = gui_harray(id)) && (kd = gui_harray(jd)))
65     {
66         rd = gui_state(kd, text, GUI_SML, token, 0);
67         gui_label(jd, label, GUI_SML, GUI_ALL, 0, 0);
68     }
69
70     return rd;
71 }
72
73 static void conf_toggle(int id, const char *label, int value,
74                         const char *text1, int token1, int value1,
75                         const char *text0, int token0, int value0)
76 {
77     int jd, kd;
78
79     if ((jd = gui_harray(id)) && (kd = gui_harray(jd)))
80     {
81         gui_state(kd, text0, GUI_SML, token0, (value == value0));
82         gui_state(kd, text1, GUI_SML, token1, (value == value1));
83
84         gui_label(jd, label, GUI_SML, GUI_ALL, 0, 0);
85     }
86 }
87
88 /*---------------------------------------------------------------------------*/
89
90 enum
91 {
92     CONF_BACK = 1,
93     CONF_VIDEO,
94     CONF_PLAYER,
95     CONF_BALL
96 };
97
98 static int music_id[11];
99 static int sound_id[11];
100
101 static int conf_action(int i)
102 {
103     int s = config_get_d(CONFIG_SOUND_VOLUME);
104     int m = config_get_d(CONFIG_MUSIC_VOLUME);
105     int r = 1;
106
107     audio_play(AUD_MENU, 1.0f);
108
109     switch (i)
110     {
111     case CONF_BACK:
112         goto_state(&st_title);
113         break;
114
115     case CONF_VIDEO:
116         goto_state(&st_conf_video);
117         break;
118
119     case CONF_PLAYER:
120         goto_name(&st_conf, &st_conf, 1);
121         break;
122
123     case CONF_BALL:
124         goto_state(&st_ball);
125         break;
126
127     default:
128         if (100 <= i && i <= 110)
129         {
130             int n = i - 100;
131
132             config_set_d(CONFIG_SOUND_VOLUME, n);
133             audio_volume(n, m);
134             audio_play(AUD_BUMPM, 1.f);
135
136             gui_toggle(sound_id[n]);
137             gui_toggle(sound_id[s]);
138         }
139         if (200 <= i && i <= 210)
140         {
141             int n = i - 200;
142
143             config_set_d(CONFIG_MUSIC_VOLUME, n);
144             audio_volume(s, n);
145             audio_play(AUD_BUMPM, 1.f);
146
147             gui_toggle(music_id[n]);
148             gui_toggle(music_id[m]);
149         }
150     }
151
152     return r;
153 }
154
155 static int conf_gui(void)
156 {
157     int id, jd;
158
159     /* Initialize the configuration GUI. */
160
161     if ((id = gui_vstack(0)))
162     {
163         int s = config_get_d(CONFIG_SOUND_VOLUME);
164         int m = config_get_d(CONFIG_MUSIC_VOLUME);
165
166         const char *player = config_get_s(CONFIG_PLAYER);
167         const char *ball   = config_get_s(CONFIG_BALL_FILE);
168
169         int name_id = 0, ball_id = 0;
170
171         if ((jd = gui_harray(id)))
172         {
173             gui_label(jd, _("Options"), GUI_SML, GUI_ALL, 0, 0);
174             gui_space(jd);
175             gui_start(jd, _("Back"),    GUI_SML, CONF_BACK, 0);
176         }
177
178         gui_space(id);
179
180         conf_state(id, _("Video"), _("Configure"), CONF_VIDEO);
181
182         gui_space(id);
183
184         conf_slider(id, _("Sound Volume"), 100, s,
185                     sound_id, ARRAYSIZE(sound_id));
186         conf_slider(id, _("Music Volume"), 200, m,
187                     music_id, ARRAYSIZE(music_id));
188
189         gui_space(id);
190
191         name_id = conf_state(id, _("Player Name"), " ", CONF_PLAYER);
192         ball_id = conf_state(id, _("Ball Model"), " ", CONF_BALL);
193
194         gui_layout(id, 0, 0);
195
196         gui_set_trunc(name_id, TRUNC_TAIL);
197         gui_set_trunc(ball_id, TRUNC_TAIL);
198
199         gui_set_label(name_id, player);
200         gui_set_label(ball_id, base_name(ball));
201     }
202
203     return id;
204 }
205
206 static int conf_enter(struct state *st, struct state *prev)
207 {
208     game_client_free();
209     back_init("back/gui.png");
210     audio_music_fade_to(0.5f, "bgm/inter.ogg");
211
212     return conf_gui();
213 }
214
215 static void conf_leave(struct state *st, struct state *next, int id)
216 {
217     back_free();
218     gui_delete(id);
219 }
220
221 static void conf_paint(int id, float t)
222 {
223     video_push_persp((float) config_get_d(CONFIG_VIEW_FOV), 0.1f, FAR_DIST);
224     {
225         back_draw(0);
226     }
227     video_pop_matrix();
228     gui_paint(id);
229 }
230
231 static int conf_buttn(int b, int d)
232 {
233     if (d)
234     {
235         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
236             return conf_action(gui_token(gui_click()));
237         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
238             return conf_action(CONF_BACK);
239     }
240     return 1;
241 }
242
243 /*---------------------------------------------------------------------------*/
244
245 enum
246 {
247     CONF_VIDEO_BACK = 1,
248     CONF_VIDEO_WIN,
249     CONF_VIDEO_FULL,
250     CONF_VIDEO_RES,
251     CONF_VIDEO_TEXLO,
252     CONF_VIDEO_TEXHI,
253     CONF_VIDEO_REFOF,
254     CONF_VIDEO_REFON,
255     CONF_VIDEO_BACOF,
256     CONF_VIDEO_BACON,
257     CONF_VIDEO_SHDOF,
258     CONF_VIDEO_SHDON
259 };
260
261 static int conf_video_action(int i)
262 {
263     int w = config_get_d(CONFIG_WIDTH);
264     int h = config_get_d(CONFIG_HEIGHT);
265     int r = 1;
266
267     audio_play(AUD_MENU, 1.0f);
268
269     switch (i)
270     {
271     case CONF_VIDEO_FULL:
272         goto_state(&st_null);
273         r = video_mode(1, w, h);
274         goto_state(&st_conf_video);
275         break;
276
277     case CONF_VIDEO_WIN:
278         goto_state(&st_null);
279         r = video_mode(0, w, h);
280         goto_state(&st_conf_video);
281         break;
282
283     case CONF_VIDEO_TEXHI:
284         goto_state(&st_null);
285         config_set_d(CONFIG_TEXTURES, 1);
286         goto_state(&st_conf_video);
287         break;
288
289     case CONF_VIDEO_TEXLO:
290         goto_state(&st_null);
291         config_set_d(CONFIG_TEXTURES, 2);
292         goto_state(&st_conf_video);
293         break;
294
295     case CONF_VIDEO_REFON:
296         goto_state(&st_null);
297         config_set_d(CONFIG_REFLECTION, 1);
298         r = video_init(TITLE, ICON);
299         goto_state(&st_conf_video);
300         break;
301
302     case CONF_VIDEO_REFOF:
303         goto_state(&st_null);
304         config_set_d(CONFIG_REFLECTION, 0);
305         goto_state(&st_conf_video);
306         break;
307
308     case CONF_VIDEO_BACON:
309         goto_state(&st_null);
310         config_set_d(CONFIG_BACKGROUND, 1);
311         goto_state(&st_conf_video);
312         break;
313
314     case CONF_VIDEO_BACOF:
315         goto_state(&st_null);
316         config_set_d(CONFIG_BACKGROUND, 0);
317         goto_state(&st_conf_video);
318         break;
319
320     case CONF_VIDEO_SHDON:
321         goto_state(&st_null);
322         config_set_d(CONFIG_SHADOW, 1);
323         goto_state(&st_conf_video);
324         break;
325
326     case CONF_VIDEO_SHDOF:
327         goto_state(&st_null);
328         config_set_d(CONFIG_SHADOW, 0);
329         goto_state(&st_conf_video);
330         break;
331
332     case CONF_VIDEO_BACK:
333         goto_state(&st_conf);
334         break;
335
336     case CONF_VIDEO_RES:
337         goto_state(&st_resol);
338         break;
339     }
340
341     return r;
342 }
343
344 static int conf_video_gui(void)
345 {
346     int id, jd;
347
348     if ((id = gui_vstack(0)))
349     {
350         int f = config_get_d(CONFIG_FULLSCREEN);
351         int t = config_get_d(CONFIG_TEXTURES);
352         int r = config_get_d(CONFIG_REFLECTION);
353         int b = config_get_d(CONFIG_BACKGROUND);
354         int s = config_get_d(CONFIG_SHADOW);
355
356         char resolution[sizeof ("12345678 x 12345678")];
357
358         sprintf(resolution, "%d x %d",
359                 config_get_d(CONFIG_WIDTH),
360                 config_get_d(CONFIG_HEIGHT));
361
362         if ((jd = gui_harray(id)))
363         {
364             gui_label(jd, _("Video Options"), GUI_SML, GUI_ALL, 0, 0);
365             gui_space(jd);
366             gui_start(jd, _("Back"), GUI_SML, CONF_VIDEO_BACK, 0);
367         }
368
369         gui_space(id);
370
371         conf_toggle(id, _("Fullscreen"), f,
372                     _("Yes"), CONF_VIDEO_FULL, 1,
373                     _("No"), CONF_VIDEO_WIN,  0);
374
375         conf_state(id, _("Resolution"), resolution, CONF_VIDEO_RES);
376
377         gui_space(id);
378
379         conf_toggle(id, _("Textures"), t,
380                     _("High"), CONF_VIDEO_TEXHI, 1,
381                     _("Low"), CONF_VIDEO_TEXLO, 2);
382
383         conf_toggle(id, _("Reflection"), r,
384                     _("On"), CONF_VIDEO_REFON, 1,
385                     _("Off"), CONF_VIDEO_REFOF, 0);
386
387         conf_toggle(id, _("Background"), b,
388                     _("On"), CONF_VIDEO_BACON, 1,
389                     _("Off"), CONF_VIDEO_BACOF, 0);
390
391         conf_toggle(id, _("Shadow"), s,
392                     _("On"), CONF_VIDEO_SHDON, 1,
393                     _("Off"), CONF_VIDEO_SHDOF, 0);
394
395         gui_layout(id, 0, 0);
396     }
397
398     return id;
399 }
400
401 static int conf_video_enter(struct state *st, struct state *prev)
402 {
403     game_client_free();
404     back_init("back/gui.png");
405     audio_music_fade_to(0.5f, "bgm/inter.ogg");
406
407     return conf_video_gui();
408 }
409
410 static void conf_video_leave(struct state *st, struct state *next, int id)
411 {
412     back_free();
413     gui_delete(id);
414 }
415
416 static void conf_video_paint(int id, float t)
417 {
418     video_push_persp((float) config_get_d(CONFIG_VIEW_FOV), 0.1f, FAR_DIST);
419     {
420         back_draw(0);
421     }
422     video_pop_matrix();
423     gui_paint(id);
424 }
425
426 static int conf_video_buttn(int b, int d)
427 {
428     if (d)
429     {
430         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
431             return conf_video_action(gui_token(gui_click()));
432         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
433             return conf_video_action(CONF_BACK);
434     }
435     return 1;
436 }
437
438 /*---------------------------------------------------------------------------*/
439
440 static int null_enter(struct state *st, struct state *prev)
441 {
442     hud_free();
443     gui_free();
444     swch_free();
445     jump_free();
446     goal_free();
447     item_free();
448     ball_free();
449     shad_free();
450     part_free();
451
452     return 0;
453 }
454
455 static void null_leave(struct state *st, struct state *next, int id)
456 {
457     part_init(GOAL_HEIGHT, JUMP_HEIGHT);
458     shad_init();
459     ball_init();
460     item_init();
461     goal_init();
462     jump_init();
463     swch_init();
464     gui_init();
465     hud_init();
466 }
467
468 /*---------------------------------------------------------------------------*/
469
470 struct state st_conf = {
471     conf_enter,
472     conf_leave,
473     conf_paint,
474     shared_timer,
475     shared_point,
476     shared_stick,
477     shared_angle,
478     shared_click,
479     NULL,
480     conf_buttn
481 };
482
483 struct state st_conf_video = {
484     conf_video_enter,
485     conf_video_leave,
486     conf_video_paint,
487     shared_timer,
488     shared_point,
489     shared_stick,
490     shared_angle,
491     shared_click,
492     NULL,
493     conf_video_buttn
494 };
495
496 struct state st_null = {
497     null_enter,
498     null_leave,
499     NULL,
500     NULL,
501     NULL,
502     NULL,
503     NULL,
504     NULL,
505     NULL,
506     NULL
507 };