mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-02-26 05:41:07 +00:00
- advanced coordinate control for overlays over DTA_Fullscreen images.
This commit is contained in:
parent
09d163cb2f
commit
9f6d244016
8 changed files with 105 additions and 46 deletions
|
@ -40,6 +40,7 @@
|
||||||
#include "texturemanager.h"
|
#include "texturemanager.h"
|
||||||
#include "r_videoscale.h"
|
#include "r_videoscale.h"
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
|
#include "intrect.h"
|
||||||
|
|
||||||
EXTERN_CVAR(Int, vid_aspect)
|
EXTERN_CVAR(Int, vid_aspect)
|
||||||
EXTERN_CVAR(Int, uiscale)
|
EXTERN_CVAR(Int, uiscale)
|
||||||
|
@ -329,6 +330,50 @@ DEFINE_ACTION_FUNCTION(_Screen, GetClipRect)
|
||||||
return MIN(numret, 4);
|
return MIN(numret, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void CalcFullscreenScale(F2DDrawer* drawer, double srcwidth, double srcheight, int autoaspect, DoubleRect &rect)
|
||||||
|
{
|
||||||
|
auto GetWidth = [=]() { return drawer->GetWidth(); };
|
||||||
|
auto GetHeight = [=]() {return drawer->GetHeight(); };
|
||||||
|
|
||||||
|
double aspect;
|
||||||
|
if (srcheight == 200) aspect = srcwidth / 240.;
|
||||||
|
else if (srcheight == 400) aspect = srcwidth / 480;
|
||||||
|
else aspect = srcwidth / srcheight;
|
||||||
|
rect.left = rect.top = 0;
|
||||||
|
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 pillarboxed 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.);
|
||||||
|
rect.width = (double)GetWidth() * srcwidth / width4_3;
|
||||||
|
rect.height = GetHeight() * screenratio * (3. / 4.); // use 4:3 for the image
|
||||||
|
rect.top = (GetHeight() - rect.height) / 2;
|
||||||
|
rect.left = -(srcwidth - width4_3) / 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((screenratio > aspect) ^ (autoaspect == 2))
|
||||||
|
{
|
||||||
|
// pillarboxed or vertically cropped (i.e. scale to height)
|
||||||
|
rect.height = GetHeight();
|
||||||
|
rect.width = GetWidth() * aspect / screenratio;
|
||||||
|
rect.left = (GetWidth() - rect.width) / 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// letterboxed or horizontally cropped (i.e. scale to width)
|
||||||
|
rect.width = GetWidth();
|
||||||
|
rect.height = GetHeight() * screenratio / aspect;
|
||||||
|
rect.top = (GetHeight() - rect.height) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Draw parameter parsing
|
// Draw parameter parsing
|
||||||
|
@ -384,49 +429,30 @@ bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FGameTexture *img, do
|
||||||
parms->destheight = parms->texheight * CleanYfac_1;
|
parms->destheight = parms->texheight * CleanYfac_1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DTA_Base:
|
||||||
|
if (parms->fsscalemode != -1)
|
||||||
|
{
|
||||||
|
// First calculate the destination rect for an image of the given size and then reposition this object in it.
|
||||||
|
DoubleRect rect;
|
||||||
|
CalcFullscreenScale(drawer, parms->virtWidth, parms->virtHeight, parms->fsscalemode, rect);
|
||||||
|
parms->x = rect.left + parms->x * rect.width / parms->virtWidth;
|
||||||
|
parms->y = rect.top + parms->y * rect.height / parms->virtHeight;
|
||||||
|
parms->destwidth = parms->destwidth * rect.width / parms->virtWidth;
|
||||||
|
parms->destheight = parms->destheight * rect.height / parms->virtHeight;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case DTA_Fullscreen:
|
case DTA_Fullscreen:
|
||||||
case DTA_FullscreenEx:
|
case DTA_FullscreenEx:
|
||||||
{
|
{
|
||||||
double aspect;
|
DoubleRect rect;
|
||||||
double srcwidth = img->GetDisplayWidth();
|
CalcFullscreenScale(drawer, img->GetDisplayWidth(), img->GetDisplayHeight(), parms->fsscalemode, rect);
|
||||||
double srcheight = img->GetDisplayHeight();
|
|
||||||
int autoaspect = parms->fsscalemode;
|
|
||||||
if (srcheight == 200) aspect = srcwidth / 240.;
|
|
||||||
else if (srcheight == 400) aspect = srcwidth / 480;
|
|
||||||
else aspect = srcwidth / srcheight;
|
|
||||||
parms->x = parms->y = 0;
|
|
||||||
parms->keepratio = true;
|
parms->keepratio = true;
|
||||||
auto screenratio = ActiveRatio(GetWidth(), GetHeight());
|
parms->x = rect.left;
|
||||||
if (autoaspect == 3)
|
parms->y = rect.top;
|
||||||
{
|
parms->destwidth = rect.width;
|
||||||
if (screenratio >= aspect || aspect < 1.4) autoaspect = 1; // screen is wider than the image -> pillarbox it. 4:3 images must also be pillarboxed if the screen is taller than the image
|
parms->destheight = rect.height;
|
||||||
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!
|
return false; // Do not call VirtualToRealCoords for this!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,6 +624,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
|
||||||
parms->burn = false;
|
parms->burn = false;
|
||||||
parms->monospace = EMonospacing::Off;
|
parms->monospace = EMonospacing::Off;
|
||||||
parms->spacing = 0;
|
parms->spacing = 0;
|
||||||
|
parms->fsscalemode = -1;
|
||||||
|
|
||||||
// Parse the tag list for attributes. (For floating point attributes,
|
// Parse the tag list for attributes. (For floating point attributes,
|
||||||
// consider that the C ABI dictates that all floats be promoted to
|
// consider that the C ABI dictates that all floats be promoted to
|
||||||
|
@ -717,6 +744,14 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
|
||||||
parms->cleanmode = DTA_Base;
|
parms->cleanmode = DTA_Base;
|
||||||
parms->virtHeight = ListGetDouble(tags);
|
parms->virtHeight = ListGetDouble(tags);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DTA_FullscreenScale:
|
||||||
|
intval = ListGetInt(tags);
|
||||||
|
if (intval >= 0 && intval <= 3)
|
||||||
|
{
|
||||||
|
parms->fsscalemode = (uint8_t)intval;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case DTA_Fullscreen:
|
case DTA_Fullscreen:
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,8 @@ enum
|
||||||
DTA_Monospace, // Fonts only: Use a fixed distance between characters.
|
DTA_Monospace, // Fonts only: Use a fixed distance between characters.
|
||||||
|
|
||||||
DTA_FullscreenEx,
|
DTA_FullscreenEx,
|
||||||
|
DTA_FullscreenScale,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EMonospacing : int
|
enum EMonospacing : int
|
||||||
|
@ -152,7 +154,7 @@ struct DrawParms
|
||||||
bool fortext;
|
bool fortext;
|
||||||
bool virtBottom;
|
bool virtBottom;
|
||||||
bool burn;
|
bool burn;
|
||||||
uint8_t fsscalemode;
|
int8_t fsscalemode;
|
||||||
double srcx, srcy;
|
double srcx, srcy;
|
||||||
double srcwidth, srcheight;
|
double srcwidth, srcheight;
|
||||||
};
|
};
|
||||||
|
|
|
@ -332,7 +332,7 @@ void FSkyVertexBuffer::SetupMatrices(FGameTexture *tex, float x_offset, float y_
|
||||||
modelMatrix.loadIdentity();
|
modelMatrix.loadIdentity();
|
||||||
modelMatrix.rotate(-180.0f + x_offset, 0.f, 1.f, 0.f);
|
modelMatrix.rotate(-180.0f + x_offset, 0.f, 1.f, 0.f);
|
||||||
|
|
||||||
float xscale = texw < 1024.f ? floor(1024.f / float(texw)) : 1.f;
|
float xscale = texw < 1024.f ? floorf(1024.f / float(texw)) : 1.f;
|
||||||
float yscale = 1.f;
|
float yscale = 1.f;
|
||||||
auto texskyoffset = tex->GetSkyOffset() + skyoffset;
|
auto texskyoffset = tex->GetSkyOffset() + skyoffset;
|
||||||
if (texh <= 128 && tiled)
|
if (texh <= 128 && tiled)
|
||||||
|
|
|
@ -462,7 +462,7 @@ float FTexCoordInfo::TextureAdjustWidth() const
|
||||||
{
|
{
|
||||||
float tscale = fabsf(mTempScale.X);
|
float tscale = fabsf(mTempScale.X);
|
||||||
if (tscale == 1.f) return (float)mRenderWidth;
|
if (tscale == 1.f) return (float)mRenderWidth;
|
||||||
else return mWidth / fabs(tscale);
|
else return mWidth / fabsf(tscale);
|
||||||
}
|
}
|
||||||
else return (float)mWidth;
|
else return (float)mWidth;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,3 +19,23 @@ struct FloatRect
|
||||||
height*=yfac;
|
height*=yfac;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DoubleRect
|
||||||
|
{
|
||||||
|
double left, top;
|
||||||
|
double width, height;
|
||||||
|
|
||||||
|
|
||||||
|
void Offset(double xofs, double yofs)
|
||||||
|
{
|
||||||
|
left += xofs;
|
||||||
|
top += yofs;
|
||||||
|
}
|
||||||
|
void Scale(double xfac, double yfac)
|
||||||
|
{
|
||||||
|
left *= xfac;
|
||||||
|
width *= xfac;
|
||||||
|
top *= yfac;
|
||||||
|
height *= yfac;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -1986,10 +1986,10 @@ class CommandAspectRatio : public SBarInfoCommandFlowControl
|
||||||
};
|
};
|
||||||
|
|
||||||
int ratio = ratioTypes[0].second;
|
int ratio = ratioTypes[0].second;
|
||||||
float distance = fabs(ratioTypes[0].first - aspect);
|
float distance = fabsf(ratioTypes[0].first - aspect);
|
||||||
for (int i = 1; ratioTypes[i].first != 0.0f; i++)
|
for (int i = 1; ratioTypes[i].first != 0.0f; i++)
|
||||||
{
|
{
|
||||||
float d = fabs(ratioTypes[i].first - aspect);
|
float d = fabsf(ratioTypes[i].first - aspect);
|
||||||
if (d < distance)
|
if (d < distance)
|
||||||
{
|
{
|
||||||
ratio = ratioTypes[i].second;
|
ratio = ratioTypes[i].second;
|
||||||
|
|
|
@ -601,7 +601,7 @@ void DInterBackground::drawBackground(int state, bool drawsplat, bool snl_pointe
|
||||||
// placing the animations precisely where they belong on the base pic
|
// placing the animations precisely where they belong on the base pic
|
||||||
animwidth = background->GetDisplayWidth();
|
animwidth = background->GetDisplayWidth();
|
||||||
animheight = background->GetDisplayHeight();
|
animheight = background->GetDisplayHeight();
|
||||||
if (gameinfo.fullscreenautoaspect == 3 && animheight == 200 && animwidth > 320) animwidth = 320; // deal with widescreen replacements that keep the original coordinates.
|
if (gameinfo.fullscreenautoaspect > 0) animwidth = 320; // deal with widescreen replacements that keep the original coordinates.
|
||||||
DrawTexture(twod, background, 0, 0, DTA_Fullscreen, true, TAG_DONE);
|
DrawTexture(twod, background, 0, 0, DTA_Fullscreen, true, TAG_DONE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -658,7 +658,7 @@ void DInterBackground::drawBackground(int state, bool drawsplat, bool snl_pointe
|
||||||
}
|
}
|
||||||
if (a->ctr >= 0)
|
if (a->ctr >= 0)
|
||||||
DrawTexture(twod, a->frames[a->ctr], a->loc.x, a->loc.y,
|
DrawTexture(twod, a->frames[a->ctr], a->loc.x, a->loc.y,
|
||||||
DTA_VirtualWidthF, animwidth, DTA_VirtualHeightF, animheight, TAG_DONE);
|
DTA_VirtualWidthF, animwidth, DTA_VirtualHeightF, animheight, DTA_FullscreenScale, gameinfo.fullscreenautoaspect, TAG_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drawsplat)
|
if (drawsplat)
|
||||||
|
|
|
@ -193,6 +193,8 @@ enum DrawTextureTags
|
||||||
DTA_Monospace, // Strings only: Use a fixed distance between characters.
|
DTA_Monospace, // Strings only: Use a fixed distance between characters.
|
||||||
|
|
||||||
DTA_FullscreenEx, // advanced fullscreen control.
|
DTA_FullscreenEx, // advanced fullscreen control.
|
||||||
|
DTA_FullscreenScale, // enable DTA_Fullscreen coordinate calculation for placed overlays.
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Shape2DTransform : Object native
|
class Shape2DTransform : Object native
|
||||||
|
|
Loading…
Reference in a new issue