diff --git a/doomsday/plugins/common/include/f_infine.h b/doomsday/plugins/common/include/f_infine.h index 4a6079347a..a011e0a56f 100644 --- a/doomsday/plugins/common/include/f_infine.h +++ b/doomsday/plugins/common/include/f_infine.h @@ -3,8 +3,8 @@ * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * - *\author Copyright © 2003-2009 Jaakko Keränen - *\author Copyright © 2006-2009 Daniel Swanson + *\author Copyright © 2003-2010 Jaakko Keränen + *\author Copyright © 2006-2010 Daniel Swanson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,6 +47,8 @@ extern boolean fiActive; extern boolean fiCmdExecuted; // Set to true after first command. extern boolean briefDisabled; +void FI_Register(void); + void FI_Reset(void); void FI_Start(char* finalescript, infinemode_t mode); void FI_End(void); diff --git a/doomsday/plugins/common/src/f_infine.c b/doomsday/plugins/common/src/f_infine.c index c1024ebd94..4f3fd7e9f4 100644 --- a/doomsday/plugins/common/src/f_infine.c +++ b/doomsday/plugins/common/src/f_infine.c @@ -67,6 +67,12 @@ // TYPES ------------------------------------------------------------------- +enum { + STRETCH = 0, + PILLARBOX, + LETTERBOX, +}; + typedef char handle_t[32]; typedef struct ficmd_s { @@ -387,15 +393,31 @@ static fitext_t fiDummyText; static boolean conditionPresets[NUM_FICONDS]; +// Cvars for finales: +cvar_t fiCVars[] = { + {"finale-nostretch", 0, CVT_BYTE, &cfg.fiNoStretch, 0, 1}, + {NULL} +}; + // CODE -------------------------------------------------------------------- +/** + * Called during pre-init to register cvars and ccmds for the finale system. + */ +void FI_Register(void) +{ + int i; + for(i = 0; fiCVars[i].name; ++i) + Con_AddVariable(fiCVars + i); +} + /** * Clear the InFine state to the default, blank state. * The 'fi' pointer must be set before calling this function. */ void FI_ClearState(void) { - int i, c; + int i, c; // General game state. G_SetGameAction(GA_NONE); @@ -1695,34 +1717,123 @@ void FI_GetTurnCenter(fipic_t *pic, float *center) center[VY] *= pic->object.scale[VY].value; } +static int pickScalingStrategy(int winWidth, int winHeight, float* outScale) +{ + float scale = (winWidth >= winHeight? (float)winHeight/SCREENHEIGHT : (float)winWidth/SCREENWIDTH); + float a = (float)winWidth/winHeight; + float b = (float)SCREENWIDTH/SCREENHEIGHT; + int displayMode = STRETCH; + + if(!INRANGE_OF(a, b, .001f) && (cfg.fiNoStretch || !INRANGE_OF(a, b, .38f))) + { + if(SCREENWIDTH * scale > winWidth || SCREENHEIGHT * scale < winHeight) + { + scale *= (float)winWidth/(SCREENWIDTH*scale); + displayMode = LETTERBOX; + } + else if(SCREENWIDTH * scale < winWidth) + { + displayMode = PILLARBOX; + } + } + if(outScale) + *outScale = scale; + return displayMode; +} + /** * Drawing is the most complex task here. */ void FI_Drawer(void) { - int i, sq; - float mid[2]; - fipic_t *pic; - fitext_t *tex; + int winWidth, winHeight, displayMode, scissorState[5], i, sq; + float scale, mid[2]; + fipic_t* pic; + fitext_t* tex; // Don't draw anything until we are sure the script has started. if(!fiActive || !fiCmdExecuted) return; + winWidth = Get(DD_WINDOW_WIDTH); + winHeight = Get(DD_WINDOW_HEIGHT); + displayMode = pickScalingStrategy(winWidth, winHeight, &scale); + + DGL_MatrixMode(DGL_PROJECTION); + DGL_PushMatrix(); + DGL_LoadIdentity(); + switch(displayMode) + { + case PILLARBOX: + { + /** + * Use an orthographic projection in native screenspace. Then + * translate and scale the projection to produce an aspect + * corrected coordinate space at 4:3, centered horizontally + * in the window. + */ + int w = (winWidth-SCREENWIDTH*scale)/2; + DGL_Ortho(0, 0, winWidth, winHeight, -1, 1); + + DGL_SetNoMaterial(); + DGL_DrawRect(0, 0, w, winHeight, 0, 0, 0, 1); + DGL_DrawRect(winWidth - w, 0, w, winHeight, 0, 0, 0, 1); + + DGL_GetIntegerv(DGL_SCISSOR_TEST, scissorState); + DGL_GetIntegerv(DGL_SCISSOR_BOX, scissorState + 1); + DGL_Scissor(w, 0, SCREENWIDTH*scale, winHeight); + DGL_Enable(DGL_SCISSOR_TEST); + + DGL_MatrixMode(DGL_PROJECTION); + DGL_Translatef((float)winWidth/2, (float)winHeight/2, 0); + DGL_Scalef(scale, scale, 1); + DGL_Translatef(-SCREENWIDTH/2, -SCREENHEIGHT/2, 0); + break; + } + case LETTERBOX: + { + /** + * Use an orthographic projection in native screenspace. Then + * translate and scale the projection to produce an aspect + * corrected coordinate space at 4:3, centered vertically in + * the window. + */ + int h = (winHeight-SCREENHEIGHT*scale)/2; + DGL_Ortho(0, 0, winWidth, winHeight, -1, 1); + + DGL_SetNoMaterial(); + DGL_DrawRect(0, 0, winWidth, h, 0, 0, 0, 1); + DGL_DrawRect(0, winHeight - h, winWidth, h, 0, 0, 0, 1); + + DGL_GetIntegerv(DGL_SCISSOR_TEST, scissorState); + DGL_GetIntegerv(DGL_SCISSOR_BOX, scissorState + 1); + DGL_Scissor(0, h, winWidth, SCREENHEIGHT*scale); + DGL_Enable(DGL_SCISSOR_TEST); + + DGL_MatrixMode(DGL_PROJECTION); + DGL_Translatef((float)winWidth/2, (float)winHeight/2, 0); + DGL_Scalef(scale, scale, 1); + DGL_Translatef(-SCREENWIDTH/2, -SCREENHEIGHT/2, 0); + } + break; + + default: // STRETCH + DGL_Ortho(0, 0, SCREENWIDTH, SCREENHEIGHT, -1, 1); + break; + } + // Draw the background. if(fi->bgMaterial) { FI_UseColor(fi->bgColor, 4); DGL_SetMaterial(fi->bgMaterial); - DGL_DrawRectTiled(0, 0, 320, 200, 64, 64); + DGL_DrawRectTiled(0, 0, SCREENWIDTH, SCREENHEIGHT, 64, 64); } else { // Just clear the screen, then. DGL_Disable(DGL_TEXTURING); - DGL_DrawRect(0, 0, 320, 200, fi->bgColor[0].value, - fi->bgColor[1].value, fi->bgColor[2].value, - fi->bgColor[3].value); + DGL_DrawRect(0, 0, SCREENWIDTH, SCREENHEIGHT, fi->bgColor[0].value, fi->bgColor[1].value, fi->bgColor[2].value, fi->bgColor[3].value); DGL_Enable(DGL_TEXTURING); } @@ -1742,14 +1853,12 @@ void FI_Drawer(void) // Setup the transformation. DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); - DGL_Translatef(pic->object.x.value - fi->imgOffset[0].value, - pic->object.y.value - fi->imgOffset[1].value, 0); + DGL_Translatef(pic->object.x.value - fi->imgOffset[0].value, pic->object.y.value - fi->imgOffset[1].value, 0); DGL_Translatef(mid[VX], mid[VY], 0); FI_Rotate(pic->object.angle.value); // Move to origin. DGL_Translatef(-mid[VX], -mid[VY], 0); - DGL_Scalef((pic->flip[sq] ? -1 : 1) * pic->object.scale[0].value, - pic->object.scale[1].value, 1); + DGL_Scalef((pic->flip[sq] ? -1 : 1) * pic->object.scale[0].value, pic->object.scale[1].value, 1); // Draw it. if(pic->flags.is_rect) @@ -1838,12 +1947,22 @@ void FI_Drawer(void) FI_UseColor(fi->filter, 4); DGL_Begin(DGL_QUADS); DGL_Vertex2f(0, 0); - DGL_Vertex2f(320, 0); - DGL_Vertex2f(320, 200); - DGL_Vertex2f(0, 200); + DGL_Vertex2f(SCREENWIDTH, 0); + DGL_Vertex2f(SCREENWIDTH, SCREENHEIGHT); + DGL_Vertex2f(0, SCREENHEIGHT); DGL_End(); DGL_Enable(DGL_TEXTURING); } + + if(displayMode != STRETCH) + { + if(!scissorState[0]) + DGL_Disable(DGL_SCISSOR_TEST); + DGL_Scissor(scissorState[1], scissorState[2], scissorState[3], scissorState[4]); + } + + DGL_MatrixMode(DGL_PROJECTION); + DGL_PopMatrix(); } /** diff --git a/doomsday/plugins/common/src/g_game.c b/doomsday/plugins/common/src/g_game.c index 69e507380e..87ec8099b0 100644 --- a/doomsday/plugins/common/src/g_game.c +++ b/doomsday/plugins/common/src/g_game.c @@ -479,6 +479,7 @@ void G_CommonPreInit(void) D_NetConsoleRegistration(); // For network. G_Register(); // Read-only game status cvars (for playsim). G_ControlRegister(); // For controls/input. + FI_Register(); AM_Register(); // For the automap. Hu_MenuRegister(); // For the menu. Hu_LogRegister(); // For the player message logs. diff --git a/doomsday/plugins/jdoom/data/conhelp.txt b/doomsday/plugins/jdoom/data/conhelp.txt index a522d1fcae..8e74866851 100644 --- a/doomsday/plugins/jdoom/data/conhelp.txt +++ b/doomsday/plugins/jdoom/data/conhelp.txt @@ -202,6 +202,9 @@ desc = 1=Disable exit buttons during map rotation. [server-game-cheat] desc = 1=Allow cheating in multiplayer games (god, noclip, give). +[finale-nostretch] +desc = If the window dimension aspect ratio is not equal to but close to that of the original game, fixed-aspect finale animations will be stretched 1= disabled. + [menu-flash-r] desc = Menu selection flash color, red component. diff --git a/doomsday/plugins/jdoom/include/d_config.h b/doomsday/plugins/jdoom/include/d_config.h index d95be3cb1d..6e3204cbb1 100644 --- a/doomsday/plugins/jdoom/include/d_config.h +++ b/doomsday/plugins/jdoom/include/d_config.h @@ -174,6 +174,8 @@ typedef struct jdoom_config_s { byte automapPanResetOnOpen; float automapOpenSeconds; + byte fiNoStretch; // Do not stretch finales to fill the screen at near 4:3 aspect ratios. + int msgCount; float msgScale; float msgUptime; diff --git a/doomsday/plugins/jdoom/src/d_main.c b/doomsday/plugins/jdoom/src/d_main.c index b19353ef44..001f1dc70a 100644 --- a/doomsday/plugins/jdoom/src/d_main.c +++ b/doomsday/plugins/jdoom/src/d_main.c @@ -368,6 +368,7 @@ void G_PreInit(void) cfg.dclickUse = false; cfg.povLookAround = true; cfg.screenBlocks = cfg.setBlocks = 10; + cfg.fiNoStretch = false; cfg.echoMsg = true; cfg.lookSpeed = 3; cfg.turnSpeed = 1; diff --git a/doomsday/plugins/jdoom64/data/conhelp.txt b/doomsday/plugins/jdoom64/data/conhelp.txt index 6321d13306..8b0c142d8b 100644 --- a/doomsday/plugins/jdoom64/data/conhelp.txt +++ b/doomsday/plugins/jdoom64/data/conhelp.txt @@ -198,6 +198,9 @@ desc = 1=Disable exit buttons during map rotation. [server-game-cheat] desc = 1=Allow cheating in multiplayer games (god, noclip, give). +[finale-nostretch] +desc = If the window dimension aspect ratio is not equal to but close to that of the original game, fixed-aspect finale animations will be stretched 1= disabled. + [menu-flash-r] desc = Menu selection flash color, red component. diff --git a/doomsday/plugins/jdoom64/include/d_config.h b/doomsday/plugins/jdoom64/include/d_config.h index 650bd4799f..42517cc956 100644 --- a/doomsday/plugins/jdoom64/include/d_config.h +++ b/doomsday/plugins/jdoom64/include/d_config.h @@ -169,6 +169,8 @@ typedef struct jdoom64_config_s { byte automapPanResetOnOpen; float automapOpenSeconds; + byte fiNoStretch; // Do not stretch finales to fill the screen at near 4:3 aspect ratios. + int msgCount; float msgScale; float msgUptime; diff --git a/doomsday/plugins/jdoom64/src/d_main.c b/doomsday/plugins/jdoom64/src/d_main.c index 33c50d6538..972324bf37 100644 --- a/doomsday/plugins/jdoom64/src/d_main.c +++ b/doomsday/plugins/jdoom64/src/d_main.c @@ -255,6 +255,7 @@ void G_PreInit(void) cfg.dclickUse = false; cfg.povLookAround = true; cfg.screenBlocks = cfg.setBlocks = 10; + cfg.fiNoStretch = false; cfg.echoMsg = true; cfg.lookSpeed = 3; cfg.turnSpeed = 1; diff --git a/doomsday/plugins/jheretic/data/conhelp.txt b/doomsday/plugins/jheretic/data/conhelp.txt index 74076017ef..0218515392 100644 --- a/doomsday/plugins/jheretic/data/conhelp.txt +++ b/doomsday/plugins/jheretic/data/conhelp.txt @@ -208,6 +208,9 @@ desc = 1=Disable exit buttons during map rotation. [server-game-cheat] desc = 1=Allow cheating in multiplayer games (god, noclip, give). +[finale-nostretch] +desc = If the window dimension aspect ratio is not equal to but close to that of the original game, fixed-aspect finale animations will be stretched 1= disabled. + [menu-flash-r] desc = Menu selection flash color, red component. diff --git a/doomsday/plugins/jheretic/include/h_config.h b/doomsday/plugins/jheretic/include/h_config.h index 0c3eec9ef7..9bfa4c4f06 100644 --- a/doomsday/plugins/jheretic/include/h_config.h +++ b/doomsday/plugins/jheretic/include/h_config.h @@ -171,6 +171,8 @@ typedef struct jheretic_config_s { byte automapPanResetOnOpen; float automapOpenSeconds; + byte fiNoStretch; // Do not stretch finales to fill the screen at near 4:3 aspect ratios. + int msgCount; float msgScale; float msgUptime; diff --git a/doomsday/plugins/jheretic/src/h_main.c b/doomsday/plugins/jheretic/src/h_main.c index c2eabcf594..c10c10ed0c 100644 --- a/doomsday/plugins/jheretic/src/h_main.c +++ b/doomsday/plugins/jheretic/src/h_main.c @@ -261,6 +261,7 @@ void G_PreInit(void) cfg.povLookAround = true; cfg.statusbarScale = 1; cfg.screenBlocks = cfg.setBlocks = 10; + cfg.fiNoStretch = false; cfg.echoMsg = true; cfg.lookSpeed = 3; cfg.turnSpeed = 1; diff --git a/doomsday/plugins/jhexen/data/conhelp.txt b/doomsday/plugins/jhexen/data/conhelp.txt index 813e04047a..af151b4177 100644 --- a/doomsday/plugins/jhexen/data/conhelp.txt +++ b/doomsday/plugins/jhexen/data/conhelp.txt @@ -220,6 +220,9 @@ desc = 1=Disable exit buttons during map rotation. [server-game-cheat] desc = 1=Allow cheating in multiplayer games (god, noclip, give). +[finale-nostretch] +desc = If the window dimension aspect ratio is not equal to but close to that of the original game, fixed-aspect finale animations will be stretched 1= disabled. + [menu-flash-r] desc = Menu selection flash color, red component. diff --git a/doomsday/plugins/jhexen/include/x_config.h b/doomsday/plugins/jhexen/include/x_config.h index abe4d98bc4..66a89bcc4b 100644 --- a/doomsday/plugins/jhexen/include/x_config.h +++ b/doomsday/plugins/jhexen/include/x_config.h @@ -141,6 +141,8 @@ typedef struct { byte automapPanResetOnOpen; float automapOpenSeconds; + byte fiNoStretch; // Do not stretch finales to fill the screen at near 4:3 aspect ratios. + int messagesOn; char* chatMacros[10]; byte chatBeep; diff --git a/doomsday/plugins/jhexen/src/h2_main.c b/doomsday/plugins/jhexen/src/h2_main.c index 2fba8a796a..fe712ac4ca 100644 --- a/doomsday/plugins/jhexen/src/h2_main.c +++ b/doomsday/plugins/jhexen/src/h2_main.c @@ -245,6 +245,7 @@ void G_PreInit(void) cfg.statusbarScale = 1; cfg.dclickUse = false; cfg.screenBlocks = cfg.setBlocks = 10; + cfg.fiNoStretch = false; cfg.hudShown[HUD_MANA] = true; cfg.hudShown[HUD_HEALTH] = true; cfg.hudShown[HUD_CURRENTITEM] = true;