Finally merged the keyboard-nav branch.
[neverball] / putt / st_all.c
1 /*
2  * Copyright (C) 2003 Robert Kooima
3  *
4  * NEVERPUTT 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 <math.h>
16
17 #include "hud.h"
18 #include "back.h"
19 #include "geom.h"
20 #include "gui.h"
21 #include "vec3.h"
22 #include "game.h"
23 #include "hole.h"
24 #include "audio.h"
25 #include "course.h"
26 #include "config.h"
27
28 #include "st_all.h"
29 #include "st_conf.h"
30
31 /*---------------------------------------------------------------------------*/
32
33 static SDL_Joystick *joystick = NULL;
34
35 void set_joystick(SDL_Joystick *j)
36 {
37     joystick = j;
38 }
39
40 /*---------------------------------------------------------------------------*/
41
42 static char *number(int i)
43 {
44     static char str[MAXSTR];
45
46     sprintf(str, "%02d", i);
47
48     return str;
49 }
50
51 static int score_card(const char  *title,
52                       const float *c0,
53                       const float *c1)
54 {
55     int id, jd, kd, ld;
56
57     int p1 = (curr_party() >= 1) ? 1 : 0, l1 = (curr_party() == 1) ? 1 : 0;
58     int p2 = (curr_party() >= 2) ? 1 : 0, l2 = (curr_party() == 2) ? 1 : 0;
59     int p3 = (curr_party() >= 3) ? 1 : 0, l3 = (curr_party() == 3) ? 1 : 0;
60     int p4 = (curr_party() >= 4) ? 1 : 0, l4 = (curr_party() == 4) ? 1 : 0;
61
62     int i;
63     int n = curr_count() - 1;
64     int m = curr_count() / 2;
65
66     if ((id = gui_vstack(0)))
67     {
68         gui_label(id, title, GUI_MED, GUI_ALL, c0, c1);
69         gui_space(id);
70
71         if ((jd = gui_hstack(id)))
72         {
73             if ((kd = gui_varray(jd)))
74             {
75                 if (p1) gui_label(kd, _("O"),         0, GUI_NE, 0, 0);
76                 if (p1) gui_label(kd, hole_out(0), 0, 0,           gui_wht, gui_wht);
77                 if (p1) gui_label(kd, hole_out(1), 0, GUI_SE * l1, gui_red, gui_wht);
78                 if (p2) gui_label(kd, hole_out(2), 0, GUI_SE * l2, gui_grn, gui_wht);
79                 if (p3) gui_label(kd, hole_out(3), 0, GUI_SE * l3, gui_blu, gui_wht);
80                 if (p4) gui_label(kd, hole_out(4), 0, GUI_SE * l4, gui_yel, gui_wht);
81             }
82
83             if ((kd = gui_harray(jd)))
84                 for (i = m; i > 0; i--)
85                     if ((ld = gui_varray(kd)))
86                     {
87                         if (p1) gui_label(ld, number(i), 0, (i == 1) ? GUI_NW : 0, 0, 0);
88                         if (p1) gui_label(ld, hole_score(i, 0), 0, 0, gui_wht, gui_wht);
89                         if (p1) gui_label(ld, hole_score(i, 1), 0, 0, gui_red, gui_wht);
90                         if (p2) gui_label(ld, hole_score(i, 2), 0, 0, gui_grn, gui_wht);
91                         if (p3) gui_label(ld, hole_score(i, 3), 0, 0, gui_blu, gui_wht);
92                         if (p4) gui_label(ld, hole_score(i, 4), 0, 0, gui_yel, gui_wht);
93                     }
94             if ((kd = gui_varray(jd)))
95             {
96                 gui_filler(kd);
97                 if (p1) gui_label(kd, _("Par"), 0, GUI_NW,      gui_wht, gui_wht);
98                 if (p1) gui_label(kd, _("P1"),  0, GUI_SW * l1, gui_red, gui_wht);
99                 if (p2) gui_label(kd, _("P2"),  0, GUI_SW * l2, gui_grn, gui_wht);
100                 if (p3) gui_label(kd, _("P3"),  0, GUI_SW * l3, gui_blu, gui_wht);
101                 if (p4) gui_label(kd, _("P4"),  0, GUI_SW * l4, gui_yel, gui_wht);
102             }
103         }
104
105         gui_space(id);
106
107         if ((jd = gui_hstack(id)))
108         {
109             if ((kd = gui_varray(jd)))
110             {
111                 if (p1) gui_label(kd, _("Tot"),    0, GUI_TOP, 0, 0);
112                 if (p1) gui_label(kd, hole_tot(0), 0, 0,           gui_wht, gui_wht);
113                 if (p1) gui_label(kd, hole_tot(1), 0, GUI_BOT * l1, gui_red, gui_wht);
114                 if (p2) gui_label(kd, hole_tot(2), 0, GUI_BOT * l2, gui_grn, gui_wht);
115                 if (p3) gui_label(kd, hole_tot(3), 0, GUI_BOT * l3, gui_blu, gui_wht);
116                 if (p4) gui_label(kd, hole_tot(4), 0, GUI_BOT * l4, gui_yel, gui_wht);
117             }
118             if ((kd = gui_varray(jd)))
119             {
120                 if (p1) gui_label(kd, _("I"),     0, GUI_NE, 0, 0);
121                 if (p1) gui_label(kd, hole_in(0), 0, 0,           gui_wht, gui_wht);
122                 if (p1) gui_label(kd, hole_in(1), 0, GUI_SE * l1, gui_red, gui_wht);
123                 if (p2) gui_label(kd, hole_in(2), 0, GUI_SE * l2, gui_grn, gui_wht);
124                 if (p3) gui_label(kd, hole_in(3), 0, GUI_SE * l3, gui_blu, gui_wht);
125                 if (p4) gui_label(kd, hole_in(4), 0, GUI_SE * l4, gui_yel, gui_wht);
126             }
127             if ((kd = gui_harray(jd)))
128                 for (i = n; i > m; i--)
129                     if ((ld = gui_varray(kd)))
130                     {
131                         if (p1) gui_label(ld, number(i), 0, (i == m+1) ? GUI_NW : 0, 0, 0);
132                         if (p1) gui_label(ld, hole_score(i, 0), 0, 0, gui_wht, gui_wht);
133                         if (p1) gui_label(ld, hole_score(i, 1), 0, 0, gui_red, gui_wht);
134                         if (p2) gui_label(ld, hole_score(i, 2), 0, 0, gui_grn, gui_wht);
135                         if (p3) gui_label(ld, hole_score(i, 3), 0, 0, gui_blu, gui_wht);
136                         if (p4) gui_label(ld, hole_score(i, 4), 0, 0, gui_yel, gui_wht);
137                     }
138             if ((kd = gui_varray(jd)))
139             {
140                 gui_filler(kd);
141                 if (p1) gui_label(kd, _("Par"), 0, GUI_NW,      gui_wht, gui_wht);
142                 if (p1) gui_label(kd, _("P1"),  0, GUI_SW * l1, gui_red, gui_wht);
143                 if (p2) gui_label(kd, _("P2"),  0, GUI_SW * l2, gui_grn, gui_wht);
144                 if (p3) gui_label(kd, _("P3"),  0, GUI_SW * l3, gui_blu, gui_wht);
145                 if (p4) gui_label(kd, _("P4"),  0, GUI_SW * l4, gui_yel, gui_wht);
146             }
147         }
148
149         gui_layout(id, 0, 0);
150     }
151
152     return id;
153 }
154
155 /*---------------------------------------------------------------------------*/
156
157 static void shared_stick(int id, int a, int v)
158 {
159     int jd = 0;
160
161     if (config_tst_d(CONFIG_JOYSTICK_AXIS_X, a))
162         jd = gui_stick(id, v, 0);
163     else if (config_tst_d(CONFIG_JOYSTICK_AXIS_Y, a))
164         jd = gui_stick(id, 0, v);
165
166     if (jd)
167         gui_pulse(jd, 1.2f);
168 }
169
170 /*---------------------------------------------------------------------------*/
171
172 #define TITLE_PLAY 1
173 #define TITLE_CONF 2
174 #define TITLE_EXIT 3
175
176 static int title_action(int i)
177 {
178     audio_play(AUD_MENU, 1.0f);
179
180     switch (i)
181     {
182     case TITLE_PLAY: return goto_state(&st_course);
183     case TITLE_CONF: return goto_state(&st_conf);
184     case TITLE_EXIT: return 0;
185     }
186     return 1;
187 }
188
189 static int title_enter(void)
190 {
191     int id, jd, kd;
192
193     /* Build the title GUI. */
194
195     if ((id = gui_vstack(0)))
196     {
197         gui_label(id, "Neverputt", GUI_LRG, GUI_ALL, 0, 0);
198         gui_space(id);
199
200         if ((jd = gui_harray(id)))
201         {
202             gui_filler(jd);
203
204             if ((kd = gui_varray(jd)))
205             {
206                 gui_start(kd, sgettext("menu^Play"),    GUI_MED, TITLE_PLAY, 1);
207                 gui_state(kd, sgettext("menu^Options"), GUI_MED, TITLE_CONF, 0);
208                 gui_state(kd, sgettext("menu^Exit"),    GUI_MED, TITLE_EXIT, 0);
209             }
210
211             gui_filler(jd);
212         }
213         gui_layout(id, 0, 0);
214     }
215
216     course_init();
217     course_rand();
218
219     return id;
220 }
221
222 static void title_leave(int id)
223 {
224     gui_delete(id);
225 }
226
227 static void title_paint(int id, float st)
228 {
229     game_draw(0);
230     gui_paint(id);
231 }
232
233 static void title_timer(int id, float dt)
234 {
235     float g[3] = { 0.f, 0.f, 0.f };
236
237     game_step(g, dt);
238     game_set_fly(fcosf(time_state() / 10.f));
239
240     gui_timer(id, dt);
241     audio_timer(dt);
242 }
243
244 static void title_point(int id, int x, int y, int dx, int dy)
245 {
246     gui_pulse(gui_point(id, x, y), 1.2f);
247 }
248
249 static int title_click(int b, int d)
250 {
251     return (d && b < 0) ? title_action(gui_token(gui_click())) : 1;
252 }
253
254 static int title_buttn(int b, int d)
255 {
256     if (d)
257     {
258         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
259             return title_action(gui_token(gui_click()));
260         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
261             return title_action(TITLE_EXIT);
262     }
263     return 1;
264 }
265
266 /*---------------------------------------------------------------------------*/
267
268 static int desc_id;
269 static int shot_id;
270
271 #define COURSE_BACK -1
272
273 static int course_action(int i)
274 {
275     if (course_exists(i))
276     {
277         course_goto(i);
278         goto_state(&st_party);
279     }
280     if (i == COURSE_BACK)
281         goto_state(&st_title);
282
283     return 1;
284 }
285
286 static int course_enter(void)
287 {
288     int w = config_get_d(CONFIG_WIDTH);
289     int h = config_get_d(CONFIG_HEIGHT);
290
291     int id, jd, kd, ld, md, i = 0, j, n = course_count();
292     int m = (int)(sqrt(n/2.0)*2);
293
294     if ((id = gui_vstack(0)))
295     {
296         gui_label(id, _("Select Course"), GUI_MED, GUI_ALL, 0, 0);
297         gui_space(id);
298
299         if ((jd = gui_hstack(id)))
300         {
301             shot_id = gui_image(jd, course_shot(0), w / 3, h / 3);
302
303             gui_filler(jd);
304
305             if ((kd = gui_varray(jd)))
306             {
307                 for(i = 0; i < n; i += m)
308                 {
309                     if ((ld = gui_harray(kd)))
310                     {
311                         for (j = (m - 1); j >= 0; j--)
312                         {
313                             if (i + j < n)
314                             {
315                                 md = gui_image(ld, course_shot(i + j),
316                                                w / 3 / m, h / 3 / m);
317                                 gui_active(md, i + j, 0);
318
319                                 if (i + j == 0)
320                                     gui_focus(md);
321                             }
322                             else
323                                 gui_space(ld);
324                         }
325                     }
326                 }
327             }
328         }
329
330         gui_space(id);
331         desc_id = gui_multi(id, _(course_desc(0)), GUI_SML, GUI_ALL, gui_yel, gui_wht);
332         gui_space(id);
333
334         if ((jd = gui_hstack(id)))
335         {
336             gui_filler(jd);
337             gui_state(jd, _("Back"), GUI_SML, COURSE_BACK, 0);
338         }
339
340         gui_layout(id, 0, 0);
341     }
342
343     audio_music_fade_to(0.5f, "bgm/inter.ogg");
344
345     return id;
346 }
347
348 static void course_leave(int id)
349 {
350     gui_delete(id);
351 }
352
353 static void course_paint(int id, float st)
354 {
355     game_draw(0);
356     gui_paint(id);
357 }
358
359 static void course_timer(int id, float dt)
360 {
361     gui_timer(id, dt);
362     audio_timer(dt);
363 }
364
365 static void course_point(int id, int x, int y, int dx, int dy)
366 {
367     int jd;
368
369     if ((jd = gui_point(id, x, y)))
370     {
371         int i = gui_token(jd);
372         if (course_exists(i))
373         {
374             gui_set_image(shot_id, course_shot(i));
375             gui_set_multi(desc_id, _(course_desc(i)));
376         }
377         gui_pulse(jd, 1.2f);
378     }
379 }
380
381 static int course_click(int b, int d)
382 {
383     return (d && b < 0) ? course_action(gui_token(gui_click())) : 1;
384 }
385
386 static int course_buttn(int b, int d)
387 {
388     if (d)
389     {
390         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
391             return course_action(gui_token(gui_click()));
392         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
393             return course_action(COURSE_BACK);
394     }
395     return 1;
396 }
397
398 /*---------------------------------------------------------------------------*/
399
400 #define PARTY_T 0
401 #define PARTY_1 1
402 #define PARTY_2 2
403 #define PARTY_3 3
404 #define PARTY_4 4
405 #define PARTY_B 5
406
407 static int party_action(int i)
408 {
409     switch (i)
410     {
411     case PARTY_1:
412         audio_play(AUD_MENU, 1.f);
413         hole_goto(1, 1);
414         goto_state(&st_next);
415         break;
416     case PARTY_2:
417         audio_play(AUD_MENU, 1.f);
418         hole_goto(1, 2);
419         goto_state(&st_next);
420         break;
421     case PARTY_3:
422         audio_play(AUD_MENU, 1.f);
423         hole_goto(1, 3);
424         goto_state(&st_next);
425         break;
426     case PARTY_4:
427         audio_play(AUD_MENU, 1.f);
428         hole_goto(1, 4);
429         goto_state(&st_next);
430         break;
431     case PARTY_B:
432         audio_play(AUD_MENU, 1.f);
433         goto_state(&st_course);
434         break;
435     }
436     return 1;
437 }
438
439 static int party_enter(void)
440 {
441     int id, jd;
442
443     if ((id = gui_vstack(0)))
444     {
445         gui_label(id, _("Players?"), GUI_MED, GUI_ALL, 0, 0);
446         gui_space(id);
447
448         if ((jd = gui_harray(id)))
449         {
450             int p4 = gui_state(jd, "4", GUI_LRG, PARTY_4, 0);
451             int p3 = gui_state(jd, "3", GUI_LRG, PARTY_3, 0);
452             int p2 = gui_state(jd, "2", GUI_LRG, PARTY_2, 0);
453             int p1 = gui_state(jd, "1", GUI_LRG, PARTY_1, 0);
454
455             gui_set_color(p1, gui_red, gui_wht);
456             gui_set_color(p2, gui_grn, gui_wht);
457             gui_set_color(p3, gui_blu, gui_wht);
458             gui_set_color(p4, gui_yel, gui_wht);
459
460             gui_focus(p1);
461         }
462
463         gui_space(id);
464
465         if ((jd = gui_hstack(id)))
466         {
467             gui_filler(jd);
468             gui_state(jd, _("Back"), GUI_SML, PARTY_B, 0);
469         }
470
471         gui_layout(id, 0, 0);
472     }
473
474     return id;
475 }
476
477 static void party_leave(int id)
478 {
479     gui_delete(id);
480 }
481
482 static void party_paint(int id, float st)
483 {
484     game_draw(0);
485     gui_paint(id);
486 }
487
488 static void party_timer(int id, float dt)
489 {
490     gui_timer(id, dt);
491     audio_timer(dt);
492 }
493
494 static void party_point(int id, int x, int y, int dx, int dy)
495 {
496     gui_pulse(gui_point(id, x, y), 1.2f);
497 }
498
499 static int party_click(int b, int d)
500 {
501     return (d && b < 0) ? party_action(gui_token(gui_click())) : 1;
502 }
503
504 static int party_buttn(int b, int d)
505 {
506     if (d)
507     {
508         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
509             return party_action(gui_token(gui_click()));
510         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
511             return party_action(PARTY_B);
512     }
513     return 1;
514 }
515
516 /*---------------------------------------------------------------------------*/
517
518 static int paused = 0;
519
520 static struct state *st_continue;
521 static struct state *st_quit;
522
523 #define PAUSE_CONTINUE 1
524 #define PAUSE_QUIT     2
525
526 int goto_pause(struct state *s, int e)
527 {
528     if (e && (SDL_GetModState() & (KMOD_SHIFT | KMOD_CTRL | KMOD_ALT | KMOD_META)))
529         return goto_state(s);
530     st_continue = curr_state();
531     st_quit = s;
532     paused = 1;
533     return goto_state(&st_pause);
534 }
535
536 static int pause_action(int i)
537 {
538     audio_play(AUD_MENU, 1.0f);
539
540     switch(i)
541     {
542     case PAUSE_CONTINUE:
543         return goto_state(st_continue ? st_continue : &st_title);
544
545     case PAUSE_QUIT:
546         return goto_state(st_quit);
547     }
548     return 1;
549 }
550
551 static int pause_enter(void)
552 {
553     int id, jd, td;
554
555     audio_music_fade_out(0.2f);
556
557     if ((id = gui_vstack(0)))
558     {
559         td = gui_label(id, _("Paused"), GUI_LRG, GUI_ALL, 0, 0);
560         gui_space(id);
561
562         if ((jd = gui_harray(id)))
563         {
564             gui_state(jd, _("Quit"), GUI_SML, PAUSE_QUIT, 0);
565             gui_start(jd, _("Continue"), GUI_SML, PAUSE_CONTINUE, 1);
566         }
567
568         gui_pulse(td, 1.2f);
569         gui_layout(id, 0, 0);
570     }
571
572     hud_init();
573     return id;
574 }
575
576 static void pause_leave(int id)
577 {
578     gui_delete(id);
579     hud_free();
580     audio_music_fade_in(0.5f);
581 }
582
583 static void pause_paint(int id, float st)
584 {
585     game_draw(0);
586     gui_paint(id);
587     hud_paint();
588 }
589
590 static void pause_timer(int id, float dt)
591 {
592     gui_timer(id, dt);
593     audio_timer(dt);
594 }
595
596 static void pause_point(int id, int x, int y, int dx, int dy)
597 {
598     gui_pulse(gui_point(id, x, y), 1.2f);
599 }
600
601 static int pause_click(int b, int d)
602 {
603     return (d && b < 0) ? pause_action(gui_token(gui_click())) : 1;
604 }
605
606 static int pause_keybd(int c, int d)
607 {
608     if (d && config_tst_d(CONFIG_KEY_PAUSE, c))
609         return pause_action(PAUSE_CONTINUE);
610     return 1;
611 }
612
613 static int pause_buttn(int b, int d)
614 {
615     if (d)
616     {
617         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
618             return pause_action(gui_token(gui_click()));
619         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
620             return pause_action(PAUSE_CONTINUE);
621     }
622     return 1;
623 }
624
625 /*---------------------------------------------------------------------------*/
626
627 static int shared_keybd(int c, int d)
628 {
629     if (d)
630     {
631         if (c == SDLK_ESCAPE)
632             return goto_pause(&st_over, 1);
633         if (config_tst_d(CONFIG_KEY_PAUSE, c))
634             return goto_pause(&st_over, 0);
635     }
636     return 1;
637 }
638
639 /*---------------------------------------------------------------------------*/
640
641 static int num = 0;
642
643 static int next_enter(void)
644 {
645     int id;
646     char str[MAXSTR];
647
648     sprintf(str, _("Hole %02d"), curr_hole());
649
650     if ((id = gui_vstack(0)))
651     {
652         gui_label(id, str, GUI_MED, GUI_ALL, 0, 0);
653         gui_space(id);
654
655         gui_label(id, _("Player"), GUI_SML, GUI_TOP, 0, 0);
656
657         switch (curr_player())
658         {
659         case 1:
660             gui_label(id, "1", GUI_LRG, GUI_BOT, gui_red, gui_wht);
661             if (curr_party() > 1) audio_play(AUD_PLAYER1, 1.f);
662             break;
663         case 2:
664             gui_label(id, "2", GUI_LRG, GUI_BOT, gui_grn, gui_wht);
665             if (curr_party() > 1) audio_play(AUD_PLAYER2, 1.f);
666             break;
667         case 3:
668             gui_label(id, "3", GUI_LRG, GUI_BOT, gui_blu, gui_wht);
669             if (curr_party() > 1) audio_play(AUD_PLAYER3, 1.f);
670             break;
671         case 4:
672             gui_label(id, "4", GUI_LRG, GUI_BOT, gui_yel, gui_wht);
673             if (curr_party() > 1) audio_play(AUD_PLAYER4, 1.f);
674             break;
675         }
676         gui_layout(id, 0, 0);
677     }
678
679     hud_init();
680     game_set_fly(1.f);
681
682     if (paused)
683         paused = 0;
684
685     return id;
686 }
687
688 static void next_leave(int id)
689 {
690     hud_free();
691     gui_delete(id);
692 }
693
694 static void next_paint(int id, float st)
695 {
696     game_draw(0);
697     hud_paint();
698     gui_paint(id);
699 }
700
701 static void next_timer(int id, float dt)
702 {
703     gui_timer(id, dt);
704     audio_timer(dt);
705 }
706
707 static void next_point(int id, int x, int y, int dx, int dy)
708 {
709     gui_pulse(gui_point(id, x, y), 1.2f);
710 }
711
712 static int next_click(int b, int d)
713 {
714     return (d && b < 0) ? goto_state(&st_flyby) : 1;
715 }
716
717 static int next_keybd(int c, int d)
718 {
719     if (d)
720     {
721         if (c == SDLK_F12)
722             return goto_state(&st_poser);
723         if (config_tst_d(CONFIG_KEY_PAUSE, c))
724             return goto_pause(&st_over, 0);
725         if (c == SDLK_c)
726         {
727             hole_goto(num, -1);
728             num = 0;
729             return goto_state(&st_next);
730         }
731         if ('0' <= c && c <= '9')
732             num = num * 10 + c - '0';
733     }
734     return 1;
735 }
736
737 static int next_buttn(int b, int d)
738 {
739     if (d)
740     {
741         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
742             return goto_state(&st_flyby);
743         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
744             return goto_pause(&st_over, 1);
745     }
746     return 1;
747 }
748
749 /*---------------------------------------------------------------------------*/
750
751 static int poser_enter(void)
752 {
753     game_set_fly(-1.f);
754     return 0;
755 }
756
757 static void poser_paint(int id, float st)
758 {
759     game_draw(1);
760 }
761
762 static int poser_buttn(int b, int d)
763 {
764     if (d)
765     {
766         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
767             return goto_state(&st_next);
768         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
769             return goto_state(&st_next);
770     }
771     return 1;
772 }
773
774 /*---------------------------------------------------------------------------*/
775
776 static int flyby_enter(void)
777 {
778     if (paused)
779         paused = 0;
780     else
781         hud_init();
782
783     return 0;
784 }
785
786 static void flyby_leave(int id)
787 {
788     hud_free();
789 }
790
791 static void flyby_paint(int id, float st)
792 {
793     game_draw(0);
794     hud_paint();
795 }
796
797 static void flyby_timer(int id, float dt)
798 {
799     float t = time_state();
800
801     if (dt > 0.f && t > 1.f)
802         goto_state(&st_stroke);
803     else
804         game_set_fly(1.f - t);
805
806     gui_timer(id, dt);
807     audio_timer(dt);
808 }
809
810 static int flyby_click(int b, int d)
811 {
812     if (d && b < 0)
813     {
814         game_set_fly(0.f);
815         return goto_state(&st_stroke);
816     }
817     return 1;
818 }
819
820 static int flyby_buttn(int b, int d)
821 {
822     if (d)
823     {
824         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
825         {
826             game_set_fly(0.f);
827             return goto_state(&st_stroke);
828         }
829         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
830             return goto_pause(&st_over, 1);
831     }
832     return 1;
833 }
834
835 /*---------------------------------------------------------------------------*/
836
837 static int stroke_rotate = 0;
838 static int stroke_mag    = 0;
839
840 static int stroke_enter(void)
841 {
842     hud_init();
843     game_clr_mag();
844     config_set_d(CONFIG_CAMERA, 2);
845     config_set_grab(!paused);
846
847     if (paused)
848         paused = 0;
849
850     return 0;
851 }
852
853 static void stroke_leave(int id)
854 {
855     hud_free();
856     config_clr_grab();
857     config_set_d(CONFIG_CAMERA, 0);
858 }
859
860 static void stroke_paint(int id, float st)
861 {
862     game_draw(0);
863     hud_paint();
864 }
865
866 static void stroke_timer(int id, float dt)
867 {
868     float g[3] = { 0.f, 0.f, 0.f };
869
870     float k;
871
872     if (SDL_GetModState() & (KMOD_SHIFT | KMOD_CTRL | KMOD_ALT | KMOD_META) ||
873         joystick &&
874         SDL_JoystickGetButton(joystick, config_get_d(CONFIG_JOYSTICK_BUTTON_B)))
875         k = 0.25;
876     else
877         k = 1.0;
878
879     game_set_rot(stroke_rotate * k);
880     game_set_mag(stroke_mag * k);
881
882     game_update_view(dt);
883     game_step(g, dt);
884     audio_timer(dt);
885 }
886
887 static void stroke_point(int id, int x, int y, int dx, int dy)
888 {
889     game_set_rot(dx);
890     game_set_mag(dy);
891 }
892
893 static void stroke_stick(int id, int a, int v)
894 {
895     if (v == 1) /* See 'loop' in main.c */
896         v = 0;
897
898     if (config_tst_d(CONFIG_JOYSTICK_AXIS_X, a))
899         stroke_rotate = (6 * v) / JOY_MAX;
900     else if (config_tst_d(CONFIG_JOYSTICK_AXIS_Y, a))
901         stroke_mag = -((6 * v) / JOY_MAX);
902 }
903
904 static int stroke_click(int b, int d)
905 {
906     return (d && b < 0) ? goto_state(&st_roll) : 1;
907 }
908
909 static int stroke_buttn(int b, int d)
910 {
911     if (d)
912     {
913         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
914             return goto_state(&st_roll);
915         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
916             return goto_pause(&st_over, 1);
917     }
918     return 1;
919 }
920
921 /*---------------------------------------------------------------------------*/
922
923 static int roll_enter(void)
924 {
925     hud_init();
926
927     if (paused)
928         paused = 0;
929     else
930         game_putt();
931
932     return 0;
933 }
934
935 static void roll_leave(int id)
936 {
937     hud_free();
938 }
939
940 static void roll_paint(int id, float st)
941 {
942     game_draw(0);
943     hud_paint();
944 }
945
946 static void roll_timer(int id, float dt)
947 {
948     float g[3] = { 0.0f, -9.8f, 0.0f };
949
950     switch (game_step(g, dt))
951     {
952     case GAME_STOP: goto_state(&st_stop); break;
953     case GAME_GOAL: goto_state(&st_goal); break;
954     case GAME_FALL: goto_state(&st_fall); break;
955     }
956     audio_timer(dt);
957 }
958
959 static int roll_buttn(int b, int d)
960 {
961     if (d)
962     {
963         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
964             return goto_pause(&st_over, 1);
965     }
966     return 1;
967 }
968
969 /*---------------------------------------------------------------------------*/
970
971 static int goal_enter(void)
972 {
973     int id;
974
975     if ((id = gui_label(0, _("It's In!"), GUI_MED, GUI_ALL, gui_grn, gui_grn)))
976         gui_layout(id, 0, 0);
977
978     if (paused)
979         paused = 0;
980     else
981         hole_goal();
982
983     hud_init();
984
985     return id;
986 }
987
988 static void goal_leave(int id)
989 {
990     gui_delete(id);
991     hud_free();
992 }
993
994 static void goal_paint(int id, float st)
995 {
996     game_draw(0);
997     gui_paint(id);
998     hud_paint();
999 }
1000
1001 static void goal_timer(int id, float dt)
1002 {
1003     if (time_state() > 3)
1004     {
1005         if (hole_next())
1006             goto_state(&st_next);
1007         else
1008             goto_state(&st_score);
1009     }
1010     audio_timer(dt);
1011 }
1012
1013 static int goal_click(int b, int d)
1014 {
1015     if (b < 0 && d == 1)
1016     {
1017         if (hole_next())
1018             goto_state(&st_next);
1019         else
1020             goto_state(&st_score);
1021     }
1022     return 1;
1023 }
1024
1025 static int goal_buttn(int b, int d)
1026 {
1027     if (d)
1028     {
1029         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
1030         {
1031             if (hole_next())
1032                 goto_state(&st_next);
1033             else
1034                 goto_state(&st_score);
1035         }
1036         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
1037             return goto_pause(&st_over, 1);
1038     }
1039     return 1;
1040 }
1041
1042 /*---------------------------------------------------------------------------*/
1043
1044 static int stop_enter(void)
1045 {
1046     if (paused)
1047         paused = 0;
1048     else
1049         hole_stop();
1050
1051     hud_init();
1052
1053     return 0;
1054 }
1055
1056 static void stop_leave(int id)
1057 {
1058     hud_free();
1059 }
1060
1061 static void stop_paint(int id, float st)
1062 {
1063     game_draw(0);
1064     hud_paint();
1065 }
1066
1067 static void stop_timer(int id, float dt)
1068 {
1069     float g[3] = { 0.f, 0.f, 0.f };
1070
1071     game_update_view(dt);
1072     game_step(g, dt);
1073     audio_timer(dt);
1074
1075     if (time_state() > 1)
1076     {
1077         if (hole_next())
1078             goto_state(&st_next);
1079         else
1080             goto_state(&st_score);
1081     }
1082 }
1083
1084 static int stop_click(int b, int d)
1085 {
1086     if (b < 0 && d == 1)
1087     {
1088         if (hole_next())
1089             goto_state(&st_next);
1090         else
1091             goto_state(&st_score);
1092     }
1093     return 1;
1094 }
1095
1096 static int stop_buttn(int b, int d)
1097 {
1098     if (d)
1099     {
1100         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
1101         {
1102             if (hole_next())
1103                 goto_state(&st_next);
1104             else
1105                 goto_state(&st_score);
1106         }
1107         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
1108             return goto_pause(&st_over, 1);
1109     }
1110     return 1;
1111 }
1112
1113 /*---------------------------------------------------------------------------*/
1114
1115 static int fall_enter(void)
1116 {
1117     int id;
1118
1119     if ((id = gui_label(0, _("1 Stroke Penalty"), GUI_MED, GUI_ALL, gui_blk, gui_red)))
1120         gui_layout(id, 0, 0);
1121
1122     if (paused)
1123         paused = 0;
1124     else
1125     {
1126         hole_fall();
1127         game_draw(0); /*TODO: is this call ok? */
1128     }
1129
1130     hud_init();
1131
1132     return id;
1133 }
1134
1135 static void fall_leave(int id)
1136 {
1137     gui_delete(id);
1138     hud_free();
1139 }
1140
1141 static void fall_paint(int id, float st)
1142 {
1143     game_draw(0);
1144     gui_paint(id);
1145     hud_paint();
1146 }
1147
1148 static void fall_timer(int id, float dt)
1149 {
1150     if (time_state() > 3)
1151     {
1152         if (hole_next())
1153             goto_state(&st_next);
1154         else
1155             goto_state(&st_score);
1156     }
1157     audio_timer(dt);
1158 }
1159
1160 static int fall_click(int b, int d)
1161 {
1162     if (b < 0 && d == 1)
1163     {
1164         if (hole_next())
1165             goto_state(&st_next);
1166         else
1167             goto_state(&st_score);
1168     }
1169     return 1;
1170 }
1171
1172 static int fall_buttn(int b, int d)
1173 {
1174     if (d)
1175     {
1176         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
1177         {
1178             if (hole_next())
1179                 goto_state(&st_next);
1180             else
1181                 goto_state(&st_score);
1182         }
1183         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
1184             return goto_pause(&st_over, 1);
1185     }
1186     return 1;
1187 }
1188
1189 /*---------------------------------------------------------------------------*/
1190
1191 static int score_enter(void)
1192 {
1193     audio_music_fade_out(2.f);
1194
1195     if (paused)
1196         paused = 0;
1197
1198     return score_card(_("Scores"), gui_yel, gui_red);
1199 }
1200
1201 static void score_leave(int id)
1202 {
1203     gui_delete(id);
1204 }
1205
1206 static void score_paint(int id, float st)
1207 {
1208     game_draw(0);
1209     gui_paint(id);
1210 }
1211
1212 static void score_timer(int id, float dt)
1213 {
1214     gui_timer(id, dt);
1215     audio_timer(dt);
1216 }
1217
1218 static int score_click(int b, int d)
1219 {
1220     if (b < 0 && d == 1)
1221     {
1222         if (hole_move())
1223             return goto_state(&st_next);
1224         else
1225             return goto_state(&st_title);
1226     }
1227     return 1;
1228 }
1229
1230 static int score_buttn(int b, int d)
1231 {
1232     if (d)
1233     {
1234         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
1235         {
1236             if (hole_move())
1237                 goto_state(&st_next);
1238             else
1239                 goto_state(&st_score);
1240         }
1241         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
1242             return goto_pause(&st_over, 1);
1243     }
1244     return 1;
1245 }
1246
1247 /*---------------------------------------------------------------------------*/
1248
1249 static int over_enter(void)
1250 {
1251     audio_music_fade_out(2.f);
1252     return score_card(_("Final Scores"), gui_yel, gui_red);
1253 }
1254
1255 static void over_leave(int id)
1256 {
1257     gui_delete(id);
1258 }
1259
1260 static void over_paint(int id, float st)
1261 {
1262     game_draw(0);
1263     gui_paint(id);
1264 }
1265
1266 static void over_timer(int id, float dt)
1267 {
1268     gui_timer(id, dt);
1269     audio_timer(dt);
1270 }
1271
1272 static int over_click(int b, int d)
1273 {
1274     return (d && b < 0) ? goto_state(&st_title) : 1;
1275 }
1276
1277 static int over_buttn(int b, int d)
1278 {
1279     if (d)
1280     {
1281         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
1282             return goto_state(&st_title);
1283         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
1284             return goto_state(&st_title);
1285     }
1286     return 1;
1287 }
1288
1289 /*---------------------------------------------------------------------------*/
1290
1291 struct state st_title = {
1292     title_enter,
1293     title_leave,
1294     title_paint,
1295     title_timer,
1296     title_point,
1297     shared_stick,
1298     title_click,
1299     NULL,
1300     title_buttn,
1301     1, 0
1302 };
1303
1304 struct state st_course = {
1305     course_enter,
1306     course_leave,
1307     course_paint,
1308     course_timer,
1309     course_point,
1310     shared_stick,
1311     course_click,
1312     NULL,
1313     course_buttn,
1314     1, 0
1315 };
1316
1317 struct state st_party = {
1318     party_enter,
1319     party_leave,
1320     party_paint,
1321     party_timer,
1322     party_point,
1323     shared_stick,
1324     party_click,
1325     NULL,
1326     party_buttn,
1327     1, 0
1328 };
1329
1330 struct state st_next = {
1331     next_enter,
1332     next_leave,
1333     next_paint,
1334     next_timer,
1335     next_point,
1336     shared_stick,
1337     next_click,
1338     next_keybd,
1339     next_buttn,
1340     1, 0
1341 };
1342
1343 struct state st_poser = {
1344     poser_enter,
1345     NULL,
1346     poser_paint,
1347     NULL,
1348     NULL,
1349     NULL,
1350     NULL,
1351     NULL,
1352     poser_buttn,
1353     1, 0
1354 };
1355
1356 struct state st_flyby = {
1357     flyby_enter,
1358     flyby_leave,
1359     flyby_paint,
1360     flyby_timer,
1361     NULL,
1362     NULL,
1363     flyby_click,
1364     shared_keybd,
1365     flyby_buttn,
1366     1, 0
1367 };
1368
1369 struct state st_stroke = {
1370     stroke_enter,
1371     stroke_leave,
1372     stroke_paint,
1373     stroke_timer,
1374     stroke_point,
1375     stroke_stick,
1376     stroke_click,
1377     shared_keybd,
1378     stroke_buttn,
1379     0, 0
1380 };
1381
1382 struct state st_roll = {
1383     roll_enter,
1384     roll_leave,
1385     roll_paint,
1386     roll_timer,
1387     NULL,
1388     NULL,
1389     NULL,
1390     shared_keybd,
1391     roll_buttn,
1392     0, 0
1393 };
1394
1395 struct state st_goal = {
1396     goal_enter,
1397     goal_leave,
1398     goal_paint,
1399     goal_timer,
1400     NULL,
1401     NULL,
1402     goal_click,
1403     shared_keybd,
1404     goal_buttn,
1405     0, 0
1406 };
1407
1408 struct state st_stop = {
1409     stop_enter,
1410     stop_leave,
1411     stop_paint,
1412     stop_timer,
1413     NULL,
1414     NULL,
1415     stop_click,
1416     shared_keybd,
1417     stop_buttn,
1418     0, 0
1419 };
1420
1421 struct state st_fall = {
1422     fall_enter,
1423     fall_leave,
1424     fall_paint,
1425     fall_timer,
1426     NULL,
1427     NULL,
1428     fall_click,
1429     shared_keybd,
1430     fall_buttn,
1431     0, 0
1432 };
1433
1434 struct state st_score = {
1435     score_enter,
1436     score_leave,
1437     score_paint,
1438     score_timer,
1439     NULL,
1440     NULL,
1441     score_click,
1442     shared_keybd,
1443     score_buttn,
1444     0, 0
1445 };
1446
1447 struct state st_over = {
1448     over_enter,
1449     over_leave,
1450     over_paint,
1451     over_timer,
1452     NULL,
1453     NULL,
1454     over_click,
1455     NULL,
1456     over_buttn,
1457     1, 0
1458 };
1459
1460 struct state st_pause = {
1461     pause_enter,
1462     pause_leave,
1463     pause_paint,
1464     pause_timer,
1465     pause_point,
1466     shared_stick,
1467     pause_click,
1468     pause_keybd,
1469     pause_buttn,
1470     1, 0
1471 };