That is, remove code for closing menus with the key that's bound to open them. As it turns out, UIEvent.keystring isn't 1:1 with key binds for a command. This SEEMINGLY worked since the Demolitionist Menu is by default bound to Q, and pressing Q does send an UIEvent to the menu with the string "Q". But if, for example, the menu had been bound to Tab, this would fall apart because then the key string sent is " " (a literal tab character). If there is a way to do this properly, I don't know about it. I've looked everywhere in GZDoom's code for a solution, something that would let me do what I need, but alas, there is nothing there. Better to get rid of this in its entirety than keep the flaky code in the mod until someone with a special setup that breaks it shows up to complain.
608 lines
19 KiB
Text
608 lines
19 KiB
Text
// internal "knowledge base" and more
|
|
Class MenuTransaction
|
|
{
|
|
enum ETransactionType
|
|
{
|
|
TT_ITEMUSE,
|
|
TT_ITEMDROP
|
|
};
|
|
|
|
int uid, type;
|
|
Class<Inventory> used;
|
|
bool result, usedup;
|
|
}
|
|
|
|
enum EKMenuKey
|
|
{
|
|
MK_DOWN,
|
|
MK_UP,
|
|
MK_LEFT,
|
|
MK_RIGHT,
|
|
MK_ENTER,
|
|
MK_BACK
|
|
};
|
|
|
|
enum EKMouseButton
|
|
{
|
|
MB_LEFT,
|
|
MB_RIGHT,
|
|
MB_WHEELUP,
|
|
MB_WHEELDOWN,
|
|
MB_DRAG,
|
|
MB_RELEASE
|
|
}
|
|
|
|
Class DemolitionistMenu : GenericMenu
|
|
{
|
|
TextureID FancyBg, FrameTex, VSepTex, HSepTex;
|
|
// for resolution scaling and such
|
|
double hs;
|
|
Vector2 ss, ws, origin;
|
|
// temporary bottom messages, such as "not enough money"
|
|
String tmsg;
|
|
int tmsgtic;
|
|
// money owned, for store
|
|
int muns;
|
|
// other text
|
|
String clockstr, munstr;
|
|
// for checks (duh)
|
|
Array<MenuTransaction> checklist;
|
|
int lasttuid;
|
|
SWWMHandler hnd;
|
|
SWWMStaticHandler shnd;
|
|
// seeeeecret
|
|
int kcode;
|
|
// crimey clock stuff
|
|
int c_year, c_month, c_day, c_hour, c_minute;
|
|
String c_tz;
|
|
// mouse stuff
|
|
Vector2 curmouse;
|
|
bool isrclick;
|
|
// somehow Drawer can be called while closing prematurely, which is big bollocks
|
|
bool isclosing, forceclose;
|
|
// the tabs
|
|
Array<DemolitionistMenuTab> tabs;
|
|
int curtab;
|
|
int oldtab; // used for returning from help tab
|
|
// fonts
|
|
Font mSmallFont, mTinyFont;
|
|
// for open/close animation
|
|
double animtimer;
|
|
|
|
int GenTUID()
|
|
{
|
|
return lasttuid++;
|
|
}
|
|
|
|
// tab functions
|
|
int FindTabType( Class<DemolitionistMenuTab> t, bool nothidden = false )
|
|
{
|
|
for ( int i=0; i<tabs.Size(); i++ )
|
|
{
|
|
if ( !(tabs[i] is t) ) continue;
|
|
if ( nothidden && tabs[i].bHidden ) continue;
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
int GetFirstTab()
|
|
{
|
|
for ( int i=0; i<tabs.Size(); i++ )
|
|
{
|
|
if ( tabs[i].bHidden ) continue;
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
int GetLastTab()
|
|
{
|
|
for ( int i=tabs.Size()-1; i>=0; i-- )
|
|
{
|
|
if ( tabs[i].bHidden ) continue;
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
int GetNextTab()
|
|
{
|
|
int lst = GetLastTab();
|
|
if ( lst == -1 ) return -1;
|
|
if ( curtab >= lst ) return GetFirstTab();
|
|
for ( int i=curtab+1; i<tabs.Size(); i++ )
|
|
{
|
|
if ( tabs[i].bHidden ) continue;
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
int GetPrevTab()
|
|
{
|
|
int fst = GetFirstTab();
|
|
if ( fst == -1 ) return -1;
|
|
if ( curtab <= fst ) return GetLastTab();
|
|
for ( int i=curtab-1; i>=0; i-- )
|
|
{
|
|
if ( tabs[i].bHidden ) continue;
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
private void DoClose()
|
|
{
|
|
EventHandler.SendNetworkEvent("swwmclearalltransactions",consoleplayer);
|
|
for ( int i=0; i<tabs.Size(); i++ )
|
|
{
|
|
if ( i == curtab )
|
|
{
|
|
shnd.menustate.Insert("LastTab",tabs[i].GetClassName());
|
|
tabs[i].OnDeselect();
|
|
}
|
|
tabs[i].Destroy();
|
|
}
|
|
}
|
|
|
|
override void Init( Menu parent )
|
|
{
|
|
Super.Init(parent);
|
|
Animated = DontDim = DontBlur = true;
|
|
// can't open this menu outside of the game or if dead
|
|
// also can't if you're not the Demolitionist
|
|
if ( (gamestate != GS_LEVEL) || (players[consoleplayer].Health <= 0) || !(players[consoleplayer].mo is 'Demolitionist') )
|
|
{
|
|
animtimer = -1.;
|
|
isclosing = true;
|
|
return;
|
|
}
|
|
FancyBg = TexMan.CheckForTexture("graphics/tempbg.png",TexMan.Type_MiscPatch);
|
|
FrameTex = TexMan.CheckForTexture("graphics/KBase/FrameTex.png",TexMan.Type_MiscPatch);
|
|
VSepTex = TexMan.CheckForTexture("graphics/KBase/VSepTex.png",TexMan.Type_MiscPatch);
|
|
HSepTex = TexMan.CheckForTexture("graphics/KBase/HSepTex.png",TexMan.Type_MiscPatch);
|
|
mSmallFont = Font.GetFont('TewiFont');
|
|
mTinyFont = Font.GetFont('MiniwiFont');
|
|
// note that we can assume 640x400 will always be the smallest resolution allowed by gzdoom, but we still need to handle widescreen
|
|
double sw = max(Screen.GetWidth(),640);
|
|
double sh = max(Screen.GetHeight(),400);
|
|
hs = max(min(floor(sw/640.),floor(sh/266.)),1.);
|
|
ss = (sw,sh)/hs;
|
|
ws.x = 640.;
|
|
double th = 640*(ss.y/ss.x);
|
|
ws.y = round(th);
|
|
origin = (int(ss.x-ws.x)/2,int(ss.y-ws.y)/2);
|
|
MenuSound("menu/demoopen");
|
|
tmsg = StringTable.Localize("$SWWM_MAINCONTROLS");
|
|
tmsgtic = MenuTime()+50;
|
|
lasttuid = Random[TUID]();
|
|
hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
|
|
shnd = SWWMStaticHandler(StaticEventHandler.Find("SWWMStaticHandler"));
|
|
SetClock();
|
|
static const class<DemolitionistMenuTab> deftabs[] =
|
|
{
|
|
'DemolitionistMissionTab',
|
|
'DemolitionistStatsTab',
|
|
'DemolitionistInventoryTab',
|
|
'DemolitionistKeychainTab',
|
|
'DemolitionistLibraryTab',
|
|
'DemolitionistStoreTab',
|
|
'DemolitionistChatTab',
|
|
//'DemolitionistGameTab', // disabled until 1.5
|
|
'DemolitionistHelpTab',
|
|
'DemolitionistSecretTab'
|
|
};
|
|
for ( int i=0; i<deftabs.Size()-2; i++ )
|
|
tabs.Push(DemolitionistMenuTab(new(deftabs[i])).Init(self));
|
|
// custom tabs go before the help and secret tabs
|
|
for ( int i=0; i<AllClasses.Size(); i++ )
|
|
{
|
|
let ct = (Class<DemolitionistMenuTabCustom>)(AllClasses[i]);
|
|
if ( !ct || (ct.GetParentClass() != 'DemolitionistMenuTabCustom') ) continue;
|
|
tabs.Push(DemolitionistMenuTab(new(ct)).Init(self));
|
|
}
|
|
for ( int i=deftabs.Size()-2; i<deftabs.Size(); i++ )
|
|
tabs.Push(DemolitionistMenuTab(new(deftabs[i])).Init(self));
|
|
if ( shnd.menustate )
|
|
{
|
|
Class<DemolitionistMenuTab> saved = shnd.menustate.At("LastTab");
|
|
if ( saved ) curtab = FindTabType(saved,true);
|
|
}
|
|
else
|
|
{
|
|
shnd.menustate = Dictionary.Create();
|
|
curtab = -1;
|
|
}
|
|
if ( curtab == -1 ) curtab = GetFirstTab();
|
|
tabs[curtab].OnSelect();
|
|
}
|
|
|
|
override bool MenuEvent( int mkey, bool fromcontroller )
|
|
{
|
|
if ( isclosing || (animtimer < 1.) ) return false;
|
|
// pachinko code only handled if the tab lacks direct input
|
|
if ( !tabs[curtab].bDirectInput )
|
|
{
|
|
switch ( kcode )
|
|
{
|
|
case 0:
|
|
case 1:
|
|
if ( mkey == MKEY_UP ) kcode++;
|
|
else kcode = 0;
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
if ( mkey == MKEY_DOWN ) kcode++;
|
|
else kcode = 0;
|
|
break;
|
|
case 4:
|
|
case 6:
|
|
if ( mkey == MKEY_LEFT ) kcode++;
|
|
else kcode = 0;
|
|
break;
|
|
case 5:
|
|
case 7:
|
|
if ( mkey == MKEY_RIGHT ) kcode++;
|
|
else kcode = 0;
|
|
break;
|
|
case 10:
|
|
if ( mkey == MKEY_ENTER )
|
|
{
|
|
int secret = FindTabType('DemolitionistSecretTab');
|
|
if ( curtab != secret )
|
|
{
|
|
MenuSound("misc/secret");
|
|
tabs[curtab].OnDeselect();
|
|
curtab = secret;
|
|
tabs[curtab].OnSelect();
|
|
}
|
|
|
|
}
|
|
default:
|
|
kcode = 0;
|
|
break;
|
|
}
|
|
}
|
|
switch ( mkey )
|
|
{
|
|
case MKEY_BACK:
|
|
isclosing = true;
|
|
MenuSound("menu/democlose");
|
|
return true;
|
|
case MKEY_PAGEDOWN:
|
|
int next = GetNextTab();
|
|
if ( next != curtab )
|
|
{
|
|
MenuSound("menu/demotab");
|
|
tabs[curtab].OnDeselect();
|
|
curtab = next;
|
|
tabs[curtab].OnSelect();
|
|
}
|
|
return true;
|
|
case MKEY_PAGEUP:
|
|
int prev = GetPrevTab();
|
|
if ( prev != curtab )
|
|
{
|
|
MenuSound("menu/demotab");
|
|
tabs[curtab].OnDeselect();
|
|
curtab = prev;
|
|
tabs[curtab].OnSelect();
|
|
}
|
|
return true;
|
|
case MKEY_DOWN:
|
|
tabs[curtab].MenuInput(MK_DOWN);
|
|
return true;
|
|
case MKEY_UP:
|
|
tabs[curtab].MenuInput(MK_UP);
|
|
return true;
|
|
case MKEY_LEFT:
|
|
tabs[curtab].MenuInput(MK_LEFT);
|
|
return true;
|
|
case MKEY_RIGHT:
|
|
tabs[curtab].MenuInput(MK_RIGHT);
|
|
return true;
|
|
case MKEY_ENTER:
|
|
tabs[curtab].MenuInput(MK_ENTER);
|
|
return true;
|
|
case MKEY_CLEAR:
|
|
tabs[curtab].MenuInput(MK_BACK);
|
|
return true;
|
|
}
|
|
return Super.MenuEvent(mkey,fromcontroller);
|
|
}
|
|
|
|
override void Ticker()
|
|
{
|
|
Super.Ticker();
|
|
if ( ((gamestate != GS_LEVEL) || (players[consoleplayer].Health <= 0) || isclosing) && (animtimer <= 0.) )
|
|
{
|
|
// ded (or force close)
|
|
DoClose();
|
|
Close();
|
|
return;
|
|
}
|
|
if ( swwm_menupause ) menuactive = Menu.On;
|
|
else menuactive = Menu.OnNoPause;
|
|
// forcibly tick hud (mainly so interpolators can still update in the background)
|
|
if ( !multiplayer && (menuactive == Menu.On) )
|
|
{
|
|
let bar = SWWMStatusBar(StatusBar);
|
|
if ( bar ) bar.TickInterpolators();
|
|
}
|
|
CheckTransactions();
|
|
// update time string
|
|
clockstr = CrimeTime();
|
|
// update money
|
|
muns = SWWMCredits.Get(players[consoleplayer]);
|
|
munstr = String.Format("\cg¥\c-%09d",muns);
|
|
if ( isclosing )
|
|
{
|
|
if ( animtimer >= 1. ) DontDim = DontBlur = true;
|
|
animtimer -= .1;
|
|
return;
|
|
}
|
|
if ( animtimer < 1. )
|
|
{
|
|
animtimer += .1;
|
|
if ( animtimer < 1. ) return; // ensure tabs tick before first draw
|
|
else DontDim = DontBlur = false;
|
|
}
|
|
if ( (tabs.Size() <= 0) || (curtab == -1) || !tabs[curtab] ) return;
|
|
tabs[curtab].Ticker();
|
|
}
|
|
|
|
override bool MouseEvent( int type, int mx, int my )
|
|
{
|
|
if ( isclosing || (animtimer < 1.) ) return false;
|
|
bool res = Super.MouseEvent(type,mx,my);
|
|
Vector2 mpos = (mx/hs,my/hs)-origin;
|
|
if ( type == MOUSE_Click )
|
|
{
|
|
// outside clickable area
|
|
if ( (mpos.x < 0) || (mpos.x > ws.x) || (mpos.y < 0) || (mpos.y > ws.y-14) ) return res;
|
|
else if ( mpos.y < 14 )
|
|
{
|
|
if ( isrclick ) return res;
|
|
// check which tab we're clicking
|
|
int xx = 0;
|
|
String str;
|
|
int len;
|
|
for ( int i=0; i<tabs.Size(); i++ )
|
|
{
|
|
if ( tabs[i].bHidden ) continue;
|
|
str = tabs[i].title;
|
|
len = mSmallFont.StringWidth(str)+10;
|
|
if ( (mpos.x >= xx) && (mpos.x < xx+len) )
|
|
{
|
|
if ( curtab == i ) break;
|
|
MenuSound("menu/demotab");
|
|
tabs[curtab].OnDeselect();
|
|
curtab = i;
|
|
tabs[curtab].OnSelect();
|
|
break;
|
|
}
|
|
xx += len;
|
|
}
|
|
return res;
|
|
}
|
|
else if ( (tabs.Size() <= 0) || (curtab == -1) || !tabs[curtab] ) return res;
|
|
tabs[curtab].MouseInput(mpos,isrclick?MB_RIGHT:MB_LEFT);
|
|
}
|
|
else if ( type == MOUSE_Move )
|
|
{
|
|
if ( (tabs.Size() <= 0) || (curtab == -1) || !tabs[curtab] ) return res;
|
|
tabs[curtab].MouseInput(mpos,MB_DRAG);
|
|
}
|
|
else if ( type == MOUSE_Release )
|
|
{
|
|
if ( (tabs.Size() <= 0) || (curtab == -1) || !tabs[curtab] ) return res;
|
|
tabs[curtab].MouseInput(mpos,MB_RELEASE);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
override bool OnUiEvent( UIEvent ev )
|
|
{
|
|
if ( isclosing || (animtimer < 1.) ) return false;
|
|
if ( tabs[curtab].bDirectInput && ((ev.type == UIEvent.Type_KeyDown) || (ev.type == UIEvent.Type_KeyUp)) )
|
|
return tabs[curtab].DirectInput(ev);
|
|
switch ( ev.type )
|
|
{
|
|
case UIEvent.Type_KeyDown:
|
|
if ( ev.keychar == UiEvent.Key_F1 )
|
|
{
|
|
int help = FindTabType('DemolitionistHelpTab');
|
|
if ( curtab == help )
|
|
{
|
|
tabs[curtab].OnDeselect();
|
|
curtab = oldtab;
|
|
tabs[curtab].OnSelect();
|
|
}
|
|
else
|
|
{
|
|
int secret = FindTabType('DemolitionistSecretTab');
|
|
if ( curtab == secret ) oldtab = GetLastTab();
|
|
else oldtab = curtab;
|
|
tabs[curtab].OnDeselect();
|
|
curtab = help;
|
|
tabs[curtab].OnSelect();
|
|
}
|
|
MenuSound("menu/demotab");
|
|
return true;
|
|
}
|
|
switch ( kcode )
|
|
{
|
|
case 8:
|
|
if ( ev.keystring ~== "B" )
|
|
kcode++;
|
|
else kcode = 0;
|
|
break;
|
|
case 9:
|
|
if ( ev.keystring ~== "A" ) kcode++;
|
|
else kcode = 0;
|
|
break;
|
|
default:
|
|
kcode = 0;
|
|
break;
|
|
}
|
|
break;
|
|
case UIEvent.Type_WheelDown:
|
|
tabs[curtab].MouseInput((curmouse/hs)-origin,MB_WHEELDOWN);
|
|
return true;
|
|
case UIEvent.Type_WheelUp:
|
|
tabs[curtab].MouseInput((curmouse/hs)-origin,MB_WHEELUP);
|
|
return true;
|
|
case UIEvent.Type_LButtonDown:
|
|
{
|
|
isrclick = false;
|
|
bool res = MouseEvent(MOUSE_Click,ev.MouseX,ev.MouseY);
|
|
if ( res ) SetCapture(true);
|
|
return res;
|
|
}
|
|
case UIEvent.Type_RButtonDown:
|
|
{
|
|
isrclick = true;
|
|
bool res = MouseEvent(MOUSE_Click,ev.MouseX,ev.MouseY);
|
|
if ( res ) SetCapture(true);
|
|
return res;
|
|
}
|
|
case UIEvent.Type_LButtonUp:
|
|
case UIEvent.Type_RButtonUp:
|
|
if ( mMouseCapture )
|
|
{
|
|
SetCapture(false);
|
|
return MouseEvent(MOUSE_Release,ev.MouseX,ev.MouseY);
|
|
}
|
|
break;
|
|
case UIEvent.Type_MouseMove:
|
|
curmouse = (ev.MouseX,ev.MouseY);
|
|
if ( mMouseCapture || (m_use_mouse == 1) )
|
|
return MouseEvent(MOUSE_Move,ev.MouseX,ev.MouseY);
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// fundamental drawing functions (good god these are hacky)
|
|
void DrawFrame( double x, double y, double w, double h, bool shadow = true )
|
|
{
|
|
x += origin.x;
|
|
y += origin.y;
|
|
Screen.DrawTexture(FrameTex,false,x,y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,0.,DTA_SrcY,0.,DTA_SrcWidth,1.,DTA_SrcHeight,1.,DTA_DestWidth,1,DTA_DestHeight,1);
|
|
if ( w > 2 ) Screen.DrawTexture(FrameTex,false,x+1,y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,1.,DTA_SrcY,0.,DTA_SrcWidth,1.,DTA_SrcHeight,1.,DTA_DestWidth,int(w-2),DTA_DestHeight,1);
|
|
if ( h > 2 ) Screen.DrawTexture(FrameTex,false,x,y+1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,0.,DTA_SrcY,1.,DTA_SrcWidth,1.,DTA_SrcHeight,1.,DTA_DestWidth,1,DTA_DestHeight,int(h-2));
|
|
Screen.DrawTexture(FrameTex,false,(x+w)-1,y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,2.,DTA_SrcY,0.,DTA_SrcWidth,1.,DTA_SrcHeight,1.,DTA_DestWidth,1,DTA_DestHeight,1);
|
|
Screen.DrawTexture(FrameTex,false,x,(y+h)-1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,0.,DTA_SrcY,2.,DTA_SrcWidth,1.,DTA_SrcHeight,1.,DTA_DestWidth,1,DTA_DestHeight,1);
|
|
if ( shadow )
|
|
{
|
|
if ( h > 2 ) Screen.DrawTexture(FrameTex,false,(x+w)-1,y+1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,2.,DTA_SrcY,1.,DTA_SrcWidth,2.,DTA_SrcHeight,1.,DTA_DestWidth,2,DTA_DestHeight,int(h-2));
|
|
if ( w > 2 ) Screen.DrawTexture(FrameTex,false,x+1,(y+h)-1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,1.,DTA_SrcY,2.,DTA_SrcWidth,1.,DTA_SrcHeight,2.,DTA_DestWidth,int(w-2),DTA_DestHeight,2);
|
|
Screen.DrawTexture(FrameTex,false,(x+w)-1,(y+h)-1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,2.,DTA_SrcY,2.,DTA_SrcWidth,2.,DTA_SrcHeight,2.,DTA_DestWidth,2,DTA_DestHeight,2);
|
|
}
|
|
else
|
|
{
|
|
if ( h > 2 ) Screen.DrawTexture(FrameTex,false,(x+w)-1,y+1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,2.,DTA_SrcY,1.,DTA_SrcWidth,1.,DTA_SrcHeight,1.,DTA_DestWidth,1,DTA_DestHeight,int(h-2));
|
|
if ( w > 2 ) Screen.DrawTexture(FrameTex,false,x+1,(y+h)-1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,1.,DTA_SrcY,2.,DTA_SrcWidth,1.,DTA_SrcHeight,1.,DTA_DestWidth,int(w-2),DTA_DestHeight,1);
|
|
Screen.DrawTexture(FrameTex,false,(x+w)-1,(y+h)-1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,2.,DTA_SrcY,2.,DTA_SrcWidth,1.,DTA_SrcHeight,1.,DTA_DestWidth,1,DTA_DestHeight,1);
|
|
}
|
|
}
|
|
|
|
// these ones thankfully only need three drawtexture calls each
|
|
void DrawVSeparator( double x, double y, double h )
|
|
{
|
|
x += origin.x;
|
|
y += origin.y;
|
|
Screen.DrawTexture(VSepTex,false,x-1,y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcY,0.,DTA_SrcHeight,1.,DTA_DestHeight,1);
|
|
Screen.DrawTexture(VSepTex,false,x-1,y+1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcY,1.,DTA_SrcHeight,1.,DTA_DestHeight,int(h-2));
|
|
Screen.DrawTexture(VSepTex,false,x-1,(y+h)-1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcY,2.,DTA_SrcHeight,1.,DTA_DestHeight,1);
|
|
}
|
|
void DrawHSeparator( double x, double y, double w )
|
|
{
|
|
x += origin.x;
|
|
y += origin.y;
|
|
Screen.DrawTexture(HSepTex,false,x,y-1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,0.,DTA_SrcWidth,1.,DTA_DestWidth,1);
|
|
Screen.DrawTexture(HSepTex,false,x+1,y-1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,1.,DTA_SrcWidth,1.,DTA_DestWidth,int(w-2));
|
|
Screen.DrawTexture(HSepTex,false,(x+w)-1,y-1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,2.,DTA_SrcWidth,1.,DTA_DestWidth,1);
|
|
}
|
|
|
|
override void Drawer()
|
|
{
|
|
if ( animtimer < 0 ) return;
|
|
// animated frame (more math)
|
|
if ( isclosing || (animtimer < 1.) )
|
|
{
|
|
double intp, xfact, yfact;
|
|
if ( isclosing )
|
|
{
|
|
intp = animtimer-.1*System.GetTimeFrac();
|
|
xfact = clamp(intp*2.,0.,1.)**2.;
|
|
yfact = clamp(intp,0.,1.)**5.;
|
|
}
|
|
else
|
|
{
|
|
intp = animtimer+.1*System.GetTimeFrac();
|
|
xfact = clamp(intp*2,0.,1.)**2.;
|
|
yfact = clamp(intp,0.,1.)**5.;
|
|
}
|
|
double rwsx = int(SWWMUtility.Lerp(2,ws.x,xfact));
|
|
double rwsy = int(SWWMUtility.Lerp(2,ws.y,yfact));
|
|
if ( (rwsx == 2) && (rwsy == 2) ) return;
|
|
double rox = int(ss.x-rwsx)/2;
|
|
double roy = int(ss.y-rwsy)/2;
|
|
// copy the menu dim below the window during animations, so the transition looks smoother
|
|
Screen.Dim((dimamount<0)?Color("Black"):dimcolor,(dimamount<0)?.5:dimamount,int(rox*hs),int(roy*hs),int(rwsx*hs),int(rwsy*hs));
|
|
// draw the background and main frame
|
|
if ( swwm_fuzz )
|
|
{
|
|
// fuzz was designed for 16:10, so we'll have to extend it at taller ratios
|
|
int count = int(ceil(ws.y/400.));
|
|
Screen.SetClipRect(int(rox*hs),int(roy*hs),int(rwsx*hs),int(rwsy*hs));
|
|
for ( int i=0; i<count; i++ )
|
|
Screen.DrawTexture(FancyBg,false,origin.x,origin.y+400.*i,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_LegacyRenderStyle,STYLE_Add,DTA_Alpha,.5);
|
|
Screen.ClearClipRect();
|
|
}
|
|
Screen.Dim("Black",.8,int(rox*hs),int(roy*hs),int(rwsx*hs),int(rwsy*hs));
|
|
DrawFrame(rox-origin.x,roy-origin.y,rwsx,rwsy,true);
|
|
return;
|
|
}
|
|
// draw the background and main frame
|
|
if ( swwm_fuzz )
|
|
{
|
|
// fuzz was designed for 16:10, so we'll have to extend it at taller ratios
|
|
int count = int(ceil(ws.y/400.));
|
|
Screen.SetClipRect(int(origin.x*hs),int(origin.y*hs),int(ws.x*hs),int(ws.y*hs));
|
|
for ( int i=0; i<count; i++ )
|
|
Screen.DrawTexture(FancyBg,false,origin.x,origin.y+400.*i,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_LegacyRenderStyle,STYLE_Add,DTA_Alpha,.5);
|
|
Screen.ClearClipRect();
|
|
}
|
|
Screen.Dim("Black",.8,int(origin.x*hs),int(origin.y*hs),int(ws.x*hs),int(ws.y*hs));
|
|
DrawFrame(0,0,ws.x,ws.y,true);
|
|
// draw top and bottom separators
|
|
DrawHSeparator(0,14,ws.x);
|
|
DrawHSeparator(0,ws.y-14,ws.x);
|
|
double xx = 5, yy = 1;
|
|
String str;
|
|
// draw tab listing
|
|
for ( int i=0; i<tabs.Size(); i++ )
|
|
{
|
|
if ( tabs[i].bHidden ) continue;
|
|
str = tabs[i].title;
|
|
Screen.DrawText(mSmallFont,(curtab==i)?Font.CR_FIRE:Font.CR_DARKGRAY,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
xx += mSmallFont.StringWidth(str)+10;
|
|
DrawVSeparator(xx-5,0,14);
|
|
}
|
|
// draw money
|
|
xx = 637-mSmallFont.StringWidth(munstr);
|
|
Screen.DrawText(mSmallFont,Font.CR_FIRE,origin.x+xx,origin.y+yy,munstr,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
yy = ws.y-13;
|
|
// draw clock / messages
|
|
if ( MenuTime() < tmsgtic ) str = tmsg;
|
|
else str = clockstr;
|
|
xx = 4;
|
|
Screen.DrawText(mSmallFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
// draw os version
|
|
str = "DemolitionOS v1.0";
|
|
xx = 637-mSmallFont.StringWidth(str);
|
|
Screen.DrawText(mSmallFont,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
|
|
// draw tab contents
|
|
if ( (tabs.Size() <= 0) || (curtab == -1) || !tabs[curtab] ) return;
|
|
tabs[curtab].Drawer(System.GetTimeFrac());
|
|
}
|
|
}
|