mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-25 11:10:47 +00:00
Ball-busting new menus. Still WIP.
Mouse/touch/pointer support is yet to come. #SOON. Exposure to scripting is a LONG way off. Months. The spec and data structure needs time for comment and revision. The eventual scripting access will be Lua-only. git-svn-id: https://svn.eduke32.com/eduke32@4496 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
c24c08599f
commit
11e9b8f4ce
11 changed files with 4668 additions and 5113 deletions
|
@ -935,7 +935,7 @@ nextdemo_nomenu:
|
||||||
if (ud.recstat != 2)
|
if (ud.recstat != 2)
|
||||||
M_DisplayMenus();
|
M_DisplayMenus();
|
||||||
|
|
||||||
if ((g_netServer || ud.multimode > 1) && !M_IsTextInput(g_currentMenu))
|
if ((g_netServer || ud.multimode > 1) && !M_IsTextInput(m_currentMenu))
|
||||||
{
|
{
|
||||||
ControlInfo noshareinfo;
|
ControlInfo noshareinfo;
|
||||||
CONTROL_GetInput(&noshareinfo);
|
CONTROL_GetInput(&noshareinfo);
|
||||||
|
@ -945,7 +945,6 @@ nextdemo_nomenu:
|
||||||
CONTROL_ClearButton(gamefunc_SendMessage);
|
CONTROL_ClearButton(gamefunc_SendMessage);
|
||||||
g_player[myconnectindex].ps->gm = MODE_TYPE;
|
g_player[myconnectindex].ps->gm = MODE_TYPE;
|
||||||
typebuf[0] = 0;
|
typebuf[0] = 0;
|
||||||
inputloc = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1240,15 +1240,10 @@ int32_t G_GameTextLen(int32_t x,const char *t)
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t mpgametext(int32_t y,const char *t,int32_t s,int32_t dabits)
|
|
||||||
{
|
|
||||||
return G_PrintGameText(4,STARTALPHANUM, 5,y,t,s,0,dabits,0, 0, xdim-1, ydim-1, 65536);
|
|
||||||
}
|
|
||||||
|
|
||||||
// minitext_yofs: in hud_scale-independent, (<<16)-scaled, 0-200-normalized y coords,
|
// minitext_yofs: in hud_scale-independent, (<<16)-scaled, 0-200-normalized y coords,
|
||||||
// (sb&ROTATESPRITE_MAX) only.
|
// (sb&ROTATESPRITE_MAX) only.
|
||||||
static int32_t minitext_yofs = 0;
|
static int32_t minitext_yofs = 0;
|
||||||
static int32_t minitext_lowercase = 0;
|
int32_t minitext_lowercase = 0;
|
||||||
int32_t minitext_(int32_t x,int32_t y,const char *t,int32_t s,int32_t p,int32_t sb)
|
int32_t minitext_(int32_t x,int32_t y,const char *t,int32_t s,int32_t p,int32_t sb)
|
||||||
{
|
{
|
||||||
vec2_t dim;
|
vec2_t dim;
|
||||||
|
@ -1288,6 +1283,15 @@ int32_t minitext_(int32_t x,int32_t y,const char *t,int32_t s,int32_t p,int32_t
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
void shadowminitext(int32_t x,int32_t y,const char *t,int32_t p,int32_t sb)
|
||||||
|
{
|
||||||
|
int32_t f = 0;
|
||||||
|
|
||||||
|
if (!minitext_lowercase)
|
||||||
|
f |= TEXT_UPPERCASE;
|
||||||
|
|
||||||
|
G_ScreenTextShadow(1, 1, MINIFONT, x, y, 65536, 0, 0, t, 0, p, sb, 0, 4, 8, 1, 0, f, 0, 0, xdim-1, ydim-1);
|
||||||
|
}
|
||||||
void creditsminitext(int32_t x,int32_t y,const char *t,int32_t p,int32_t sb)
|
void creditsminitext(int32_t x,int32_t y,const char *t,int32_t p,int32_t sb)
|
||||||
{
|
{
|
||||||
int32_t f = TEXT_XCENTER;
|
int32_t f = TEXT_XCENTER;
|
||||||
|
@ -8847,7 +8851,6 @@ void G_HandleLocalKeys(void)
|
||||||
CONTROL_ClearButton(gamefunc_SendMessage);
|
CONTROL_ClearButton(gamefunc_SendMessage);
|
||||||
g_player[myconnectindex].ps->gm |= MODE_TYPE;
|
g_player[myconnectindex].ps->gm |= MODE_TYPE;
|
||||||
typebuf[0] = 0;
|
typebuf[0] = 0;
|
||||||
inputloc = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (KB_UnBoundKeyPressed(sc_F1)/* || (ud.show_help && I_AdvanceTrigger())*/)
|
if (KB_UnBoundKeyPressed(sc_F1)/* || (ud.show_help && I_AdvanceTrigger())*/)
|
||||||
|
@ -8975,13 +8978,7 @@ FAKE_F3:
|
||||||
g_screenCapture = 0;
|
g_screenCapture = 0;
|
||||||
|
|
||||||
if (g_lastSaveSlot >= 0)
|
if (g_lastSaveSlot >= 0)
|
||||||
{
|
|
||||||
/* inputloc = Bstrlen(&ud.savegame[g_lastSaveSlot][0]);
|
|
||||||
g_currentMenu = MENU_SAVETYPING+g_lastSaveSlot;
|
|
||||||
probey = g_lastSaveSlot; */
|
|
||||||
|
|
||||||
G_SavePlayerMaybeMulti(g_lastSaveSlot);
|
G_SavePlayerMaybeMulti(g_lastSaveSlot);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (KB_UnBoundKeyPressed(sc_F7))
|
if (KB_UnBoundKeyPressed(sc_F7))
|
||||||
|
@ -9046,7 +9043,7 @@ FAKE_F3:
|
||||||
if (KB_UnBoundKeyPressed(sc_F10))
|
if (KB_UnBoundKeyPressed(sc_F10))
|
||||||
{
|
{
|
||||||
KB_ClearKeyDown(sc_F10);
|
KB_ClearKeyDown(sc_F10);
|
||||||
M_ChangeMenu(MENU_QUIT);
|
M_ChangeMenu(MENU_QUIT_INGAME);
|
||||||
FX_StopAllSounds();
|
FX_StopAllSounds();
|
||||||
S_ClearSoundLocks();
|
S_ClearSoundLocks();
|
||||||
g_player[myconnectindex].ps->gm |= MODE_MENU;
|
g_player[myconnectindex].ps->gm |= MODE_MENU;
|
||||||
|
@ -11064,7 +11061,6 @@ static int32_t G_EndOfLevel(void)
|
||||||
G_DoOrderScreen();
|
G_DoOrderScreen();
|
||||||
g_player[myconnectindex].ps->gm = MODE_MENU;
|
g_player[myconnectindex].ps->gm = MODE_MENU;
|
||||||
M_ChangeMenu(MENU_MAIN);
|
M_ChangeMenu(MENU_MAIN);
|
||||||
probey = 0;
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -11820,6 +11816,8 @@ int32_t app_main(int32_t argc, const char **argv)
|
||||||
}
|
}
|
||||||
// loadtmb();
|
// loadtmb();
|
||||||
|
|
||||||
|
M_Init();
|
||||||
|
|
||||||
if (ud.warp_on > 1 && (!g_netServer && ud.multimode < 2))
|
if (ud.warp_on > 1 && (!g_netServer && ud.multimode < 2))
|
||||||
{
|
{
|
||||||
clearview(0L);
|
clearview(0L);
|
||||||
|
@ -11841,6 +11839,8 @@ int32_t app_main(int32_t argc, const char **argv)
|
||||||
|
|
||||||
MAIN_LOOP_RESTART:
|
MAIN_LOOP_RESTART:
|
||||||
|
|
||||||
|
M_ChangeMenu(MENU_MAIN);
|
||||||
|
|
||||||
if (g_networkMode != NET_DEDICATED_SERVER)
|
if (g_networkMode != NET_DEDICATED_SERVER)
|
||||||
{
|
{
|
||||||
G_GetCrosshairColor();
|
G_GetCrosshairColor();
|
||||||
|
|
|
@ -261,7 +261,6 @@ extern const char *defaultrtsfilename[GAMECOUNT];
|
||||||
extern const char *G_DefaultRtsFile(void);
|
extern const char *G_DefaultRtsFile(void);
|
||||||
|
|
||||||
extern char g_modDir[BMAX_PATH];
|
extern char g_modDir[BMAX_PATH];
|
||||||
extern char inputloc;
|
|
||||||
#ifdef LEGACY_ROR
|
#ifdef LEGACY_ROR
|
||||||
extern char ror_protectedsectors[MAXSECTORS];
|
extern char ror_protectedsectors[MAXSECTORS];
|
||||||
#endif
|
#endif
|
||||||
|
@ -320,9 +319,12 @@ int32_t G_GameTextLen(int32_t x,const char *t);
|
||||||
int32_t G_PrintGameText(int32_t hack,int32_t tile,int32_t x,int32_t y,const char *t,int32_t s,int32_t p,int32_t o,int32_t x1,int32_t y1,int32_t x2,int32_t y2,int32_t z);
|
int32_t G_PrintGameText(int32_t hack,int32_t tile,int32_t x,int32_t y,const char *t,int32_t s,int32_t p,int32_t o,int32_t x1,int32_t y1,int32_t x2,int32_t y2,int32_t z);
|
||||||
int32_t GetTime(void);
|
int32_t GetTime(void);
|
||||||
int32_t kopen4loadfrommod(const char *filename,char searchfirst);
|
int32_t kopen4loadfrommod(const char *filename,char searchfirst);
|
||||||
|
extern int32_t minitext_lowercase;
|
||||||
int32_t minitext_(int32_t x,int32_t y,const char *t,int32_t s,int32_t p,int32_t sb);
|
int32_t minitext_(int32_t x,int32_t y,const char *t,int32_t s,int32_t p,int32_t sb);
|
||||||
|
void shadowminitext(int32_t x,int32_t y,const char *t,int32_t p,int32_t sb);
|
||||||
void creditsminitext(int32_t x,int32_t y,const char *t,int32_t p,int32_t sb);
|
void creditsminitext(int32_t x,int32_t y,const char *t,int32_t p,int32_t sb);
|
||||||
int32_t mpgametext(int32_t y,const char *t,int32_t s,int32_t dabits);
|
int32_t mpgametext(int32_t y,const char *t,int32_t s,int32_t dabits);
|
||||||
|
|
||||||
int32_t startwin_run(void);
|
int32_t startwin_run(void);
|
||||||
|
|
||||||
#ifdef YAX_ENABLE
|
#ifdef YAX_ENABLE
|
||||||
|
@ -421,11 +423,11 @@ extern char forcegl;
|
||||||
#define gametextscaled(x,y,t,s,dabits) G_PrintGameText(1,STARTALPHANUM, x,y,t,s,0,dabits,0, 0, xdim-1, ydim-1, 65536)
|
#define gametextscaled(x,y,t,s,dabits) G_PrintGameText(1,STARTALPHANUM, x,y,t,s,0,dabits,0, 0, xdim-1, ydim-1, 65536)
|
||||||
#define gametextpal(x,y,t,s,p) G_PrintGameText(0,STARTALPHANUM, x,y,t,s,p,26,0, 0, xdim-1, ydim-1, 65536)
|
#define gametextpal(x,y,t,s,p) G_PrintGameText(0,STARTALPHANUM, x,y,t,s,p,26,0, 0, xdim-1, ydim-1, 65536)
|
||||||
#define gametextpalbits(x,y,t,s,p,dabits) G_PrintGameText(0,STARTALPHANUM, x,y,t,s,p,dabits,0, 0, xdim-1, ydim-1, 65536)
|
#define gametextpalbits(x,y,t,s,p,dabits) G_PrintGameText(0,STARTALPHANUM, x,y,t,s,p,dabits,0, 0, xdim-1, ydim-1, 65536)
|
||||||
|
#define mpgametext(y, t, s, dabits) G_PrintGameText(4,STARTALPHANUM, 5,y,t,s,0,dabits,0, 0, xdim-1, ydim-1, 65536);
|
||||||
|
|
||||||
#define A_CheckSpriteFlags(iActor, iType) (((g_tile[sprite[iActor].picnum].flags^actor[iActor].flags) & iType) != 0)
|
#define A_CheckSpriteFlags(iActor, iType) (((g_tile[sprite[iActor].picnum].flags^actor[iActor].flags) & iType) != 0)
|
||||||
// (unsigned)iPicnum check: AMC TC Rusty Nails, bayonet MG alt. fire, iPicnum == -1 (via aplWeaponShoots)
|
// (unsigned)iPicnum check: AMC TC Rusty Nails, bayonet MG alt. fire, iPicnum == -1 (via aplWeaponShoots)
|
||||||
#define A_CheckSpriteTileFlags(iPicnum, iType) (((unsigned)iPicnum < MAXTILES) && (g_tile[iPicnum].flags & iType) != 0)
|
#define A_CheckSpriteTileFlags(iPicnum, iType) (((unsigned)iPicnum < MAXTILES) && (g_tile[iPicnum].flags & iType) != 0)
|
||||||
#define G_EnterText(x, y, t, dalen, c) _EnterText(0,x,y,t,dalen,c)
|
|
||||||
#define Net_EnterText(x, y, t, dalen, c) _EnterText(1,x,y,t,dalen,c)
|
|
||||||
#define S_StopSound(num) S_StopEnvSound(num, -1)
|
#define S_StopSound(num) S_StopEnvSound(num, -1)
|
||||||
|
|
||||||
extern int32_t G_StartRTS(int32_t i, int localp);
|
extern int32_t G_StartRTS(int32_t i, int localp);
|
||||||
|
|
|
@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include "gamedef.h"
|
#include "gamedef.h"
|
||||||
#include "osd.h"
|
#include "osd.h"
|
||||||
#include "savegame.h"
|
#include "savegame.h"
|
||||||
|
#include "menus.h"
|
||||||
|
|
||||||
#define _gamevars_c_
|
#define _gamevars_c_
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,6 @@ G_EXTERN int32_t animategoal[MAXANIMATES],animatevel[MAXANIMATES],g_animateCount
|
||||||
G_EXTERN int32_t cloudtotalclock;
|
G_EXTERN int32_t cloudtotalclock;
|
||||||
G_EXTERN int32_t fricxv,fricyv;
|
G_EXTERN int32_t fricxv,fricyv;
|
||||||
G_EXTERN int32_t g_currentFrameRate;
|
G_EXTERN int32_t g_currentFrameRate;
|
||||||
G_EXTERN int32_t g_currentMenu;
|
|
||||||
G_EXTERN int32_t g_damageCameras,g_freezerSelfDamage;
|
G_EXTERN int32_t g_damageCameras,g_freezerSelfDamage;
|
||||||
G_EXTERN int32_t g_doQuickSave;
|
G_EXTERN int32_t g_doQuickSave;
|
||||||
G_EXTERN uint16_t g_earthquakeTime;
|
G_EXTERN uint16_t g_earthquakeTime;
|
||||||
|
|
|
@ -179,7 +179,6 @@ int32_t I_EscapeTriggerClear(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int32_t I_PanelUp(void)
|
int32_t I_PanelUp(void)
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
|
@ -248,15 +247,56 @@ int32_t I_PanelDownClear(void)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int32_t I_SliderLeft(void)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
KB_KeyPressed(sc_LeftArrow) ||
|
||||||
|
KB_KeyPressed(sc_kpad_4) ||
|
||||||
|
((MOUSE_GetButtons()&LEFT_MOUSE) && (MOUSE_GetButtons()&WHEELUP_MOUSE)) ||
|
||||||
|
BUTTON(gamefunc_Turn_Left) ||
|
||||||
|
BUTTON(gamefunc_Strafe_Left) ||
|
||||||
|
(JOYSTICK_GetHat(0)&HAT_LEFT)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
int32_t I_SliderLeftClear(void)
|
||||||
|
{
|
||||||
|
KB_ClearKeyDown(sc_LeftArrow);
|
||||||
|
KB_ClearKeyDown(sc_kpad_4);
|
||||||
|
CONTROL_ClearButton(gamefunc_Turn_Left);
|
||||||
|
CONTROL_ClearButton(gamefunc_Strafe_Left);
|
||||||
|
JOYSTICK_ClearHat(0);
|
||||||
|
return (
|
||||||
|
MOUSE_ClearButton(WHEELUP_MOUSE)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t I_SliderRight(void)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
KB_KeyPressed(sc_RightArrow) ||
|
||||||
|
KB_KeyPressed(sc_kpad_6) ||
|
||||||
|
((MOUSE_GetButtons()&LEFT_MOUSE) && (MOUSE_GetButtons()&WHEELDOWN_MOUSE)) ||
|
||||||
|
BUTTON(gamefunc_Turn_Right) ||
|
||||||
|
BUTTON(gamefunc_Strafe_Right) ||
|
||||||
|
(JOYSTICK_GetHat(0)&HAT_RIGHT)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
int32_t I_SliderRightClear(void)
|
||||||
|
{
|
||||||
|
KB_ClearKeyDown(sc_RightArrow);
|
||||||
|
KB_ClearKeyDown(sc_kpad_6);
|
||||||
|
CONTROL_ClearButton(gamefunc_Turn_Right);
|
||||||
|
CONTROL_ClearButton(gamefunc_Strafe_Right);
|
||||||
|
JOYSTICK_ClearHat(0);
|
||||||
|
return (
|
||||||
|
MOUSE_ClearButton(WHEELDOWN_MOUSE)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
char inputloc = 0;
|
int32_t I_EnterText(char *t, int32_t maxlength, int32_t flags)
|
||||||
|
|
||||||
int32_t _EnterText(int32_t small,int32_t x,int32_t y,char *t,int32_t dalen,int32_t c)
|
|
||||||
{
|
{
|
||||||
char ch;
|
char ch;
|
||||||
int32_t i;
|
int32_t inputloc = Bstrlen(typebuf);
|
||||||
const int32_t startx = x;
|
|
||||||
|
|
||||||
while ((ch = KB_GetCh()) != 0)
|
while ((ch = KB_GetCh()) != 0)
|
||||||
{
|
{
|
||||||
|
@ -273,16 +313,16 @@ int32_t _EnterText(int32_t small,int32_t x,int32_t y,char *t,int32_t dalen,int32
|
||||||
if (ch == asc_Enter)
|
if (ch == asc_Enter)
|
||||||
{
|
{
|
||||||
I_AdvanceTriggerClear();
|
I_AdvanceTriggerClear();
|
||||||
return (1);
|
return 1;
|
||||||
}
|
}
|
||||||
else if (ch == asc_Escape)
|
else if (ch == asc_Escape)
|
||||||
{
|
{
|
||||||
I_ReturnTriggerClear();
|
I_ReturnTriggerClear();
|
||||||
return (-1);
|
return -1;
|
||||||
}
|
}
|
||||||
else if (ch >= 32 && inputloc < dalen && ch < 127)
|
else if (ch >= 32 && inputloc < maxlength && ch < 127)
|
||||||
{
|
{
|
||||||
if (c != 997 || (ch >= '0' && ch <= '9'))
|
if (!(flags & INPUT_NUMERIC) || (ch >= '0' && ch <= '9'))
|
||||||
{
|
{
|
||||||
// JBF 20040508: so we can have numeric only if we want
|
// JBF 20040508: so we can have numeric only if we want
|
||||||
*(t+inputloc) = ch;
|
*(t+inputloc) = ch;
|
||||||
|
@ -293,39 +333,13 @@ int32_t _EnterText(int32_t small,int32_t x,int32_t y,char *t,int32_t dalen,int32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == 999) return(0);
|
// All gamefuncs (and *only* _gamefuncs_) in I_ReturnTriggerClear() should be replicated here.
|
||||||
if (c == 998)
|
CONTROL_ClearButton(gamefunc_Crouch);
|
||||||
|
if (I_ReturnTrigger())
|
||||||
{
|
{
|
||||||
char b[91],ii;
|
I_ReturnTriggerClear();
|
||||||
for (ii=0; ii<inputloc; ii++)
|
return -1;
|
||||||
b[(uint8_t)ii] = '*';
|
|
||||||
b[(uint8_t)inputloc] = 0;
|
|
||||||
if (g_player[myconnectindex].ps->gm&MODE_TYPE)
|
|
||||||
x = mpgametext(y,b,c,2+8+16);
|
|
||||||
else x = gametext(x,y,b,c,2+8+16);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (g_player[myconnectindex].ps->gm&MODE_TYPE)
|
|
||||||
x = mpgametext(y,t,c,2+8+16);
|
|
||||||
else x = gametext(x,y,t,c,2+8+16);
|
|
||||||
}
|
|
||||||
c = 4-(sintable[(totalclock<<4)&2047]>>11);
|
|
||||||
|
|
||||||
i = G_GameTextLen(USERQUOTE_LEFTOFFSET,OSD_StripColors(tempbuf,t));
|
|
||||||
while (i > (ud.config.ScreenWidth - USERQUOTE_RIGHTOFFSET))
|
|
||||||
{
|
|
||||||
i -= (ud.config.ScreenWidth - USERQUOTE_RIGHTOFFSET);
|
|
||||||
if (small&1)
|
|
||||||
y += textsc(6);
|
|
||||||
y += 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startx == 160) // gametext center
|
return 0;
|
||||||
x = startx + ((x - startx)>>1);
|
|
||||||
|
|
||||||
if (small&1)
|
|
||||||
rotatesprite_fs(textsc(x)<<16,(y<<16),32768,0,SPINNINGNUKEICON+((totalclock>>3)%7),c,0,(8|16));
|
|
||||||
else rotatesprite_fs((x+8)<<16,(y+4)<<16,32768,0,SPINNINGNUKEICON+((totalclock>>3)%7),c,0,2+8);
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,17 @@ extern int32_t I_PanelUpClear(void);
|
||||||
extern int32_t I_PanelDown(void);
|
extern int32_t I_PanelDown(void);
|
||||||
extern int32_t I_PanelDownClear(void);
|
extern int32_t I_PanelDownClear(void);
|
||||||
|
|
||||||
extern char inputloc;
|
extern int32_t I_SliderLeft(void);
|
||||||
extern int32_t _EnterText(int32_t small,int32_t x,int32_t y,char *t,int32_t dalen,int32_t c);
|
extern int32_t I_SliderLeftClear(void);
|
||||||
|
|
||||||
|
extern int32_t I_SliderRight(void);
|
||||||
|
extern int32_t I_SliderRightClear(void);
|
||||||
|
|
||||||
|
|
||||||
|
enum EnterTextFlags_t {
|
||||||
|
INPUT_NUMERIC = 0x00000001,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int32_t I_EnterText(char *t, int32_t maxlength, int32_t flags);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -23,20 +23,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#ifndef __menus_h__
|
#ifndef __menus_h__
|
||||||
#define __menus_h__
|
#define __menus_h__
|
||||||
|
|
||||||
#include "savegame.h"
|
#include "compat.h"
|
||||||
|
|
||||||
#define MENU_MARGIN_REGULAR 40
|
|
||||||
#define MENU_MARGIN_CENTER 160
|
|
||||||
|
|
||||||
enum MenuIndex_t {
|
enum MenuIndex_t {
|
||||||
|
MENU_NULL = INT32_MIN, // sentinel for "do nothing"
|
||||||
|
MENU_CLOSE = -2, // sentinel for "close the menu"/"no menu"
|
||||||
|
MENU_PREVIOUS = -1, // sentinel for "go to previous menu"
|
||||||
MENU_MAIN = 0,
|
MENU_MAIN = 0,
|
||||||
MENU_MAIN_INGAME = 50,
|
MENU_MAIN_INGAME = 50,
|
||||||
MENU_EPISODE = 100,
|
MENU_EPISODE = 100,
|
||||||
MENU_USERMAP = 101,
|
MENU_USERMAP = 101,
|
||||||
MENU_SELECTMAP = 102,
|
|
||||||
MENU_SKILL = 110,
|
MENU_SKILL = 110,
|
||||||
MENU_SETUP = 200,
|
MENU_GAMESETUP = 200,
|
||||||
MENU_GAMESETUP = 201,
|
|
||||||
MENU_OPTIONS = 202,
|
MENU_OPTIONS = 202,
|
||||||
MENU_VIDEOSETUP = 203,
|
MENU_VIDEOSETUP = 203,
|
||||||
MENU_KEYBOARDSETUP = 204,
|
MENU_KEYBOARDSETUP = 204,
|
||||||
|
@ -44,46 +42,26 @@ enum MenuIndex_t {
|
||||||
MENU_JOYSTICKSETUP = 206,
|
MENU_JOYSTICKSETUP = 206,
|
||||||
MENU_JOYSTICKBTNS = 207,
|
MENU_JOYSTICKBTNS = 207,
|
||||||
MENU_JOYSTICKAXES = 208,
|
MENU_JOYSTICKAXES = 208,
|
||||||
MENU_JOYSTICKAXES2 = 209,
|
MENU_KEYBOARDKEYS = 209,
|
||||||
MENU_KEYBOARDASSIGN = 210,
|
MENU_MOUSEBTNS = 210,
|
||||||
MENU_MOUSEASSIGN = 211,
|
|
||||||
MENU_MOUSEADVANCED = 212,
|
MENU_MOUSEADVANCED = 212,
|
||||||
MENU_JOYSTICKDEAD = 213,
|
MENU_JOYSTICKAXIS = 213,
|
||||||
MENU_JOYSTICKDEAD2 = 214,
|
|
||||||
MENU_JOYSTICKDEAD3 = 215,
|
|
||||||
MENU_JOYSTICKDEAD4 = 216,
|
|
||||||
MENU_JOYSTICKAXES3 = 217,
|
|
||||||
MENU_JOYSTICKAXES4 = 218,
|
|
||||||
MENU_JOYSTICKAXES5 = 219,
|
|
||||||
MENU_JOYSTICKAXES6 = 220,
|
|
||||||
MENU_JOYSTICKAXES7 = 221,
|
|
||||||
MENU_JOYSTICKAXES8 = 222,
|
|
||||||
MENU_RENDERERSETUP = 230,
|
MENU_RENDERERSETUP = 230,
|
||||||
MENU_COLCORR = 231,
|
MENU_COLCORR = 231,
|
||||||
MENU_COLCORR_INGAME = 232,
|
MENU_COLCORR_INGAME = 232,
|
||||||
MENU_LOAD = 300,
|
MENU_LOAD = 300,
|
||||||
MENU_SAVE = 350,
|
MENU_SAVE = 350,
|
||||||
MENU_SAVE_ = 351,
|
|
||||||
MENU_SAVETYPING = 360,
|
|
||||||
MENU_SAVETYPING2 = 361,
|
|
||||||
MENU_SAVETYPING3 = 362,
|
|
||||||
MENU_SAVETYPING4 = 363,
|
|
||||||
MENU_SAVETYPING5 = 364,
|
|
||||||
MENU_SAVETYPING6 = 365,
|
|
||||||
MENU_SAVETYPING7 = 366,
|
|
||||||
MENU_SAVETYPING8 = 367,
|
|
||||||
MENU_SAVETYPING9 = 368,
|
|
||||||
MENU_SAVETYPING10 = 369,
|
|
||||||
MENU_STORY = 400,
|
MENU_STORY = 400,
|
||||||
MENU_F1HELP = 401,
|
MENU_F1HELP = 401,
|
||||||
MENU_ORDERING = 402,
|
MENU_ORDERING = 402,
|
||||||
MENU_ORDERING2 = 403,
|
MENU_ORDERING2 = 403,
|
||||||
|
MENU_ORDERING3 = 404,
|
||||||
|
MENU_ORDERING4 = 405,
|
||||||
MENU_QUIT = 500,
|
MENU_QUIT = 500,
|
||||||
MENU_QUITTOTITLE = 501,
|
MENU_QUITTOTITLE = 501,
|
||||||
MENU_QUIT2 = 502,
|
MENU_QUIT_INGAME = 502,
|
||||||
MENU_NETSETUP = 600,
|
MENU_NETSETUP = 600,
|
||||||
MENU_NETWAITMASTER = 601,
|
MENU_NETWAITMASTER = 601,
|
||||||
MENU_PRENETSETUP = 602,
|
|
||||||
MENU_NETWAITVOTES = 603,
|
MENU_NETWAITVOTES = 603,
|
||||||
MENU_SOUND = 700,
|
MENU_SOUND = 700,
|
||||||
MENU_SOUND_INGAME = 701,
|
MENU_SOUND_INGAME = 701,
|
||||||
|
@ -92,58 +70,290 @@ enum MenuIndex_t {
|
||||||
MENU_CREDITS3 = 992,
|
MENU_CREDITS3 = 992,
|
||||||
MENU_CREDITS4 = 993,
|
MENU_CREDITS4 = 993,
|
||||||
MENU_CREDITS5 = 994,
|
MENU_CREDITS5 = 994,
|
||||||
MENU_CREDITS6 = 995,
|
|
||||||
MENU_CREDITS7 = 996,
|
|
||||||
MENU_CREDITS8 = 997,
|
|
||||||
MENU_CREDITS9 = 998,
|
|
||||||
MENU_CREDITS10 = 999,
|
|
||||||
MENU_LOADVERIFY = 1000,
|
MENU_LOADVERIFY = 1000,
|
||||||
MENU_LOADVERIFY2 = 1001,
|
|
||||||
MENU_LOADVERIFY3 = 1002,
|
|
||||||
MENU_LOADVERIFY4 = 1003,
|
|
||||||
MENU_LOADVERIFY5 = 1004,
|
|
||||||
MENU_LOADVERIFY6 = 1005,
|
|
||||||
MENU_LOADVERIFY7 = 1006,
|
|
||||||
MENU_LOADVERIFY8 = 1007,
|
|
||||||
MENU_LOADVERIFY9 = 1008,
|
|
||||||
MENU_LOADVERIFY10 = 1009,
|
|
||||||
MENU_NEWVERIFY = 1500,
|
MENU_NEWVERIFY = 1500,
|
||||||
MENU_SAVEVERIFY = 2000,
|
MENU_SAVEVERIFY = 2000,
|
||||||
MENU_SAVEVERIFY2 = 2001,
|
|
||||||
MENU_SAVEVERIFY3 = 2002,
|
|
||||||
MENU_SAVEVERIFY4 = 2003,
|
|
||||||
MENU_SAVEVERIFY5 = 2004,
|
|
||||||
MENU_SAVEVERIFY6 = 2005,
|
|
||||||
MENU_SAVEVERIFY7 = 2006,
|
|
||||||
MENU_SAVEVERIFY8 = 2007,
|
|
||||||
MENU_SAVEVERIFY9 = 2008,
|
|
||||||
MENU_SAVEVERIFY10 = 2009,
|
|
||||||
MENU_ADULTMODE = 10000,
|
MENU_ADULTMODE = 10000,
|
||||||
MENU_ADULTPASSWORD = 10001,
|
MENU_ADULTPASSWORD = 10001,
|
||||||
MENU_RESETPLAYER = 15000,
|
MENU_RESETPLAYER = 15000,
|
||||||
MENU_RESETPLAYER2 = 15001,
|
|
||||||
MENU_BUYDUKE = 20000,
|
MENU_BUYDUKE = 20000,
|
||||||
MENU_NETWORK = 20001,
|
MENU_NETWORK = 20001,
|
||||||
MENU_PLAYER = 20002,
|
MENU_PLAYER = 20002,
|
||||||
MENU_PLAYERNAME = 20003,
|
|
||||||
MENU_MACROS = 20004,
|
MENU_MACROS = 20004,
|
||||||
MENU_MACROSTYPING = 20005,
|
|
||||||
MENU_NETHOST = 20010,
|
MENU_NETHOST = 20010,
|
||||||
MENU_NETOPTIONS = 20011,
|
MENU_NETOPTIONS = 20011,
|
||||||
|
MENU_NETUSERMAP = 20012,
|
||||||
MENU_NETJOIN = 20020,
|
MENU_NETJOIN = 20020,
|
||||||
MENU_NETJOINSERVER = 20021,
|
|
||||||
MENU_NETJOINPORT = 20022,
|
|
||||||
|
|
||||||
};
|
};
|
||||||
extern char inputloc;
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef int32_t MenuID_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// a subset of screentext parameters, restricted because menus require accessibility
|
||||||
|
typedef struct MenuTextType_t
|
||||||
|
{
|
||||||
|
int32_t tilenum;
|
||||||
|
int32_t shade_deselected; // selected entries are mandated to glow
|
||||||
|
int32_t pal, pal_disabled;
|
||||||
|
int32_t xspace, yline;
|
||||||
|
int32_t xbetween, ybetween;
|
||||||
|
int32_t textflags;
|
||||||
|
} MenuTextType_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum MenuEntryType_t
|
||||||
|
{
|
||||||
|
Dummy,
|
||||||
|
Link,
|
||||||
|
Option,
|
||||||
|
Custom2Col,
|
||||||
|
RangeInt32,
|
||||||
|
RangeFloat,
|
||||||
|
RangeDouble,
|
||||||
|
String,
|
||||||
|
} MenuEntryType_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct MenuPos_t
|
||||||
|
{
|
||||||
|
vec2_t pos;
|
||||||
|
|
||||||
|
int32_t groupspacing;
|
||||||
|
int32_t entryspacing;
|
||||||
|
int32_t width; // 0: center, >0: width of the label column (left-aligned options), <0: -width of everything (right-aligned)
|
||||||
|
int32_t bottomcutoff;
|
||||||
|
|
||||||
|
int32_t cursorPosition, cursorScale;
|
||||||
|
} MenuPos_t;
|
||||||
|
|
||||||
|
typedef struct MenuLink_t
|
||||||
|
{
|
||||||
|
// traits
|
||||||
|
MenuID_t linkID;
|
||||||
|
} MenuLink_t;
|
||||||
|
typedef struct MenuOptionSet_t
|
||||||
|
{
|
||||||
|
uint8_t features; // bit 1 = disable left/right arrows, bit 2 = disable list
|
||||||
|
|
||||||
|
// traits
|
||||||
|
char **optionNames;
|
||||||
|
int32_t *optionValues; // If NULL, the identity of currentOption is assumed.
|
||||||
|
int32_t numOptions;
|
||||||
|
|
||||||
|
// specifically for a pop-up list
|
||||||
|
MenuPos_t *list;
|
||||||
|
int32_t currentEntry;
|
||||||
|
int32_t scrollPos;
|
||||||
|
} MenuOptionSet_t;
|
||||||
|
typedef struct MenuOption_t
|
||||||
|
{
|
||||||
|
// appearance
|
||||||
|
MenuTextType_t *font;
|
||||||
|
|
||||||
|
// traits
|
||||||
|
MenuOptionSet_t *options; // so that common sets such as Yes/No, On/Off can be reused
|
||||||
|
|
||||||
|
// effect
|
||||||
|
int32_t *data;
|
||||||
|
|
||||||
|
// state
|
||||||
|
int32_t currentOption;
|
||||||
|
} MenuOption_t;
|
||||||
|
typedef struct MenuCustom2Col_t
|
||||||
|
{
|
||||||
|
// appearance
|
||||||
|
MenuTextType_t *font;
|
||||||
|
int32_t columnWidth;
|
||||||
|
|
||||||
|
char **key;
|
||||||
|
size_t numvalid;
|
||||||
|
|
||||||
|
uint8_t *column[2];
|
||||||
|
|
||||||
|
// state
|
||||||
|
int8_t screenOpen;
|
||||||
|
} MenuCustom2Col_t;
|
||||||
|
typedef struct MenuRangeInt32_t
|
||||||
|
{
|
||||||
|
// appearance
|
||||||
|
MenuTextType_t *font;
|
||||||
|
uint8_t displaytype; // 0 = none, 1 = integer, 2 = percent, 3 = normalized decimal
|
||||||
|
|
||||||
|
// traits
|
||||||
|
int32_t min;
|
||||||
|
int32_t max;
|
||||||
|
int32_t steps;
|
||||||
|
int32_t onehundredpercent; // 0 implies max
|
||||||
|
|
||||||
|
// effect
|
||||||
|
int32_t* variable;
|
||||||
|
} MenuRangeInt32_t;
|
||||||
|
typedef struct MenuRangeFloat_t
|
||||||
|
{
|
||||||
|
// appearance
|
||||||
|
MenuTextType_t *font;
|
||||||
|
uint8_t displaytype; // 0 = none, 1 = decimal, 2 = percent, 3 = normalized decimal
|
||||||
|
|
||||||
|
// traits
|
||||||
|
float min;
|
||||||
|
float max;
|
||||||
|
int32_t steps;
|
||||||
|
float onehundredpercent; // 0 implies 1.0
|
||||||
|
|
||||||
|
// effect
|
||||||
|
float* variable;
|
||||||
|
} MenuRangeFloat_t;
|
||||||
|
typedef struct MenuRangeDouble_t
|
||||||
|
{
|
||||||
|
// appearance
|
||||||
|
MenuTextType_t *font;
|
||||||
|
uint8_t displaytype; // 0 = none, 1 = decimal, 2 = percent
|
||||||
|
|
||||||
|
// traits
|
||||||
|
double min;
|
||||||
|
double max;
|
||||||
|
int32_t steps;
|
||||||
|
double onehundredpercent; // 0 implies 1.0
|
||||||
|
|
||||||
|
// effect
|
||||||
|
double* variable;
|
||||||
|
} MenuRangeDouble_t;
|
||||||
|
typedef struct MenuString_t
|
||||||
|
{
|
||||||
|
// appearance
|
||||||
|
MenuTextType_t *font;
|
||||||
|
|
||||||
|
// effect
|
||||||
|
char* variable;
|
||||||
|
int32_t maxlength;
|
||||||
|
|
||||||
|
int32_t flags;
|
||||||
|
|
||||||
|
// state
|
||||||
|
char* editfield;
|
||||||
|
} MenuString_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct MenuEntry_t
|
||||||
|
{
|
||||||
|
// appearance
|
||||||
|
MenuTextType_t *font;
|
||||||
|
|
||||||
|
// traits
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
MenuEntryType_t type;
|
||||||
|
void *entry;
|
||||||
|
|
||||||
|
// state
|
||||||
|
int32_t disabled;
|
||||||
|
|
||||||
|
int32_t ytop, ybottom;
|
||||||
|
} MenuEntry_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct MenuGroup_t
|
||||||
|
{
|
||||||
|
MenuEntry_t **entrylist;
|
||||||
|
int32_t numEntries;
|
||||||
|
|
||||||
|
MenuPos_t *position;
|
||||||
|
|
||||||
|
int32_t currentEntry;
|
||||||
|
int32_t currentColumn; // a little hackish but not too bad
|
||||||
|
} MenuGroup_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum MenuType_t
|
||||||
|
{
|
||||||
|
Menu,
|
||||||
|
Panel,
|
||||||
|
Verify,
|
||||||
|
Message,
|
||||||
|
Password,
|
||||||
|
FileSelect,
|
||||||
|
} MenuType_t;
|
||||||
|
|
||||||
|
typedef struct MenuMenu_t
|
||||||
|
{
|
||||||
|
MenuGroup_t **grouplist;
|
||||||
|
int32_t numGroups;
|
||||||
|
|
||||||
|
const char *title;
|
||||||
|
|
||||||
|
// state
|
||||||
|
int32_t currentGroup;
|
||||||
|
int32_t ytop, bottomcutoff, totalHeight, scrollPos;
|
||||||
|
} MenuMenu_t;
|
||||||
|
typedef struct MenuPanel_t
|
||||||
|
{
|
||||||
|
const char *title;
|
||||||
|
|
||||||
|
MenuID_t previousID;
|
||||||
|
MenuID_t nextID;
|
||||||
|
} MenuPanel_t;
|
||||||
|
typedef struct MenuVerify_t
|
||||||
|
{
|
||||||
|
vec2_t cursorpos;
|
||||||
|
|
||||||
|
MenuID_t linkID;
|
||||||
|
} MenuVerify_t;
|
||||||
|
typedef struct MenuMessage_t
|
||||||
|
{
|
||||||
|
vec2_t cursorpos;
|
||||||
|
|
||||||
|
MenuID_t linkID;
|
||||||
|
} MenuMessage_t;
|
||||||
|
typedef struct MenuPassword_t
|
||||||
|
{
|
||||||
|
// traits
|
||||||
|
int32_t maxlength;
|
||||||
|
|
||||||
|
// state
|
||||||
|
char *input;
|
||||||
|
} MenuPassword_t;
|
||||||
|
typedef struct MenuFileSelect_t
|
||||||
|
{
|
||||||
|
const char *title;
|
||||||
|
|
||||||
|
// appearance
|
||||||
|
MenuTextType_t *dirfont;
|
||||||
|
MenuTextType_t *filefont;
|
||||||
|
|
||||||
|
// traits
|
||||||
|
const char *pattern;
|
||||||
|
char *destination;
|
||||||
|
|
||||||
|
// state
|
||||||
|
fnlist_t fnlist;
|
||||||
|
CACHE1D_FIND_REC *finddirshigh, *findfileshigh, *dir;
|
||||||
|
int32_t currentEntry, currentlist;
|
||||||
|
} MenuFileSelect_t;
|
||||||
|
|
||||||
|
typedef struct Menu_t
|
||||||
|
{
|
||||||
|
MenuID_t menuID;
|
||||||
|
MenuID_t parentID;
|
||||||
|
MenuType_t type;
|
||||||
|
void *object;
|
||||||
|
} Menu_t;
|
||||||
|
|
||||||
|
extern MenuID_t g_currentMenu;
|
||||||
|
extern Menu_t *m_currentMenu;
|
||||||
|
|
||||||
extern int32_t g_lastSaveSlot;
|
extern int32_t g_lastSaveSlot;
|
||||||
extern int32_t g_quitDeadline;
|
extern int32_t g_quitDeadline;
|
||||||
extern int32_t probey;
|
|
||||||
extern int32_t voting;
|
extern int32_t voting;
|
||||||
int32_t menutext_(int32_t x,int32_t y,int32_t s,int32_t p,char *t,int32_t bits);
|
int32_t menutext_(int32_t x,int32_t y,int32_t s,int32_t p,char *t,int32_t bits);
|
||||||
void M_ChangeMenu(int32_t cm);
|
void M_ChangeMenu(int32_t cm);
|
||||||
int32_t M_IsTextInput(int32_t cm);
|
int32_t M_IsTextInput(Menu_t *cm);
|
||||||
void G_CheckPlayerColor(int32_t *color,int32_t prev_color);
|
void G_CheckPlayerColor(int32_t *color,int32_t prev_color);
|
||||||
|
void M_Init(void);
|
||||||
void M_DisplayMenus(void);
|
void M_DisplayMenus(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1709,7 +1709,7 @@ void Net_ReceiveClientUpdate(ENetEvent *event)
|
||||||
|
|
||||||
void Net_SendMessage(void)
|
void Net_SendMessage(void)
|
||||||
{
|
{
|
||||||
int16_t hitstate, i, j, l;
|
int32_t hitstate, i, j, l;
|
||||||
|
|
||||||
if (g_player[myconnectindex].ps->gm&MODE_SENDTOWHOM)
|
if (g_player[myconnectindex].ps->gm&MODE_SENDTOWHOM)
|
||||||
{
|
{
|
||||||
|
@ -1832,11 +1832,31 @@ void Net_SendMessage(void)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ud.screen_size > 1) j = 200-45;
|
hitstate = I_EnterText(typebuf, 120, 0);
|
||||||
else j = 200-8;
|
|
||||||
|
if (ud.screen_size > 1) j = (200-45)<<16;
|
||||||
|
else j = (200-8)<<16;
|
||||||
if (xdim >= 640 && ydim >= 480)
|
if (xdim >= 640 && ydim >= 480)
|
||||||
j = scale(j,ydim,200);
|
j = scale(j,ydim,200);
|
||||||
hitstate = Net_EnterText(320>>1,j,typebuf,120,1);
|
|
||||||
|
i = textsc(5<<16);
|
||||||
|
|
||||||
|
{
|
||||||
|
const vec2_t dim = G_ScreenTextSize(STARTALPHANUM, i, 0, textsc(65536), 0, typebuf, 8|16|ROTATESPRITE_FULL16, 5<<16, 7<<16, 0, 0, TEXT_LITERALESCAPE, 0, 0, xdim-1, ydim-1);
|
||||||
|
|
||||||
|
l = i + dim.x + scale(textsc((tilesizx[SPINNINGNUKEICON]+2)<<13), ydim, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l >= (xdim<<16))
|
||||||
|
i -= (l - (xdim<<16));
|
||||||
|
|
||||||
|
{
|
||||||
|
const vec2_t dim = G_ScreenText(STARTALPHANUM, i, j, textsc(65536), 0, 0, typebuf, 1, 0, 8|16|ROTATESPRITE_FULL16, 0, 5<<16, 7<<16, 0, 0, TEXT_YCENTER|TEXT_LITERALESCAPE, 0, 0, xdim-1, ydim-1);
|
||||||
|
|
||||||
|
i += dim.x + scale(textsc((tilesizx[SPINNINGNUKEICON]+1)<<12), ydim, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
rotatesprite_fs(i, j, textsc(32768), 0, SPINNINGNUKEICON+((totalclock>>3)%7), 4-(sintable[(totalclock<<4)&2047]>>11), 0, 0);
|
||||||
|
|
||||||
if (hitstate == 1)
|
if (hitstate == 1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,7 +37,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#define LOUDESTVOLUME 150
|
#define LOUDESTVOLUME 150
|
||||||
#define MUSIC_ID -65536
|
#define MUSIC_ID -65536
|
||||||
|
|
||||||
#define FX_VOLUME(x) scale(x, 255, ud.config.FXVolume)
|
#define FX_VOLUME(x) (ud.config.FXVolume > 0 ? scale(x, 255, ud.config.FXVolume) : 0)
|
||||||
#define MASTER_VOLUME(x) scale(ud.config.MasterVolume, x, 255)
|
#define MASTER_VOLUME(x) scale(ud.config.MasterVolume, x, 255)
|
||||||
|
|
||||||
struct audioenumdev
|
struct audioenumdev
|
||||||
|
|
Loading…
Reference in a new issue