168 lines
3.9 KiB
C
168 lines
3.9 KiB
C
/*
|
|
* This software is licensed under the terms of the MIT-License
|
|
* See COPYING for further information.
|
|
* ---
|
|
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
|
|
*/
|
|
|
|
#include "menu.h"
|
|
#include "global.h"
|
|
#include "video.h"
|
|
|
|
MenuEntry *add_menu_entry(MenuData *menu, char *name, MenuAction action, void *arg) {
|
|
return add_menu_entry_f(menu, name, action, arg, 0);
|
|
}
|
|
|
|
MenuEntry *add_menu_entry_f(MenuData *menu, char *name, MenuAction action, void *arg, int flags) {
|
|
menu->entries = realloc(menu->entries, (++menu->ecount)*sizeof(MenuEntry));
|
|
MenuEntry *e = &(menu->entries[menu->ecount-1]);
|
|
memset(e, 0, sizeof(MenuEntry));
|
|
|
|
e->name = malloc(strlen(name)+1);
|
|
strcpy(e->name, name);
|
|
e->action = action;
|
|
e->arg = arg;
|
|
e->flags = flags;
|
|
e->transition = menu->transition;
|
|
return e;
|
|
}
|
|
|
|
void add_menu_separator(MenuData *menu) {
|
|
menu->entries = realloc(menu->entries, (++menu->ecount)*sizeof(MenuEntry));
|
|
memset(&(menu->entries[menu->ecount-1]), 0, sizeof(MenuEntry));
|
|
}
|
|
|
|
void destroy_menu(MenuData *menu) {
|
|
int i;
|
|
|
|
for(i = 0; i < menu->ecount; i++) {
|
|
MenuEntry *e = &(menu->entries[i]);
|
|
|
|
free(e->name);
|
|
}
|
|
|
|
free(menu->entries);
|
|
}
|
|
|
|
void create_menu(MenuData *menu) {
|
|
memset(menu, 0, sizeof(MenuData));
|
|
|
|
menu->selected = -1;
|
|
menu->quitdelay = FADE_TIME;
|
|
menu->transition = TransFadeBlack;
|
|
}
|
|
|
|
void close_menu(MenuData *menu) {
|
|
TransitionRule trans = menu->transition;
|
|
|
|
if(menu->selected != -1)
|
|
trans = menu->entries[menu->selected].transition;
|
|
|
|
set_transition(trans, menu->quitdelay, menu->quitdelay);
|
|
|
|
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;
|
|
}
|
|
|
|
void menu_event(EventType type, int state, void *arg) {
|
|
MenuData *menu = arg;
|
|
|
|
switch(type) {
|
|
case E_CursorDown:
|
|
play_ui_sound("generic_shot");
|
|
do {
|
|
if(++menu->cursor >= menu->ecount)
|
|
menu->cursor = 0;
|
|
} while(menu->entries[menu->cursor].action == NULL);
|
|
break;
|
|
|
|
case E_CursorUp:
|
|
play_ui_sound("generic_shot");
|
|
do {
|
|
if(--menu->cursor < 0)
|
|
menu->cursor = menu->ecount - 1;
|
|
} while(menu->entries[menu->cursor].action == NULL);
|
|
break;
|
|
|
|
case E_MenuAccept:
|
|
play_ui_sound("shot_special1");
|
|
if(menu->entries[menu->cursor].action) {
|
|
menu->selected = menu->cursor;
|
|
close_menu(menu);
|
|
}
|
|
break;
|
|
|
|
case E_MenuAbort:
|
|
play_ui_sound("hit");
|
|
if(menu->flags & MF_Abortable) {
|
|
menu->selected = -1;
|
|
close_menu(menu);
|
|
}
|
|
break;
|
|
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
void menu_input(MenuData *menu) {
|
|
handle_events(menu_event, EF_Menu, (void*)menu);
|
|
}
|
|
|
|
void menu_logic(MenuData *menu) {
|
|
menu->frames++;
|
|
|
|
if(menu->quitframe && menu->frames >= menu->quitframe)
|
|
menu->state = MS_FadeOut;
|
|
|
|
if(menu->quitframe && menu->frames >= menu->quitframe + menu->quitdelay*!(menu->state & MF_InstantSelect || menu->selected != -1 && menu->entries[menu->selected].flags & MF_InstantSelect)) {
|
|
menu->state = MS_Dead;
|
|
if(menu->selected != -1 && menu->entries[menu->selected].action != NULL) {
|
|
if(!(menu->flags & MF_Transient)) {
|
|
menu->state = MS_Normal;
|
|
menu->quitframe = 0;
|
|
}
|
|
|
|
menu->entries[menu->selected].action(menu, menu->entries[menu->selected].arg);
|
|
}
|
|
}
|
|
}
|
|
|
|
int menu_loop(MenuData *menu, void (*input)(MenuData*), void (*draw)(MenuData*), void (*end)(MenuData*)) {
|
|
set_ortho();
|
|
while(menu->state != MS_Dead) {
|
|
menu_logic(menu);
|
|
|
|
if(menu->state != MS_FadeOut || menu->flags & MF_AlwaysProcessInput) {
|
|
if(input)
|
|
input(menu);
|
|
else
|
|
menu_input(menu);
|
|
} else handle_events(NULL, 0, NULL);
|
|
|
|
draw(menu);
|
|
if(!(menu->flags & MF_ManualDrawTransition))
|
|
draw_transition();
|
|
|
|
SDL_GL_SwapWindow(video.window);
|
|
frame_rate(&menu->lasttime);
|
|
}
|
|
|
|
if(end)
|
|
end(menu);
|
|
destroy_menu(menu);
|
|
|
|
return menu->selected;
|
|
}
|