improved the no-stage-bg feature, and extended the options menu functionality while I was at it

This commit is contained in:
Andrew "Akari" Alexeyew 2012-07-13 23:42:35 +03:00
parent c25566346e
commit 7fb8b25732
8 changed files with 105 additions and 44 deletions

View file

@ -34,7 +34,8 @@ enum {
NO_SHADER,
NO_AUDIO,
NO_STAGEBG
NO_STAGEBG,
NO_STAGEBG_FPSLIMIT
};
void parse_config(char *filename);

View file

@ -37,6 +37,7 @@
"disable_shader" { yylval = NO_SHADER; return tNO_SHADER; }
"disable_audio" {yylval = NO_AUDIO; return tNO_AUDIO; }
"disable_stagebg" { yylval = NO_STAGEBG; return tNO_STAGEBG; }
"disable_stagebg_auto_fpslimit" { yylval = NO_STAGEBG_FPSLIMIT; return tNO_STAGEBG_FPSLIMIT; }
"shift" { yylval = SDLK_LSHIFT; return SKEY; }
"ctrl" { yylval = SDLK_LCTRL; return SKEY; }

View file

@ -48,6 +48,7 @@
%token tNO_SHADER
%token tNO_AUDIO
%token tNO_STAGEBG
%token tNO_STAGEBG_FPSLIMIT
%token SKEY
@ -86,7 +87,8 @@ key_key : tKEY_UP
| tNO_SHADER
| tNO_AUDIO
| tFULLSCREEN
| tNO_STAGEBG;
| tNO_STAGEBG
| tNO_STAGEBG_FPSLIMIT;
nl : LB { lineno++; };
%%
@ -137,4 +139,5 @@ void config_preset() {
tconfig.intval[NO_AUDIO] = 0;
tconfig.intval[NO_STAGEBG] = 0;
tconfig.intval[NO_STAGEBG_FPSLIMIT] = 40;
}

View file

@ -104,6 +104,7 @@ typedef struct {
FPSCounter fps;
int nostagebg; // I don't want the automatic stagebg handling to mess with the config, and I don't want that longass if in more than one place either.
} Global;
extern Global global;

View file

@ -103,7 +103,6 @@ int main(int argc, char** argv) {
atexit(taisei_shutdown);
#ifdef DEBUG
printf("** Compiled with DEBUG flag!\n");
if(argc >= 2 && argv[1]) {

View file

@ -111,37 +111,60 @@ int bind_addvalue(OptionBinding *b, char *val)
return b->valcount-1;
}
void bind_setvaluerange(OptionBinding *b, int vmin, int vmax) {
b->valrange_min = vmin;
b->valrange_max = vmax;
}
// Called to select a value of a BT_IntValue type binding by index
int binding_setvalue(OptionBinding *b, int v)
int bind_setvalue(OptionBinding *b, int v)
{
return b->selected = b->setter(b, v);
}
// Called to get the selected value of a BT_IntValue type binding by index
int binding_getvalue(OptionBinding *b)
int bind_getvalue(OptionBinding *b)
{
// query AND update
return b->selected = b->getter(b);
}
// Selects the next to current value of a BT_IntValue type binding
int binding_setnext(OptionBinding *b)
int bind_setnext(OptionBinding *b)
{
int s = b->selected + 1;
if(s >= b->valcount)
int s = b->selected +1;
if(b->valrange_max) {
if(s > b->valrange_max)
s = b->valrange_min;
} else if(s >= b->valcount)
s = 0;
return binding_setvalue(b, s);
return bind_setvalue(b, s);
}
// Selects the previous to current value of a BT_IntValue type binding
int binding_setprev(OptionBinding *b)
int bind_setprev(OptionBinding *b)
{
int s = b->selected - 1;
if(s < 0)
if(b->valrange_max) {
if(s < b->valrange_min)
s = b->valrange_max;
} else if(s < 0)
s = b->valcount - 1;
return binding_setvalue(b, s);
return bind_setvalue(b, s);
}
void bind_setdependence(OptionBinding *b, BindingDependence dep) {
b->dependence = dep;
}
int bind_isactive(OptionBinding *b) {
if(!b->dependence)
return True;
return b->dependence();
}
// Initializes selection for all BT_IntValue type bindings
@ -152,7 +175,7 @@ void bindings_initvalues(MenuData *m)
int i;
for(i = 0; i < m->ecount; ++i)
if(binds[i].enabled && binds[i].type == BT_IntValue)
binding_getvalue(&(binds[i]));
bind_getvalue(&(binds[i]));
}
// --- Shared binding callbacks --- //
@ -177,6 +200,9 @@ int bind_common_onoffset_inverted(void *b, int v)
return tconfig.intval[((OptionBinding*)b)->configentry] = v;
}
#define bind_common_intget bind_common_onoffget_inverted
#define bind_common_intset bind_common_onoffset_inverted
// --- Binding callbacks for individual options --- //
int bind_fullscreen_set(void *b, int v)
@ -227,6 +253,10 @@ int bind_noshader_set(void *b, int v)
return i;
}
int bind_stagebg_fpslimit_dependence() {
return tconfig.intval[NO_STAGEBG] == 2;
}
// --- Config saving --- //
void menu_save_config(MenuData *m, char *filename)
@ -293,7 +323,7 @@ void backtomain(void *arg)
}
void create_options_menu(MenuData *m) {
OptionBinding* b;
OptionBinding *b;
create_menu(m);
m->type = MT_Persistent;
@ -317,10 +347,18 @@ void create_options_menu(MenuData *m) {
bind_onoff(b);
add_menu_entry(m, "Stage Background", do_nothing, NULL);
b = bind_option(m, "disable_stagebg", NO_STAGEBG, bind_common_onoffget_inverted,
bind_common_onoffset_inverted);
bind_onoff(b);
b = bind_option(m, "disable_stagebg", NO_STAGEBG, bind_common_intget,
bind_common_intset);
bind_addvalue(b, "on");
bind_addvalue(b, "off");
bind_addvalue(b, "auto");
add_menu_entry(m, "Minimum FPS", do_nothing, NULL);
b = bind_option(m, "disable_stagebg_auto_fpslimit", NO_STAGEBG_FPSLIMIT, bind_common_intget,
bind_common_intset);
bind_setvaluerange(b, 20, 60);
bind_setdependence(b, bind_stagebg_fpslimit_dependence);
add_menu_entry(m, " ", NULL, NULL);
allocate_binding(m);
@ -403,37 +441,46 @@ void draw_options_menu(MenuData *menu) {
for(i = 0; i < menu->ecount; i++) {
menu->entries[i].drawdata += 0.2 * (10*(i == menu->cursor) - menu->entries[i].drawdata);
bind = &(binds[i]);
int hasbind = bind->enabled;
float alpha = (!hasbind || bind_isactive(bind))? 1 : 0.5;
if(menu->entries[i].action == NULL && clr != 0) {
clr = 0;
glColor4f(0.5, 0.5, 0.5, 0.7);
glColor4f(0.5, 0.5, 0.5, 0.7 * alpha);
} else if(i == menu->cursor && clr != 1) {
clr = 1;
glColor4f(1,1,0,0.7);
glColor4f(1,1,0,0.7 * alpha);
} else if(clr != 2) {
clr = 2;
glColor4f(1, 1, 1, 0.7);
glColor4f(1, 1, 1, 0.7 * alpha);
}
draw_text(AL_Left, 20 - menu->entries[i].drawdata, 20*i, menu->entries[i].name, _fonts.standard);
draw_text(AL_Left,
((hasbind && bind->dependence)? 20 : 0) // hack hack hack
+ 20 - menu->entries[i].drawdata, 20*i, menu->entries[i].name, _fonts.standard);
bind = &(binds[i]);
if(bind->enabled)
if(hasbind)
{
int j, origin = SCREEN_W - 220;
switch(bind->type)
{
case BT_IntValue:
for(j = bind->valcount-1; j+1; --j)
{
if(bind->valrange_max) {
char tmp[16]; // who'd use a 16-digit number here anyway?
snprintf(tmp, 16, "%d", bind_getvalue(bind));
draw_text(AL_Right, origin, 20*i, tmp, _fonts.standard);
} else for(j = bind->valcount-1; j+1; --j) {
if(j != bind->valcount-1)
origin -= strlen(bind->values[j+1])/2.0 * 20;
if(binding_getvalue(bind) == j && clr != 1) {
if(bind_getvalue(bind) == j) {
clr = 1;
glColor4f(1,1,0,0.7);
glColor4f(1,1,0,0.7 * alpha);
} else if(clr != 0) {
clr = 0;
glColor4f(0.5,0.5,0.5,0.7);
glColor4f(0.5,0.5,0.5,0.7 * alpha);
}
draw_text(AL_Right, origin, 20*i, bind->values[j], _fonts.standard);
@ -473,7 +520,7 @@ void draw_options_menu(MenuData *menu) {
// --- Input processing --- //
void binding_input(MenuData *menu, OptionBinding *b)
void bind_input(MenuData *menu, OptionBinding *b)
{
// yes, no global_input() here.
@ -499,20 +546,22 @@ void binding_input(MenuData *menu, OptionBinding *b)
}
static void options_key_action(MenuData *menu, int sym) {
#define SHOULD_SKIP (!menu->entries[menu->cursor].action || (((OptionBinding*)menu->context)[menu->cursor].enabled && !bind_isactive(&(((OptionBinding*)menu->context)[menu->cursor]))))
if(sym == tconfig.intval[KEY_DOWN] || sym == SDLK_DOWN) {
menu->drawdata[3] = 10;
do {
menu->cursor++;
if(menu->cursor >= menu->ecount)
menu->cursor = 0;
} while(!menu->entries[menu->cursor].action);
} while SHOULD_SKIP;
} else if(sym == tconfig.intval[KEY_UP] || sym == SDLK_UP) {
menu->drawdata[3] = 10;
do {
menu->cursor--;
if(menu->cursor < 0)
menu->cursor = menu->ecount - 1;
} while(!menu->entries[menu->cursor].action);
} while SHOULD_SKIP;
} else if((sym == tconfig.intval[KEY_SHOT] || sym == SDLK_RETURN) && menu->entries[menu->cursor].action) {
menu->selected = menu->cursor;
@ -521,7 +570,7 @@ static void options_key_action(MenuData *menu, int sym) {
if(bind->enabled) switch(bind->type)
{
case BT_IntValue: binding_setnext(bind); break;
case BT_IntValue: bind_setnext(bind); break;
case BT_KeyBinding: bind->blockinput = True; break;
}
else
@ -532,14 +581,14 @@ static void options_key_action(MenuData *menu, int sym) {
OptionBinding *bind = &(binds[menu->selected]);
if(bind->enabled && bind->type == BT_IntValue)
binding_setprev(bind);
bind_setprev(bind);
} else if(sym == tconfig.intval[KEY_RIGHT] || sym == SDLK_RIGHT) {
menu->selected = menu->cursor;
OptionBinding *binds = (OptionBinding*)menu->context;
OptionBinding *bind = &(binds[menu->selected]);
if(bind->enabled && bind->type == BT_IntValue)
binding_setnext(bind);
bind_setnext(bind);
} else if(sym == SDLK_ESCAPE) {
menu->quit = 2;
}
@ -553,7 +602,7 @@ void options_menu_input(MenuData *menu) {
if((b = get_input_blocking_binding(menu)) != NULL)
{
binding_input(menu, b);
bind_input(menu, b);
return;
}

View file

@ -18,6 +18,7 @@ int options_menu_loop(MenuData *m);
typedef int (*BindingGetter)(void*);
typedef int (*BindingSetter)(void*, int);
typedef int (*BindingDependence)();
typedef enum BindingType {
BT_IntValue,
@ -27,8 +28,11 @@ typedef enum BindingType {
typedef struct OptionBinding {
char **values;
int valcount;
int valrange_min;
int valrange_max;
BindingGetter getter;
BindingSetter setter;
BindingDependence dependence;
int selected;
int configentry;
int enabled;

View file

@ -16,6 +16,7 @@ void stage_start() {
global.frames = 0;
global.game_over = 0;
global.points = 0;
global.nostagebg = False;
}
void stage_input() {
@ -129,9 +130,14 @@ void stage_draw(StageRule bgdraw, ShaderRule *shaderrules, int time) {
glTranslatef(-(VIEWPORT_X+VIEWPORT_W/2.0), -(VIEWPORT_Y+VIEWPORT_H/2.0),0);
glEnable(GL_DEPTH_TEST);
if(!global.menu && !tconfig.intval[NO_STAGEBG])
// NO_STAGEBG == 2 means "automatic mode". Do we need a derpenum for this?
// global.fps.fps is unreliable here, show_fps is better
if(!global.nostagebg && ((!global.menu && !tconfig.intval[NO_STAGEBG]) ||
(tconfig.intval[NO_STAGEBG] == 2 && (global.fps.show_fps == 0 || global.fps.show_fps > tconfig.intval[NO_STAGEBG_FPSLIMIT]))))
bgdraw();
else global.nostagebg = True;
glPopMatrix();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
@ -234,7 +240,7 @@ void apply_bg_shaders(ShaderRule *shaderrules) {
glPopMatrix();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
} else if(!tconfig.intval[NO_STAGEBG]) {
} else if(!global.nostagebg) {
for(i = 0; shaderrules != NULL && shaderrules[i] != NULL; i++) {
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbg[!fbonum].fbo);
shaderrules[i](fbonum);
@ -357,9 +363,6 @@ void stage_loop(StageRule start, StageRule end, StageRule draw, StageRule event,
SDL_GL_SwapBuffers();
frame_rate(&global.lasttime);
if(global.fps.fps <= 40)
tconfig.intval[NO_STAGEBG] = 1;
}
end();
@ -371,4 +374,4 @@ void draw_stage_title(int t, int dur, char *stage, char *subtitle) {
return;
draw_text(AL_Center, VIEWPORT_W/2, VIEWPORT_H/2, stage, _fonts.mainmenu);
}
}