mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-24 13:11:33 +00:00
Merge branch 'master' of https://github.com/coelckers/gzdoom into vulkan2
This commit is contained in:
commit
655b0c27de
10 changed files with 81 additions and 76 deletions
|
@ -866,12 +866,6 @@ static void M_Dim()
|
|||
amount = gameinfo.dimamount;
|
||||
}
|
||||
|
||||
if (gameinfo.gametype == GAME_Hexen && gamestate == GS_DEMOSCREEN)
|
||||
{ // On the Hexen title screen, the default dimming is not
|
||||
// enough to make the menus readable.
|
||||
amount = MIN<float>(1.f, amount*2.f);
|
||||
}
|
||||
|
||||
screen->Dim(dimmer, amount, 0, 0, screen->GetWidth(), screen->GetHeight());
|
||||
}
|
||||
|
||||
|
|
|
@ -53,12 +53,12 @@ EXTERN_CVAR(Bool, cl_run)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, ColorChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(r);
|
||||
PARAM_INT(g);
|
||||
PARAM_INT(b);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == CurrentMenu)
|
||||
if (DMenu::InMenu)
|
||||
{
|
||||
char command[24];
|
||||
players[consoleplayer].userinfo.ColorChanged(MAKERGB(r, g, b));
|
||||
|
@ -78,12 +78,12 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, ColorChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, PlayerNameChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_STRING(s);
|
||||
const char *pp = s;
|
||||
FString command("name \"");
|
||||
|
||||
if (self == CurrentMenu || self == CurrentMenu->mParentMenu)
|
||||
if (DMenu::InMenu)
|
||||
{
|
||||
// Escape any backslashes or quotation marks before sending the name to the console.
|
||||
for (auto p = pp; *p != '\0'; ++p)
|
||||
|
@ -108,9 +108,9 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, PlayerNameChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, ColorSetChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(sel);
|
||||
if (self == CurrentMenu)
|
||||
if (DMenu::InMenu)
|
||||
{
|
||||
players[consoleplayer].userinfo.ColorSetChanged(sel);
|
||||
char command[24];
|
||||
|
@ -128,10 +128,10 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, ColorSetChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, ClassChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(sel);
|
||||
PARAM_POINTER(cls, FPlayerClass);
|
||||
if (self == CurrentMenu)
|
||||
if (DMenu::InMenu)
|
||||
{
|
||||
players[consoleplayer].userinfo.PlayerClassNumChanged(gameinfo.norandomplayerclass ? sel : sel - 1);
|
||||
cvar_set("playerclass", sel == 0 && !gameinfo.norandomplayerclass ? "Random" : GetPrintableDisplayName(cls->Type).GetChars());
|
||||
|
@ -148,9 +148,9 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, ClassChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, SkinChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(sel);
|
||||
if (self == CurrentMenu)
|
||||
if (DMenu::InMenu)
|
||||
{
|
||||
players[consoleplayer].userinfo.SkinNumChanged(sel);
|
||||
cvar_set("skin", Skins[sel].Name);
|
||||
|
@ -166,10 +166,10 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, SkinChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, AutoaimChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_FLOAT(val);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == CurrentMenu)
|
||||
if (DMenu::InMenu)
|
||||
{
|
||||
autoaim = float(val);
|
||||
}
|
||||
|
@ -184,10 +184,10 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, AutoaimChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, TeamChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(val);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == CurrentMenu)
|
||||
if (DMenu::InMenu)
|
||||
{
|
||||
team = val == 0 ? TEAM_NONE : val - 1;
|
||||
}
|
||||
|
@ -202,10 +202,10 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, TeamChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, GenderChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(v);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == CurrentMenu)
|
||||
if (DMenu::InMenu)
|
||||
{
|
||||
switch(v)
|
||||
{
|
||||
|
@ -226,10 +226,10 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, GenderChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, SwitchOnPickupChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(v);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == CurrentMenu)
|
||||
if (DMenu::InMenu)
|
||||
{
|
||||
neverswitchonpickup = !!v;
|
||||
}
|
||||
|
@ -244,10 +244,10 @@ DEFINE_ACTION_FUNCTION(DPlayerMenu, SwitchOnPickupChanged)
|
|||
|
||||
DEFINE_ACTION_FUNCTION(DPlayerMenu, AlwaysRunChanged)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DMenu);
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(v);
|
||||
// only allow if the menu is active to prevent abuse.
|
||||
if (self == CurrentMenu)
|
||||
if (DMenu::InMenu)
|
||||
{
|
||||
cl_run = !!v;
|
||||
}
|
||||
|
|
|
@ -2652,12 +2652,14 @@ OptionMenu "ReverbSave" protected
|
|||
OptionString "LanguageOptions"
|
||||
{
|
||||
"auto", "Auto"
|
||||
"default", "English (US)"
|
||||
"eng", "English (UK)"
|
||||
"enu", "English (US)"
|
||||
"fr", "Français (FR)"
|
||||
"ita", "Italiano (ITA)"
|
||||
"ptb", "Português do Brasil (PTB)"
|
||||
"rus", "Русский (RU)"
|
||||
"de", "Deutsch"
|
||||
"es", "Español (España)"
|
||||
"esm", "Español (Latino)"
|
||||
"fr", "Français"
|
||||
"it", "Italiano"
|
||||
"ru", "Русский"
|
||||
}
|
||||
|
||||
/*=======================================
|
||||
|
|
|
@ -127,7 +127,7 @@ class LoadSaveMenu : ListMenu
|
|||
savepicHeight = 135*screen.GetHeight() / 400;
|
||||
|
||||
FontScale = max(screen.GetHeight() / 480, 1);
|
||||
rowHeight = max((NewConsoleFont.GetHeight() + 1) * FontScale, 1);
|
||||
rowHeight = int(max((NewConsoleFont.GetHeight() + 1) * FontScale, 1));
|
||||
|
||||
listboxLeft = savepicLeft + savepicWidth + 14;
|
||||
listboxTop = savepicTop;
|
||||
|
@ -216,7 +216,7 @@ class LoadSaveMenu : ListMenu
|
|||
if (manager.SavegameCount() == 0)
|
||||
{
|
||||
String text = Stringtable.Localize("$MNU_NOFILES");
|
||||
int textlen = NewConsoleFont.StringWidth(text) * FontScale;
|
||||
int textlen = int(NewConsoleFont.StringWidth(text) * FontScale);
|
||||
|
||||
screen.DrawText (NewConsoleFont, Font.CR_GOLD, (listboxLeft+(listboxWidth-textlen)/2) / FontScale, (listboxTop+(listboxHeight-rowHeight)/2) / FontScale, text,
|
||||
DTA_VirtualWidthF, screen.GetWidth() / FontScale, DTA_VirtualHeightF, screen.GetHeight() / FontScale, DTA_KeepRatio, true);
|
||||
|
@ -259,7 +259,7 @@ class LoadSaveMenu : ListMenu
|
|||
else
|
||||
{
|
||||
String s = mInput.GetText() .. NewConsoleFont.GetCursor();
|
||||
int length = NewConsoleFont.StringWidth(s) * FontScale;
|
||||
int length = int(NewConsoleFont.StringWidth(s) * FontScale);
|
||||
int displacement = min(0, listboxWidth - 2 - length);
|
||||
screen.DrawText (NewConsoleFont, Font.CR_WHITE, (listboxLeft + 1 + displacement) / FontScale, (listboxTop+rowHeight*i + FontScale) / FontScale, s,
|
||||
DTA_VirtualWidthF, screen.GetWidth() / FontScale, DTA_VirtualHeightF, screen.GetHeight() / FontScale, DTA_KeepRatio, true);
|
||||
|
@ -277,7 +277,7 @@ class LoadSaveMenu : ListMenu
|
|||
|
||||
void UpdateSaveComment()
|
||||
{
|
||||
BrokenSaveComment = NewConsoleFont.BreakLines(manager.SaveCommentString, commentWidth / FontScale);
|
||||
BrokenSaveComment = NewConsoleFont.BreakLines(manager.SaveCommentString, int(commentWidth / FontScale));
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -512,7 +512,7 @@ class SaveMenu : LoadSaveMenu
|
|||
if (mkey == MKEY_Enter)
|
||||
{
|
||||
String SavegameString = (Selected != 0)? manager.GetSavegame(Selected).SaveTitle : "";
|
||||
mInput = TextEnterMenu.OpenTextEnter(self, ConFont, SavegameString, -1, fromcontroller);
|
||||
mInput = TextEnterMenu.OpenTextEnter(self, Menu.OptionFont(), SavegameString, -1, fromcontroller);
|
||||
mInput.ActivateMenu();
|
||||
mEntering = true;
|
||||
}
|
||||
|
|
|
@ -1033,7 +1033,13 @@ class OptionMenuItemTextField : OptionMenuFieldBase
|
|||
override String Represent()
|
||||
{
|
||||
if (mEnter) return mEnter.GetText() .. Menu.OptionFont().GetCursor();
|
||||
else return GetCVarString();
|
||||
else
|
||||
{
|
||||
bool b;
|
||||
String s;
|
||||
[b, s] = GetString(0);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
override int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected)
|
||||
|
@ -1053,14 +1059,17 @@ class OptionMenuItemTextField : OptionMenuFieldBase
|
|||
{
|
||||
if (mkey == Menu.MKEY_Enter)
|
||||
{
|
||||
bool b;
|
||||
String s;
|
||||
[b, s] = GetString(0);
|
||||
Menu.MenuSound("menu/choose");
|
||||
mEnter = TextEnterMenu.OpenTextEnter(Menu.GetCurrentMenu(), Menu.OptionFont(), GetCVarString(), -1, fromcontroller);
|
||||
mEnter = TextEnterMenu.OpenTextEnter(Menu.GetCurrentMenu(), Menu.OptionFont(), s, -1, fromcontroller);
|
||||
mEnter.ActivateMenu();
|
||||
return true;
|
||||
}
|
||||
else if (mkey == Menu.MKEY_Input)
|
||||
{
|
||||
if (mCVar) mCVar.SetString(mEnter.GetText());
|
||||
SetString(0, mEnter.GetText());
|
||||
mEnter = null;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -187,7 +187,7 @@ class ListMenuItemPlayerNameBox : ListMenuItemSelectable
|
|||
if (mkey == Menu.MKEY_Enter)
|
||||
{
|
||||
Menu.MenuSound ("menu/choose");
|
||||
mEnter = TextEnterMenu.OpenTextEnter(Menu.GetCurrentMenu(), SmallFont, mPlayerName, 128, fromcontroller);
|
||||
mEnter = TextEnterMenu.OpenTextEnter(Menu.GetCurrentMenu(), Menu.OptionFont(), mPlayerName, 128, fromcontroller);
|
||||
mEnter.ActivateMenu();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -42,16 +42,16 @@ class PlayerMenu : ListMenu
|
|||
Array<int> mPlayerSkins;
|
||||
|
||||
// All write function for the player config are native to prevent abuse.
|
||||
protected native void AutoaimChanged(float val);
|
||||
protected native void TeamChanged(int val);
|
||||
protected native void AlwaysRunChanged(int val);
|
||||
protected native void GenderChanged(int val);
|
||||
protected native void SwitchOnPickupChanged(int val);
|
||||
protected native void ColorChanged(int red, int green, int blue);
|
||||
protected native void ColorSetChanged(int red);
|
||||
protected native void PlayerNameChanged(String name);
|
||||
protected native void SkinChanged (int val);
|
||||
protected native void ClassChanged(int sel, PlayerClass cls);
|
||||
protected static native void AutoaimChanged(float val);
|
||||
protected static native void TeamChanged(int val);
|
||||
protected static native void AlwaysRunChanged(int val);
|
||||
protected static native void GenderChanged(int val);
|
||||
protected static native void SwitchOnPickupChanged(int val);
|
||||
protected static native void ColorChanged(int red, int green, int blue);
|
||||
protected static native void ColorSetChanged(int red);
|
||||
protected static native void PlayerNameChanged(String name);
|
||||
protected static native void SkinChanged (int val);
|
||||
protected static native void ClassChanged(int sel, PlayerClass cls);
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
|
|
|
@ -24,7 +24,7 @@ class os_SearchField : OptionMenuItemTextField
|
|||
if (mkey == Menu.MKEY_Enter)
|
||||
{
|
||||
Menu.MenuSound("menu/choose");
|
||||
mEnter = TextEnterMenu.OpenTextEnter(Menu.GetCurrentMenu(), SmallFont, mText, -1, fromcontroller);
|
||||
mEnter = TextEnterMenu.OpenTextEnter(Menu.GetCurrentMenu(), Menu.OptionFont(), mText, -1, fromcontroller);
|
||||
mEnter.ActivateMenu();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -175,8 +175,8 @@ class TextEnterMenu : Menu
|
|||
|
||||
override bool MouseEvent(int type, int x, int y)
|
||||
{
|
||||
int cell_width = 18 * CleanXfac;
|
||||
int cell_height = 12 * CleanYfac;
|
||||
int cell_width = 18 * CleanXfac_1;
|
||||
int cell_height = 16 * CleanYfac_1;
|
||||
int screen_y = screen.GetHeight() - INPUTGRID_HEIGHT * cell_height;
|
||||
int screen_x = (screen.GetWidth() - INPUTGRID_WIDTH * cell_width) / 2;
|
||||
|
||||
|
@ -264,7 +264,7 @@ class TextEnterMenu : Menu
|
|||
case MKEY_Clear:
|
||||
if (mEnterString.Length() > 0)
|
||||
{
|
||||
mEnterString.Truncate(mEnterString.Length() - 1);
|
||||
mEnterString.DeleteLastCharacter();
|
||||
}
|
||||
return true;
|
||||
|
||||
|
@ -297,7 +297,7 @@ class TextEnterMenu : Menu
|
|||
return true;
|
||||
|
||||
default:
|
||||
break; // Keep GCC quiet
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -316,9 +316,9 @@ class TextEnterMenu : Menu
|
|||
if (mInputGridOkay)
|
||||
{
|
||||
String InputGridChars = Chars;
|
||||
int cell_width = 18 * CleanXfac;
|
||||
int cell_height = 12 * CleanYfac;
|
||||
int top_padding = cell_height / 2 - displayFont.GetHeight() * CleanYfac / 2;
|
||||
int cell_width = 18 * CleanXfac_1;
|
||||
int cell_height = 16 * CleanYfac_1;
|
||||
int top_padding = cell_height / 2 - displayFont.GetHeight() * CleanYfac_1 / 2;
|
||||
|
||||
// Darken the background behind the character grid.
|
||||
screen.Dim(0, 0.8, 0, screen.GetHeight() - INPUTGRID_HEIGHT * cell_height, screen.GetWidth(), INPUTGRID_HEIGHT * cell_height);
|
||||
|
@ -348,27 +348,27 @@ class TextEnterMenu : Menu
|
|||
if (ch > 32)
|
||||
{
|
||||
// Draw a normal character.
|
||||
screen.DrawChar(displayFont, colr, xx + cell_width/2 - width*CleanXfac/2, yy + top_padding, ch, DTA_CleanNoMove, true);
|
||||
screen.DrawChar(displayFont, colr, xx + cell_width/2 - width*CleanXfac_1/2, yy + top_padding, ch, DTA_CleanNoMove_1, true);
|
||||
}
|
||||
else if (ch == 32)
|
||||
{
|
||||
// Draw the space as a box outline. We also draw it 50% wider than it really is.
|
||||
int x1 = xx + cell_width/2 - width * CleanXfac * 3 / 4;
|
||||
int x2 = x1 + width * 3 * CleanXfac / 2;
|
||||
int x1 = xx + cell_width/2 - width * CleanXfac_1 * 3 / 4;
|
||||
int x2 = x1 + width * 3 * CleanXfac_1 / 2;
|
||||
int y1 = yy + top_padding;
|
||||
int y2 = y1 + displayFont.GetHeight() * CleanYfac;
|
||||
screen.Clear(x1, y1, x2, y1+CleanYfac, palcolor); // top
|
||||
screen.Clear(x1, y2, x2, y2+CleanYfac, palcolor); // bottom
|
||||
screen.Clear(x1, y1+CleanYfac, x1+CleanXfac, y2, palcolor); // left
|
||||
screen.Clear(x2-CleanXfac, y1+CleanYfac, x2, y2, palcolor); // right
|
||||
int y2 = y1 + displayFont.GetHeight() * CleanYfac_1;
|
||||
screen.Clear(x1, y1, x2, y1+CleanYfac_1, palcolor); // top
|
||||
screen.Clear(x1, y2, x2, y2+CleanYfac_1, palcolor); // bottom
|
||||
screen.Clear(x1, y1+CleanYfac_1, x1+CleanXfac_1, y2, palcolor); // left
|
||||
screen.Clear(x2-CleanXfac_1, y1+CleanYfac_1, x2, y2, palcolor); // right
|
||||
}
|
||||
else if (ch == 8 || ch == 0)
|
||||
{
|
||||
// Draw the backspace and end "characters".
|
||||
String str = ch == 8 ? "BS" : "ED";
|
||||
screen.DrawText(displayFont, colr,
|
||||
xx + cell_width/2 - displayFont.StringWidth(str)*CleanXfac/2,
|
||||
yy + top_padding, str, DTA_CleanNoMove, true);
|
||||
xx + cell_width/2 - displayFont.StringWidth(str)*CleanXfac_1/2,
|
||||
yy + top_padding, str, DTA_CleanNoMove_1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ class CoopStatusScreen : StatusScreen
|
|||
ng_state = 1;
|
||||
displayFont = NewSmallFont;
|
||||
FontScale = max(screen.GetHeight() / 480, 1);
|
||||
RowHeight = max((displayFont.GetHeight() + 1) * FontScale, 1);
|
||||
RowHeight = int(max((displayFont.GetHeight() + 1) * FontScale, 1));
|
||||
|
||||
cnt_pause = Thinker.TICRATE;
|
||||
|
||||
|
@ -229,7 +229,7 @@ class CoopStatusScreen : StatusScreen
|
|||
Vector2 readyoffset = TexMan.GetScaledOffset(readyico);
|
||||
height = int(readysize.Y - readyoffset.Y);
|
||||
maxiconheight = MAX(height, maxiconheight);
|
||||
height = displayFont.GetHeight() * FontScale;
|
||||
height = int(displayFont.GetHeight() * FontScale);
|
||||
lineheight = MAX(height, maxiconheight * CleanYfac);
|
||||
ypadding = (lineheight - height + 1) / 2;
|
||||
y += CleanYfac;
|
||||
|
@ -238,11 +238,11 @@ class CoopStatusScreen : StatusScreen
|
|||
text_secret = Stringtable.Localize("$SCORE_SECRET");
|
||||
text_kills = Stringtable.Localize("$SCORE_KILLS");
|
||||
|
||||
icon_x = 8 * FontScale;
|
||||
name_x = icon_x + maxscorewidth * FontScale;
|
||||
kills_x = name_x + (maxnamewidth + 1 + MAX(displayFont.StringWidth("XXXXXXXXXX"), displayFont.StringWidth(text_kills)) + 16) * FontScale;
|
||||
bonus_x = kills_x + ((bonus_len = displayFont.StringWidth(text_bonus)) + 16) * FontScale;
|
||||
secret_x = bonus_x + ((secret_len = displayFont.StringWidth(text_secret)) + 16) * FontScale;
|
||||
icon_x = int(8 * FontScale);
|
||||
name_x = int(icon_x + maxscorewidth * FontScale);
|
||||
kills_x = int(name_x + (maxnamewidth + 1 + MAX(displayFont.StringWidth("XXXXXXXXXX"), displayFont.StringWidth(text_kills)) + 16) * FontScale);
|
||||
bonus_x = int(kills_x + ((bonus_len = displayFont.StringWidth(text_bonus)) + 16) * FontScale);
|
||||
secret_x = int(bonus_x + ((secret_len = displayFont.StringWidth(text_secret)) + 16) * FontScale);
|
||||
|
||||
x = (screen.GetWidth() - secret_x) >> 1;
|
||||
icon_x += x;
|
||||
|
@ -256,7 +256,7 @@ class CoopStatusScreen : StatusScreen
|
|||
drawTextScaled(displayFont, kills_x - displayFont.StringWidth(text_kills) * FontScale, y, text_kills, FontScale, textcolor);
|
||||
drawTextScaled(displayFont, bonus_x - bonus_len * FontScale, y, text_bonus, FontScale, textcolor);
|
||||
drawTextScaled(displayFont, secret_x - secret_len * FontScale, y, text_secret, FontScale, textcolor);
|
||||
y += height + 6 * FontScale;
|
||||
y += int(height + 6 * FontScale);
|
||||
|
||||
missed_kills = wbs.maxkills;
|
||||
missed_items = wbs.maxitems;
|
||||
|
|
Loading…
Reference in a new issue