// Menu stuff // voice selector Class OptionMenuItemSWWMVoiceOption : OptionMenuItemOptionBase { CVar mCVar; Array types; OptionMenuItemSWWMVoiceOption Init( String label, Name command, CVar graycheck = null, int center = 0 ) { Super.Init(label,command,'',graycheck,center); mCVar = CVar.FindCVar(mAction); int lmp; for ( lmp = Wads.FindLump("swwmvoicepack.txt"); lmp > 0; lmp = Wads.FindLump("swwmvoicepack.txt",lmp+1) ) { Array lst; lst.Clear(); String dat = Wads.ReadLump(lmp); dat.Split(lst,"\n",0); for ( int i=0; i= 0 ) { mValues = newtext; int s = GetSelection(); if ( (s >= cnt) || (s < 0) ) s = 0; SetSelection(s); return true; } } return false; } override int GetSelection() { int Selection = -1; int cnt = types.Size(); if ( (cnt > 0) && mCVar ) { String cv = mCVar.GetString(); for( int i=0; i 0) && mCVar ) mCVar.SetString(types[Selection]); } override int Draw( OptionMenuDescriptor desc, int y, int indent, bool selected ) { if ( mCenter ) indent = (screen.GetWidth()/2); drawLabel(indent,y,selected?OptionMenuSettings.mFontColorSelection:OptionMenuSettings.mFontColor,isGrayed()); int Selection = GetSelection(); String loc; if ( Selection == -1 ) loc = "Unknown"; else { String uptxt = types[Selection]; uptxt.MakeUpper(); String str = String.Format("SWWM_VOICENAME_%s",uptxt); loc = StringTable.Localize(str,false); if ( str == loc ) loc = types[Selection]; } drawValue(indent,y,OptionMenuSettings.mFontColorValue,loc,isGrayed()); return indent; } override bool MenuEvent( int mkey, bool fromcontroller ) { int cnt = types.Size(); if ( cnt > 0 ) { int Selection = GetSelection(); if ( mkey == Menu.MKEY_Left ) { if ( Selection == -1 ) Selection = 0; else if ( --Selection < 0 ) Selection = cnt-1; } else if ( (mkey == Menu.MKEY_Right) || (mkey == Menu.MKEY_Enter) ) { if ( ++Selection >= cnt ) Selection = 0; } else return OptionMenuItem.MenuEvent(mkey,fromcontroller); SetSelection(Selection); Menu.MenuSound("menu/change"); } else return OptionMenuItem.MenuEvent(mkey,fromcontroller); return true; } } Class OptionMenuItemSWWMPlayTime : OptionMenuItem { CVar mCVar; bool dformat; // switch between short form and long form time display OptionMenuItemSWWMPlayTime Init( String label, Name command ) { Super.Init(label,command); return self; } override bool MenuEvent( int mkey, bool fromcontroller ) { if ( (mkey == Menu.MKEY_Left) || (mkey == Menu.MKEY_Right) || (mkey == Menu.MKEY_Enter) ) dformat = !dformat; else return Super.MenuEvent(mkey,fromcontroller); Menu.MenuSound("menu/change"); return true; } override int Draw( OptionMenuDescriptor desc, int y, int indent, bool selected ) { drawLabel(indent,y,selected?OptionMenuSettings.mFontColorSelection:OptionMenuSettings.mFontColor); int val = swwm_playtime; int sec = (val%60); int min = ((val/60)%60); int hour = ((val/3600)%24); int day = val/86400; String str = ""; if ( dformat ) { if ( day ) str.AppendFormat("%d %s",day,StringTable.Localize((day!=1)?"$SWWM_TIME_DAYS":"$SWWM_TIME_DAY")); if ( hour ) { if ( str != "" ) str = str..", "; str.AppendFormat("%d %s",hour,StringTable.Localize((hour!=1)?"$SWWM_TIME_HOURS":"$SWWM_TIME_HOUR")); } if ( min ) { if ( str != "" ) str = str..", "; str.AppendFormat("%d %s",min,StringTable.Localize((min!=1)?"$SWWM_TIME_MINUTES":"$SWWM_TIME_MINUTE")); } if ( sec ) { if ( str != "" ) str = str..", "; str.AppendFormat("%d %s",sec,StringTable.Localize((sec!=1)?"$SWWM_TIME_SECONDS":"$SWWM_TIME_SECOND")); } if ( str == "" ) str.AppendFormat("0 %s",StringTable.Localize("$SWWM_TIME_SECONDS")); } else { if ( day ) str = String.Format("%d:%02d:%02d:%02d",day,hour,min,sec); else if ( hour ) str = String.Format("%d:%02d:%02d",hour,min,sec); else str = String.Format("%d:%02d",min,sec); } drawValue(indent,y,OptionMenuSettings.mFontColorValue,str); return indent; } } // option menu /w tooltips Class SWWMOptionMenu : OptionMenu { private String ttip, olttip; private Font mTipFont; private BrokenLines ttlines; override void Init( Menu parent, OptionMenuDescriptor desc ) { Super.Init(parent,desc); mTipFont = Font.GetFont('TewiFont'); } override void Ticker() { Super.Ticker(); // fetch the tooltip for whatever's selected (if any) if ( mDesc.mSelectedItem == -1 ) return; String mcvar = mDesc.mItems[mDesc.mSelectedItem].GetAction(); mcvar.Replace(" ","_"); // need to strip whitespace for command actions String locstr = String.Format("TOOLTIP_%s",mcvar); olttip = ttip; ttip = StringTable.Localize(locstr,false); if ( ttip == locstr ) ttip = ""; if ( (ttip != olttip) && ttlines ) ttlines.Destroy(); if ( !ttlines ) ttlines = mTipFont.BreakLines(ttip,CleanWidth_1-8); } override void Drawer() { Super.Drawer(); if ( (ttip == "") || !ttlines ) return; // re-evaluate y to check where the cursor is int cy = 0; int y = mDesc.mPosition; if ( y <= 0 ) { let font = generic_ui||!mDesc.mFont?NewSmallFont:mDesc.mFont; if ( font && (mDesc.mTitle.Length() > 0) ) y = -y+font.GetHeight(); else y = -y; } int fontheight = OptionMenuSettings.mLinespacing*CleanYfac_1; y *= CleanYfac_1; int lastrow = Screen.GetHeight()-OptionHeight()*CleanYfac_1; for ( int i=0; ((i < mDesc.mItems.Size()) && (y <= lastrow)); i++ ) { // Don't scroll the uppermost items if ( i == mDesc.mScrollTop ) { i += mDesc.mScrollPos; if ( i >= mDesc.mItems.Size() ) break; // skipped beyond end of menu } y += fontheight; if ( mDesc.mSelectedItem == i ) { cy = y+fontheight; break; } } int height = (4+mTipFont.GetHeight()*ttlines.Count())*CleanYFac_1; // draw at the bottom unless the selected option could be covered by the tooltip int ypos = Screen.GetHeight()-height; if ( cy > ypos ) ypos = 0; Screen.Dim("Black",.75,0,ypos,Screen.GetWidth(),height); ypos += 2*CleanYFac_1; for ( int i=0; i mDesc.mWLeft)) && ((mDesc.mWRight <= 0) || (x < mDesc.mWRight)) ) { for( int i=0;i done; Array candidates; let c = CVar.FindCVar('swwm_menuposehistory'); String str = c.GetString(); if ( str != "" ) str.Split(done,";"); else { c.SetString("2"); return TexMan.CheckForTexture(StringTable.Localize("$SWWM_MENUPOSE2"),TexMan.Type_Any); } int npose = StringTable.Localize("$SWWM_NMENUPOSE").ToInt(); for ( int i=1; i<=npose; i++ ) { String sn = String.Format("%d",i); if ( done.Find(sn) < done.Size() ) continue; candidates.Push(i); } if ( candidates.Size() == 0 ) { c.SetString("2"); return TexMan.CheckForTexture(StringTable.Localize("$SWWM_MENUPOSE2"),TexMan.Type_Any); } int which = candidates[Random[UIStuff](0,candidates.Size()-1)]; c.SetString(str..";"..which); return TexMan.CheckForTexture(StringTable.Localize("$SWWM_MENUPOSE"..which),TexMan.Type_Any); } override void Init( Menu parent, ListMenuDescriptor desc ) { Super.Init(parent,desc); mSmallFont = Font.GetFont('TewiFont'); demotex = GetDemoTex(); demopos = 120; prevms = MSTimeF(); } override void OnReturn() { demotex = GetDemoTex(); demopos = 120; prevms = MSTimeF(); } private int GetMenuYOffset() { int mofs = CleanHeight_1/2-160; return mofs; } override void Drawer() { double frametime = (MSTimeF()-prevms)/1000.; double theta; // naive, but whatever if ( swwm_oldlogo ) theta = clamp(2.*frametime,0.,1.); else theta = clamp(4.*frametime,0.,1.); if ( prevms ) demopos = SWWMUtility.Lerp(demopos,-40,theta); double alph = clamp(1.-(demopos/100),0.,1.); if ( !swwm_oldlogo ) { if ( !gradtex ) gradtex = TexMan.CheckForTexture("graphics/M_GRAD.png",TexMan.Type_Any); double scl = Screen.GetHeight()/960.; Screen.DrawTexture(gradtex,false,0,Screen.GetHeight(),DTA_DestWidth,Screen.GetWidth(),DTA_DestHeight,256*CleanYFac_1,DTA_LegacyRenderStyle,STYLE_Shaded,DTA_FillColor,Color(0,0,0),DTA_TopOffset,256,DTA_Alpha,.35); Screen.DrawTexture(gradtex,false,Screen.GetWidth()/2,Screen.GetHeight(),DTA_Rotate,90,DTA_DestHeight,Screen.GetHeight(),DTA_DestWidthF,600*scl*alph,DTA_LegacyRenderStyle,STYLE_Shaded,DTA_FillColor,Color(0,0,0),DTA_TopOffset,256,DTA_Alpha,alph*.5); Screen.DrawTexture(gradtex,false,Screen.GetWidth()/2,0,DTA_Rotate,270,DTA_DestHeight,Screen.GetHeight(),DTA_DestWidthF,600*scl*alph,DTA_LegacyRenderStyle,STYLE_Shaded,DTA_FillColor,Color(0,0,0),DTA_TopOffset,256,DTA_Alpha,alph*.5); Screen.DrawTexture(gradtex,false,Screen.GetWidth()/2,Screen.GetHeight(),DTA_Rotate,90,DTA_DestHeight,Screen.GetHeight(),DTA_DestWidthF,500*scl*alph,DTA_LegacyRenderStyle,STYLE_AddShaded,DTA_FillColor,Color(40,80,120),DTA_TopOffset,256,DTA_Alpha,alph); Screen.DrawTexture(gradtex,false,Screen.GetWidth()/2,0,DTA_Rotate,270,DTA_DestHeight,Screen.GetHeight(),DTA_DestWidthF,500*scl*alph,DTA_LegacyRenderStyle,STYLE_AddShaded,DTA_FillColor,Color(40,80,120),DTA_TopOffset,256,DTA_Alpha,alph); Screen.DrawTexture(demotex,false,Screen.GetWidth()/2,0,DTA_ScaleX,scl,DTA_ScaleY,scl,DTA_Alpha,alph,DTA_ColorOverlay,Color(int(255*(1.-(alph**2))),0,0,0)); } else Screen.DrawTexture(demotex,false,(demopos-160)*CleanXFac_1+(Screen.GetWidth()*.5),(Screen.GetHeight()-400*CleanYFac_1)/2 + sin(gametic*GameTicRate*.1)*CleanYFac_1*8*(alph**2),DTA_CleanNoMove_1,true,DTA_Alpha,alph,DTA_ColorOverlay,Color(64+int(191*(1.-(alph**2))),0,0,0)); if ( !swwm_oldlogo ) for ( int i=0; i 7 ) { longlist = true; ntext = 7; } double theight = ntext*BIGMENUSPACING+56; int h = mDesc.DisplayHeight(); if ( h == -1 ) h = 200; double oy = int((h-theight)/2); // apply offsets for ( int i=0, j=0; i 0 ) { if ( isclean ) Screen.DrawText(mSmallFont,Font.CR_FIRE,x,y+16*CleanYFac_1,str,DTA_CleanNoMove_1,true); else Screen.DrawText(mSmallFont,Font.CR_FIRE,x,y+16,str,DTA_VirtualWidth,w,DTA_VirtualHeight,h,DTA_FullscreenScale,FSMode_ScaleToFit43); } if ( ofs < (mDesc.mItems.Size()-8) ) { str = "⌄ ⌄ ⌄"; if ( isclean ) Screen.DrawText(mSmallFont,Font.CR_FIRE,x,y+256*CleanYFac_1,str,DTA_CleanNoMove_1,true); else Screen.DrawText(mSmallFont,Font.CR_FIRE,x,y+256,str,DTA_VirtualWidth,w,DTA_VirtualHeight,h,DTA_FullscreenScale,FSMode_ScaleToFit43); } for ( int i=0; i ofs+7) ) continue; offsetme = true; } if ( offsetme ) mDesc.mItems[i].OffsetPositionY(-ofs*BIGMENUSPACING); mDesc.mItems[i].Draw((mDesc.mSelectedItem==i),mDesc); if ( mDesc.mSelectedItem == i ) mDesc.mItems[i].DrawSelector(mDesc.mSelectOfsX,mDesc.mSelectOfsY,mDesc.mSelector,mDesc); if ( offsetme ) mDesc.mItems[i].OffsetPositionY(ofs*BIGMENUSPACING); } Menu.Drawer(); } // mouse input is also a hack override bool MouseEvent( int type, int x, int y ) { // set offsets for ( int i=0; i ofs+7) ) continue; offsetme = true; } if ( offsetme ) mDesc.mItems[i].OffsetPositionY(-ofs*BIGMENUSPACING); else mDesc.mItems[i].OffsetPositionY(-65536); } bool res = Super.MouseEvent(type,x,y); // unset offsets for ( int i=0; i ofs+7) ) continue; offsetme = true; } if ( offsetme ) mDesc.mItems[i].OffsetPositionY(ofs*BIGMENUSPACING); else mDesc.mItems[i].OffsetPositionY(65536); } return res; } } Class ListMenuItemSWWMStaticTextM : ListMenuItem { String mText; Font mFont; int mColor; void Init( ListMenuDescriptor desc, double x, double y, String text, int color = -1 ) { Super.Init(x,y); mText = text; mFont = desc.mFont; mColor = (color>=0)?color:desc.mFontColor; } void InitDirect( double x, double y, String text, Font font, int color = Font.CR_UNTRANSLATED ) { Super.Init(x,y); mText = text; mFont = font; mColor = color; } override void Draw( bool selected, ListMenuDescriptor desc ) { if ( mText.Length() == 0 ) return; String text = Stringtable.Localize(mText); int w = desc?desc.DisplayWidth():ListMenuDescriptor.CleanScale; int h = desc?desc.DisplayHeight():-1; let font = menuDelegate.PickFont(mFont); int scl; if ( font != NewSmallFont ) scl = 3; else scl = 2; if ( w == ListMenuDescriptor.CleanScale ) { double x = (320-mFont.StringWidth(text)*scl)/2; double y = mYpos; SWWMUtility.AdjustClean_1(x,y); Screen.DrawText(mFont,mColor,x,y,text,DTA_ScaleX,CleanXFac_1*scl,DTA_ScaleY,CleanYFac_1*scl); } else { double x = (w-mFont.StringWidth(text)*scl)/2; Screen.DrawText(mFont,mColor,x,mYpos,text,DTA_VirtualWidth,w,DTA_VirtualHeight,h,DTA_FullscreenScale,FSMode_ScaleToFit43,DTA_ScaleX,scl,DTA_ScaleY,scl); } } } // scaled mod logo class ListMenuItemSWWMLogo : ListMenuItem { TextureID mTexture, mOldTexture; void Init( ListMenuDescriptor desc ) { Super.Init(desc.mXpos,desc.mYpos); mTexture = TexMan.CheckForTexture("graphics/M_DEMOLITIONIST.png",TexMan.Type_Any); mOldTexture = TexMan.CheckForTexture("graphics/M_SWWM.png",TexMan.Type_Any); } private int GetMenuYOffset() { int mofs = CleanHeight_1/2-160; return mofs; } override void Draw( bool selected, ListMenuDescriptor desc ) { let tex = swwm_oldlogo?mOldTexture:mTexture; if ( !tex.Exists() ) return; int w = desc?desc.DisplayWidth():ListMenuDescriptor.CleanScale; int h = desc?desc.DisplayHeight():-1; Vector2 vs = TexMan.GetScaledSize(tex); double scl = swwm_oldlogo?(256./vs.x):(2./3.); double x; if ( w == ListMenuDescriptor.CleanScale ) { x = (320-vs.x*scl)/2; double y = swwm_oldlogo?(-48):(-24+GetMenuYOffset()); SWWMUtility.AdjustClean_1(x,y); Screen.DrawTexture(tex,false,x,y,DTA_ScaleX,CleanXFac_1*scl,DTA_ScaleY,CleanYFac_1*scl); } else { x = (w-vs.x*scl)/2; Screen.DrawTexture(tex,false,x,swwm_oldlogo?(-48):(-24+GetMenuYOffset()),DTA_VirtualWidth,w,DTA_VirtualHeight,h,DTA_FullscreenScale,FSMode_ScaleToFit43,DTA_ScaleX,scl,DTA_ScaleY,scl); } } } // message box that changes text color to match menus and applies special scaling Class SWWMMessageBox : 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); if ( generic_ui ) { destWidth = CleanWidth_1; destHeight = CleanHeight_1; textfont = newsmallfont; mMessage = textfont.BreakLines(Stringtable.Localize(message),480); } else { destWidth = CleanWidth_1; destHeight = CleanHeight_1; textfont = Font.GetFont('TewiFontOutline'); mMessage = textfont.BreakLines(Stringtable.Localize(message),480); } } override void Drawer() { let fontheight = textfont.GetHeight()-2; double y = destHeight/2; int c = mMessage.Count(); int theight = 0; int l1 = c; int l2 = c-1; for ( int i=0; i=l2)||(mMessage.StringWidth(i)==0))?1:(i>l1)?1:2; else scl = ((i>=l2)||(mMessage.StringWidth(i)==0))?2:(i>l1)?1:3; theight += fontheight*scl; } y -= theight/2; for ( int i=0; i=l2)||(mMessage.StringWidth(i)==0))?1.:(i>l1)?1.:2.; else scl = ((i>=l2)||(mMessage.StringWidth(i)==0))?2.:(i>l1)?1.:3.; Screen.DrawText(textfont,OptionMenuSettings.mFontColorValue,int(destWidth/2-mMessage.StringWidth(i)*(scl/2.)),y,mMessage.StringAt(i),DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true,DTA_ScaleX,scl,DTA_ScaleY,scl); y += fontheight*scl; } if ( mMessageMode != 0 ) return; y += fontheight; mMouseY = int(y); String stryes = Stringtable.Localize("$TXT_YES"); String strno = Stringtable.Localize("$TXT_NO"); if ( generic_ui ) { Screen.DrawText(textfont,messageSelection==0?OptionMenuSettings.mFontColorSelection:OptionMenuSettings.mFontColor,(destWidth-textfont.StringWidth(stryes))/2,y,stryes, DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true); Screen.DrawText(textfont,messageSelection==1?OptionMenuSettings.mFontColorSelection:OptionMenuSettings.mFontColor,(destWidth-textfont.StringWidth(strno))/2,y+fontheight,strno,DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true); if ( (messageSelection < 0) || ((MenuTime()%8) >= 4) ) return; Screen.DrawText(textfont,OptionMenuSettings.mFontColorSelection,(destWidth-textfont.StringWidth(messageSelection?strno:stryes))/2-16,y+fontheight*messageSelection,"►",DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true); Screen.DrawText(textfont,OptionMenuSettings.mFontColorSelection,(destWidth+textfont.StringWidth(messageSelection?strno:stryes))/2+8,y+fontheight*messageSelection,"◄",DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true); } else { Screen.DrawText(textfont,messageSelection==0?OptionMenuSettings.mFontColorSelection:OptionMenuSettings.mFontColor,(destWidth-2*textfont.StringWidth(stryes))/2,y,stryes, DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true,DTA_ScaleX,2.,DTA_ScaleY,2.); Screen.DrawText(textfont,messageSelection==1?OptionMenuSettings.mFontColorSelection:OptionMenuSettings.mFontColor,(destWidth-2*textfont.StringWidth(strno))/2,y+fontheight*2,strno,DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true,DTA_ScaleX,2.,DTA_ScaleY,2.); if ( (messageSelection < 0) || ((MenuTime()%8) >= 4) ) return; Screen.DrawText(textfont,OptionMenuSettings.mFontColorSelection,(destWidth-2*textfont.StringWidth(messageSelection?strno:stryes))/2-26,y+fontheight*2*messageSelection,"►",DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true,DTA_ScaleX,2.,DTA_ScaleY,2.); Screen.DrawText(textfont,OptionMenuSettings.mFontColorSelection,(destWidth+2*textfont.StringWidth(messageSelection?strno:stryes))/2+12,y+fontheight*2*messageSelection,"◄",DTA_VirtualWidth,destWidth,DTA_VirtualHeight,destHeight,DTA_KeepRatio,true,DTA_ScaleX,2.,DTA_ScaleY,2.); } } override bool MouseEvent( int type, int x, int y ) { if ( mMessageMode == 1 ) { if ( type == MOUSE_Click ) return MenuEvent(MKEY_Enter,true); return false; } else { int sel = -1; int fh = (textfont.GetHeight()-2)*(generic_ui?1:2); // convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture x = x*destWidth/screen.GetWidth(); y = y*destHeight/screen.GetHeight(); if ( (y >= mMouseY) && (y < mMouseY+(generic_ui?1:2)*fh) ) { sel = (y >= mMouseY+fh); // are we actually selecting the text? String txt = sel?Stringtable.Localize("$TXT_NO"):Stringtable.Localize("$TXT_YES"); int txtln = textfont.StringWidth(txt); int minx = (destWidth-txtln); if ( (x < (destWidth-txtln)) && (x > (destWidth+txtln)) ) sel = -1; } messageSelection = sel; if ( type == MOUSE_Release ) return MenuEvent(MKEY_Enter,true); return true; } } } Mixin Class SWWMSelector { override void DrawSelector( double xofs, double yofs, TextureID tex, ListMenuDescriptor desc ) { if ( tex.isNull() ) return; int w = desc?desc.DisplayWidth():ListMenuDescriptor.CleanScale; int h = desc?desc.DisplayHeight():-1; double y = mYpos+mHeight/2; if ( w == ListMenuDescriptor.CleanScale ) { xofs *= CleanXFac_1; yofs *= CleanYFac_1; double x = (320-GetWidth())/2; SWWMUtility.AdjustClean_1(x,y); Screen.DrawTexture(tex,true,x+xofs,y+yofs,DTA_ScaleX,CleanXFac_1/4.,DTA_ScaleY,CleanYFac_1/4.,DTA_Rotate,15.*sin(8*Menu.MenuTime())); x = (320+GetWidth())/2; SWWMUtility.AdjustClean_1x(x); Screen.DrawTexture(tex,true,x-xofs,y+yofs,DTA_ScaleX,CleanXFac_1/4.,DTA_ScaleY,CleanYFac_1/4.,DTA_Rotate,-15.*sin(8*Menu.MenuTime())); } else { double x = (w-GetWidth())/2; Screen.DrawTexture(tex,true,x+xofs,y+yofs,DTA_ScaleX,.25,DTA_ScaleY,.25,DTA_VirtualWidth,w,DTA_VirtualHeight,h,DTA_FullscreenScale,FSMode_ScaleToFit43,DTA_Rotate,15.*sin(8*Menu.MenuTime())); x = (w+GetWidth())/2; Screen.DrawTexture(tex,true,x-xofs,y+yofs,DTA_ScaleX,.25,DTA_ScaleY,.25,DTA_VirtualWidth,w,DTA_VirtualHeight,h,DTA_FullscreenScale,FSMode_ScaleToFit43,DTA_Rotate,-15.*sin(8*Menu.MenuTime())); } } } // allow the player to skip skill confirmation message boxes Mixin Class SWWMSkillConfirmSkippable { override bool Activate() { Menu.SetMenu(((mAction=='StartgameConfirm')&&swwm_skipskill)?'Startgame':mAction,mParam); return true; } override Name, int GetAction() { return (((mAction=='StartgameConfirm')&&swwm_skipskill)?'Startgame':mAction),mParam; } } // main menu item with wiggly text when selected and Demo face selectors on both sides Class ListMenuItemSWWMTextItemM : ListMenuItemSelectable { Mixin SWWMSelector; Mixin SWWMSkillConfirmSkippable; String mText; Font mFont; int mColor; int mColorSelected; 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 = desc.mFont; mColor = desc.mFontColor; mColorSelected = desc.mFontcolor2; mHotkey = hotkey.GetNextCodePoint(0); } void InitDirect( double x, double y, int height, int 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; mColor = color; mColorSelected = color2; mHotkey = hotkey; } override int GetWidth() { let font = menuDelegate.PickFont(mFont); int w = font.StringWidth(StringTable.Localize(mText)); if ( font != NewSmallFont ) w *= 2; return max(1,w); } override void Draw( bool selected, ListMenuDescriptor desc ) { int w = desc?desc.DisplayWidth():ListMenuDescriptor.CleanScale; int h = desc?desc.DisplayHeight():-1; String text = StringTable.Localize(mText); let font = menuDelegate.PickFont(mFont); int scl; if ( font != NewSmallFont ) scl = 2; else scl = 1; double x; // centered if ( w == ListMenuDescriptor.CleanScale ) x = (320-font.StringWidth(text)*scl)/2; else x = (w-font.StringWidth(text)*scl)/2; double y = mYpos; // offset text so it's centered y += (mHeight-font.GetHeight()*scl)/2; if ( selected ) { double xx = x; SWWMUtility.StripColor(text); int tlen = text.CodePointCount(); int kern = font.GetDefaultKerning(); if ( w == ListMenuDescriptor.CleanScale ) { SWWMUtility.AdjustClean_1(xx,y); for ( int i=0, pos=0; i 0 ) return; // haha more crimes Menu.SetMenu('QuitMenu'); let m = MessageBoxMenu(Menu.GetCurrentMenu()); if ( m ) m.HandleResult(true); } override bool Activate() { Menu.MenuSound("bruh"); cdown = int(S_GetLength("bruh")*GameTicRate)+4; return true; } } // this is kind of a fucky // scalesliders kinda fuck up keyboard input if the step is not 1, // so I'll fix that for my super special use cases Class OptionMenuItemScaleSliderFix : OptionMenuItemScaleSlider { override bool MenuEvent ( int mkey, bool fromcontroller ) { double value = GetSliderValue(); if ( mkey == Menu.MKEY_Left ) { if ( value <= 0 ) value--; else value = max(0,value-mStep); } else if ( mkey == Menu.MKEY_Right ) { if ( value < 0 ) value++; else value += mStep; } else return OptionMenuItem.MenuEvent(mkey,fromcontroller); if ( value ~== 0 ) value = 0; // This is to prevent formatting anomalies with very small values SetSliderValue(clamp(value,mMin,mMax)); Menu.MenuSound("menu/change"); return true; } } // draw captions using our own font Class SWWMMenuDelegate : DoomMenuDelegate { Font mBigFont; override int DrawCaption( String title, Font fnt, int y, bool drawit ) { if ( !mBigFont ) mBigFont = Font.GetFont('TewiFontOutline'); fnt = mBigFont; if ( drawit ) Screen.DrawText(fnt,OptionMenuSettings.mTitleColor,(Screen.GetWidth()-fnt.StringWidth(title)*CleanXFac_1*2)/2,8*CleanYFac_1,title,DTA_ScaleX,CleanXFac_1*2,DTA_ScaleY,CleanYFac_1*2); return (y+fnt.GetHeight()*2)*CleanYFac_1; } }