mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-14 00:20:51 +00:00
- implemented better aspect ratio control for fullscreen images.
Due to backwards compatibility needs and for flexibility this needs to be controlled by a gameinfo setting (fullscreenautoaspect): 0: Treat all images as having an aspect ratio of 4:3, this is the default for compatibility reasons 1: Scale all images to fit the screen, i.e. either pillarbox or letterbox them. 2: Scale all images to fill the screen. 3: Scale all images so that the center 4:3 area is always fully visible. This is the recommended mode for 16:9 images designed to be shown with the sides being cropped on narrower displays. A new DTA_ tag - DTA_FullscreenEx also exists which allows specifying the scale mode directly
This commit is contained in:
parent
2edbbac759
commit
db5efddf12
5 changed files with 64 additions and 76 deletions
|
@ -116,6 +116,7 @@ const char* GameInfoBorders[] =
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define GAMEINFOKEY_CSTRING(key, variable, length) \
|
#define GAMEINFOKEY_CSTRING(key, variable, length) \
|
||||||
else if(nextKey.CompareNoCase(variable) == 0) \
|
else if(nextKey.CompareNoCase(variable) == 0) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -382,6 +383,7 @@ void FMapInfoParser::ParseGameInfo()
|
||||||
GAMEINFOKEY_DOUBLE(telefogheight, "telefogheight")
|
GAMEINFOKEY_DOUBLE(telefogheight, "telefogheight")
|
||||||
GAMEINFOKEY_DOUBLE(gibfactor, "gibfactor")
|
GAMEINFOKEY_DOUBLE(gibfactor, "gibfactor")
|
||||||
GAMEINFOKEY_INT(defKickback, "defKickback")
|
GAMEINFOKEY_INT(defKickback, "defKickback")
|
||||||
|
GAMEINFOKEY_INT(fullscreenautoaspect, "fullscreenautoaspect")
|
||||||
GAMEINFOKEY_STRING(SkyFlatName, "SkyFlatName")
|
GAMEINFOKEY_STRING(SkyFlatName, "SkyFlatName")
|
||||||
GAMEINFOKEY_STRING(translator, "translator")
|
GAMEINFOKEY_STRING(translator, "translator")
|
||||||
GAMEINFOKEY_COLOR(pickupcolor, "pickupcolor")
|
GAMEINFOKEY_COLOR(pickupcolor, "pickupcolor")
|
||||||
|
|
|
@ -204,6 +204,7 @@ struct gameinfo_t
|
||||||
int berserkpic;
|
int berserkpic;
|
||||||
double normforwardmove[2];
|
double normforwardmove[2];
|
||||||
double normsidemove[2];
|
double normsidemove[2];
|
||||||
|
int fullscreenautoaspect = 3;
|
||||||
|
|
||||||
const char *GetFinalePage(unsigned int num) const;
|
const char *GetFinalePage(unsigned int num) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -375,8 +375,48 @@ bool DFrameBuffer::SetTextureParms(DrawParms *parms, FTexture *img, double xx, d
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DTA_Fullscreen:
|
case DTA_Fullscreen:
|
||||||
|
case DTA_FullscreenEx:
|
||||||
|
{
|
||||||
|
double aspect;
|
||||||
|
double srcwidth = img->GetDisplayWidthDouble();
|
||||||
|
double srcheight = img->GetDisplayHeightDouble();
|
||||||
|
int autoaspect = parms->fsscalemode;
|
||||||
|
aspect = autoaspect == 0 || (srcwidth == 320 && srcheight == 200) || (srcwidth == 640 && srcheight == 200)? 1.333 : srcwidth / srcheight;
|
||||||
parms->x = parms->y = 0;
|
parms->x = parms->y = 0;
|
||||||
break;
|
parms->keepratio = true;
|
||||||
|
auto screenratio = ActiveRatio(GetWidth(), GetHeight());
|
||||||
|
if (autoaspect == 3)
|
||||||
|
{
|
||||||
|
if (screenratio >= aspect || aspect < 1.4) autoaspect = 1; // screen is wider than the image -> pillarbox it. 4:3 images must also be pillarboxes if the screen is taller than the image
|
||||||
|
else if (screenratio > 1.32) autoaspect = 2; // on anything 4:3 and wider crop the sides of the image.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// special case: Crop image to 4:3 and then letterbox this. This avoids too much cropping on narrow windows.
|
||||||
|
double width4_3 = srcheight * (4. / 3.);
|
||||||
|
parms->destwidth = (double)GetWidth() * srcwidth / width4_3;
|
||||||
|
parms->destheight = GetHeight() * screenratio * (3. / 4.); // use 4:3 for the image
|
||||||
|
parms->y = (GetHeight() - parms->destheight) / 2;
|
||||||
|
parms->x = -(srcwidth - width4_3) / 2;
|
||||||
|
return false; // Do not call VirtualToRealCoords for this!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((screenratio > aspect) ^ (autoaspect == 2))
|
||||||
|
{
|
||||||
|
// pillarboxed or vertically cropped (i.e. scale to height)
|
||||||
|
parms->destheight = GetHeight();
|
||||||
|
parms->destwidth =GetWidth() * aspect / screenratio;
|
||||||
|
parms->x = (GetWidth() - parms->destwidth) / 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// letterboxed or horizontally cropped (i.e. scale to width)
|
||||||
|
parms->destwidth = GetWidth();
|
||||||
|
parms->destheight = GetHeight() * screenratio / aspect;
|
||||||
|
parms->y = (GetHeight() - parms->destheight) / 2;
|
||||||
|
}
|
||||||
|
return false; // Do not call VirtualToRealCoords for this!
|
||||||
|
}
|
||||||
|
|
||||||
case DTA_HUDRules:
|
case DTA_HUDRules:
|
||||||
case DTA_HUDRulesC:
|
case DTA_HUDRulesC:
|
||||||
|
@ -667,12 +707,28 @@ bool DFrameBuffer::ParseDrawTextureTags(FTexture *img, double x, double y, uint3
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DTA_Fullscreen:
|
case DTA_Fullscreen:
|
||||||
|
|
||||||
boolval = ListGetInt(tags);
|
boolval = ListGetInt(tags);
|
||||||
if (boolval)
|
if (boolval)
|
||||||
{
|
{
|
||||||
assert(fortext == false);
|
assert(fortext == false);
|
||||||
if (img == NULL) return false;
|
if (img == NULL) return false;
|
||||||
parms->cleanmode = DTA_Fullscreen;
|
parms->cleanmode = DTA_Fullscreen;
|
||||||
|
parms->fsscalemode = (uint8_t)gameinfo.fullscreenautoaspect;
|
||||||
|
parms->virtWidth = img->GetDisplayWidthDouble();
|
||||||
|
parms->virtHeight = img->GetDisplayHeightDouble();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DTA_FullscreenEx:
|
||||||
|
|
||||||
|
intval = ListGetInt(tags);
|
||||||
|
if (intval >= 0 && intval <= 3)
|
||||||
|
{
|
||||||
|
assert(fortext == false);
|
||||||
|
if (img == NULL) return false;
|
||||||
|
parms->cleanmode = DTA_Fullscreen;
|
||||||
|
parms->fsscalemode = (uint8_t)intval;
|
||||||
parms->virtWidth = img->GetDisplayWidthDouble();
|
parms->virtWidth = img->GetDisplayWidthDouble();
|
||||||
parms->virtHeight = img->GetDisplayHeightDouble();
|
parms->virtHeight = img->GetDisplayHeightDouble();
|
||||||
}
|
}
|
||||||
|
|
|
@ -702,51 +702,6 @@ DEFINE_ACTION_FUNCTION(_Screen, GetAspectRatio)
|
||||||
ACTION_RETURN_FLOAT(ActiveRatio(screen->GetWidth(), screen->GetHeight(), nullptr));
|
ACTION_RETURN_FLOAT(ActiveRatio(screen->GetWidth(), screen->GetHeight(), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tries to guess the physical dimensions of the screen based on the
|
|
||||||
// screen's pixel dimensions. Can return:
|
|
||||||
// 0: 4:3
|
|
||||||
// 1: 16:9
|
|
||||||
// 2: 16:10
|
|
||||||
// 3: 17:10
|
|
||||||
// 4: 5:4
|
|
||||||
// 5: 17:10 (redundant, never returned)
|
|
||||||
// 6: 21:9
|
|
||||||
int CheckRatio (int width, int height, int *trueratio)
|
|
||||||
{
|
|
||||||
float aspect = width / (float)height;
|
|
||||||
|
|
||||||
static std::pair<float, int> ratioTypes[] =
|
|
||||||
{
|
|
||||||
{ 21 / 9.0f , 6 },
|
|
||||||
{ 16 / 9.0f , 1 },
|
|
||||||
{ 17 / 10.0f , 3 },
|
|
||||||
{ 16 / 10.0f , 2 },
|
|
||||||
{ 4 / 3.0f , 0 },
|
|
||||||
{ 5 / 4.0f , 4 },
|
|
||||||
{ 0.0f, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
int ratio = ratioTypes[0].second;
|
|
||||||
float distance = fabs(ratioTypes[0].first - aspect);
|
|
||||||
for (int i = 1; ratioTypes[i].first != 0.0f; i++)
|
|
||||||
{
|
|
||||||
float d = fabs(ratioTypes[i].first - aspect);
|
|
||||||
if (d < distance)
|
|
||||||
{
|
|
||||||
ratio = ratioTypes[i].second;
|
|
||||||
distance = d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int fakeratio = ActiveFakeRatio(width, height);
|
|
||||||
if (fakeratio == -1)
|
|
||||||
fakeratio = ratio;
|
|
||||||
|
|
||||||
if (trueratio)
|
|
||||||
*trueratio = ratio;
|
|
||||||
return fakeratio;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AspectBaseWidth(float aspect)
|
int AspectBaseWidth(float aspect)
|
||||||
{
|
{
|
||||||
return (int)round(240.0f * aspect * 3.0f);
|
return (int)round(240.0f * aspect * 3.0f);
|
||||||
|
@ -781,32 +736,6 @@ bool AspectTallerThanWide(float aspect)
|
||||||
return aspect < 1.333f;
|
return aspect < 1.333f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScaleWithAspect (int &w, int &h, int Width, int Height)
|
|
||||||
{
|
|
||||||
int resRatio = CheckRatio (Width, Height);
|
|
||||||
int screenRatio;
|
|
||||||
CheckRatio (w, h, &screenRatio);
|
|
||||||
if (resRatio == screenRatio)
|
|
||||||
return;
|
|
||||||
|
|
||||||
double yratio;
|
|
||||||
switch(resRatio)
|
|
||||||
{
|
|
||||||
case 0: yratio = 4./3.; break;
|
|
||||||
case 1: yratio = 16./9.; break;
|
|
||||||
case 2: yratio = 16./10.; break;
|
|
||||||
case 3: yratio = 17./10.; break;
|
|
||||||
case 4: yratio = 5./4.; break;
|
|
||||||
case 6: yratio = 21./9.; break;
|
|
||||||
default: return;
|
|
||||||
}
|
|
||||||
double y = w/yratio;
|
|
||||||
if (y > h)
|
|
||||||
w = static_cast<int>(h * yratio);
|
|
||||||
else
|
|
||||||
h = static_cast<int>(y);
|
|
||||||
}
|
|
||||||
|
|
||||||
CCMD(vid_setsize)
|
CCMD(vid_setsize)
|
||||||
{
|
{
|
||||||
if (argv.argc() < 3)
|
if (argv.argc() < 3)
|
||||||
|
|
|
@ -240,6 +240,8 @@ enum
|
||||||
DTA_Burn, // activates the burn shader for this element
|
DTA_Burn, // activates the burn shader for this element
|
||||||
DTA_Spacing, // Strings only: Additional spacing between characters
|
DTA_Spacing, // Strings only: Additional spacing between characters
|
||||||
DTA_Monospace, // Fonts only: Use a fixed distance between characters.
|
DTA_Monospace, // Fonts only: Use a fixed distance between characters.
|
||||||
|
|
||||||
|
DTA_FullscreenEx,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EMonospacing : int
|
enum EMonospacing : int
|
||||||
|
@ -303,9 +305,10 @@ struct DrawParms
|
||||||
int maxstrlen;
|
int maxstrlen;
|
||||||
bool fortext;
|
bool fortext;
|
||||||
bool virtBottom;
|
bool virtBottom;
|
||||||
|
bool burn;
|
||||||
|
uint8_t fsscalemode;
|
||||||
double srcx, srcy;
|
double srcx, srcy;
|
||||||
double srcwidth, srcheight;
|
double srcwidth, srcheight;
|
||||||
bool burn;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Va_List
|
struct Va_List
|
||||||
|
@ -621,8 +624,6 @@ FString V_GetColorStringByName (const char *name, FScriptPosition *sc = nullptr)
|
||||||
int V_GetColor (const uint32_t *palette, const char *str, FScriptPosition *sc = nullptr);
|
int V_GetColor (const uint32_t *palette, const char *str, FScriptPosition *sc = nullptr);
|
||||||
int V_GetColor(const uint32_t *palette, FScanner &sc);
|
int V_GetColor(const uint32_t *palette, FScanner &sc);
|
||||||
|
|
||||||
int CheckRatio (int width, int height, int *trueratio=NULL);
|
|
||||||
static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); }
|
|
||||||
inline bool IsRatioWidescreen(int ratio) { return (ratio & 3) != 0; }
|
inline bool IsRatioWidescreen(int ratio) { return (ratio & 3) != 0; }
|
||||||
|
|
||||||
float ActiveRatio (int width, int height, float *trueratio = NULL);
|
float ActiveRatio (int width, int height, float *trueratio = NULL);
|
||||||
|
@ -633,7 +634,6 @@ int AspectBaseHeight(float aspect);
|
||||||
double AspectPspriteOffset(float aspect);
|
double AspectPspriteOffset(float aspect);
|
||||||
int AspectMultiplier(float aspect);
|
int AspectMultiplier(float aspect);
|
||||||
bool AspectTallerThanWide(float aspect);
|
bool AspectTallerThanWide(float aspect);
|
||||||
void ScaleWithAspect(int &w, int &h, int Width, int Height);
|
|
||||||
|
|
||||||
int GetUIScale(int altval);
|
int GetUIScale(int altval);
|
||||||
int GetConScale(int altval);
|
int GetConScale(int altval);
|
||||||
|
|
Loading…
Reference in a new issue