stinger_m/zscript/unrealmenus.zsc

494 lines
16 KiB
Text

// draws unreal-style main menu
Class UnrealListMenu : ListMenu
{
TextureID tex[3];
override void Init( Menu parent, ListMenuDescriptor desc )
{
Super.Init(parent,desc);
tex[0] = TexMan.CheckForTexture("graphics/rmetal.png",TexMan.Type_Any);
tex[1] = TexMan.CheckForTexture("graphics/menubarr.png",TexMan.Type_Any);
tex[2] = TexMan.CheckForTexture("graphics/unlogo.png",TexMan.Type_Any);
}
override void Drawer()
{
double StartX = 0.5*CleanWidth_1-128;
int num = (CleanHeight_1/512)+1;
for ( int i=0; i<=num; i++ )
Screen.DrawTexture(tex[0],false,StartX*CleanXFac_1,512*CleanYFac_1*i,DTA_CleanNoMove_1,true);
Screen.DrawTexture(tex[1],false,StartX*CleanXFac_1,(CleanHeight_1-58)*CleanYFac_1,DTA_CleanNoMove_1,true,DTA_LegacyRenderStyle,STYLE_Add);
Screen.DrawTexture(tex[2],false,StartX*CleanXFac_1,(CleanHeight_1-52)*CleanYFac_1,DTA_CleanNoMove_1,true);
Super.Drawer();
}
override bool MouseEvent( int type, int x, int y )
{
int sel = -1;
if ( mFocusControl )
{
x = ((x-(screen.GetWidth()/2))/CleanXfac)+160;
y = ((y-(screen.GetHeight()/2))/CleanYfac)+100;
mFocusControl.MouseEvent(type,x,y);
return true;
}
else
{
// menu uses different scaling
x /= CleanXfac_1;
y /= CleanYfac_1;
for ( int i=0; i<mDesc.mItems.Size(); i++ )
{
if ( mDesc.mItems[i].CheckCoordinate(x,y) )
{
mDesc.mSelectedItem = i;
mDesc.mItems[i].MouseEvent(type,x,y);
return true;
}
}
}
mDesc.mSelectedItem = -1;
return true;
}
}
Class ListMenuItemUnrealTextItem : ListMenuItemSelectable
{
String mText;
Font mFont;
int mColor;
int mSpacing;
void Init( ListMenuDescriptor desc, String text, String hotkey, Name child, int param = 0 )
{
Super.Init(desc.mXpos,desc.mYpos,desc.mLinespacing,child,param);
mText = text;
mFont = Font.GetFont('ULargeFont');
mColor = Font.CR_UNTRANSLATED;
mSpacing = desc.mLineSpacing;
mHotkey = hotkey.GetNextCodePoint(0);
}
void InitDirect( double x, double y, int height, String hotkey, String text, Font font, int color, int color2, Name child, int param = 0 )
{
Super.Init(x,y,height,child,param);
mText = text;
mFont = Font.GetFont('ULargeFont');
mColor = Font.CR_UNTRANSLATED;
int pos = 0;
mHotkey = hotkey.GetNextCodePoint(0);
}
override void Drawer( bool selected )
{
String str = StringTable.Localize(mText);
let fnt = (generic_ui||!mFont.CanPrint(str))?NewSmallFont:mFont;
double basex = floor(0.5*(CleanWidth_1-fnt.StringWidth(str)));
double basey = floor(0.25*(CleanHeight_1-mSpacing*5));
Screen.DrawText(fnt,(fnt==NewSmallFont)?Font.CR_GREEN:mColor,(basex+mXPos)*CleanXFac_1,(basey+mYpos)*CleanYFac_1,str,DTA_CleanNoMove_1,true,DTA_Alpha,selected?1.0:0.5);
}
override int GetWidth()
{
String str = StringTable.Localize(mText);
let fnt = (generic_ui||!mFont.CanPrint(str))?NewSmallFont:mFont;
return max(1,fnt.StringWidth(StringTable.Localize(mText)));
}
override bool CheckCoordinate( int x, int y )
{
String str = StringTable.Localize(mText);
let fnt = (generic_ui||!mFont.CanPrint(str))?NewSmallFont:mFont;
int w = fnt.StringWidth(str);
int h = fnt.GetHeight();
double basex = floor(0.5*(CleanWidth_1-w))+mXPos;
double basey = floor(0.25*(CleanHeight_1-mSpacing*5))+mYPos;
return (mEnabled && (x >= basex) && (x < basex+w) && (y >= basey) && (y < basey+h));
}
override void DrawSelector( double xofs, double yofs, TextureID tex )
{
// nothing
}
}
// for hud config
Class OptionMenuItemHudType : OptionMenuItem
{
TextureID tex[6];
CVar mCVar;
OptionMenuItemHudType Init( String label )
{
Super.Init(label,"",true);
mCVar = CVar.FindCVar('sting_hudmode');
tex[0] = TexMan.CheckForTexture("graphics/Hud1.png",TexMan.Type_Any);
tex[1] = TexMan.CheckForTexture("graphics/Hud2.png",TexMan.Type_Any);
tex[2] = TexMan.CheckForTexture("graphics/Hud3.png",TexMan.Type_Any);
tex[3] = TexMan.CheckForTexture("graphics/Hud4.png",TexMan.Type_Any);
tex[4] = TexMan.CheckForTexture("graphics/Hud5.png",TexMan.Type_Any);
tex[5] = TexMan.CheckForTexture("graphics/Hud6.png",TexMan.Type_Any);
return self;
}
override bool Selectable()
{
return false;
}
override int Draw( OptionMenuDescriptor desc, int y, int indent, bool selected )
{
int xpos = indent + CursorSpace();
int ypos = y + OptionMenuSettings.mLinespacing*CleanYfac_1;
Screen.DrawFrame(xpos,ypos,64*CleanXFac_1,64*CleanYFac_1);
Screen.DrawTexture(tex[mCVar.GetInt()],false,xpos,ypos,DTA_CleanNoMove_1,true);
return -1;
}
}
// because I can't change the font or color in mapinfo
Class GreenMessageBox : MessageBoxMenu
{
override void Init( Menu parent, String message, int messagemode, bool playsound, Name cmd, voidptr native_handler )
{
Super.Init(parent,message,messagemode,playsound,cmd,native_handler);
Font NFont = Font.GetFont('UMedFont');
if ( !generic_ui )
{
if ( NFont && NFont.CanPrint(message) && NFont.CanPrint("$TXT_YES") && NFont.CanPrint("$TXT_NO") ) textFont = NFont;
else if ( OriginalSmallFont && OriginalSmallFont.CanPrint(message) && OriginalSmallFont.CanPrint("$TXT_YES") && OriginalSmallFont.CanPrint("$TXT_NO") ) textFont = OriginalSmallFont;
}
if ( !textFont )
{
arrowFont = textFont = NewSmallFont;
int factor = (CleanXfac+1)/2;
destWidth = screen.GetWidth()/factor;
destHeight = screen.GetHeight()/factor;
selector = "▶";
}
else
{
arrowFont = ConFont;
destWidth = CleanWidth;
destHeight = CleanHeight;
selector = "\xd";
}
int mr1 = destWidth/2+10+textFont.StringWidth(Stringtable.Localize("$TXT_YES"));
int mr2 = destWidth/2+10+textFont.StringWidth(Stringtable.Localize("$TXT_NO"));
mMouseRight = MAX(mr1,mr2);
mMessage = textFont.BreakLines(Stringtable.Localize(message),generic_ui?600:300);
}
override void Drawer ()
{
int i, y;
int fontheight = textFont.GetHeight();
y = destHeight/2;
int c = mMessage.Count();
y -= c*fontHeight/2;
for ( i=0; i<c; i++ )
{
screen.DrawText (textFont,Font.CR_GREEN,(destWidth/2)-mMessage.StringWidth(i)/2,y,mMessage.StringAt(i),DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true);
y += fontheight;
}
if ( mMessageMode == 0 )
{
y += fontheight;
mMouseY = y;
screen.DrawText(textFont,(messageSelection==0)?Font.CR_WHITE:Font.CR_DARKGREEN,destWidth/2,y,Stringtable.Localize("$TXT_YES"),DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true);
screen.DrawText(textFont,(messageSelection==1)?Font.CR_WHITE:Font.CR_DARKGREEN,destWidth/2,y+fontheight,Stringtable.Localize("$TXT_NO"),DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true);
if ( messageSelection >= 0 )
{
if ( (MenuTime()%8) < 6 )
{
screen.DrawText(arrowFont,OptionMenuSettings.mFontColorSelection,(destWidth/2)-11,y+fontheight*messageSelection,selector,DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true);
}
}
}
}
}
// TODO BONUS: Code input menu, like those in various oldskool SP campaigns
// except it's somewhat prettier looking and supports alphanumeric input
Class CodeEntryMenu : GenericMenu {}
// Translator display as a menu, allows for more interactivity
Class TranslatorMenu : GenericMenu
{
bool bShowHint;
UTranslator trns;
TextureID thud[2], scroll[4];
Font tfnt, mfnt, pfnt;
BrokenLines lines;
int th, startline[2], maxlines[2], entry;
CVar ext;
bool drag;
private void SetText( String txt )
{
String ttxt = (txt.Length()>0)?txt:StringTable.Localize("$TR_NOMSG");
tfnt = (!mfnt.CanPrint(ttxt))?NewSmallFont:mfnt;
lines = tfnt.BreakLines(ttxt,200);
th = tfnt.GetHeight();
startline[0] = 0;
startline[1] = 0;
maxlines[0] = 81/th;
maxlines[1] = 201/th;
}
override void Init( Menu parent )
{
Super.Init(parent);
trns = UTranslator(players[consoleplayer].mo.FindInventory('UTranslator'));
mfnt = Font.GetFont('UMedFont');
pfnt = Font.GetFont('UOldTinyFont');
ext = CVar.GetCVar('sting_transext',players[consoleplayer]);
if ( !trns || !trns.Owner || (trns.Owner.Health <= 0) )
{
// don't do anything, will get killed in the next tick
return;
}
MenuSound("menu/activate");
thud[0] = TexMan.CheckForTexture("TranHUD3",TexMan.Type_Any);
thud[1] = TexMan.CheckForTexture("TranHUDX",TexMan.Type_Any);
scroll[0] = TexMan.CheckForTexture("VSldT",TexMan.Type_Any);
scroll[1] = TexMan.CheckForTexture("VSldM",TexMan.Type_Any);
scroll[2] = TexMan.CheckForTexture("VSldB",TexMan.Type_Any);
scroll[3] = TexMan.CheckForTexture("VSldO",TexMan.Type_Any);
if ( StatusBar is 'UnrealHUD' )
UnrealHUD(StatusBar).bTranslatorActive = true;
entry = 0;
SetText(StringTable.Localize(GetMessage(entry)));
}
private String GetMessage( int idx = 0 )
{
if ( idx == 0 ) return trns.NewMessage;
else return trns.OldMessages[trns.OldMessages.Size()-idx];
}
private String GetHint( int idx = 0 )
{
if ( idx == 0 ) return trns.Hint;
else return trns.OldHints[trns.OldHints.Size()-idx];
}
override void Ticker()
{
menuactive = OnNoPause; // don't pause game while translator is active
if ( trns && trns.Owner && (trns.Owner.Health > 0) ) return;
if ( StatusBar is 'UnrealHUD' )
UnrealHUD(StatusBar).bTranslatorActive = false;
Close();
}
override bool OnUIEvent( UIEvent ev )
{
switch ( ev.type )
{
case UIEvent.Type_WheelUp:
if ( startline[ext.GetInt()] > 0 ) MenuSound("menu/cursor");
startline[ext.GetInt()] = max(0,startline[ext.GetInt()]-1);
return true;
case UIEvent.Type_WheelDown:
if ( startline[ext.GetInt()] < max(0,lines.Count()-maxlines[ext.GetInt()]) ) MenuSound("menu/cursor");
startline[ext.GetInt()] = min(max(0,lines.Count()-maxlines[ext.GetInt()]),startline[ext.GetInt()]+1);
return true;
}
return Super.OnUIEvent(ev);
}
protected bool InBox( Vector2 p, Vector2 a, Vector2 b )
{
// pad to make input easier w/ small scales
a -= (8,8);
b += (8,8);
return ((p.x >= a.x) && (p.x < b.x) && (p.y >= a.y) && (p.y < b.y));
}
override bool MouseEvent( int type, int mx, int my )
{
bool res = Super.MouseEvent(type,mx,my);
// box locations for various elements
Vector2 validarea[2], prevmsg[2], nextmsg[2], openhint[2], closehint[2], scrollbar[2];
double ClipX, ClipY, CurX, CurY;
Vector2 vpos;
if ( StatusBar is 'UnrealHUD' )
{
ClipX = UnrealHUD(StatusBar).ClipX;
ClipY = UnrealHUD(StatusBar).ClipY;
vpos.x = mx/UnrealHUD(StatusBar).scalev.x;
vpos.y = my/UnrealHUD(StatusBar).scalev.y;
}
else
{
ClipX = CleanWidth_1;
ClipY = CleanHeight_1;
vpos.x = mx/double(CleanXFac_1);
vpos.y = my/double(CleanYFac_1);
}
if ( ext.GetBool() )
{
validarea[0] = (ClipX/2-112,ClipY/2-112);
validarea[1] = validarea[0]+(224,224);
prevmsg[0] = (ClipX/2-106,ClipY/2+100);
prevmsg[1] = prevmsg[0]+(4,6);
String pagestr = String.Format("< %d / %d ",trns.OldMessages.Size()+1-entry,trns.OldMessages.Size()+1);
int strl = pfnt.StringWidth(pagestr);
nextmsg[0] = prevmsg[0]+(strl,0);
nextmsg[1] = nextmsg[0]+(4,6);
openhint[0] = (ClipX/2+100,ClipY/2+100);
openhint[1] = openhint[0]+(8,6);
closehint[0] = (ClipX/2-106,ClipY/2+100);
closehint[1] = closehint[0]+(8,6);
scrollbar[0] = (ClipX/2+100,ClipY/2-110);
scrollbar[1] = scrollbar[0]+(7,208);
}
else
{
validarea[0] = (ClipX/2-112,ClipY/2-52);
validarea[1] = validarea[0]+(224,104);
prevmsg[0] = (ClipX/2-106,ClipY/2+40);
prevmsg[1] = prevmsg[0]+(4,6);
String pagestr = String.Format("< %d / %d ",trns.OldMessages.Size()+1-entry,trns.OldMessages.Size()+1);
int strl = pfnt.StringWidth(pagestr);
nextmsg[0] = prevmsg[0]+(strl,0);
nextmsg[1] = nextmsg[0]+(4,6);
openhint[0] = (ClipX/2+100,ClipY/2+40);
openhint[1] = openhint[0]+(8,6);
closehint[0] = (ClipX/2-106,ClipY/2+50);
closehint[1] = closehint[0]+(8,6);
scrollbar[0] = (ClipX/2+100,ClipY/2-50);
scrollbar[1] = scrollbar[0]+(7,88);
}
if ( type == MOUSE_Click )
{
if ( !InBox(vpos,validarea[0],validarea[1]) ) MenuEvent(MKEY_Back,true);
else if ( !bShowHint && InBox(vpos,prevmsg[0],prevmsg[1]) ) MenuEvent(MKEY_Left,true);
else if ( !bShowHint && InBox(vpos,nextmsg[0],nextmsg[1]) ) MenuEvent(MKEY_Right,true);
else if ( !bShowHint && InBox(vpos,openhint[0],openhint[1]) ) MenuEvent(MKEY_PageDown,true);
else if ( bShowHint && InBox(vpos,closehint[0],closehint[1]) ) MenuEvent(MKEY_PageUp,true);
else if ( InBox(vpos,scrollbar[0],scrollbar[1]) ) drag = true;
}
else if ( type == MOUSE_Release ) drag = false;
if ( drag )
{
double scl = (ext.GetInt()?192:72)/max(1,lines.Count()-maxlines[ext.GetInt()]);
int vclamp = int((clamp(vpos.y,scrollbar[0].y+4,scrollbar[1].y-4)-(scrollbar[0].y+4))/scl);
startline[ext.GetInt()] = clamp(vclamp,0,max(0,lines.Count()-maxlines[ext.GetInt()]));
}
return res;
}
override bool MenuEvent( int mkey, bool fromcontroller )
{
switch( mkey )
{
case MKEY_Enter:
case MKEY_Back:
if ( StatusBar is 'UnrealHUD' )
UnrealHUD(StatusBar).bTranslatorActive = false;
MenuSound(GetCurrentMenu()?"menu/backup":"menu/clear");
Close();
return true;
case MKEY_Up:
if ( startline[ext.GetInt()] > 0 ) MenuSound("menu/cursor");
startline[ext.GetInt()] = max(0,startline[ext.GetInt()]-1);
return true;
case MKEY_Down:
if ( startline[ext.GetInt()] < max(0,lines.Count()-maxlines[ext.GetInt()]) ) MenuSound("menu/cursor");
startline[ext.GetInt()] = min(max(0,lines.Count()-maxlines[ext.GetInt()]),startline[ext.GetInt()]+1);
return true;
case MKEY_PageDown:
if ( trns && (GetHint(entry).length() > 0) )
{
MenuSound("menu/cursor");
bShowHint = true;
SetText(StringTable.Localize(GetHint(entry)));
}
return true;
case MKEY_PageUp:
if ( trns && bShowHint )
{
MenuSound("menu/cursor");
bShowHint = false;
SetText(StringTable.Localize(GetMessage(entry)));
}
return true;
case MKEY_Left:
if ( trns && (entry < trns.OldMessages.Size()) )
{
MenuSound("menu/cursor");
bShowHint = false;
entry++;
SetText(StringTable.Localize(GetMessage(entry)));
}
return true;
case MKEY_Right:
if ( trns && (entry > 0) )
{
MenuSound("menu/cursor");
bShowHint = false;
entry--;
SetText(StringTable.Localize(GetMessage(entry)));
}
return true;
}
return false;
}
override void Drawer()
{
Super.Drawer();
if ( !trns || !trns.Owner || (trns.Owner.Health <= 0) ) return;
double ClipX, ClipY, CurX, CurY;
if ( StatusBar is 'UnrealHUD' )
{
ClipX = UnrealHUD(StatusBar).ClipX;
ClipY = UnrealHUD(StatusBar).ClipY;
}
else
{
ClipX = CleanWidth_1;
ClipY = CleanHeight_1;
}
// The translator
CurX = ClipX/2-128;
CurY = ClipY/2-(ext.GetInt()?128:68);
Screen.DrawTexture(thud[ext.GetInt()],false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
// The message text
CurX += 22;
CurY += 22;
int l = startline[ext.GetInt()];
for ( int i=0; i<maxlines[ext.GetInt()]; i++ )
{
if ( l >= lines.Count() ) break;
Screen.DrawText(tfnt,Font.CR_UNTRANSLATED,CurX,CurY,lines.StringAt(l),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
l++;
CurY += th;
}
// Scrollbar
CurX = ClipX/2+100;
if ( lines.Count() > maxlines[ext.GetInt()] )
{
CurY = ClipY/2-(ext.GetInt()?114:54);
Screen.DrawTexture(scroll[0],false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurY += 8;
int cnt = ext.GetInt()?25:10;
for ( int i=0; i<cnt; i++ )
{
Screen.DrawTexture(scroll[1],false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurY += 8;
}
Screen.DrawTexture(scroll[2],false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
CurY = (ClipY/2-(ext.GetInt()?106:46)) + ((startline[ext.GetInt()]*(ext.GetInt()?192:72))/max(1,lines.Count()-maxlines[ext.GetInt()]));
Screen.DrawTexture(scroll[3],false,CurX,CurY,DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
}
if ( !bShowHint && (GetHint(entry).length() > 0) )
{
CurY = ClipY/2+(ext.GetInt()?100:40);
Screen.DrawText(pfnt,Font.CR_GREEN,CurX,CurY,">>",DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_Alpha,(MenuTime()%16)/16.);
}
CurX = ClipX/2-106;
CurY = ClipY/2+(ext.GetInt()?100:40);
if ( bShowHint ) Screen.DrawText(pfnt,Font.CR_GREEN,CurX,CurY,"<<",DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true,DTA_Alpha,(MenuTime()%16)/16.);
else if ( trns.OldMessages.Size() > 0 ) Screen.DrawText(pfnt,Font.CR_GREEN,CurX,CurY,String.Format("%s %d / %d %s",(entry<trns.OldMessages.Size())?"<":" ",trns.OldMessages.Size()+1-entry,trns.OldMessages.Size()+1,(entry>0)?">":" "),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true);
}
}