// 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= 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('stinger_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= 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= 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 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",(entry0)?">":" "),DTA_VirtualWidthF,ClipX,DTA_VirtualHeightF,ClipY,DTA_KeepRatio,true); } }