revisited menus
This commit is contained in:
parent
6cac793550
commit
d3bea2f52b
15 changed files with 222 additions and 289 deletions
|
@ -265,6 +265,5 @@ void credits_loop(void) {
|
|||
SDL_GL_SwapBuffers();
|
||||
frame_rate(&global.lasttime);
|
||||
}
|
||||
global.whitefade = 1.0;
|
||||
credits_free();
|
||||
}
|
||||
|
|
|
@ -121,8 +121,6 @@ typedef struct {
|
|||
|
||||
RandomState rand_game;
|
||||
RandomState rand_visual;
|
||||
|
||||
float whitefade; // hack for credits --> main transition
|
||||
} Global;
|
||||
|
||||
extern Global global;
|
||||
|
|
|
@ -17,13 +17,6 @@ void set_shotmode(void *p) {
|
|||
global.plr.shot = (ShotMode) p;
|
||||
}
|
||||
|
||||
void create_char_menu(MenuData *m) {
|
||||
create_menu(m);
|
||||
|
||||
add_menu_entry(m, "dialog/marisa|Kirisame Marisa|Black Magician", set_player, (void *)Marisa);
|
||||
add_menu_entry(m, "dialog/youmu|Konpaku Youmu|Half Ghost Girl", set_player, (void *)Youmu);
|
||||
}
|
||||
|
||||
void create_shottype_menu(MenuData *m) {
|
||||
create_menu(m);
|
||||
|
||||
|
@ -31,9 +24,21 @@ void create_shottype_menu(MenuData *m) {
|
|||
add_menu_entry(m, "Star Sign|Haunting Sign", set_shotmode, (void *) YoumuHoming);
|
||||
}
|
||||
|
||||
void draw_char_menu(MenuData *menu, MenuData *mod) {
|
||||
void create_char_menu(MenuData *m) {
|
||||
create_menu(m);
|
||||
|
||||
m->context = malloc(sizeof(MenuData));
|
||||
create_shottype_menu(m->context);
|
||||
|
||||
add_menu_entry(m, "dialog/marisa|Kirisame Marisa|Black Magician", set_player, (void *)Marisa);
|
||||
add_menu_entry(m, "dialog/youmu|Konpaku Youmu|Half Ghost Girl", set_player, (void *)Youmu);
|
||||
}
|
||||
|
||||
void draw_char_menu(MenuData *menu) {
|
||||
MenuData *mod = ((MenuData *)menu->context);
|
||||
|
||||
draw_options_menu_bg(menu);
|
||||
draw_text(AL_Right, 220*(1-menu->fade), 30, "Player Select", _fonts.mainmenu);
|
||||
draw_text(AL_Right, 220*(1-menu_fade(menu)), 30, "Player Select", _fonts.mainmenu);
|
||||
|
||||
glPushMatrix();
|
||||
glColor4f(0,0,0,0.7);
|
||||
|
@ -115,13 +120,13 @@ void draw_char_menu(MenuData *menu, MenuData *mod) {
|
|||
}
|
||||
|
||||
glColor3f(1,1,1);
|
||||
|
||||
fade_out(menu->fade);
|
||||
}
|
||||
|
||||
void char_menu_input(MenuData *menu, MenuData *mod) {
|
||||
void char_menu_input(MenuData *menu) {
|
||||
SDL_Event event;
|
||||
|
||||
MenuData *mod = menu->context;
|
||||
|
||||
while(SDL_PollEvent(&event)) {
|
||||
int sym = event.key.keysym.sym;
|
||||
Uint8 *keys = SDL_GetKeyState(NULL);
|
||||
|
@ -137,40 +142,24 @@ void char_menu_input(MenuData *menu, MenuData *mod) {
|
|||
} else if(sym == tconfig.intval[KEY_UP] || sym == SDLK_UP) {
|
||||
mod->cursor--;
|
||||
} else if((sym == tconfig.intval[KEY_SHOT] || (sym == SDLK_RETURN && !keys[SDLK_LALT] && !keys[SDLK_RALT])) && menu->entries[menu->cursor].action) {
|
||||
menu->quit = 1;
|
||||
close_menu(menu);
|
||||
menu->selected = menu->cursor;
|
||||
mod->quit = 1;
|
||||
close_menu(mod);
|
||||
mod->selected = mod->cursor;
|
||||
mod->fade = 1;
|
||||
} else if(sym == SDLK_ESCAPE && menu->type == MT_Transient) {
|
||||
menu->quit = 1;
|
||||
} else if(sym == SDLK_ESCAPE) {
|
||||
close_menu(menu);
|
||||
}
|
||||
|
||||
menu->cursor = (menu->cursor % menu->ecount) + menu->ecount*(menu->cursor < 0);
|
||||
mod->cursor = (mod->cursor % mod->ecount) + mod->ecount*(mod->cursor < 0);
|
||||
} else if(event.type == SDL_QUIT) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int char_menu_loop(MenuData *menu) {
|
||||
set_ortho();
|
||||
|
||||
MenuData mod;
|
||||
create_shottype_menu(&mod);
|
||||
|
||||
while(menu->quit != 2) {
|
||||
menu_logic(menu);
|
||||
menu_logic(&mod);
|
||||
char_menu_input(menu, &mod);
|
||||
|
||||
draw_char_menu(menu, &mod);
|
||||
SDL_GL_SwapBuffers();
|
||||
frame_rate(&menu->lasttime);
|
||||
}
|
||||
destroy_menu(menu);
|
||||
|
||||
|
||||
return menu->selected;
|
||||
void free_char_menu(MenuData *menu) {
|
||||
free(menu->context);
|
||||
}
|
||||
|
||||
int char_menu_loop(MenuData *menu) {
|
||||
return menu_loop(menu, char_menu_input, draw_char_menu, free_char_menu);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ void set_difficulty(void *d) {
|
|||
void create_difficulty_menu(MenuData *m) {
|
||||
create_menu(m);
|
||||
|
||||
m->flags = MF_Transient | MF_Abortable;
|
||||
|
||||
add_menu_entry(m, "Easy\nfor fearful fairies", set_difficulty, (void *)D_Easy);
|
||||
add_menu_entry(m, "Normal\nfor confident kappa", set_difficulty, (void *)D_Normal);
|
||||
add_menu_entry(m, "Hard\nfor omnipotent oni", set_difficulty, (void *)D_Hard);
|
||||
|
@ -25,7 +27,7 @@ void create_difficulty_menu(MenuData *m) {
|
|||
|
||||
void draw_difficulty_menu(MenuData *menu) {
|
||||
draw_options_menu_bg(menu);
|
||||
draw_text(AL_Right, 210*(1-menu->fade), 30, "Rank Select", _fonts.mainmenu);
|
||||
draw_text(AL_Right, 210*(1-menu_fade(menu)), 30, "Rank Select", _fonts.mainmenu);
|
||||
|
||||
int i;
|
||||
for(i = 0; i < menu->ecount; i++) {
|
||||
|
@ -50,10 +52,8 @@ void draw_difficulty_menu(MenuData *menu) {
|
|||
glColor3f(1,1,1);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
fade_out(menu->fade);
|
||||
}
|
||||
|
||||
int difficulty_menu_loop(MenuData *menu) {
|
||||
return menu_loop(menu, NULL, draw_difficulty_menu);
|
||||
return menu_loop(menu, NULL, draw_difficulty_menu, NULL);
|
||||
}
|
||||
|
|
|
@ -33,8 +33,6 @@ void give_up(void *arg) {
|
|||
MenuData *create_gameover_menu(void) {
|
||||
MenuData *m = malloc(sizeof(MenuData));
|
||||
create_menu(m);
|
||||
m->abortable = -1;
|
||||
m->title = "Game over!";
|
||||
|
||||
char s[64];
|
||||
int c = MAX_CONTINUES - global.plr.continues;
|
||||
|
|
|
@ -18,7 +18,9 @@ void return_to_title(void *arg) {
|
|||
|
||||
MenuData *create_ingame_menu(void) {
|
||||
MenuData *m = malloc(sizeof(MenuData));
|
||||
|
||||
create_menu(m);
|
||||
m->flags = MF_Abortable | MF_Transient;
|
||||
add_menu_entry(m, "Return to Game", return_to_game, NULL);
|
||||
add_menu_entry(m, "Return to Title", return_to_title, NULL);
|
||||
|
||||
|
@ -28,7 +30,7 @@ MenuData *create_ingame_menu(void) {
|
|||
void ingame_menu_logic(MenuData **menu) {
|
||||
menu_logic(*menu);
|
||||
|
||||
if((*menu)->quit == 2 && (*menu)->selected != 1) { // let the stage clean up when returning to title
|
||||
if((*menu)->state == MS_FadeOut && (*menu)->selected != 1) { // let the stage clean up when returning to title
|
||||
destroy_menu(*menu);
|
||||
free(*menu);
|
||||
*menu = NULL;
|
||||
|
@ -36,11 +38,8 @@ void ingame_menu_logic(MenuData **menu) {
|
|||
}
|
||||
|
||||
void draw_ingame_menu(MenuData *menu) {
|
||||
float rad = IMENU_BLUR;
|
||||
float fade = menu->fade;
|
||||
float rad = (1.0-menu_fade(menu))*IMENU_BLUR;
|
||||
|
||||
if(menu->selected != 1) // hardly hardcoded. 1 -> "Return to Title"
|
||||
rad = IMENU_BLUR * (1.0-fade);
|
||||
|
||||
if(!tconfig.intval[NO_SHADER]) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
@ -54,25 +53,18 @@ void draw_ingame_menu(MenuData *menu) {
|
|||
|
||||
glPushMatrix();
|
||||
glTranslatef(VIEWPORT_W/2, VIEWPORT_H/4, 0);
|
||||
|
||||
glColor4f(0.6,0.6,0.8,0.23*rad/IMENU_BLUR);
|
||||
glPushMatrix();
|
||||
glTranslatef(0, menu->drawdata[0], 0);
|
||||
glScalef(menu->drawdata[1]/45.0,0.25,1);
|
||||
glRotatef(menu->frames*2,0,0,1);
|
||||
draw_texture(0,0,"part/smoke");
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
draw_menu_selector(0, menu->drawdata[0], menu->drawdata[1]/45.0, 0.25, menu->frames);
|
||||
|
||||
// cirno's perfect math class #2: Euler Sign ~ Differential Fun
|
||||
menu->drawdata[0] += (menu->cursor*35 - menu->drawdata[0])/7.0;
|
||||
menu->drawdata[1] += (strlen(menu->entries[menu->cursor].name)*5 - menu->drawdata[1])/10.0;
|
||||
|
||||
if(menu->title) {
|
||||
float s = 0.3 + 0.2 * sin(menu->frames/10.0);
|
||||
glColor4f(1-s/2, 1-s/2, 1-s, 1.0 - menu->fade);
|
||||
draw_text(AL_Center, 0, -2 * 35, menu->title, _fonts.standard);
|
||||
}
|
||||
// if(menu->title) {
|
||||
// float s = 0.3 + 0.2 * sin(menu->frames/10.0);
|
||||
// glColor4f(1-s/2, 1-s/2, 1-s, 1-menu_fade(menu));
|
||||
// draw_text(AL_Center, 0, -2 * 35, menu->title, _fonts.standard);
|
||||
// }
|
||||
|
||||
int i;
|
||||
for(i = 0; i < menu->ecount; i++) {
|
||||
|
@ -83,7 +75,7 @@ void draw_ingame_menu(MenuData *menu) {
|
|||
s = 0.3 + 0.2*sin(menu->frames/7.0);
|
||||
}
|
||||
|
||||
glColor4f(t-s,t-s,t-s/2, 1.0 - menu->fade);
|
||||
glColor4f(t-s,t-s,t-s/2, 1-menu_fade(menu));
|
||||
} else
|
||||
glColor4f(0.5, 0.5, 0.5, 0.5);
|
||||
|
||||
|
|
|
@ -21,11 +21,6 @@
|
|||
#include "credits.h"
|
||||
#include "paths/native.h"
|
||||
|
||||
void quit_menu(void *arg) {
|
||||
MenuData *m = arg;
|
||||
m->quit = 2;
|
||||
}
|
||||
|
||||
void start_story(void *arg) {
|
||||
MenuData m;
|
||||
|
||||
|
@ -97,9 +92,7 @@ void enter_replayview(void *arg) {
|
|||
|
||||
void create_main_menu(MenuData *m) {
|
||||
create_menu(m);
|
||||
|
||||
m->type = MT_Persistent;
|
||||
|
||||
|
||||
add_menu_entry(m, "Start Story", start_story, NULL);
|
||||
add_menu_entry(m, "Start Extra", NULL, NULL);
|
||||
#ifdef DEBUG
|
||||
|
@ -107,7 +100,7 @@ void create_main_menu(MenuData *m) {
|
|||
#endif
|
||||
add_menu_entry(m, "Replays", enter_replayview, NULL);
|
||||
add_menu_entry(m, "Options", enter_options, NULL);
|
||||
add_menu_entry(m, "Quit", quit_menu, m);
|
||||
add_menu_entry(m, "Quit", (MenuAction)kill_menu, m);
|
||||
}
|
||||
|
||||
|
||||
|
@ -159,15 +152,8 @@ void draw_main_menu(MenuData *menu) {
|
|||
}
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
|
||||
fade_out(menu->fade);
|
||||
if(global.whitefade > 0) {
|
||||
colorfill(1, 1, 1, global.whitefade);
|
||||
global.whitefade -= 1 / 300.0;
|
||||
} else global.whitefade = 0;
|
||||
}
|
||||
|
||||
void main_menu_loop(MenuData *menu) {
|
||||
menu_loop(menu, NULL, draw_main_menu);
|
||||
menu_loop(menu, NULL, draw_main_menu, NULL);
|
||||
}
|
||||
|
|
110
src/menu/menu.c
110
src/menu/menu.c
|
@ -26,16 +26,11 @@ void add_menu_separator(MenuData *menu) {
|
|||
|
||||
void destroy_menu(MenuData *menu) {
|
||||
int i;
|
||||
|
||||
if(menu->ondestroy)
|
||||
menu->ondestroy(menu);
|
||||
|
||||
|
||||
for(i = 0; i < menu->ecount; i++) {
|
||||
MenuEntry *e = &(menu->entries[i]);
|
||||
|
||||
free(e->name);
|
||||
if(e->freearg)
|
||||
e->freearg(e->arg);
|
||||
}
|
||||
|
||||
free(menu->entries);
|
||||
|
@ -44,33 +39,48 @@ void destroy_menu(MenuData *menu) {
|
|||
void create_menu(MenuData *menu) {
|
||||
memset(menu, 0, sizeof(MenuData));
|
||||
|
||||
menu->fade = 1;
|
||||
menu->selected = -1;
|
||||
menu->quitdelay = FADE_TIME;
|
||||
}
|
||||
|
||||
void close_menu(MenuData *menu) {
|
||||
menu->quitframe = menu->frames;
|
||||
}
|
||||
|
||||
void kill_menu(MenuData *menu) {
|
||||
menu->state = MS_Dead;
|
||||
}
|
||||
|
||||
float menu_fade(MenuData *menu) {
|
||||
if(menu->frames < menu->quitdelay)
|
||||
return 1.0 - menu->frames/(float)menu->quitdelay;
|
||||
|
||||
if(menu->quitframe && menu->frames >= menu->quitframe)
|
||||
return (menu->frames - menu->quitframe)/(float)menu->quitdelay;
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
static void key_action(MenuData *menu, int sym) {
|
||||
Uint8 *keys = SDL_GetKeyState(NULL);
|
||||
|
||||
int look_i_can_hardcode_annoying_menu_hacks_too = menu->title && !strcmp(menu->title, "Save replay?");
|
||||
|
||||
if(sym == tconfig.intval[KEY_DOWN] || sym == SDLK_DOWN || look_i_can_hardcode_annoying_menu_hacks_too &&
|
||||
(sym == tconfig.intval[KEY_RIGHT] || sym == SDLK_RIGHT)) {
|
||||
|
||||
if(sym == tconfig.intval[KEY_DOWN] || sym == SDLK_DOWN) {
|
||||
do {
|
||||
if(++menu->cursor >= menu->ecount)
|
||||
menu->cursor = 0;
|
||||
} while(menu->entries[menu->cursor].action == NULL);
|
||||
} else if(sym == tconfig.intval[KEY_UP] || sym == SDLK_UP || look_i_can_hardcode_annoying_menu_hacks_too &&
|
||||
(sym == tconfig.intval[KEY_LEFT] || sym == SDLK_LEFT)) {
|
||||
} else if(sym == tconfig.intval[KEY_UP] || sym == SDLK_UP) {
|
||||
do {
|
||||
if(--menu->cursor < 0)
|
||||
menu->cursor = menu->ecount - 1;
|
||||
} while(menu->entries[menu->cursor].action == NULL);
|
||||
} else if((sym == tconfig.intval[KEY_SHOT] || (sym == SDLK_RETURN && !keys[SDLK_LALT] && !keys[SDLK_RALT])) && menu->entries[menu->cursor].action) {
|
||||
menu->quit = 1;
|
||||
menu->selected = menu->cursor;
|
||||
} else if(sym == SDLK_ESCAPE && (menu->type == MT_Transient || menu->abortable) && menu->abortable >= 0) {
|
||||
menu->quit = 1;
|
||||
menu->abort = 1;
|
||||
|
||||
close_menu(menu);
|
||||
} else if(sym == SDLK_ESCAPE && menu->flags & MF_Abortable) {
|
||||
close_menu(menu);
|
||||
menu->selected = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,46 +97,56 @@ void menu_input(MenuData *menu) {
|
|||
}
|
||||
|
||||
void menu_logic(MenuData *menu) {
|
||||
int hax = 0;
|
||||
menu->frames++;
|
||||
|
||||
if(menu->quit == 1 && menu->fade < 1.0)
|
||||
menu->fade += 1.0/FADE_TIME;
|
||||
if(menu->quit == 0 && menu->fade > 0)
|
||||
menu->fade -= 1.0/FADE_TIME;
|
||||
|
||||
if(menu->fade < 0)
|
||||
menu->fade = 0;
|
||||
if(menu->fade > 1)
|
||||
menu->fade = 1;
|
||||
|
||||
if(menu->quit == 1 && (menu->fade >= 1.0 || (hax = (!menu->abort && menu->instantselect)))) {
|
||||
if(hax)
|
||||
menu->fade = 0;
|
||||
global.whitefade = 0;
|
||||
menu->quit = menu->type == MT_Transient ? 2 : 0;
|
||||
if(menu->quitframe && menu->frames >= menu->quitframe)
|
||||
menu->state = MS_FadeOut;
|
||||
|
||||
if(menu->abort && menu->abortaction)
|
||||
menu->abortaction(menu->abortarg);
|
||||
else if(menu->selected != -1 && menu->entries[menu->selected].action != NULL)
|
||||
menu->entries[menu->selected].action(menu->entries[menu->selected].arg);
|
||||
if(menu->quitframe && menu->frames >= menu->quitframe + menu->quitdelay) {
|
||||
menu->state = MS_Dead;
|
||||
if(!(menu->flags & MF_Transient) && menu->selected != -1 && menu->entries[menu->selected].action != NULL) {
|
||||
menu->state = MS_Normal;
|
||||
menu->quitframe = 0;
|
||||
menu->entries[menu->selected].action(menu->entries[menu->selected].arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int menu_loop(MenuData *menu, void (*input)(MenuData*), void (*draw)(MenuData*)) {
|
||||
int menu_loop(MenuData *menu, void (*input)(MenuData*), void (*draw)(MenuData*), void (*end)(MenuData*)) {
|
||||
set_ortho();
|
||||
while(menu->quit != 2) {
|
||||
while(menu->state != MS_Dead) {
|
||||
menu_logic(menu);
|
||||
if(input)
|
||||
input(menu);
|
||||
else
|
||||
menu_input(menu);
|
||||
|
||||
if(menu->state != MS_FadeOut) {
|
||||
if(input)
|
||||
input(menu);
|
||||
else
|
||||
menu_input(menu);
|
||||
}
|
||||
|
||||
draw(menu);
|
||||
SDL_GL_SwapBuffers();
|
||||
frame_rate(&menu->lasttime);
|
||||
}
|
||||
destroy_menu(menu);
|
||||
|
||||
if(end)
|
||||
end(menu);
|
||||
destroy_menu(menu);
|
||||
|
||||
return menu->selected;
|
||||
}
|
||||
|
||||
void draw_menu_selector(float x, float y, float w, float h, float t) {
|
||||
Texture *bg = get_tex("part/smoke");
|
||||
glPushMatrix();
|
||||
glTranslatef(x, y, 0);
|
||||
glScalef(w, h, 1);
|
||||
glRotatef(t*2,0,0,1);
|
||||
glColor4f(0,0,0,0.5);
|
||||
draw_texture_p(0,0,bg);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void draw_menu_title(MenuData *m, char *title) {
|
||||
draw_text(AL_Right, (stringwidth(title, _fonts.mainmenu) + 10) * (1.0-menu_fade(m)), 30, title, _fonts.mainmenu);
|
||||
}
|
|
@ -9,26 +9,35 @@
|
|||
#define MENU_H
|
||||
|
||||
#define IMENU_BLUR 0.05
|
||||
#define FADE_TIME 15
|
||||
#define TS_KR_DELAY SDL_DEFAULT_REPEAT_DELAY
|
||||
#define TS_KR_INTERVAL (SDL_DEFAULT_REPEAT_INTERVAL*2)
|
||||
|
||||
enum {
|
||||
FADE_TIME = 15
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
void (*action)(void *arg);
|
||||
void *arg;
|
||||
float drawdata;
|
||||
void (*freearg)(void *arg);
|
||||
void (*draw)(void *e, int i, int cnt);
|
||||
} MenuEntry;
|
||||
|
||||
typedef enum MenuType { // whether to close on selection or not.
|
||||
MT_Transient, // ingame menus are for the transient people.
|
||||
MT_Persistent
|
||||
typedef enum MenuFlag {
|
||||
MF_Transient = 1, // whether to close on selection or not.
|
||||
MF_Abortable = 2
|
||||
} MenuType;
|
||||
|
||||
enum MenuState{
|
||||
MS_Normal = 0,
|
||||
MS_FadeOut,
|
||||
MS_Dead
|
||||
};
|
||||
|
||||
typedef void (*MenuAction)(void*);
|
||||
|
||||
typedef struct MenuData{
|
||||
MenuType type;
|
||||
int flags;
|
||||
|
||||
int cursor;
|
||||
int selected;
|
||||
|
@ -39,22 +48,16 @@ typedef struct MenuData{
|
|||
int frames;
|
||||
int lasttime;
|
||||
|
||||
int quit;
|
||||
float fade;
|
||||
int abort;
|
||||
int abortable;
|
||||
void (*abortaction)(void *arg);
|
||||
void *abortarg;
|
||||
int instantselect;
|
||||
int state;
|
||||
int quitframe;
|
||||
int quitdelay;
|
||||
|
||||
float drawdata[4];
|
||||
float drawdata[4];
|
||||
|
||||
char *title;
|
||||
void *context;
|
||||
void (*ondestroy)(void*);
|
||||
} MenuData;
|
||||
|
||||
void add_menu_entry(MenuData *menu, char *name, void (*action)(void *), void *arg);
|
||||
void add_menu_entry(MenuData *menu, char *name, MenuAction action, void *arg);
|
||||
void add_menu_separator(MenuData *menu);
|
||||
void create_menu(MenuData *menu);
|
||||
void destroy_menu(MenuData *menu);
|
||||
|
@ -62,7 +65,14 @@ void destroy_menu(MenuData *menu);
|
|||
void menu_logic(MenuData *menu);
|
||||
void menu_input(MenuData *menu);
|
||||
|
||||
int menu_loop(MenuData *menu, void (*input)(MenuData*), void (*draw)(MenuData*));
|
||||
void close_menu(MenuData *menu); // softly close menu (should be used in most cases)
|
||||
void kill_menu(MenuData *menu); // quit action for persistent menus
|
||||
|
||||
|
||||
int menu_loop(MenuData *menu, void (*input)(MenuData*), void (*draw)(MenuData*), void (*end)(MenuData*));
|
||||
|
||||
float menu_fade(MenuData *menu);
|
||||
|
||||
void draw_menu_selector(float x, float y, float w, float h, float t);
|
||||
void draw_menu_title(MenuData *m, char *title);
|
||||
#endif
|
||||
|
|
|
@ -321,9 +321,8 @@ int bind_saverpy_set(void *b, int v)
|
|||
|
||||
// --- Creating, destroying, filling the menu --- //
|
||||
|
||||
void destroy_options_menu(void *menu)
|
||||
void destroy_options_menu(MenuData *m)
|
||||
{
|
||||
MenuData *m = (MenuData*)menu;
|
||||
OptionBinding *binds = (OptionBinding*)m->context;
|
||||
int i;
|
||||
|
||||
|
@ -343,22 +342,16 @@ void destroy_options_menu(void *menu)
|
|||
}
|
||||
|
||||
config_save(CONFIG_FILE);
|
||||
free_bindings(menu);
|
||||
free_bindings(m);
|
||||
}
|
||||
|
||||
void do_nothing(void *arg) { }
|
||||
void backtomain(void *arg)
|
||||
{
|
||||
MenuData *m = arg;
|
||||
m->quit = 2;
|
||||
}
|
||||
|
||||
void create_options_menu(MenuData *m) {
|
||||
OptionBinding *b;
|
||||
|
||||
create_menu(m);
|
||||
m->type = MT_Transient;
|
||||
m->ondestroy = destroy_options_menu;
|
||||
m->flags = MF_Abortable;
|
||||
m->context = NULL;
|
||||
|
||||
#define bind_onoff(b) bind_addvalue(b, "on"); bind_addvalue(b, "off")
|
||||
|
@ -448,7 +441,7 @@ void create_options_menu(MenuData *m) {
|
|||
add_menu_separator(m);
|
||||
allocate_binding(m);
|
||||
|
||||
add_menu_entry(m, "Return to the main menu", backtomain, m);
|
||||
add_menu_entry(m, "Return to the main menu", (MenuAction)close_menu, m);
|
||||
allocate_binding(m);
|
||||
}
|
||||
|
||||
|
@ -464,20 +457,11 @@ void draw_options_menu_bg(MenuData* menu) {
|
|||
void draw_options_menu(MenuData *menu) {
|
||||
draw_options_menu_bg(menu);
|
||||
|
||||
draw_text(AL_Right, 140*(1-menu->fade), 30, "Options", _fonts.mainmenu);
|
||||
draw_text(AL_Right, 140*(1-menu_fade(menu)), 30, "Options", _fonts.mainmenu);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(100, 100, 0);
|
||||
|
||||
/*
|
||||
glPushMatrix();
|
||||
glTranslatef(SCREEN_W/2 - 100, menu->drawdata[2], 0);
|
||||
glScalef(SCREEN_W - 200, 20, 1);
|
||||
glColor4f(0,0,0,0.5);
|
||||
draw_quad();
|
||||
glPopMatrix();
|
||||
*/
|
||||
|
||||
|
||||
Texture *bg = get_tex("part/smoke");
|
||||
glPushMatrix();
|
||||
glTranslatef(menu->drawdata[0], menu->drawdata[2], 0);
|
||||
|
@ -590,8 +574,6 @@ void draw_options_menu(MenuData *menu) {
|
|||
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
fade_out(menu->fade);
|
||||
}
|
||||
|
||||
// --- Input processing --- //
|
||||
|
@ -683,7 +665,7 @@ static void options_key_action(MenuData *menu, int sym) {
|
|||
break;
|
||||
default:
|
||||
break;
|
||||
} else menu->quit = 1;
|
||||
} else close_menu(menu);
|
||||
} else if(sym == tconfig.intval[KEY_LEFT] || sym == SDLK_LEFT) {
|
||||
menu->selected = menu->cursor;
|
||||
OptionBinding *binds = (OptionBinding*)menu->context;
|
||||
|
@ -699,7 +681,7 @@ static void options_key_action(MenuData *menu, int sym) {
|
|||
if(bind->enabled && (bind->type == BT_IntValue || bind->type == BT_Resolution))
|
||||
bind_setnext(bind);
|
||||
} else if(sym == SDLK_ESCAPE) {
|
||||
menu->quit = 1;
|
||||
close_menu(menu);
|
||||
}
|
||||
|
||||
menu->cursor = (menu->cursor % menu->ecount) + menu->ecount*(menu->cursor < 0);
|
||||
|
@ -725,6 +707,6 @@ void options_menu_input(MenuData *menu) {
|
|||
}
|
||||
|
||||
int options_menu_loop(MenuData *menu) {
|
||||
return menu_loop(menu, options_menu_input, draw_options_menu);
|
||||
return menu_loop(menu, options_menu_input, draw_options_menu, destroy_options_menu);
|
||||
}
|
||||
|
||||
|
|
|
@ -54,8 +54,6 @@ void start_replay(void *arg) {
|
|||
global.game_over = 0;
|
||||
global.replaymode = REPLAY_RECORD;
|
||||
replay_destroy(&global.replay);
|
||||
|
||||
replayview->instantselect = False;
|
||||
}
|
||||
|
||||
MenuData* replayview_stageselect(Replay *rpy) {
|
||||
|
@ -102,7 +100,7 @@ static void shorten(char *s, int width) {
|
|||
}
|
||||
|
||||
static void replayview_draw_stagemenu(MenuData *m) {
|
||||
float alpha = 1 - m->fade;
|
||||
float alpha = min(1, m->frames/40.0);
|
||||
int i;
|
||||
|
||||
float height = (1+m->ecount) * 20;
|
||||
|
@ -138,31 +136,16 @@ static void replayview_draw_stagemenu(MenuData *m) {
|
|||
glPopMatrix();
|
||||
}
|
||||
|
||||
static void replayview_draw(MenuData *m) {
|
||||
draw_stage_menu(m);
|
||||
|
||||
if(m->context) {
|
||||
MenuData *sm = m->context;
|
||||
menu_logic(sm);
|
||||
if(sm->quit == 2) {
|
||||
destroy_menu(sm);
|
||||
m->context = NULL;
|
||||
} else {
|
||||
fade_out(0.3 * (1 - sm->fade));
|
||||
replayview_draw_stagemenu(sm);
|
||||
|
||||
if(!sm->abort && sm->quit == 1)
|
||||
m->fade = sm->fade;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void replayview_drawitem(void *n, int item, int cnt) {
|
||||
MenuEntry *e = (MenuEntry*)n;
|
||||
Replay *rpy = (Replay*)e->arg;
|
||||
float sizes[] = {1.2, 1.45, 0.8, 0.8, 0.65};
|
||||
|
||||
|
||||
int columns = 5, i, j;
|
||||
|
||||
if(!rpy)
|
||||
return;
|
||||
|
||||
for(i = 0; i < columns; ++i) {
|
||||
char tmp[128];
|
||||
int csize = sizes[i] * (SCREEN_W - 210)/columns;
|
||||
|
@ -216,6 +199,29 @@ static void replayview_drawitem(void *n, int item, int cnt) {
|
|||
}
|
||||
}
|
||||
|
||||
static void replayview_draw(MenuData *m) {
|
||||
draw_options_menu_bg(m);
|
||||
draw_menu_title(m, "Replays");
|
||||
|
||||
m->drawdata[0] = SCREEN_W/2 - 100;
|
||||
m->drawdata[1] = (SCREEN_W - 200)*0.85;
|
||||
m->drawdata[2] += (20*m->cursor - m->drawdata[2])/10.0;
|
||||
|
||||
draw_menu_list(m, 100, 100, replayview_drawitem);
|
||||
|
||||
if(m->context) {
|
||||
MenuData *sm = m->context;
|
||||
menu_logic(sm);
|
||||
if(sm->state == MS_Dead) {
|
||||
destroy_menu(sm);
|
||||
m->context = NULL;
|
||||
} else {
|
||||
replayview_draw_stagemenu(sm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int replayview_cmp(const void *a, const void *b) {
|
||||
return ((Replay*)(((MenuEntry*)b)->arg))->stages[0].seed - ((Replay*)(((MenuEntry*)a)->arg))->stages[0].seed;
|
||||
}
|
||||
|
@ -244,8 +250,6 @@ int fill_replayview_menu(MenuData *m) {
|
|||
}
|
||||
|
||||
add_menu_entry(m, " ", replayview_run, rpy);
|
||||
m->entries[m->ecount-1].freearg = replayview_freearg;
|
||||
m->entries[m->ecount-1].draw = replayview_drawitem;
|
||||
++rpys;
|
||||
}
|
||||
|
||||
|
@ -257,7 +261,7 @@ int fill_replayview_menu(MenuData *m) {
|
|||
|
||||
void replayview_abort(void *a) {
|
||||
MenuData *m = a;
|
||||
m->quit = 2;
|
||||
close_menu(m);
|
||||
|
||||
if(m->context) { // will unlikely get here
|
||||
MenuData *sm = m->context;
|
||||
|
@ -268,13 +272,10 @@ void replayview_abort(void *a) {
|
|||
|
||||
void create_replayview_menu(MenuData *m) {
|
||||
create_menu(m);
|
||||
m->type = MT_Persistent;
|
||||
m->abortable = True;
|
||||
m->abortaction = replayview_abort;
|
||||
m->abortarg = m;
|
||||
m->title = "Replays";
|
||||
replayview = m;
|
||||
|
||||
m->flags = MF_Abortable;
|
||||
|
||||
int r = fill_replayview_menu(m);
|
||||
|
||||
if(!r) {
|
||||
|
@ -295,11 +296,17 @@ void replayview_menu_input(MenuData *m) {
|
|||
else
|
||||
menu_input(m);
|
||||
|
||||
if(m->selected >= 0)
|
||||
m->instantselect = m->selected != m->ecount-1 && (((Replay*)m->entries[m->selected].arg)->stgcount > 1);
|
||||
}
|
||||
|
||||
void free_replayview(MenuData *m) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < m->ecount; i++)
|
||||
if(m->entries[i].action == replayview_run)
|
||||
replayview_freearg(m->entries[i].arg);
|
||||
}
|
||||
|
||||
int replayview_menu_loop(MenuData *m) {
|
||||
return menu_loop(m, replayview_menu_input, replayview_draw);
|
||||
return menu_loop(m, replayview_menu_input, replayview_draw, free_replayview);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,43 +35,32 @@ void save_rpy(void *a) {
|
|||
snprintf(name, 128, "taisei_%s_stg%d_%s_%s", strtime, rpy->stages[0].stage, prepr, drepr);
|
||||
|
||||
replay_save(rpy, name);
|
||||
if(a) ((MenuData*)a)->quit = 2;
|
||||
}
|
||||
|
||||
void dont_save_rpy(void *a) {
|
||||
((MenuData*)a)->quit = 2;
|
||||
if(a) close_menu(a);
|
||||
}
|
||||
|
||||
void create_saverpy_menu(MenuData *m) {
|
||||
create_menu(m);
|
||||
m->type = MT_Persistent;
|
||||
m->title = "Save replay?";
|
||||
|
||||
add_menu_entry(m, "Yes", save_rpy, m);
|
||||
add_menu_entry(m, "No", dont_save_rpy, m);
|
||||
add_menu_entry(m, "No", (MenuAction) close_menu, m);
|
||||
}
|
||||
|
||||
void draw_saverpy_menu(MenuData *m) {
|
||||
draw_options_menu_bg(m);
|
||||
int i;
|
||||
|
||||
Texture *bg = get_tex("part/smoke");
|
||||
glPushMatrix();
|
||||
glTranslatef(SCREEN_W/2 + 100 * m->drawdata[0] - 50, SCREEN_H/2, 0); // 135
|
||||
glScalef(1, 0.5, 1);
|
||||
glRotatef(m->frames*2,0,0,1);
|
||||
glColor4f(0,0,0,0.5);
|
||||
draw_texture_p(0,0,bg);
|
||||
glPopMatrix();
|
||||
draw_options_menu_bg(m);
|
||||
|
||||
draw_menu_selector(SCREEN_W/2 + 100 * m->drawdata[0] - 50, SCREEN_H/2, 1, 0.5, m->frames);
|
||||
|
||||
glPushMatrix();
|
||||
glColor4f(1, 1, 1, 1);
|
||||
glTranslatef(SCREEN_W/2, SCREEN_H/2 - 100, 0);
|
||||
draw_text(AL_Center, 0, 0, m->title, _fonts.mainmenu);
|
||||
draw_text(AL_Center, 0, 0, "Save Replay?", _fonts.mainmenu);
|
||||
glTranslatef(0, 100, 0);
|
||||
|
||||
m->drawdata[0] += (m->cursor - m->drawdata[0])/10.0;
|
||||
|
||||
int i; for(i = 0; i < m->ecount; i++) {
|
||||
for(i = 0; i < m->ecount; i++) {
|
||||
MenuEntry *e = &(m->entries[i]);
|
||||
|
||||
e->drawdata += 0.2 * (10*(i == m->cursor) - e->drawdata);
|
||||
|
@ -89,10 +78,8 @@ void draw_saverpy_menu(MenuData *m) {
|
|||
}
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
fade_out(m->fade);
|
||||
}
|
||||
|
||||
int saverpy_menu_loop(MenuData *m) {
|
||||
return menu_loop(m, NULL, draw_saverpy_menu);
|
||||
return menu_loop(m, NULL, draw_saverpy_menu, NULL);
|
||||
}
|
||||
|
|
|
@ -13,19 +13,12 @@
|
|||
#include "stageselect.h"
|
||||
#include "mainmenu.h"
|
||||
|
||||
void backtomain(void*);
|
||||
|
||||
void create_stage_menu(MenuData *m) {
|
||||
char title[STGMENU_MAX_TITLE_LENGTH];
|
||||
int i;
|
||||
|
||||
create_menu(m);
|
||||
m->type = MT_Persistent;
|
||||
m->abortable = True;
|
||||
m->abortaction = backtomain;
|
||||
m->abortarg = m;
|
||||
// TODO: I think ALL menus should use the title field, but I don't want to screw with it right now.
|
||||
m->title = "Stage Select";
|
||||
m->flags = MF_Abortable;
|
||||
|
||||
for(i = 0; stages[i].loop; ++i) if(!stages[i].hidden) {
|
||||
snprintf(title, STGMENU_MAX_TITLE_LENGTH, "%s", stages[i].title);
|
||||
|
@ -33,38 +26,14 @@ void create_stage_menu(MenuData *m) {
|
|||
}
|
||||
|
||||
add_menu_separator(m);
|
||||
add_menu_entry(m, "Back", backtomain, m);
|
||||
add_menu_entry(m, "Back", (MenuAction)close_menu, m);
|
||||
}
|
||||
|
||||
void draw_stage_menu(MenuData *m) {
|
||||
draw_options_menu_bg(m);
|
||||
draw_text(AL_Right, (stringwidth(m->title, _fonts.mainmenu) + 10) * (1-m->fade), 30, m->title, _fonts.mainmenu);
|
||||
|
||||
void draw_menu_list(MenuData *m, float x, float y, void (*draw)(void *, int, int)) {
|
||||
glPushMatrix();
|
||||
glTranslatef(100, 100 + (((m->ecount * 20 + 290) > SCREEN_W)? min(0, SCREEN_H * 0.7 - 100 - m->drawdata[2]) : 0), 0);
|
||||
glTranslatef(x, y + (((m->ecount * 20 + 290) > SCREEN_W)? min(0, SCREEN_H * 0.7 - 100 - m->drawdata[2]) : 0), 0);
|
||||
|
||||
/*
|
||||
glPushMatrix();
|
||||
glTranslatef(SCREEN_W/2 - 100, m->drawdata[2], 0);
|
||||
glScalef(SCREEN_W - 200, 20, 1);
|
||||
glColor4f(0,0,0,0.5);
|
||||
draw_quad();
|
||||
glPopMatrix();
|
||||
*/
|
||||
|
||||
Texture *bg = get_tex("part/smoke");
|
||||
glPushMatrix();
|
||||
glTranslatef(m->drawdata[0], m->drawdata[2], 0);
|
||||
glScalef(m->drawdata[1]/100.0, 0.2, 1);
|
||||
glRotatef(m->frames*2,0,0,1);
|
||||
glColor4f(0,0,0,0.5);
|
||||
draw_texture_p(0,0,bg);
|
||||
glPopMatrix();
|
||||
|
||||
MenuEntry *s = &(m->entries[m->cursor]);
|
||||
m->drawdata[0] += ((s->draw? SCREEN_W/2 - 100 : (stringwidth(s->name, _fonts.mainmenu)/2 - s->drawdata*1.5)) - m->drawdata[0])/10.0;
|
||||
m->drawdata[1] += ((s->draw? (SCREEN_W - 200)*0.85 : stringwidth(s->name, _fonts.mainmenu)) - m->drawdata[1])/10.0;
|
||||
m->drawdata[2] += (20*m->cursor - m->drawdata[2])/10.0;
|
||||
draw_menu_selector(m->drawdata[0], m->drawdata[2], m->drawdata[1]/100.0, 0.2, m->frames);
|
||||
|
||||
int i;
|
||||
for(i = 0; i < m->ecount; i++) {
|
||||
|
@ -76,22 +45,32 @@ void draw_stage_menu(MenuData *m) {
|
|||
if(e->action == NULL)
|
||||
glColor4f(0.5, 0.5, 0.5, 0.5);
|
||||
else {
|
||||
//glColor4f(0.7 + 0.3 * (1-a), 1, 1, 0.7 + 0.3 * a);
|
||||
float ia = 1-a;
|
||||
glColor4f(0.9 + ia * 0.1, 0.6 + ia * 0.4, 0.2 + ia * 0.8, 0.7 + 0.3 * a);
|
||||
}
|
||||
|
||||
if(e->draw)
|
||||
e->draw(e, i, m->ecount);
|
||||
if(draw && i < m->ecount-1)
|
||||
draw(e, i, m->ecount);
|
||||
else if(e->name)
|
||||
draw_text(AL_Left, 20 - e->drawdata, 20*i, e->name, _fonts.standard);
|
||||
draw_text(AL_Left, 20 - e->drawdata, 20*i, e->name, _fonts.standard);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
fade_out(m->fade);
|
||||
void draw_stage_menu(MenuData *m) {
|
||||
MenuEntry *s = &(m->entries[m->cursor]);
|
||||
|
||||
draw_options_menu_bg(m);
|
||||
draw_menu_title(m, "Stage Select");
|
||||
|
||||
m->drawdata[0] += (stringwidth(s->name, _fonts.mainmenu)/2.0 - s->drawdata*1.5 - m->drawdata[0])/10.0;
|
||||
m->drawdata[1] += (stringwidth(s->name, _fonts.mainmenu) - m->drawdata[1])/10.0;
|
||||
m->drawdata[2] += (20*m->cursor - m->drawdata[2])/10.0;
|
||||
|
||||
draw_menu_list(m, 100, 100, NULL);
|
||||
}
|
||||
|
||||
int stage_menu_loop(MenuData *m) {
|
||||
return menu_loop(m, NULL, draw_stage_menu);
|
||||
return menu_loop(m, NULL, draw_stage_menu, NULL);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#define STGMENU_MAX_TITLE_LENGTH 128
|
||||
|
||||
void create_stage_menu(MenuData *m);
|
||||
void draw_stage_menu(MenuData *m);
|
||||
void draw_menu_list(MenuData *m, float x, float y, void (*draw)(void *, int, int));
|
||||
int stage_menu_loop(MenuData *m);
|
||||
|
||||
#endif
|
||||
|
|
16
src/stage.c
16
src/stage.c
|
@ -55,7 +55,7 @@ void stage_ingamemenu(void) {
|
|||
if(!global.menu)
|
||||
global.menu = create_ingame_menu();
|
||||
else
|
||||
global.menu->quit = 1;
|
||||
close_menu(global.menu);
|
||||
}
|
||||
|
||||
void replay_input(void) {
|
||||
|
@ -305,12 +305,6 @@ void stage_draw(StageInfo *info, StageRule bgdraw, ShaderRule *shaderrules, int
|
|||
glPopMatrix();
|
||||
}
|
||||
|
||||
if(global.frames < 4*FADE_TIME)
|
||||
fade_out(1.0 - global.frames/(float)(4*FADE_TIME));
|
||||
if(global.timer > time - 4*FADE_TIME) {
|
||||
fade_out((global.timer - time + 4*FADE_TIME)/(float)(4*FADE_TIME));
|
||||
}
|
||||
|
||||
if(global.menu) {
|
||||
glPushMatrix();
|
||||
glTranslatef(VIEWPORT_X,VIEWPORT_Y,0);
|
||||
|
@ -319,14 +313,6 @@ void stage_draw(StageInfo *info, StageRule bgdraw, ShaderRule *shaderrules, int
|
|||
}
|
||||
|
||||
draw_hud();
|
||||
|
||||
// I don't remember how did it work before the massive transition hacking - and neither do I want to.
|
||||
// So I'll just leave these new hacks here. At least they are not AS horrible as the old ones.
|
||||
// They are still horrible, though. I hate them. HATE HATE HATE HATE HATE HATE HATE HATE HATE.
|
||||
if(global.menu && !global.menu->abort && global.menu->quit == 1 && global.menu->selected == 1)
|
||||
fade_out(global.menu->fade);
|
||||
else if(global.game_over == GAMEOVER_ABORT || global.game_over == GAMEOVER_DEFEAT)
|
||||
fade_out(1);
|
||||
}
|
||||
|
||||
int apply_shaderrules(ShaderRule *shaderrules, int fbonum) {
|
||||
|
|
Loading…
Reference in a new issue