2f2d2898e7852aa7f0379988c8757f156390e5ee
[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 static void conf_header(int id, const char *text, int token)
89 {
90     int jd;
91
92     if ((jd = gui_harray(id)))
93     {
94         gui_label(jd, text, GUI_SML, GUI_ALL, 0, 0);
95         gui_space(jd);
96         gui_start(jd, _("Back"), GUI_SML, token, 0);
97     }
98
99     gui_space(id);
100 }
101
102 /*---------------------------------------------------------------------------*/
103
104 #define CONF_SHARED_BACK 1              /* Shared GUI token.                 */
105
106 static int (*conf_shared_action)(int i);
107
108 static void conf_shared_init(int (*action_fn)(int))
109 {
110     conf_shared_action = action_fn;
111
112     game_client_free(NULL);
113     back_init("back/gui.png");
114     audio_music_fade_to(0.5f, "bgm/inter.ogg");
115 }
116
117 static void conf_shared_leave(struct state *st, struct state *next, int id)
118 {
119     back_free();
120     gui_delete(id);
121 }
122
123 static void conf_shared_paint(int id, float t)
124 {
125     video_push_persp((float) config_get_d(CONFIG_VIEW_FOV), 0.1f, FAR_DIST);
126     {
127         back_draw(0);
128     }
129     video_pop_matrix();
130     gui_paint(id);
131 }
132
133 static int conf_shared_buttn(int b, int d)
134 {
135     if (d)
136     {
137         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
138             return conf_shared_action(gui_token(gui_click()));
139         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
140             return conf_shared_action(CONF_SHARED_BACK);
141     }
142     return 1;
143 }
144
145 /*---------------------------------------------------------------------------*/
146
147 enum
148 {
149     CONF_BACK = CONF_SHARED_BACK,
150     CONF_VIDEO,
151     CONF_PLAYER,
152     CONF_BALL
153 };
154
155 static int music_id[11];
156 static int sound_id[11];
157
158 static int conf_action(int i)
159 {
160     int s = config_get_d(CONFIG_SOUND_VOLUME);
161     int m = config_get_d(CONFIG_MUSIC_VOLUME);
162     int r = 1;
163
164     audio_play(AUD_MENU, 1.0f);
165
166     switch (i)
167     {
168     case CONF_BACK:
169         goto_state(&st_title);
170         break;
171
172     case CONF_VIDEO:
173         goto_state(&st_conf_video);
174         break;
175
176     case CONF_PLAYER:
177         goto_name(&st_conf, &st_conf, 1);
178         break;
179
180     case CONF_BALL:
181         goto_state(&st_ball);
182         break;
183
184     default:
185         if (100 <= i && i <= 110)
186         {
187             int n = i - 100;
188
189             config_set_d(CONFIG_SOUND_VOLUME, n);
190             audio_volume(n, m);
191             audio_play(AUD_BUMPM, 1.f);
192
193             gui_toggle(sound_id[n]);
194             gui_toggle(sound_id[s]);
195         }
196         if (200 <= i && i <= 210)
197         {
198             int n = i - 200;
199
200             config_set_d(CONFIG_MUSIC_VOLUME, n);
201             audio_volume(s, n);
202             audio_play(AUD_BUMPM, 1.f);
203
204             gui_toggle(music_id[n]);
205             gui_toggle(music_id[m]);
206         }
207     }
208
209     return r;
210 }
211
212 static int conf_gui(void)
213 {
214     int id;
215
216     /* Initialize the configuration GUI. */
217
218     if ((id = gui_vstack(0)))
219     {
220         int s = config_get_d(CONFIG_SOUND_VOLUME);
221         int m = config_get_d(CONFIG_MUSIC_VOLUME);
222
223         const char *player = config_get_s(CONFIG_PLAYER);
224         const char *ball   = config_get_s(CONFIG_BALL_FILE);
225
226         int name_id = 0, ball_id = 0;
227
228         conf_header(id, _("Options"), CONF_BACK);
229
230         conf_state(id, _("Video"), _("Configure"), CONF_VIDEO);
231
232         gui_space(id);
233
234         conf_slider(id, _("Sound Volume"), 100, s,
235                     sound_id, ARRAYSIZE(sound_id));
236         conf_slider(id, _("Music Volume"), 200, m,
237                     music_id, ARRAYSIZE(music_id));
238
239         gui_space(id);
240
241         name_id = conf_state(id, _("Player Name"), " ", CONF_PLAYER);
242         ball_id = conf_state(id, _("Ball Model"), " ", CONF_BALL);
243
244         gui_layout(id, 0, 0);
245
246         gui_set_trunc(name_id, TRUNC_TAIL);
247         gui_set_trunc(ball_id, TRUNC_TAIL);
248
249         gui_set_label(name_id, player);
250         gui_set_label(ball_id, base_name(ball));
251     }
252
253     return id;
254 }
255
256 static int conf_enter(struct state *st, struct state *prev)
257 {
258     conf_shared_init(conf_action);
259     return conf_gui();
260 }
261
262 /*---------------------------------------------------------------------------*/
263
264 enum
265 {
266     CONF_VIDEO_BACK = CONF_SHARED_BACK,
267     CONF_VIDEO_WIN,
268     CONF_VIDEO_FULL,
269     CONF_VIDEO_RES,
270     CONF_VIDEO_TEXLO,
271     CONF_VIDEO_TEXHI,
272     CONF_VIDEO_REFOF,
273     CONF_VIDEO_REFON,
274     CONF_VIDEO_BACOF,
275     CONF_VIDEO_BACON,
276     CONF_VIDEO_SHDOF,
277     CONF_VIDEO_SHDON
278 };
279
280 static int conf_video_action(int i)
281 {
282     int w = config_get_d(CONFIG_WIDTH);
283     int h = config_get_d(CONFIG_HEIGHT);
284     int r = 1;
285
286     audio_play(AUD_MENU, 1.0f);
287
288     switch (i)
289     {
290     case CONF_VIDEO_FULL:
291         goto_state(&st_null);
292         r = video_mode(1, w, h);
293         goto_state(&st_conf_video);
294         break;
295
296     case CONF_VIDEO_WIN:
297         goto_state(&st_null);
298         r = video_mode(0, w, h);
299         goto_state(&st_conf_video);
300         break;
301
302     case CONF_VIDEO_TEXHI:
303         goto_state(&st_null);
304         config_set_d(CONFIG_TEXTURES, 1);
305         goto_state(&st_conf_video);
306         break;
307
308     case CONF_VIDEO_TEXLO:
309         goto_state(&st_null);
310         config_set_d(CONFIG_TEXTURES, 2);
311         goto_state(&st_conf_video);
312         break;
313
314     case CONF_VIDEO_REFON:
315         goto_state(&st_null);
316         config_set_d(CONFIG_REFLECTION, 1);
317         r = video_init(TITLE, ICON);
318         goto_state(&st_conf_video);
319         break;
320
321     case CONF_VIDEO_REFOF:
322         goto_state(&st_null);
323         config_set_d(CONFIG_REFLECTION, 0);
324         goto_state(&st_conf_video);
325         break;
326
327     case CONF_VIDEO_BACON:
328         goto_state(&st_null);
329         config_set_d(CONFIG_BACKGROUND, 1);
330         goto_state(&st_conf_video);
331         break;
332
333     case CONF_VIDEO_BACOF:
334         goto_state(&st_null);
335         config_set_d(CONFIG_BACKGROUND, 0);
336         goto_state(&st_conf_video);
337         break;
338
339     case CONF_VIDEO_SHDON:
340         goto_state(&st_null);
341         config_set_d(CONFIG_SHADOW, 1);
342         goto_state(&st_conf_video);
343         break;
344
345     case CONF_VIDEO_SHDOF:
346         goto_state(&st_null);
347         config_set_d(CONFIG_SHADOW, 0);
348         goto_state(&st_conf_video);
349         break;
350
351     case CONF_VIDEO_BACK:
352         goto_state(&st_conf);
353         break;
354
355     case CONF_VIDEO_RES:
356         goto_state(&st_resol);
357         break;
358     }
359
360     return r;
361 }
362
363 static int conf_video_gui(void)
364 {
365     int id;
366
367     if ((id = gui_vstack(0)))
368     {
369         int f = config_get_d(CONFIG_FULLSCREEN);
370         int t = config_get_d(CONFIG_TEXTURES);
371         int r = config_get_d(CONFIG_REFLECTION);
372         int b = config_get_d(CONFIG_BACKGROUND);
373         int s = config_get_d(CONFIG_SHADOW);
374
375         char resolution[sizeof ("12345678 x 12345678")];
376
377         sprintf(resolution, "%d x %d",
378                 config_get_d(CONFIG_WIDTH),
379                 config_get_d(CONFIG_HEIGHT));
380
381         conf_header(id, _("Video Options"), CONF_VIDEO_BACK);
382
383         conf_toggle(id, _("Fullscreen"), f,
384                     _("Yes"), CONF_VIDEO_FULL, 1,
385                     _("No"), CONF_VIDEO_WIN,  0);
386
387         conf_state(id, _("Resolution"), resolution, CONF_VIDEO_RES);
388
389         gui_space(id);
390
391         conf_toggle(id, _("Textures"), t,
392                     _("High"), CONF_VIDEO_TEXHI, 1,
393                     _("Low"), CONF_VIDEO_TEXLO, 2);
394
395         conf_toggle(id, _("Reflection"), r,
396                     _("On"), CONF_VIDEO_REFON, 1,
397                     _("Off"), CONF_VIDEO_REFOF, 0);
398
399         conf_toggle(id, _("Background"), b,
400                     _("On"), CONF_VIDEO_BACON, 1,
401                     _("Off"), CONF_VIDEO_BACOF, 0);
402
403         conf_toggle(id, _("Shadow"), s,
404                     _("On"), CONF_VIDEO_SHDON, 1,
405                     _("Off"), CONF_VIDEO_SHDOF, 0);
406
407         gui_layout(id, 0, 0);
408     }
409
410     return id;
411 }
412
413 static int conf_video_enter(struct state *st, struct state *prev)
414 {
415     conf_shared_init(conf_video_action);
416     return conf_video_gui();
417 }
418
419 /*---------------------------------------------------------------------------*/
420
421 static int null_enter(struct state *st, struct state *prev)
422 {
423     hud_free();
424     gui_free();
425     swch_free();
426     jump_free();
427     goal_free();
428     item_free();
429     ball_free();
430     shad_free();
431     part_free();
432
433     return 0;
434 }
435
436 static void null_leave(struct state *st, struct state *next, int id)
437 {
438     part_init(GOAL_HEIGHT, JUMP_HEIGHT);
439     shad_init();
440     ball_init();
441     item_init();
442     goal_init();
443     jump_init();
444     swch_init();
445     gui_init();
446     hud_init();
447 }
448
449 /*---------------------------------------------------------------------------*/
450
451 struct state st_conf = {
452     conf_enter,
453     conf_shared_leave,
454     conf_shared_paint,
455     shared_timer,
456     shared_point,
457     shared_stick,
458     shared_angle,
459     shared_click,
460     NULL,
461     conf_shared_buttn
462 };
463
464 struct state st_conf_video = {
465     conf_video_enter,
466     conf_shared_leave,
467     conf_shared_paint,
468     shared_timer,
469     shared_point,
470     shared_stick,
471     shared_angle,
472     shared_click,
473     NULL,
474     conf_shared_buttn
475 };
476
477 struct state st_null = {
478     null_enter,
479     null_leave,
480     NULL,
481     NULL,
482     NULL,
483     NULL,
484     NULL,
485     NULL,
486     NULL,
487     NULL
488 };