mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-28 06:53:58 +00:00
- add an option to the ListMenu class to draw to a fixed virtual screen size.
This allows proper dimensions in the stock menus and should make menu layout for mods a lot easier because coordinates are more predictable than with the clean factors. The feature is opt-in for custom content. As long as only stock elements are used, the menu will be able to switch between both on its own, but as soon as custom classes or custom elements are used, the virtual size must be declared explicitly, defaulting to clean scaling.
This commit is contained in:
parent
acd71f7019
commit
f1b0f32786
8 changed files with 165 additions and 67 deletions
|
@ -410,6 +410,29 @@ void CalcFullscreenScale(DrawParms *parms, double srcwidth, double srcheight, in
|
|||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Screen, GetFullscreenRect)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_FLOAT(virtw);
|
||||
PARAM_FLOAT(virth);
|
||||
PARAM_INT(fsmode);
|
||||
|
||||
if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function");
|
||||
|
||||
DrawParms parms;
|
||||
DoubleRect rect;
|
||||
parms.viewport.width = twod->GetWidth();
|
||||
parms.viewport.height = twod->GetHeight();
|
||||
CalcFullscreenScale(&parms, virtw, virth, fsmode, rect);
|
||||
if (numret >= 1) ret[0].SetFloat(rect.left);
|
||||
if (numret >= 2) ret[1].SetFloat(rect.top);
|
||||
if (numret >= 3) ret[2].SetFloat(rect.width);
|
||||
if (numret >= 4) ret[3].SetFloat(rect.height);
|
||||
return MIN(numret, 4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Draw parameter parsing
|
||||
|
@ -460,6 +483,13 @@ bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FGameTexture *img, do
|
|||
parms->destheight = parms->texheight * CleanYfac;
|
||||
break;
|
||||
|
||||
case DTA_CleanTop:
|
||||
parms->x = (parms->x - 160.0) * CleanXfac + (GetWidth() * 0.5);
|
||||
parms->y = (parms->y) * CleanYfac;
|
||||
parms->destwidth = parms->texwidth * CleanXfac;
|
||||
parms->destheight = parms->texheight * CleanYfac;
|
||||
break;
|
||||
|
||||
case DTA_CleanNoMove:
|
||||
parms->destwidth = parms->texwidth * CleanXfac;
|
||||
parms->destheight = parms->texheight * CleanYfac;
|
||||
|
@ -716,6 +746,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
|
|||
break;
|
||||
|
||||
case DTA_Clean:
|
||||
case DTA_CleanTop:
|
||||
boolval = ListGetInt(tags);
|
||||
if (boolval)
|
||||
{
|
||||
|
|
|
@ -130,6 +130,7 @@ enum
|
|||
DTA_Rotate,
|
||||
DTA_FlipOffsets, // Flips offsets when using DTA_FlipX and DTA_FlipY, this cannot be automatic due to unexpected behavior with unoffsetted graphics.
|
||||
DTA_Indexed, // Use an indexed texture combined with the given translation.
|
||||
DTA_CleanTop, // Like DTA_Clean but aligns to the top of the screen instead of the center.
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -270,6 +270,8 @@ static bool CheckSkipOptionBlock(FScanner &sc)
|
|||
|
||||
static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
|
||||
{
|
||||
bool sizeset = false;
|
||||
bool sizecompatible = true;
|
||||
sc.MustGetStringName("{");
|
||||
while (!sc.CheckString("}"))
|
||||
{
|
||||
|
@ -303,6 +305,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
|
|||
sc.ScriptError("Unknown menu class '%s'", sc.String);
|
||||
}
|
||||
desc->mClass = cls;
|
||||
sizecompatible = false;
|
||||
}
|
||||
else if (sc.Compare("Selector"))
|
||||
{
|
||||
|
@ -382,14 +385,23 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
|
|||
{
|
||||
desc->mVirtWidth = -1;
|
||||
}
|
||||
if (sc.Compare("optclean"))
|
||||
else if (sc.Compare("optclean"))
|
||||
{
|
||||
desc->mVirtWidth = -2;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Invalid value '%s' for 'size'", sc.String);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// all item classes from which we know that they support sized scaling.
|
||||
// If anything else comes through here the option to swich scaling mode is disabled for this menu.
|
||||
static const char* const compatibles[] = { "StaticPatch", "StaticText", "StaticTextCentered", "TextItem", "PatchItem", "PlayerDisplay", nullptr };
|
||||
if (sc.MatchString(compatibles) < 0) sizecompatible = false;
|
||||
|
||||
bool success = false;
|
||||
FStringf buildname("ListMenuItem%s", sc.String);
|
||||
PClass *cls = PClass::FindClass(buildname);
|
||||
|
@ -521,6 +533,10 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!sizeset && sizecompatible) // allow unclean scaling on this menu
|
||||
{
|
||||
desc->mVirtWidth = -2;
|
||||
}
|
||||
for (auto &p : desc->mItems)
|
||||
{
|
||||
GC::WriteBarrier(p);
|
||||
|
|
|
@ -231,7 +231,6 @@ ListMenu "EpisodeMenu"
|
|||
|
||||
ListMenu "SkillMenu"
|
||||
{
|
||||
|
||||
IfGame(Doom, Chex)
|
||||
{
|
||||
StaticPatch 96, 14, "M_NEWG", 0, "$MNU_NEWGAME"
|
||||
|
@ -289,6 +288,7 @@ ListMenu "LoadGameMenu"
|
|||
StaticTextCentered 160, -10, "$MNU_LOADGAME"
|
||||
Position 80,54
|
||||
Class "LoadMenu" // uses its own implementation
|
||||
Size Clean
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
@ -302,6 +302,7 @@ ListMenu "SaveGameMenu"
|
|||
StaticTextCentered 160, -10, "$MNU_SAVEGAME"
|
||||
Position 80,54
|
||||
Class "SaveMenu" // uses its own implementation
|
||||
Size Clean
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -124,6 +124,30 @@ struct TexMan
|
|||
native static void SetCameraToTexture(Actor viewpoint, String texture, double fov);
|
||||
}
|
||||
|
||||
enum EScaleMode
|
||||
{
|
||||
FSMode_None = 0,
|
||||
FSMode_ScaleToFit = 1,
|
||||
FSMode_ScaleToFill = 2,
|
||||
FSMode_ScaleToFit43 = 3,
|
||||
FSMode_ScaleToScreen = 4,
|
||||
FSMode_ScaleToFit43Top = 5,
|
||||
FSMode_ScaleToFit43Bottom = 6,
|
||||
FSMode_ScaleToHeight = 7,
|
||||
|
||||
|
||||
FSMode_Max,
|
||||
|
||||
// These all use ScaleToFit43, their purpose is to cut down on verbosity because they imply the virtual screen size.
|
||||
FSMode_Predefined = 1000,
|
||||
FSMode_Fit320x200 = 1000,
|
||||
FSMode_Fit320x240,
|
||||
FSMode_Fit640x400,
|
||||
FSMode_Fit640x480,
|
||||
FSMode_Fit320x200Top,
|
||||
FSMode_Predefined_Max,
|
||||
};
|
||||
|
||||
enum DrawTextureTags
|
||||
{
|
||||
TAG_USER = (1<<30),
|
||||
|
@ -208,6 +232,7 @@ enum DrawTextureTags
|
|||
DTA_Rotate,
|
||||
DTA_FlipOffsets, // Flips offsets when using DTA_FlipX and DTA_FlipY, this cannot be automatic due to unexpected behavior with unoffsetted graphics.
|
||||
DTA_Indexed, // Use an indexed texture combined with the given translation.
|
||||
DTA_CleanTop, // Like DTA_Clean but aligns to the top of the screen instead of the center.
|
||||
|
||||
};
|
||||
|
||||
|
@ -257,6 +282,8 @@ struct Screen native
|
|||
native static void ClearClipRect();
|
||||
native static int, int, int, int GetClipRect();
|
||||
native static int, int, int, int GetViewWindow();
|
||||
native static double, double, double, double GetFullscreenRect(double vwidth, double vheight, int fsmode);
|
||||
|
||||
|
||||
|
||||
// This is a leftover of the abandoned Inventory.DrawPowerup method.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
class ListMenuDescriptor : MenuDescriptor native
|
||||
{
|
||||
enum
|
||||
enum EScale
|
||||
{
|
||||
CleanScale = -1,
|
||||
OptCleanScale = -2
|
||||
|
@ -249,10 +249,10 @@ class ListMenu : Menu
|
|||
{
|
||||
for(int i=0;i<mDesc.mItems.Size(); i++)
|
||||
{
|
||||
if (mDesc.mItems[i].mEnabled) mDesc.mItems[i].Drawer(mDesc.mSelectedItem == i);
|
||||
if (mDesc.mItems[i].mEnabled) mDesc.mItems[i].Draw(mDesc.mSelectedItem == i, mDesc);
|
||||
}
|
||||
if (mDesc.mSelectedItem >= 0 && mDesc.mSelectedItem < mDesc.mItems.Size())
|
||||
mDesc.mItems[mDesc.mSelectedItem].DrawSelector(mDesc.mSelectOfsX, mDesc.mSelectOfsY, mDesc.mSelector);
|
||||
mDesc.mItems[mDesc.mSelectedItem].DrawSelector(mDesc.mSelectOfsX, mDesc.mSelectOfsY, mDesc.mSelector, mDesc);
|
||||
Super.Drawer();
|
||||
}
|
||||
|
||||
|
|
|
@ -35,26 +35,54 @@
|
|||
|
||||
class ListMenuItem : MenuItemBase
|
||||
{
|
||||
virtual void DrawSelector(double xofs, double yofs, TextureID tex)
|
||||
protected void DrawText(ListMenuDescriptor desc, Font fnt, int color, double x, double y, String text, bool ontop = false)
|
||||
{
|
||||
int w = desc ? desc.DisplayWidth() : ListMenuDescriptor.CleanScale;
|
||||
int h = desc ? desc.DisplayHeight() : -1;
|
||||
if (w == ListMenuDescriptor.CleanScale)
|
||||
{
|
||||
screen.DrawText(fnt, color, x, y, text, ontop? DTA_CleanTop : DTA_Clean, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
screen.DrawText(fnt, color, x, y, text, DTA_VirtualWidth, w, DTA_VirtualHeight, h, DTA_FullscreenScale, FSMode_ScaleToFit43);
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawTexture(ListMenuDescriptor desc, TextureID tex, double x, double y, bool ontop = false)
|
||||
{
|
||||
int w = desc ? desc.DisplayWidth() : ListMenuDescriptor.CleanScale;
|
||||
int h = desc ? desc.DisplayHeight() : -1;
|
||||
if (w == ListMenuDescriptor.CleanScale)
|
||||
{
|
||||
screen.DrawTexture(tex, true, x, y, ontop ? DTA_CleanTop : DTA_Clean, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
screen.DrawTexture(tex, true, x, y, DTA_VirtualWidth, w, DTA_VirtualHeight, h, DTA_FullscreenScale, FSMode_ScaleToFit43);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void DrawSelector(double xofs, double yofs, TextureID tex, ListMenuDescriptor desc = null)
|
||||
{
|
||||
if (tex.isNull())
|
||||
{
|
||||
if ((Menu.MenuTime() % 8) < 6)
|
||||
{
|
||||
screen.DrawText(ConFont, OptionMenuSettings.mFontColorSelection,
|
||||
(mXpos + xofs - 160) * CleanXfac + screen.GetWidth() / 2,
|
||||
(mYpos + yofs - 100) * CleanYfac + screen.GetHeight() / 2,
|
||||
"\xd",
|
||||
DTA_CellX, 8 * CleanXfac,
|
||||
DTA_CellY, 8 * CleanYfac
|
||||
);
|
||||
DrawText(desc, ConFont, OptionMenuSettings.mFontColorSelection, mXpos + xofs, mYpos + yofs + 8, "\xd");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
screen.DrawTexture (tex, true, mXpos + xofs, mYpos + yofs, DTA_Clean, true);
|
||||
DrawTexture(desc, tex, mXpos + xofs, mYpos + yofs);
|
||||
}
|
||||
}
|
||||
|
||||
// We cannot extend Drawer here because it is inherited from the parent class.
|
||||
virtual void Draw(bool selected, ListMenuDescriptor desc)
|
||||
{
|
||||
Drawer(selected); // fall back to the legacy version, if not overridden
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -82,43 +110,26 @@ class ListMenuItemStaticPatch : ListMenuItem
|
|||
|
||||
}
|
||||
|
||||
override void Drawer(bool selected)
|
||||
override void Draw(bool selected, ListMenuDescriptor desc)
|
||||
{
|
||||
if (!mTexture.Exists())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let font = generic_ui? NewSmallFont : mFont;
|
||||
|
||||
double x = mXpos;
|
||||
Vector2 vec = TexMan.GetScaledSize(mTexture);
|
||||
if (mYpos >= 0)
|
||||
|
||||
if (mSubstitute == "" || TexMan.OkForLocalization(mTexture, mSubstitute))
|
||||
{
|
||||
if (mSubstitute == "" || TexMan.OkForLocalization(mTexture, mSubstitute))
|
||||
{
|
||||
if (mCentered) x -= vec.X / 2;
|
||||
screen.DrawTexture (mTexture, true, x, mYpos, DTA_Clean, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mCentered) x -= font.StringWidth(mSubstitute)/2;
|
||||
screen.DrawText(font, mColor, x, mYpos, mSubstitute, DTA_Clean, true);
|
||||
}
|
||||
if (mCentered) x -= vec.X / 2;
|
||||
DrawTexture(desc, mTexture, x, abs(mYpos), mYpos < 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = (mXpos - 160) * CleanXfac + (Screen.GetWidth()>>1);
|
||||
if (mSubstitute == "" || TexMan.OkForLocalization(mTexture, mSubstitute))
|
||||
{
|
||||
if (mCentered) x -= (vec.X * CleanXfac)/2;
|
||||
screen.DrawTexture (mTexture, true, x, -mYpos*CleanYfac, DTA_CleanNoMove, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mCentered) x -= (font.StringWidth(mSubstitute) * CleanXfac)/2;
|
||||
screen.DrawText(font, mColor, x, mYpos, mSubstitute, DTA_CleanNoMove, true);
|
||||
}
|
||||
let font = generic_ui ? NewSmallFont : mFont;
|
||||
if (mCentered) x -= font.StringWidth(mSubstitute) / 2;
|
||||
DrawText(desc, font, mColor, x, abs(mYpos), mSubstitute, mYpos < 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -162,25 +173,17 @@ class ListMenuItemStaticText : ListMenuItem
|
|||
mCentered = centered;
|
||||
}
|
||||
|
||||
override void Drawer(bool selected)
|
||||
override void Draw(bool selected, ListMenuDescriptor desc)
|
||||
{
|
||||
if (mText.Length() != 0)
|
||||
{
|
||||
let font = generic_ui? NewSmallFont : mFont;
|
||||
|
||||
String text = Stringtable.Localize(mText);
|
||||
if (mYpos >= 0)
|
||||
{
|
||||
double x = mXpos;
|
||||
if (mCentered) x -= font.StringWidth(text)/2;
|
||||
screen.DrawText(font, mColor, x, mYpos, text, DTA_Clean, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
double x = (mXpos - 160) * CleanXfac + (Screen.GetWidth() >> 1);
|
||||
if (mCentered) x -= (font.StringWidth(text) * CleanXfac)/2;
|
||||
screen.DrawText (font, mColor, x, -mYpos*CleanYfac, text, DTA_CleanNoMove, true);
|
||||
}
|
||||
|
||||
double x = mXpos;
|
||||
if (mCentered) x -= font.StringWidth(text) / 2;
|
||||
DrawText(desc, font, mColor, x, abs(mYpos), text, mYpos < 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -288,10 +291,10 @@ class ListMenuItemTextItem : ListMenuItemSelectable
|
|||
mHotkey = hotkey.GetNextCodePoint(0);
|
||||
}
|
||||
|
||||
override void Drawer(bool selected)
|
||||
override void Draw(bool selected, ListMenuDescriptor desc)
|
||||
{
|
||||
let font = generic_ui? NewSmallFont : mFont;
|
||||
screen.DrawText(font, selected ? mColorSelected : mColor, mXpos, mYpos, mText, DTA_Clean, true);
|
||||
let font = generic_ui ? NewSmallFont : mFont;
|
||||
DrawText(desc, font, selected ? mColorSelected : mColor, mXpos, mYpos, mText);
|
||||
}
|
||||
|
||||
override int GetWidth()
|
||||
|
@ -325,9 +328,9 @@ class ListMenuItemPatchItem : ListMenuItemSelectable
|
|||
mTexture = patch;
|
||||
}
|
||||
|
||||
override void Drawer(bool selected)
|
||||
override void Draw(bool selected, ListMenuDescriptor desc)
|
||||
{
|
||||
screen.DrawTexture (mTexture, true, mXpos, mYpos, DTA_Clean, true);
|
||||
DrawTexture(desc, mTexture, mXpos, mYpos);
|
||||
}
|
||||
|
||||
override int GetWidth()
|
||||
|
|
|
@ -228,7 +228,7 @@ class ListMenuItemPlayerDisplay : ListMenuItem
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
override void Drawer(bool selected)
|
||||
override void Draw(bool selected, ListMenuDescriptor desc)
|
||||
{
|
||||
if (mMode == 0 && !UpdatePlayerClass())
|
||||
{
|
||||
|
@ -241,12 +241,31 @@ class ListMenuItemPlayerDisplay : ListMenuItem
|
|||
if (portrait != 'None' && !mNoportrait)
|
||||
{
|
||||
TextureID texid = TexMan.CheckForTexture(portrait, TexMan.Type_MiscPatch);
|
||||
screen.DrawTexture (texid, true, mXpos, mYpos, DTA_Clean, true);
|
||||
DrawTexture (desc, texid, mXpos, mYpos);
|
||||
}
|
||||
else
|
||||
{
|
||||
int x = int(mXpos - 160) * CleanXfac + (screen.GetWidth() >> 1);
|
||||
int y = int(mYpos - 100) * CleanYfac + (screen.GetHeight() >> 1);
|
||||
// Here we need to calculate the coordinates manually because Screen.DrawFrame only works in window coordinates and have to match the rest to it.
|
||||
int x, y;
|
||||
int w = desc.DisplayWidth();
|
||||
int h = desc.DisplayHeight();
|
||||
double sx, sy;
|
||||
if (w == ListMenuDescriptor.CleanScale)
|
||||
{
|
||||
x = int(mXpos - 160) * CleanXfac + (screen.GetWidth() >> 1);
|
||||
y = int(mYpos - 100) * CleanYfac + (screen.GetHeight() >> 1);
|
||||
sx = CleanXfac;
|
||||
sy = CleanYfac;
|
||||
}
|
||||
else
|
||||
{
|
||||
double fx, fy, fw, fh;
|
||||
[fx, fy, fw, fh] = Screen.GetFullscreenRect(w, h, FSMode_ScaleToFit43);
|
||||
sx = fw / w;
|
||||
sy = fh / h;
|
||||
x = int(fx + mXpos * sx);
|
||||
y = int(fy + mYpos * sy);
|
||||
}
|
||||
|
||||
int r = mBaseColor.r + mAddColor.r;
|
||||
int g = mBaseColor.g + mAddColor.g;
|
||||
|
@ -258,12 +277,12 @@ class ListMenuItemPlayerDisplay : ListMenuItem
|
|||
Color c = Color(255, r, g, b);
|
||||
|
||||
screen.DrawTexture(mBackdrop, false, x, y - 1,
|
||||
DTA_DestWidth, 72 * CleanXfac,
|
||||
DTA_DestHeight, 80 * CleanYfac,
|
||||
DTA_DestWidthF, 72. * sx,
|
||||
DTA_DestHeightF, 80. * sy,
|
||||
DTA_Color, c,
|
||||
DTA_Masked, true);
|
||||
|
||||
Screen.DrawFrame (x, y, 72*CleanXfac, 80*CleanYfac-1);
|
||||
Screen.DrawFrame (x, y, 72*sx, 80*sy-1);
|
||||
|
||||
if (mPlayerState != NULL)
|
||||
{
|
||||
|
@ -277,11 +296,11 @@ class ListMenuItemPlayerDisplay : ListMenuItem
|
|||
{
|
||||
int trans = mTranslate? Translation.MakeID(TRANSLATION_Players, MAXPLAYERS) : 0;
|
||||
let tscale = TexMan.GetScaledSize(sprite);
|
||||
Scale.X *= CleanXfac * tscale.X;
|
||||
Scale.Y *= CleanYfac * tscale.Y;
|
||||
Scale.X *= sx * tscale.X;
|
||||
Scale.Y *= sy * tscale.Y;
|
||||
|
||||
screen.DrawTexture (sprite, false,
|
||||
x + 36*CleanXfac, y + 71*CleanYfac,
|
||||
x + 36*sx, y + 71*sy,
|
||||
DTA_DestWidthF, Scale.X, DTA_DestHeightF, Scale.Y,
|
||||
DTA_TranslationIndex, trans,
|
||||
DTA_FlipX, flip);
|
||||
|
|
Loading…
Reference in a new issue