Added keybinds and config saving (TODO: allow the user to actually customize the keys)

This commit is contained in:
Akari 2011-07-03 18:37:18 +03:00
parent 3e4413ca1c
commit 9e35feadad
2 changed files with 137 additions and 22 deletions

View file

@ -6,6 +6,7 @@
* Copyright (C) 2011, Alexeyew Andrew <https://github.com/nexAkari>
*/
#include <stdio.h>
#include "menu.h"
#include "options.h"
#include "global.h"
@ -36,9 +37,8 @@ void allocate_bindings(MenuData *m)
m->context = (void*)binds;
}
void free_bindings(void *menu)
void free_bindings(MenuData *m)
{
MenuData *m = (MenuData*)menu;
OptionBinding *binds = (OptionBinding*)m->context;
int i, j;
@ -55,6 +55,60 @@ void free_bindings(void *menu)
free(binds);
}
void menu_save_config(MenuData *m, char *filename)
{
char *buf;
buf = malloc(strlen((char*)filename)+strlen((char*)get_config_path())+3);
strcpy(buf, (char*)get_config_path());
strcat(buf, "/");
strcat(buf, filename);
FILE *out = fopen(buf, "w");
free(buf);
if(!out)
{
perror("fopen");
return;
}
fputs("# Generated by taisei\n", out);
int i;
for(i = 0; i < m->ecount; ++i)
{
OptionBinding *binds = (OptionBinding*)m->context;
OptionBinding *bind = &(binds[i]);
if(!bind->enabled)
continue;
switch(bind->type)
{
case BT_IntValue:
fprintf(out, "%s = %i\n", bind->optname, tconfig.intval[bind->configentry]);
break;
case BT_KeyBinding:
fprintf(out, "%s = K%i # SDL key name: %s\n", bind->optname, tconfig.intval[bind->configentry],
SDL_GetKeyName(tconfig.intval[bind->configentry]));
break;
default:
printf("FIXME: unhandled BindingType %i, option '%s' will NOT be saved!\n", bind->type, bind->optname);
}
}
printf("Saved config '%s'\n", filename);
}
void options_menu_destroy(void *menu)
{
MenuData *m = (MenuData*)menu;
menu_save_config(m, CONFIG_FILE);
free_bindings(menu);
}
OptionBinding* bind_option_to_entry(MenuData *m, int entry, char *optname, int cfgentry, BindingGetter getter, BindingSetter setter)
{
OptionBinding *binds = (OptionBinding*)m->context;
@ -66,6 +120,21 @@ OptionBinding* bind_option_to_entry(MenuData *m, int entry, char *optname, int c
bind->optname = malloc((strlen(optname) + 1) * sizeof(char));
strcpy(bind->optname, optname);
bind->enabled = True;
bind->type = BT_IntValue;
return bind;
}
OptionBinding* bind_keybinding_to_entry(MenuData *m, int entry, char *optname, int cfgentry)
{
OptionBinding *binds = (OptionBinding*)m->context;
OptionBinding *bind = &(binds[entry]);
bind->configentry = cfgentry;
bind->optname = malloc((strlen(optname) + 1) * sizeof(char));
strcpy(bind->optname, optname);
bind->enabled = True;
bind->type = BT_KeyBinding;
return bind;
}
@ -111,7 +180,7 @@ void bindings_initvalues(MenuData *m)
int i;
for(i = 0; i < m->ecount; ++i)
if(binds[i].enabled)
if(binds[i].enabled && binds[i].type == BT_IntValue)
binds[i].selected = binds[i].getter(&(binds[i]));
}
@ -174,17 +243,32 @@ void create_options_menu(MenuData *m) {
create_menu(m);
m->type = MT_Persistent;
m->ondestroy = free_bindings;
m->ondestroy = options_menu_destroy;
add_menu_entry(m, "Fullscreen", do_nothing, NULL);
add_menu_entry(m, "Fullscreen", do_nothing, NULL); // entry 0
add_menu_entry(m, "Audio", do_nothing, NULL);
add_menu_entry(m, "Shader", do_nothing, NULL);
add_menu_entry(m, " ", NULL, NULL);
add_menu_entry(m, "Customize controls", NULL, NULL);
add_menu_entry(m, "Back", backtomain, m);
add_menu_entry(m, "Move up", do_nothing, NULL); // entry 4
add_menu_entry(m, "Move down", do_nothing, NULL);
add_menu_entry(m, "Move left", do_nothing, NULL);
add_menu_entry(m, "Move right", do_nothing, NULL);
add_menu_entry(m, " ", NULL, NULL);
add_menu_entry(m, "Fire", do_nothing, NULL); // entry 9
add_menu_entry(m, "Focus", do_nothing, NULL);
add_menu_entry(m, "Bomb", do_nothing, NULL);
add_menu_entry(m, " ", NULL, NULL);
add_menu_entry(m, "Toggle fullscreen", do_nothing, NULL); // entry 13
// UNCOMMENT after akari/screenshot is merged
//add_menu_entry(m, "Take a screenshot", do_nothing, NULL);
add_menu_entry(m, " ", NULL, NULL);
//add_menu_entry(m, "Customize controls", NULL, NULL);
add_menu_entry(m, "Return to the main menu", backtomain, m);
allocate_bindings(m);
// this sucks but you have to specify the positional number of the menu entry as the second argument to bind_option_to_entry or bind_keybinding_to_entry
b = bind_option_to_entry(m, 0, "fullscreen", FULLSCREEN, bind_common_onoffget, bind_fullscreen_set);
bind_onoff(b);
@ -196,6 +280,19 @@ void create_options_menu(MenuData *m) {
bind_noshader_set);
bind_onoff(b);
bind_keybinding_to_entry(m, 4, "key_up", KEY_UP);
bind_keybinding_to_entry(m, 5, "key_down", KEY_DOWN);
bind_keybinding_to_entry(m, 6, "key_left", KEY_LEFT);
bind_keybinding_to_entry(m, 7, "key_right", KEY_RIGHT);
bind_keybinding_to_entry(m, 9, "key_shot", KEY_SHOT);
bind_keybinding_to_entry(m, 10, "key_focus", KEY_FOCUS);
bind_keybinding_to_entry(m, 11, "key_bomb", KEY_BOMB);
bind_keybinding_to_entry(m, 13, "key_fullscreen", KEY_FULLSCREEN);
// UNCOMMENT after akari/screeenshot is merged
//bind_keybinding_to_entry(m, 14, "key_screenshot", KEY_SCREENSHOT);
bindings_initvalues(m);
}
@ -249,19 +346,29 @@ void draw_options_menu(MenuData *menu) {
bind = &(binds[i]);
if(bind->enabled && bind->valcount > 0)
if(bind->enabled)
{
int len = 0, j;
for(j = bind->valcount - 1; j+1; --j)
int j, origin = SCREEN_W - 220;
switch(bind->type)
{
len += strlen(bind->values[j]);
if(bind->selected == j)
glColor4f(1,1,0,0.7);
else
glColor4f(0.5,0.5,0.5,0.7);
draw_text(AL_Right, SCREEN_W - 200 - (len*20), 20*i, bind->values[j], _fonts.standard);
case BT_IntValue:
for(j = bind->valcount-1; j+1; --j)
{
if(j != bind->valcount-1)
origin -= strlen(bind->values[j+1])/2.0 * 20;
if(bind->selected == j)
glColor4f(1,1,0,0.7);
else
glColor4f(0.5,0.5,0.5,0.7);
draw_text(AL_Right, origin, 20*i, bind->values[j], _fonts.standard);
}
break;
case BT_KeyBinding:
draw_text(AL_Right, origin, 20*i, SDL_GetKeyName(tconfig.intval[bind->configentry]), _fonts.standard);
break;
}
}
}
@ -307,8 +414,10 @@ void options_menu_input(MenuData *menu) {
OptionBinding *binds = (OptionBinding*)menu->context;
OptionBinding *bind = &(binds[menu->selected]);
if(bind->enabled)
binding_setnext(bind);
if(bind->enabled) switch(bind->type)
{
case BT_IntValue: binding_setnext(bind); break;
}
else
menu->quit = 1;
} else if(sym == tconfig.intval[KEY_LEFT]) {
@ -316,14 +425,14 @@ void options_menu_input(MenuData *menu) {
OptionBinding *binds = (OptionBinding*)menu->context;
OptionBinding *bind = &(binds[menu->selected]);
if(bind->enabled)
if(bind->enabled && bind->type == BT_IntValue)
binding_setprev(bind);
} else if(sym == tconfig.intval[KEY_RIGHT]) {
menu->selected = menu->cursor;
OptionBinding *binds = (OptionBinding*)menu->context;
OptionBinding *bind = &(binds[menu->selected]);
if(bind->enabled)
if(bind->enabled && bind->type == BT_IntValue)
binding_setnext(bind);
} else if(sym == SDLK_ESCAPE) {
menu->quit = 2;

View file

@ -19,6 +19,11 @@ int options_menu_loop(MenuData *m);
typedef int (*BindingGetter)(void*);
typedef int (*BindingSetter)(void*, int);
typedef enum BindingType {
BT_IntValue,
BT_KeyBinding
} BindingType;
typedef struct OptionBinding {
char **values;
int valcount;
@ -28,6 +33,7 @@ typedef struct OptionBinding {
int configentry;
int enabled;
char *optname;
BindingType type;
} OptionBinding;
void draw_options_menu_bg(MenuData*);