Dronis

Тема в разделе "Представьтесь", создана пользователем Dronis, 4 фев 2015.

Метки:
  1. Proton

    Proton Игровой администратор

    сам не ожидал такого прозрения
     
    BAHO нравится это.
  2. Dronis

    Dronis Бандит

    Смотрю хорошо вы тут устроились, рад за вас.

    Пока вы обсуждали о подписи, нашел способ выравнить менюшку начальную. Нижние кнопки типа "выйти", "откл." обычно убегали вниз за пределами экрана.
    [​IMG]
     
  3. BAHO

    BAHO Fresh Meat

    А разве на экранах формата 4:3 убегают кнопки?
     
  4. Proton

    Proton Игровой администратор

    Дело не в экранах,а в разрешении, выставленном в игре.
     
  5. Dronis

    Dronis Бандит

    [​IMG] при низких разрешениях кнопки тонут, рано радовался. Как ни странно при высоком немного тоже уходили вниз а теперь нет.. вообще все это не то, но как то можно же довести это до ума при любых разрешениях.
     
  6. Dr_Killjoy

    Dr_Killjoy Заблокированные

    Шрифт подкручивать в зависимости от разрешения.
     
    Dronis нравится это.
  7. Dronis

    Dronis Бандит

    Да тоже такая мысль была, где то видел такой код, никак не вспомню..
    что то вроде этого чтоли
    if(C.ClipX <= float(640))
    {
    FontSize = 7;
    }
    else
    {
    if(C.ClipX <= float(800))
    {
    FontSize = 6;
    }
    else
    {
    if(C.ClipX <= float(1024))
    {
    FontSize = 5;
    }
    else
    {
    if(C.ClipX <= float(1280))
    {
    FontSize = 4;
    }
    else
    {
    FontSize = 3;
    }
    }
    }
    }
     
  8. Dr_Killjoy

    Dr_Killjoy Заблокированные

    Да, единственное что, надо понять где у этих кнопок шрифт настраивается, и всё готово.
     
  9. Dronis

    Dronis Бандит

    KFInvasionLoginMenu
    class KFInvasionLoginMenu extends UT2K4PlayerLoginMenu;

    var bool bNoSteam;

    function InitComponent(GUIController MyController, GUIComponent MyComponent)
    {
    local PlayerController PC;
    local int i;

    Super.InitComponent(MyController, MyComponent);

    // Remove Perks tab if Perks aren't enabled
    PC = PlayerOwner();
    if ( !MyController.CheckSteam() || PC == none || KFGameReplicationInfo(PC.Level.GRI) == none )
    {
    c_Main.RemoveTab(Panels[1].Caption);
    c_Main.ActivateTabByName(Panels[2].Caption, true);
    bNoSteam = true;
    }
    else if ( PC.SteamStatsAndAchievements == none )
    {
    if ( PC.Level.NetMode != NM_Client )
    {
    PC.SteamStatsAndAchievements = PC.Spawn(PC.default.SteamStatsAndAchievementsClass, PC);
    if ( !PC.SteamStatsAndAchievements.Initialize(PC) )
    {
    PC.SteamStatsAndAchievements.Destroy();
    PC.SteamStatsAndAchievements = none;
    }
    }

    c_Main.RemoveTab(Panels[1].Caption);
    c_Main.ActivateTabByName(Panels[2].Caption, true);
    bNoSteam = true;
    }
    else if ( !PC.SteamStatsAndAchievements.bInitialized )
    {
    PC.SteamStatsAndAchievements.GetStatsAndAchievements();
    c_Main.RemoveTab(Panels[1].Caption);
    c_Main.ActivateTabByName(Panels[2].Caption, true);
    bNoSteam = true;
    }
    else
    {
    for ( i = 0; i < class'KFGameType'.default.LoadedSkills.Length; i++ )
    {
    if ( KFSteamStatsAndAchievements(PC.SteamStatsAndAchievements).GetPerkProgress(i) < 0.0 )
    {
    PC.SteamStatsAndAchievements.GetStatsAndAchievements();
    c_Main.RemoveTab(Panels[1].Caption);
    c_Main.ActivateTabByName(Panels[2].Caption, true);
    bNoSteam = true;
    }
    }
    }

    c_Main.RemoveTab(Panels[0].Caption);
    if ( !bNoSteam )
    {
    c_Main.ActivateTabByName(Panels[1].Caption, true);
    }
    }

    // Overridden to stop the unnecessary removal of Panels
    function RemoveMultiplayerTabs(GameInfo Game)
    {
    }

    defaultproperties
    {
    Panels(0)=(ClassName="KFGUI.KFLoginControls")
    Panels(1)=(ClassName="KFGUI.KFTab_MidGamePerks",Caption="Perks",Hint="Select your current Perk")
    Panels(2)=(ClassName="KFGUI.KFTab_MidGameVoiceChat",Caption="Communication",Hint="Manage communication with other players")
    Panels(3)=(ClassName="KFGUI.KFTab_MidGameHelp",Caption="Help",Hint="How to survive in Killing Floor")
    Begin Object Class=GUITabControl Name=LoginMenuTC
    bDockPanels=True
    BackgroundStyleName="TabBackground"
    WinTop=0.026336
    WinLeft=0.012500
    WinWidth=0.974999
    WinHeight=0.050000
    bScaleToParent=True
    bAcceptsInput=True
    OnActivate=LoginMenuTC.InternalOnActivate
    End Object
    c_Main=GUITabControl'KFGui.KFInvasionLoginMenu.LoginMenuTC'

    WinTop=0.006158
    WinWidth=0.814844
    WinHeight=0.990311
    }
    UT2K4PlayerLoginMenu
    //==============================================================================
    // Login & Midgame menu - appears when player joins a server for the first time in a while and also on Esc press
    // Has tabs for seeing server rules & map rotation, team scores, and game controls
    //
    // Created by Matt Oelfke
    // (c) 2003, Epic Games, Inc. All Rights Reserved
    //==============================================================================

    class UT2K4PlayerLoginMenu extends FloatingWindow;

    var(MidGame) array<GUITabItem> Panels;
    var(MidGame) GUITabItem SPRulesPanel;
    var(MidGame) GUITabItem IARulesPanel;

    var(MidGame) automated GUITabControl c_Main;

    function InitComponent(GUIController MyController, GUIComponent MyComponent)
    {
    local PlayerController PC;

    Super.InitComponent(MyController, MyComponent);

    // rjp -- when playing SinglePlayer or InstantAction game, remove tabs which only apply to multiplayer
    PC = PlayerOwner();
    if ( PC != None && PC.Level.NetMode == NM_StandAlone )
    RemoveMultiplayerTabs(PC.Level.Game);
    // -- rjp

    if ( Panels.Length > 0 )
    AddPanels();

    SetTitle();
    T_WindowTitle.DockedTabs = c_Main;
    }

    function bool FloatingPreDraw( Canvas C )
    {
    if (PlayerOwner().GameReplicationInfo!=None)
    SetVisibility(true);
    else
    SetVisibility(false);

    return false;
    }


    function InternalOnClose(optional Bool bCanceled)
    {
    local PlayerController PC;

    PC = PlayerOwner();

    // Turn pause off if currently paused
    if(PC != None && PC.Level.Pauser != None)
    PC.SetPause(false);

    Super.OnClose(bCanceled);
    }

    function AddPanels()
    {
    local int i;
    local MidGamePanel Panel;

    for ( i = 0; i < Panels.Length; i++ )
    {
    Panel = MidGamePanel(c_Main.AddTabItem(Panels));
    if ( Panel != None )
    Panel.ModifiedChatRestriction = UpdateChatRestriction;
    }
    }

    // Called via delegate by a MidGamePanel when a player chat restriction has been updated
    // this notifies all other panels about the change
    function UpdateChatRestriction( MidGamePanel Sender, int PlayerID )
    {
    local int i;

    if ( Sender == None )
    return;

    for ( i = 0; i < c_Main.TabStack.Length; i++ )
    {
    if ( c_Main.TabStack != None && MidGamePanel(c_Main.TabStack.MyPanel) != None &&
    c_Main.TabStack.MyPanel != Sender )
    MidGamePanel(c_Main.TabStack.MyPanel).UpdateChatRestriction(PlayerID);
    }
    }

    function SetTitle()
    {
    local PlayerController PC;

    PC = PlayerOwner();
    if ( PC.Level.NetMode == NM_StandAlone || PC.GameReplicationInfo == None || PC.GameReplicationInfo.ServerName == "" )
    WindowName = PC.Level.GetURLMap();
    else WindowName = PC.GameReplicationInfo.ServerName;

    t_WindowTitle.SetCaption(WindowName);
    }

    function RemoveMultiplayerTabs(GameInfo Game)
    {

    if (Game.CurrentGameProfile != none)
    Panels[2] = SPRulesPanel; //there's no map rotation in a single player tournament

    Panels.Remove(3,1);
    Panels.Remove(1,1);
    }

    event bool NotifyLevelChange()
    {
    bPersistent = false;
    LevelChanged();
    return true;
    }

    defaultproperties
    {
    Panels(0)=(ClassName="GUI2K4.UT2K4Tab_PlayerLoginControls",Caption="Game",Hint="Game Controls")
    Panels(1)=(ClassName="GUI2K4.UT2K4Tab_ServerMOTD",Caption="MOTD",Hint="Message of the Day")
    Panels(2)=(ClassName="GUI2K4.UT2K4Tab_MidGameRulesCombo",Caption="Server Info",Hint="Current map rotation and game settings")
    Panels(3)=(ClassName="GUI2K4.UT2K4Tab_MidGameVoiceChat",Caption="Communication",Hint="Manage communication with other players")
    Panels(4)=(ClassName="GUI2K4.UT2K4Tab_MidGameHelp",Caption="Help",Hint="Helpful hints")
    SPRulesPanel=(ClassName="GUI2K4.UT2K4Tab_ServerInfo",Caption="Rules",Hint="Game settings")
    Begin Object Class=GUITabControl Name=LoginMenuTC
    bFillSpace=True
    bDockPanels=True
    TabHeight=0.037500
    BackgroundStyleName="TabBackground"
    WinTop=0.060215
    WinLeft=0.012500
    WinWidth=0.974999
    WinHeight=0.044644
    bScaleToParent=True
    bAcceptsInput=True
    OnActivate=LoginMenuTC.InternalOnActivate
    End Object
    c_Main=GUITabControl'GUI2K4.UT2K4PlayerLoginMenu.LoginMenuTC'

    bResizeWidthAllowed=False
    bResizeHeightAllowed=False
    bMoveAllowed=False
    DefaultLeft=0.110313
    DefaultTop=0.057916
    DefaultWidth=0.779688
    DefaultHeight=0.847083
    bRequire640x480=True
    bPersistent=True
    bAllowedAsLast=True
    OnClose=UT2K4PlayerLoginMenu.InternalOnClose
    WinTop=0.057916
    WinLeft=0.110313
    WinWidth=0.779688
    WinHeight=0.847083
    }



    FloatingWindow
    //==============================================================================
    // Created on: 10/15/2003
    // *cough*UWindows2*cough*
    //
    // Written by Ron Prestenback
    // © 2003, Epic Games, Inc. All Rights Reserved
    //==============================================================================
    class FloatingWindow extends PopupPageBase;

    var automated GUIHeader t_WindowTitle;
    var() GUIButton b_ExitButton;

    var() localized string WindowName;
    var() float MinPageWidth, MinPageHeight, MaxPageHeight, MaxPageWidth;
    var() editconst bool bResizeWidthAllowed, bResizeHeightAllowed, bResizing, bMoveAllowed, bMoving;
    var() editconst bool TSizing, RSizing, LSizing, BtSizing,
    TLSizing, TRSizing, BRSizing, BLSizing;

    var() config float DefaultLeft, DefaultTop, DefaultWidth, DefaultHeight;

    var() int HeaderMouseCursorIndex;

    function InitComponent( GUIController MyController, GUIComponent MyOwner )
    {
    Super.InitComponent( MyController, MyOwner );

    t_WindowTitle.SetCaption(WindowName);
    if ( bMoveAllowed )
    {
    // Set bAcceptsInput so that it will become the Controller's active control when moused over
    t_WindowTitle.bAcceptsInput = True;
    t_WindowTitle.MouseCursorIndex = HeaderMouseCursorIndex;
    }

    AddSystemMenu();
    i_FrameBG.OnPreDraw=AlignFrame;

    }

    function bool AlignFrame(Canvas C)
    {
    i_FrameBG.WinHeight = i_FrameBG.RelativeHeight(ActualHeight() - t_WindowTitle.ActualHeight()*0.5);
    i_FrameBG.WinTop = i_FrameBG.RelativeTop(ActualTop() + t_WindowTitle.ActualHeight()*0.5);
    return bInit;
    }

    function AddSystemMenu()
    {
    local eFontScale tFontScale;

    b_ExitButton = GUIButton(t_WindowTitle.AddComponent( "XInterface.GUIButton" ));
    b_ExitButton.Style = Controller.GetStyle("CloseButton",tFontScale);
    b_ExitButton.OnClick = XButtonClicked;
    b_ExitButton.bNeverFocus=true;
    b_ExitButton.FocusInstead = t_WindowTitle;
    b_ExitButton.RenderWeight=1;
    b_ExitButton.bScaleToParent=false;
    b_ExitButton.OnPreDraw = SystemMenuPreDraw;

    // Do not want OnClick() called from MousePressed()
    b_ExitButton.bRepeatClick = False;
    }

    function bool SystemMenuPreDraw(canvas Canvas)
    {
    b_ExitButton.SetPosition( t_WindowTitle.ActualLeft() + (t_WindowTitle.ActualWidth()-35), t_WindowTitle.ActualTop(), 24, 24, true);
    return true;
    }

    function CheckBounds()
    {
    local float AH, AW, AL, AT;

    AW = FClamp(ActualWidth(), 0.0, Controller.ResX);
    AH = FClamp(ActualHeight(), 0.0, Controller.ResY);
    AT = FClamp(ActualTop(), 0.0, Controller.ResY - AH);
    AL = FClamp(ActualLeft(), 0.0, Controller.ResX - AW);

    SetPosition( AL, AT, AW, AH, True );
    }

    function SetDefaultPosition()
    {
    local float RH, RW;

    if ( !bPositioned )
    return;

    bInit = False;

    if ( !bResizeWidthAllowed )
    DefaultWidth = WinWidth;

    if ( !bResizeHeightAllowed )
    DefaultHeight = WinHeight;

    if ( !bMoveAllowed )
    {
    DefaultLeft = WinLeft;
    DefaultTop = WinTop;
    }

    RW = FClamp( RelativeWidth(DefaultWidth), RelativeWidth(MinPageWidth), RelativeWidth(MaxPageWidth) );
    RH = FClamp( RelativeHeight(DefaultHeight), RelativeHeight(MinPageHeight), RelativeHeight(MaxPageHeight) );
    SetPosition(
    FClamp( RelativeLeft(DefaultLeft), 0.0, RelativeLeft(Controller.ResX) - RW),
    FClamp( RelativeTop(DefaultTop), 0.0, RelativeTop(Controller.ResY) - RH),
    RW, RH );
    }

    function InternalOnCreateComponent(GUIComponent NewComp, GUIComponent Sender)
    {
    if ( Sender == Self )
    {
    NewComp.bBoundToParent = True;
    NewComp.bScaleToParent = True;

    if ( !bResizeHeightAllowed && bResizeWidthAllowed )
    NewComp.ScalingType = SCALE_X;

    else if ( !bResizeWidthAllowed && bResizeHeightAllowed )
    NewComp.ScalingType = SCALE_Y;
    }
    }

    event SetFocus(GUIComponent Who)
    {
    if ( UT2K4GUIController(Controller) != None )
    UT2K4GUIController(Controller).SetFocusTo(Self);

    Super.SetFocus(Who);
    }

    function FloatingMousePressed( GUIComponent Sender, bool bRepeat )
    {
    if ( Controller == None || bRepeat )
    return;

    // If ResizeAllowed, set bCaptureMouse in order to receive OnCapturedMouseMove() calls
    TSizing = bResizeHeightAllowed && HoveringTopBorder();
    RSizing = bResizeWidthAllowed && HoveringRightBorder();
    LSizing = bResizeWidthAllowed && HoveringLeftBorder();
    BtSizing = bResizeHeightAllowed && HoveringBottomBorder();
    bMoving = bMoveAllowed && Controller.ActiveControl == t_WindowTitle && !(TSizing || RSizing || BtSizing || LSizing);

    if ( TSizing )
    {
    if ( RSizing || LSizing )
    {
    TRSizing = RSizing;
    TLSizing = LSizing;

    TSizing = False;
    RSizing = False;
    LSizing = False;
    }
    }

    else if ( BtSizing )
    {
    if ( RSizing || LSizing )
    {
    BRSizing = RSizing;
    BLSizing = LSizing;

    BtSizing = False;
    RSizing = False;
    LSizing = False;
    }
    }

    if ( bMoving )
    {
    SetMouseCursorIndex(1);
    UpdateOffset(ClientBounds[0], ClientBounds[1], ClientBounds[2], ClientBounds[3]);
    }

    bResizing = bMoving || TSizing || TRSizing || RSizing || BRSizing || BtSizing || BLSizing || LSizing || TLSizing;
    bCaptureMouse = bResizing;
    t_WindowTitle.bCaptureMouse = bCaptureMouse;
    }

    function FloatingMouseRelease( GUIComponent Sender )
    {
    local bool bSave;

    // Unset bCaptureMouse
    bSave = bCaptureMouse;

    bResizing = False;
    bCaptureMouse = False;
    t_WindowTitle.bCaptureMouse = False;

    if ( bMoving )
    {
    SetPosition( Controller.MouseX - MouseOffset[0], Controller.MouseY - MouseOffset[1], WinWidth, WinHeight, True );
    CheckBounds();
    }

    // Reset sizing vars
    bMoving = False;
    TSizing = False;
    BtSizing = False;
    RSizing = False;
    LSizing = False;
    TLSizing = False;
    BLSizing = False;
    TRSizing = False;
    BRSizing = False;

    SetMouseCursorIndex(default.MouseCursorIndex);
    UpdateOffset( -1, -1, -1, -1 );

    if ( bSave )
    SaveCurrentPosition();
    }

    function SaveCurrentPosition()
    {
    DefaultLeft = WinLeft;
    DefaultTop = WinTop;
    DefaultWidth = WinWidth;
    DefaultHeight = WinHeight;

    SaveConfig();
    }

    function bool FloatingHover( GUIComponent Sender )
    {
    if ( !ResizeAllowed() )
    return false;

    if ( bCaptureMouse )
    return true;

    // If mouse is near a border, allow resizing
    if ( bResizeHeightAllowed && bResizeWidthAllowed && (BLSizing || TRSizing || HoveringBottomLeft()) )
    SetMouseCursorIndex(2);
    else if ( bResizeHeightAllowed && bResizeWidthAllowed && (TLSizing || BRSizing || HoveringTopLeft()) )
    SetMouseCursorIndex(4);
    else if ( bResizeHeightAllowed && (TSizing || BtSizing || HoveringTopBorder() || HoveringBottomBorder()) )
    SetMouseCursorIndex(3);
    else if ( bResizeWidthAllowed && (LSizing || RSizing || HoveringLeftBorder() || HoveringRightBorder()) )
    SetMouseCursorIndex(5);
    else SetMouseCursorIndex(default.MouseCursorIndex);

    return true;
    }

    function SetPanelPosition(Canvas C);
    function bool FloatingPreDraw( Canvas C )
    {
    local float OldW, OldH, DiffX, DiffY, AW, AT, AH, AL;

    InternalOnPreDraw(C);

    if ( bInit )
    SetDefaultPosition();

    if ( !bCaptureMouse || bMoving )
    return false;

    SetPanelPosition(C);
    AL = ActualLeft();
    AT = ActualTop();
    AW = ActualWidth();
    AH = ActualHeight();
    OldH = AH;
    OldW = AW;


    // Top Left
    if( TLSizing )
    {
    DiffX = Controller.MouseX - AL;
    DiffY = Controller.MouseY - AT;

    WinWidth = RelativeWidth( FClamp( AW - DiffX, ActualWidth(MinPageWidth), ActualWidth(MaxPageWidth) ) );
    WinHeight = RelativeHeight(FClamp(AH - DiffY, ActualHeight(MinPageHeight), ActualHeight(MaxPageHeight)));
    SetPosition( AL + OldW - ActualWidth(),
    AT + OldH - ActualHeight(),
    WinWidth,
    WinHeight,
    True );

    ResizedBoth();
    return true;
    }

    if ( TRSizing )
    {
    DiffX = Controller.MouseX - (AL + AW);
    DiffY = Controller.MouseY - AT;

    WinHeight = RelativeHeight(FClamp(AH - DiffY, ActualHeight(MinPageHeight), ActualHeight(MaxPageHeight)));
    SetPosition( WinLeft,
    (AT + OldH) - ActualHeight(),
    FClamp(AW + DiffX, ActualWidth(MinPageWidth), ActualWidth(MaxPageWidth)),
    WinHeight,
    True );

    ResizedBoth();
    return true;
    }

    if ( BLSizing )
    {
    DiffX = Controller.MouseX - AL;
    DiffY = Controller.MouseY - (AT + AH);

    WinWidth = RelativeWidth( FClamp(AW - DiffX, ActualWidth(MinPageWidth), ActualWidth(MaxPageWidth)) );
    SetPosition( (AL + OldW) - ActualWidth(),
    WinTop,
    WinWidth,
    FClamp(AH + DiffY, ActualHeight(MinPageHeight), ActualHeight(MaxPageHeight)),
    True );

    ResizedBoth();
    return true;
    }

    if ( BRSizing )
    {
    DiffX = Controller.MouseX - (AL + AW);
    DiffY = Controller.MouseY - (AT + AH);

    SetPosition( WinLeft,
    WinTop,
    FClamp(AW + DiffX, ActualWidth(MinPageWidth), ActualWidth(MaxPageWidth)),
    FClamp(AH + DiffY, ActualHeight(MinPageHeight), ActualHeight(MaxPageHeight)),
    True );

    ResizedBoth();
    return true;
    }

    // Top
    if ( TSizing )
    {
    DiffY = Controller.MouseY - AT;

    WinHeight = RelativeHeight( FClamp(AH - DiffY, ActualHeight(MinPageHeight), ActualHeight(MaxPageHeight)));
    SetPosition( WinLeft,
    (AT + OldH) - ActualHeight(),
    WinWidth,
    WinHeight,
    True );

    ResizedHeight();
    return true;
    }

    // Left
    if( LSizing )
    {
    DiffX = Controller.MouseX - AL;

    WinWidth = RelativeWidth( FClamp(AW - DiffX, ActualWidth(MinPageWidth), ActualWidth(MaxPageWidth)) );
    SetPosition( (AL + OldW) - ActualWidth(),
    WinTop,
    WinWidth,
    WinHeight,
    True );

    ResizedWidth();
    return true;
    }

    // Right
    if( RSizing )
    {
    DiffX = Controller.MouseX - (AL + AW);
    SetPosition( WinLeft,
    WinTop,
    FClamp(AW + DiffX, ActualWidth(MinPageWidth), ActualWidth(MaxPageWidth)),
    WinHeight,
    True );

    ResizedWidth();
    return true;
    }

    // Bottom
    if( BtSizing )
    {
    DiffY = Controller.MouseY - (AT + AH);
    SetPosition( WinLeft,
    WinTop,
    WinWidth,
    FClamp(AH + DiffY, ActualHeight(MinPageHeight), ActualHeight(MaxPageHeight)),
    True );

    ResizedHeight();
    return true;
    }

    return false;
    }

    function FloatingRendered( Canvas C )
    {
    if ( !bMoving )
    return;

    C.SetPos( FClamp(Controller.MouseX - MouseOffset[0], 0.0, Controller.ResX - ActualWidth()),
    FClamp(Controller.MouseY - MouseOffset[1], 0.0, Controller.ResY - ActualHeight()) );
    C.SetDrawColor(255,255,255,255);
    C.DrawTileStretched( Controller.WhiteBorder, ActualWidth(), ActualHeight() );
    }

    // =====================================================================================================================
    // =====================================================================================================================
    // Notification
    // =====================================================================================================================
    // =====================================================================================================================
    event ResolutionChanged( int ResX, int ResY )
    {
    bInit = True;
    Super.ResolutionChanged(ResX,ResY);
    }

    function ResizedBoth();
    function ResizedWidth();
    function ResizedHeight();

    // =====================================================================================================================
    // =====================================================================================================================
    // Utility
    // =====================================================================================================================
    // =====================================================================================================================
    function bool ResizeAllowed()
    {
    return bResizeHeightAllowed || bResizeWidthAllowed;
    }

    function bool HoveringLeftBorder()
    {
    if ( Controller == None )
    return false;

    return Controller.MouseX > (Bounds[0] - 5) && Controller.MouseX < (Bounds[0] + 5);
    }

    function bool HoveringRightBorder()
    {
    if ( Controller == None )
    return false;

    return Controller.MouseX > (Bounds[2] - 5) && Controller.MouseX < (Bounds[2] + 5);
    }

    function bool HoveringTopBorder()
    {
    if ( Controller == None )
    return false;

    return Controller.MouseY > (Bounds[1] - 5) && Controller.MouseY < (Bounds[1] + 5);
    }

    function bool HoveringBottomBorder()
    {
    if ( Controller == None )
    return false;

    return Controller.MouseY > (Bounds[3] - 5) && Controller.MouseY < (Bounds[3] + 5);
    }

    function bool HoveringTopLeft()
    {
    return (HoveringLeftBorder() && HoveringTopBorder()) ||
    (HoveringRightBorder() && HoveringBottomBorder());
    }

    function bool HoveringBottomLeft()
    {
    return (HoveringRightBorder() && HoveringTopBorder()) ||
    (HoveringLeftBorder() && HoveringBottomBorder());
    }

    function bool XButtonClicked( GUIComponent Sender )
    {
    Controller.CloseMenu(False);
    return true;
    }

    function SetMouseCursorIndex( int NewIndex )
    {
    MouseCursorIndex = NewIndex;
    if ( MouseCursorIndex == default.MouseCursorIndex )
    t_WindowTitle.MouseCursorIndex = HeaderMouseCursorIndex;

    else t_WindowTitle.MouseCursorIndex = NewIndex;
    }

    defaultproperties
    {
    Begin Object Class=GUIHeader Name=TitleBar
    bUseTextHeight=True
    WinHeight=0.043750
    RenderWeight=0.100000
    bBoundToParent=True
    bScaleToParent=True
    bAcceptsInput=True
    bNeverFocus=False
    ScalingType=SCALE_X
    OnMousePressed=FloatingWindow.FloatingMousePressed
    OnMouseRelease=FloatingWindow.FloatingMouseRelease
    End Object
    t_WindowTitle=GUIHeader'GUI2K4.FloatingWindow.TitleBar'

    MinPageWidth=0.100000
    MinPageHeight=0.100000
    MaxPageHeight=1.000000
    MaxPageWidth=1.000000
    bResizeWidthAllowed=True
    bResizeHeightAllowed=True
    bMoveAllowed=True
    DefaultLeft=0.200000
    DefaultTop=0.200000
    DefaultWidth=0.600000
    DefaultHeight=0.600000
    HeaderMouseCursorIndex=1
    bCaptureInput=False
    InactiveFadeColor=(B=255,G=255,R=255)
    OnCreateComponent=FloatingWindow.InternalOnCreateComponent
    OnPreDraw=FloatingWindow.FloatingPreDraw
    OnRendered=FloatingWindow.FloatingRendered
    OnHover=FloatingWindow.FloatingHover
    OnMousePressed=FloatingWindow.FloatingMousePressed
    OnMouseRelease=FloatingWindow.FloatingMouseRelease
    }
    PopupPageBase
    //==============================================================================
    // Created on: 10/10/2003
    // Base class for non-fullscreen menus
    //
    // Written by Ron Prestenback
    // © 2003, Epic Games, Inc. All Rights Reserved
    //==============================================================================
    class PopupPageBase extends UT2K4GUIPage;

    var automated FloatingImage i_FrameBG;
    var bool bFading, bClosing;
    var(Fade) config float FadeTime;
    var(Fade) float CurFadeTime;
    var(Fade) byte CurFade, DesiredFade;

    delegate FadedIn();
    delegate FadedOut();

    event Opened(GUIComponent Sender)
    {
    if ( bCaptureInput )
    FadeIn();

    Super.Opened(Sender);
    }

    function bool InternalOnPreDraw( Canvas C )
    {
    if ( !bFading )
    return false;

    if (CurFadeTime >= 0.0)
    {
    CurFade += float(DesiredFade - CurFade) * (Controller.RenderDelta / CurFadeTime);
    InactiveFadeColor = class'Canvas'.static.MakeColor(CurFade, CurFade, CurFade);
    CurFadeTime -= Controller.RenderDelta;

    if ( CurFadeTime < 0 )
    {
    CurFade = DesiredFade;
    InactiveFadeColor = class'Canvas'.static.MakeColor(CurFade, CurFade, CurFade);
    bFading = False;
    if ( bClosing )
    {
    bClosing = False;
    FadedOut();
    }
    else
    FadedIn();
    }
    }

    return false;
    }

    function FadeIn()
    {
    if ( Controller.bModulateStackedMenus )
    {
    bClosing = False;
    bFading = True;
    CurFadeTime = FadeTime;
    }
    else FadedIn();
    }

    function FadeOut()
    {
    if ( Controller.bModulateStackedMenus )
    {
    bFading = True;
    bClosing = True;
    CurFadeTime = FadeTime;
    DesiredFade = default.CurFade;
    }
    else FadedOut();
    }

    defaultproperties
    {
    Begin Object Class=FloatingImage Name=FloatingFrameBackground
    Image=Texture'KF_InterfaceArt_tex.Menu.Thin_border_SlightTransparent'
    DropShadow=None
    ImageStyle=ISTY_Stretched
    ImageRenderStyle=MSTY_Normal
    WinTop=0.040000
    WinLeft=0.000000
    WinWidth=1.000000
    WinHeight=0.960000
    RenderWeight=0.000003
    End Object
    i_FrameBG=FloatingImage'GUI2K4.PopupPageBase.FloatingFrameBackground'

    FadeTime=0.350000
    CurFade=200
    DesiredFade=80
    bRenderWorld=True
    bRequire640x480=False
    BackgroundRStyle=MSTY_Modulated
    OnPreDraw=PopupPageBase.InternalOnPreDraw
    }
    UT2K4GUIPage
    //==============================================================================
    // Created on: 08/15/2003
    // Base class for all UT2004 GUIPages
    //
    // Written by Ron Prestenback
    // © 2003, Epic Games, Inc. All Rights Reserved
    //==============================================================================
    class UT2K4GUIPage extends GUIPage
    abstract;

    var Sound PopInSound, SlideInSound, FadeInSound, BeepSound;

    defaultproperties
    {
    PopInSound=Sound'KF_MenuSnd.MainMenu.OptionIn'
    SlideInSound=Sound'KF_MenuSnd.MainMenu.GraphSlide'
    FadeInSound=Sound'KF_MenuSnd.MainMenu.CharFade'
    BeepSound=Sound'KF_MenuSnd.Generic.msfxMouseClick'
    WinTop=0.375000
    WinHeight=0.500000
    }
    GUIPage
    // ====================================================================
    // Class: UT2K4UI.GUIPage
    //
    // GUIPages are the base for a full page menu. They contain the
    // Control stack for the page.
    //
    // Written by Joe Wilcox
    // (c) 2002, Epic Games, Inc. All Rights Reserved
    // ====================================================================

    class GUIPage extends GUIMultiComponent
    Native Abstract;

    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)


    var() bool bRenderWorld; // False - don't render anything behind this menu / True - render normally (everything)
    var() bool bPauseIfPossible; // Should this menu pause the game if possible
    var() bool bCheckResolution; // obsolete
    var() bool bCaptureInput; // Whether to allow input to be passed to pages lower on the menu stack.

    var() bool bRequire640x480; // Does this menu require at least 640x480
    var() bool bPersistent; // If set, page is saved across open/close/reopen.
    var() bool bDisconnectOnOpen; // Should this menu for a disconnect when opened.
    var() bool bAllowedAsLast; // If this is true, closing this page will not bring up the main menu
    var() bool bRestorable; // When the GUIController receives a call to CloseAll(), should it reopen this page the next time main is opened?

    var() noexport editconst GUIPage ParentPage; // The page that exists before this one
    var() Material Background; // The background image for the menu
    var() Color BackgroundColor; // The color of the background
    var() Color InactiveFadeColor; // Color Modulation for Inactive Page
    var() Sound OpenSound; // Sound to play when opened
    var() Sound CloseSound; // Sound to play when closed
    var() noexport editconst
    editconstarray const array<GUIComponent> Timers; // List of components with Active Timers
    // if last on the stack.

    var() EMenuRenderStyle BackgroundRStyle;

    // Delegates
    delegate OnOpen()
    {
    if ( Controller != None && Controller.bSnapCursor )
    CenterMouse();
    }

    delegate OnReOpen();
    delegate OnClose(optional bool bCancelled);

    delegate bool OnCanClose(optional Bool bCancelled)
    {
    return true;
    }

    event Closed(GUIComponent Sender, bool bCancelled)
    {
    Super.Closed(Sender, bCancelled);
    OnClose(bCancelled);
    }

    //=================================================
    // PlayOpenSound / PlayerClosedSound

    function PlayOpenSound()
    {
    PlayerOwner().PlayOwnedSound(OpenSound,SLOT_Interface,1.0);
    }

    function PlayCloseSound()
    {
    PlayerOwner().PlayOwnedSound(CloseSound,SLOT_Interface,1.0);
    }


    //=================================================
    // InitComponent is responsible for initializing all components on the page.

    function InitComponent(GUIController MyController, GUIComponent MyOwner)
    {
    Super.InitComponent(MyController, MyOwner);
    FocusFirst(none);
    }

    //=================================================
    // CheckResolution - Tests to see if this menu requires a resoltuion of at least 640x480 and if so, switches

    function CheckResolution(bool Closing, GUIController InController)
    {
    local string CurrentRes;
    local string Xstr, Ystr;
    local int ResX, ResY;

    if ( InController == None )
    return;

    if ( InController.ResX == 0 || InController.ResY == 0 )
    {
    CurrentRes = PlayerOwner().ConsoleCommand("GETCURRENTRES");
    if ( Divide(CurrentRes, "x", Xstr, Ystr) )
    {
    ResX = int(Xstr);
    ResY = int(Ystr);
    }
    }

    else
    {
    ResX = InController.ResX;
    ResY = InController.ResY;
    CurrentRes = InController.ResX $ "x" $ InController.ResY;
    }

    if (!Closing)
    {
    if ( InController != None && ResX < 640 && ResY < 480 && bRequire640x480 )
    {
    if ( InController.bModAuthor )
    log(Name$".CheckResolution() - menu requires 640x480. Currently at "$CurrentRes,'ModAuthor');

    InController.GameResolution = CurrentRes;
    Console(InController.Master.Console).DelayedConsoleCommand("TEMPSETRES 640x480");
    }

    return;

    }

    if ( !bRequire640x480 || InController.GameResolution == "" )
    return;

    if ( CurrentRes != InController.GameResolution )
    {
    if ( !InController.NeedsMenuResolution() )
    {
    if ( InController.bModAuthor )
    log(Name$".CheckResolution() - restoring menu resolution to standard value:"@InController.GameResolution,'ModAuthor');
    Console(InController.Master.Console).DelayedConsoleCommand("SETRES"@InController.GameResolution);
    InController.GameResolution = "";
    }

    else if ( InController.bModAuthor )
    log(Name$".CheckResolution() - not restoring resolution to standard value: ParentMenu would abort.",'ModAuthor');
    }
    }

    event ChangeHint(string NewHint)
    {
    SetHint(NewHint);
    }

    event SetFocus(GUIComponent Who)
    {
    if (Who==None)
    return;

    Super.SetFocus(Who);
    }

    event HandleParameters(string Param1, string Param2); // Should be subclassed
    function bool GetRestoreParams( out string Param1, out string Param2 ); // Params will be used when page is reopened

    // Should be subclassed - general purpose function to workaround menuclass dependancy
    // Not called from anywhere - call it only if you need it
    function HandleObject( Object Obj, optional Object OptionalObj_1, optional Object OptionalObj_2 );
    function string GetDataString() { return ""; }
    function SetDataString(string Str);

    // If !bPersistent, return true for GUIController to close this menu at level change
    // If bPersistent, return true to be removed from persistent stack at level change (will also be closed if open)
    function bool NotifyLevelChange()
    {
    LevelChanged();
    return true;
    }

    event Free() // This control is no longer needed
    {
    local int i;

    if ( !bPersistent )
    {
    for ( i = 0; i < Timers.Length; i++ )
    Timers=None;

    Super.Free();
    }
    }

    final function bool IsOpen()
    {
    if ( Controller == None )
    return false;

    return Controller.FindMenuIndex(Self) != -1;
    }

    function bool AllowOpen(string MenuClass)
    {
    return true;
    }

    defaultproperties
    {
    bCaptureInput=True
    bRequire640x480=True
    BackgroundColor=(B=255,G=255,R=255,A=255)
    InactiveFadeColor=(B=64,G=64,R=64,A=255)
    BackgroundRStyle=MSTY_Normal
    RenderWeight=0.000100
    bTabStop=False
    bAcceptsInput=True
    }



    GUIMultiComponent
    // ====================================================================
    // Class: UT2K4UI.GUIMultiComponent
    //
    // GUIMultiComponents are collections of components that work together.
    // When initialized, GUIMultiComponents transfer all of their components
    // to the to the GUIPage that owns them.
    //
    // Written by Joe Wilcox
    // Updated by Ron Prestenback
    // (c) 2002, Epic Games, Inc. All Rights Reserved
    // ====================================================================

    class GUIMultiComponent extends GUIComponent
    Abstract
    Native;

    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)

    var(Menu) editinlinenotify export array<GUIComponent> Controls; // An Array of Components that make up this Control
    var(State) noexport editconst GUIComponent FocusedControl; // Which component inside this one has focus
    var(Menu) noexport editconstarray array<GUIComponent> Components; // An Array of Controls that can be tabbed to

    // Animation
    var() noexport editconst int AnimationCount; // Every time a component begins an animation frame, this is increased

    var() bool PropagateVisibility; // Does changes to visibility propagate down the line
    var() bool bOldStyleMenus; // Is this a UT2003 menu or UT2004
    var(State) bool bDrawFocusedLast; // Draw focused control last (focused control will always appear on top)

    // If true, empty Controls array when InitializeControls() is called
    // (Generally required in order to use automated components when subclassing classes that have Controls members
    // defined in default properties)
    var() bool bAlwaysAutomate;

    delegate bool HandleContextMenuOpen(GUIComponent Sender, GUIContextMenu Menu, GUIComponent ContextMenuOwner)
    {
    return true;
    }

    delegate bool HandleContextMenuClose(GUIContextMenu Sender)
    {
    return true;
    }

    delegate bool NotifyContextSelect(GUIContextMenu Sender, int ClickIndex) { return false; }
    delegate OnCreateComponent(GUIComponent NewComponent, GUIComponent Sender); // Hook to allow setting of component properties before initialization

    // Adds all 'automated' GUIComponent subobjects to the Controls array (only if Controls array is empty).
    native final function InitializeControls();

    // Re-orders all controls with bTabStop = True, according to TabOrder, from lowest to highest
    native final function RemapComponents();

    // Returns the index into the Components array of GUIComponent Who
    native final function int FindComponentIndex(GUIComponent Who);

    // Stub
    function InternalOnShow();

    function InitComponent(GUIController MyController, GUIComponent MyOwner)
    {
    local int i;

    Super.InitComponent(MyController, MyOwner);

    InitializeControls(); // Build the Controls array
    for (i=0;i<Controls.Length;i++)
    {
    if (Controls == None)
    {
    if ( Controller.bModAuthor )
    log(Name@"- Invalid control found in"@GetMenuPath()$"!! (Control"@i$")",'ModAuthor');
    Controls.Remove(i--,1);
    continue;
    }

    OnCreateComponent(Controls, Self);
    Controls.InitComponent(MyController, Self);
    }

    RemapComponents();
    }

    event GUIComponent AddComponent(string ComponentClass, optional bool SkipRemap)
    {
    local class<GUIComponent> NewCompClass;
    local GUIComponent NewComp;

    if ( Controller != None )
    NewCompClass = Controller.AddComponentClass(ComponentClass);
    else NewCompClass = class<GUIComponent>(DynamicLoadObject(ComponentClass,class'class'));
    if (NewCompClass != None)
    {

    NewComp = new(None) NewCompClass;
    if (NewComp!=None)
    {
    NewComp = AppendComponent(NewComp, SkipRemap);
    return NewComp;
    }
    }

    log(Name@"could not create component"@ComponentClass,'AddComponent');
    return none;
    }

    // This function allows you to append a component that has already been initialized
    // Be very careful about how you handle the focus chain
    event GUIComponent InsertComponent(GUIComponent NewComp, int Index, optional bool SkipRemap)
    {
    if (Index < 0 || Index >= Controls.Length)
    return AppendComponent(NewComp);

    Controls.Insert(Index, 1);
    Controls[Index] = NewComp;
    if (!SkipRemap)
    RemapComponents();
    return NewComp;
    }

    event GUIComponent AppendComponent(GUIComponent NewComp, optional bool SkipRemap)
    {
    local int index;

    // Attempt to add it sorted in to the array. The Controls array is sorted by
    // Render Weight.

    while (Index<Controls.Length)
    {
    if (NewComp.RenderWeight < Controls[Index].RenderWeight) // We found our spot
    {
    Controls.Insert(Index,1);
    break;
    }
    Index++;
    }

    // Couldn't find a spot, add it at the end
    Controls[Index] = NewComp;

    OnCreateComponent(NewComp, Self);
    if ( NewComp.Controller == None )
    NewComp.InitComponent(Controller, Self);

    if (!SkipRemap)
    RemapComponents();

    // If current menu is already initialized, we need to call the opened event from here
    if (Controller.bCurMenuInitialized)
    NewComp.Opened(Self);

    return NewComp;
    }

    event bool RemoveComponent(GUIComponent Comp, optional bool SkipRemap)
    {
    local int i;
    for (i=0;i<Controls.Length;i++)
    {
    if (Controls == Comp)
    {
    Controls.Remove(i,1);

    if (!SkipRemap)
    RemapComponents();

    return true;
    }
    }
    return false;
    }

    function SetFocusInstead( GUIComponent InFocusComp )
    {
    local int i;

    Super.SetFocusInstead(InFocusComp);
    for ( i = 0; i < Controls.Length; i++ )
    Controls.SetFocusInstead(InFocusComp);
    }

    event SetFocus(GUIComponent Who)
    {
    if (Who==None)
    {
    if ( !FocusFirst(None) )
    Super.SetFocus(None);

    return;
    }
    else
    FocusedControl = Who;

    MenuStateChange(MSAT_Focused);

    if (MenuOwner!=None)
    MenuOwner.SetFocus(self);
    }

    event LoseFocus(GUIComponent Sender)
    {
    FocusedControl = None;
    Super.LoseFocus(Sender);
    }

    function bool CanAcceptFocus()
    {
    local int i;

    if ( bAcceptsInput && Super.CanAcceptFocus() )
    return true;

    for ( i = 0; i < Controls.Length; i++ )
    if ( Controls.CanAcceptFocus() )
    return true;

    return false;
    }

    event bool FocusFirst(GUIComponent Sender)
    {
    local int i;

    if (Components.Length>0)
    {
    for (i=0;i<Components.Length;i++)
    {
    if ( Components.FocusFirst(Sender) )
    return true;
    }
    }

    for (i=0;i<Controls.Length;i++)
    {
    if ( Controls.FocusFirst(Sender) )
    return true;
    }

    if ( bAcceptsInput && Super.CanAcceptFocus() )
    {
    Super.SetFocus(None);
    return true;
    }

    return false;
    }


    event bool FocusLast(GUIComponent Sender)
    {
    local int i;

    if (Components.Length>0)
    {
    for (i=Components.Length-1;i>=0;i--)
    {
    if (Components.FocusLast(Sender))
    return true;
    }
    }

    for (i=Controls.Length-1;i>=0;i--)
    {
    if ( Controls.FocusLast(Sender) )
    return true;
    }

    if ( bAcceptsInput && Super.CanAcceptFocus() )
    {
    Super.SetFocus(None);
    return true;
    }

    return false;
    }

    event bool NextControl(GUIComponent Sender)
    {
    local int Index;

    Index = FindComponentIndex(Sender);
    if ( Index >= 0 )
    {
    // Find the next possible component
    while (++Index<Components.Length)
    {
    if ( Components[Index].FocusFirst(None) )
    return true;
    }
    }

    if ( Super.NextControl(self) )
    return true;

    return FocusFirst(none);
    }

    event bool PrevControl(GUIComponent Sender)
    {

    local int Index;

    Index = FindComponentIndex(Sender);
    while (--Index>=0)
    {
    if (Components[Index].FocusLast(None))
    return true;
    }

    if ( Super.PrevControl(self) )
    return true;

    return FocusLast(none);

    }

    singular function EnableMe()
    {
    local int i;

    Super.EnableMe();
    for ( i = 0; i < Controls.Length; i++ )
    EnableComponent(Controls);
    }

    singular function DisableMe()
    {
    local int i;

    Super.DisableMe();
    for ( i = 0; i < Controls.Length; i++ )
    DisableComponent(Controls);
    }

    event SetVisibility(bool bIsVisible)
    {
    local int i;

    Super.SetVisibility(bIsVisible);

    if ( !PropagateVisibility )
    return;

    for (i=0;i<Controls.Length;i++)
    Controls.SetVisibility(bIsVisible);
    }

    event Opened(GUIComponent Sender)
    {
    local int i;

    if (Sender == None)
    Sender = Self;

    Super.Opened(Sender);
    for (i=0;i<Controls.Length;i++)
    Controls[i].Opened(Sender);
    }

    event Closed(GUIComponent Sender, bool bCancelled)
    {
    local int i;

    if (Sender == None)
    Sender = Self;

    Super.Closed(Sender, bCancelled);
    for (i=0;i<Controls.Length;i++)
    Controls[i].Closed(Sender, bCancelled);
    }

    event Free() // This control is no longer needed
    {
    local int i;

    for (i=0;i<Controls.Length;i++)
    Controls[i].Free();

    Controls.Remove(0,Controls.Length);
    Components.Remove(0,Components.Length);

    FocusedControl = None;
    Super.Free();
    }

    event BeginAnimation( GUIComponent Animating )
    {
    AnimationCount++;
    if ( AnimationCount > 0 )
    bAnimating = True;

    if ( MenuOwner != None )
    MenuOwner.BeginAnimation( Animating );
    }

    event EndAnimation( GUIComponent Animating, EAnimationType Type )
    {
    AnimationCount--;
    if ( AnimationCount <= 0 )
    {
    bAnimating = False;
    AnimationCount = 0;
    }

    if ( MenuOwner != None )
    MenuOwner.EndAnimation( Animating, Type );

    if ( Animating == Self )
    OnEndAnimation(Animating, Type);
    }

    function LevelChanged()
    {
    local int i;

    Super.LevelChanged();
    for ( i = 0; i < Controls.Length; i++ )
    Controls[i].LevelChanged();
    }

    function CenterMouse()
    {
    local int i;

    if ( FocusedControl != None )
    {
    FocusedControl.CenterMouse();
    return;
    }

    for ( i = 0; i < Components.Length; i++ )
    {
    if ( Components[i].CanAcceptFocus() )
    {
    Components[i].CenterMouse();
    return;
    }
    }

    Super.CenterMouse();
    }

    function DebugTabOrder()
    {
    local int i;

    CheckInvalidTabOrder();
    CheckDuplicateTabOrder();
    for ( i = 0; i < Controls.Length; i++ )
    Controls[i].DebugTabOrder();
    }

    function CheckInvalidTabOrder()
    {
    local int i;

    for ( i = 0; i < Components.Length; i++ )
    if ( Components[i].TabOrder == -1 )
    log(GetMenuPath()@"Component["$i$"] ("$Components[i].GetMenuPath()$") has no tab order assigned!");
    }

    function CheckDuplicateTabOrder()
    {
    local int i, j;
    local array<intbox> TabOrders;
    local bool bDup;

    for ( i = 0; i < Components.Length; i++ )
    {
    bDup = false;
    if ( Components[i].TabOrder == -1 )
    continue;

    for ( j = 0; j < TabOrders.Length; j++ )
    {
    if ( Components[i].TabOrder == TabOrders[j].X2 )
    {
    log(GetMenuPath()@"Dulicate tab order ("$Components[i].TabOrder$") - components "$TabOrders[j].X1$" ("$Components[TabOrders[j].X1].GetMenuPath()$") & "$i$" ("$Components[i].GetMenuPath()$")");
    bDup = True;
    }
    }

    if ( !bDup )
    {
    j = TabOrders.Length;
    TabOrders.Length = j + 1;
    TabOrders[j].X1 = j;
    TabOrders[j].X2 = Components[i].TabOrder;
    }
    }
    }

    defaultproperties
    {
    bDrawFocusedLast=True
    bTabStop=True
    }


    [/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i]
    [i][i][i][i][i][i][i][i][i][i][i][i][i]
    GUIComponent
    [spoiler]

    // ====================================================================
    // Class: UT2K4UI.GUIComponent
    //
    // GUIComponents are the most basic building blocks of menus.
    //
    // Written by Joe Wilcox
    // (c) 2002, Epic Games, Inc. All Rights Reserved
    // ====================================================================

    class GUIComponent extends GUI
    Abstract
    Native;

    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)

    // Variables
    var(Menu) noexport editconst GUIPage PageOwner; // Callback to the GUIPage that contains this control
    var(Menu) noexport editconst GUIComponent MenuOwner; // Callback to the Component that owns this one
    var(State) noexport GUIComponent FocusInstead; // Who should get the focus instead of this control if bNeverFocus
    var(State) noexport eMenuState MenuState; // Used to determine the current state of this component
    var(State) editconst noexport eMenuState LastMenuState; // The previous MenuState of this component
    var(State) noexport eDropState DropState; // Used to determine the current drop state of this component
    var(Style) eFontScale FontScale; // If this component has a style, which size font should be applied to the style

    // RenderStyle and MenuColor are usually pulled from the Parent menu, unless specificlly overridden

    var() string IniOption; // Points to the INI option to load for this component
    var() string IniDefault; // The default value for a missing ini option
    var(Style) string StyleName; // Name of my Style
    var() localized string Hint; // The hint that gets displayed for this component
    var() noexport GUILabel FriendlyLabel; // My state is projected on this objects state.
    var(Menu) float WinTop,WinLeft; // Where does this component exist (in world space) - Grr.. damn Left()
    var(Menu) float WinWidth,WinHeight; // Where does this component exist (in world space) - Grr.. damn Left()
    var() float RenderWeight; // Used to determine sorting in the controls stack
    var(Style) int MouseCursorIndex; // The mouse cursor to use when over this control
    var(Menu) int TabOrder; // Used to figure out tabbing
    var() int Tag; // Free (can be used for anything)

    var() bool bDebugging;
    var(Menu) bool bTabStop; // Does a TAB/Shift-Tab stop here
    var() bool bFocusOnWatch; // If true, watching focuses
    var(Menu) bool bBoundToParent; // Use the Parents Bounds for all positioning
    var(Menu) bool bScaleToParent; // Use the Parent for scaling
    var(State) noexport bool bHasFocus; // Does this component currently have input focus
    var(State) bool bVisible; // Is this component currently visible
    var(State) bool bAcceptsInput; // Does this control accept input
    var() bool bCaptureTabs; // If true, OnKeyEvent() is called for tab presses, overriding default behavior (NextControl()/PrevControl())
    var(State) bool bCaptureMouse; // Control should capture the mouse when pressed
    var(State) bool bNeverFocus; // This control should never fully receive focus
    var(State) bool bRepeatClick; // Whether this component should receive OnClick() events when the mouse button is held down
    var(State) bool bRequireReleaseClick; // If True, this component wants the click on release even if it's not active
    var() bool bMouseOverSound; // Should component bleep when mouse goes over it
    var() bool bDropSource; // Can this component act as a drag-n-drop source
    var() bool bDropTarget; // Can this component act as a drag-n-drop target
    var(State) noexport bool bPendingFocus; // Big big hack for ComboBoxes..
    var() bool bInit; // Can be used by any component as an "initialization" hook
    var() bool bNeverScale; // Do not treat position/dimension values in the -2.0 to 2.0 range as scaled values
    // useful for internally managed components (GUIComboBox's list, button, etc.)

    /*
    This property is solely for the benefit of mod authors, to indicate components which
    will be skipped by the native rendering code if the component doesn't have a valid style.
    Mod authors: changing the value of this property in your subclasses will cause your menus to crash the game
    */
    var const noexport bool bRequiresStyle;
    var() editconst const noexport bool bPositioned; // Whether this component has been positioned yet (first Pre-Render)
    var() editconst noexport bool bAnimating; // If true, all input/focus/etc will be ignored
    var() editconst noexport const bool bTravelling, bSizing; // Travelling is true when animating position, Sizing is true when animating dimensions
    var() editconst noexport const array<vector> MotionFrame, SizeFrame;

    // Notes about the Top/Left/Width/Height : This is a somewhat hack but it's really good for functionality. If
    // the value is < 2, then the control is considered to be scaled. If they are >= 2 they are considered to be normal world coords.
    // If bNeverScale is set, then values between -2/2 will also be considered actual values
    // 0 = 0, 1 = 100%, 2 = 2px
    var(Menu) editconst const noexport float Bounds[4]; // Internal normalized positions in world space
    var(Menu) editconst const noexport float ClientBounds[4]; // The bounds of the actual client area (minus any borders)


    // Timer Support
    var() bool bTimerRepeat;
    var() noexport editconst const int TimerIndex; // For easier maintenance
    var() float TimerCountdown;
    var() float TimerInterval;

    var noexport const float MouseOffset[4]; // Used natively for drawing outlines
    var() editconst GUIContextMenu ContextMenu;
    var() editconst GUIToolTip ToolTip;

    // Used for Saving the last state before drawing natively
    var noexport const color WhiteColor;

    // Style holds a pointer to the GUI style of this component.
    var(Style) noexport GUIStyles Style; // My GUI Style
    var(Style) enum EClickSound
    {
    CS_None,
    CS_Click,
    CS_Edit,
    CS_Up,
    CS_Down,
    CS_Drag,
    CS_Fade,
    CS_Hover,
    CS_Slide,
    } OnClickSound;

    var() enum EParentScaleType // Used to bound/scale in one dimension only
    {
    SCALE_All,
    SCALE_X,
    SCALE_Y,
    } BoundingType, ScalingType;

    var(Menu) bool bStandardized;
    var(Menu) float StandardHeight;

    // FOR TESTING
    var editconst const noexport int PreDrawCount, DrawCount;
    var editconst noexport int OnRenderCount, OnRenderedCount, OnPreDrawCount, OnDrawCount;
    // Delegates

    Delegate OnArrival(GUIComponent Sender, EAnimationType Type); // Called when an animating component arrives at a spot
    Delegate OnEndAnimation( GUIComponent Sender, EAnimationType Type ); // Called immediately after the component arrives at the last keypoint

    // Drawing delegates return true if you want to short-circuit the default drawing code
    // Called for all components, but natively, only ContextMenus do not perform native PreDraw if delegate returns false
    // Bounds/ClientBounds are updated just before the call to OnPreDraw().
    // If you modify the positions of the component, you can force an immediate refresh of the Bounds by returning true from OnPreDraw
    /*
    Delegate bool OnPreDraw(canvas Canvas); // Called from the GUIComponent's native PreDraw function.
    Delegate bool OnDraw(canvas Canvas); // Called the moment the native Draw function is called on a component
    Delegate OnRender(canvas Canvas); // Called immediately after a component's native Super.Draw is called
    Delegate OnRendered(canvas Canvas); // Called immediately after a component has finished rendering.
    */

    // The "default" versions of these delegates are only called if GUI.Counter > 0
    Delegate bool OnPreDraw(canvas Canvas)
    {
    if ( Counter < 1 )
    return false;

    OnPreDrawCount++;
    if ( OnPreDrawCount > Counter )
    log("OnPreDraw called"@OnPreDrawCount@"times: "$GetMenuPath());

    return false;
    }

    Delegate bool OnDraw(canvas Canvas)
    {
    if ( COUNTER < 1 )
    return false;

    OnDrawCount++;
    if ( OnDrawCount > Counter )
    log("OnDraw called"@OnDrawCount@"times: "$GetMenuPath());

    return false;
    }
    Delegate OnRender(canvas Canvas)
    {
    if ( COUNTER < 1 )
    return;

    OnRenderCount++;
    if ( OnRenderCount > Counter )
    log("OnRender called"@OnRenderCount@"times: "$GetMenuPath());
    }
    Delegate OnRendered(canvas Canvas)
    {
    if ( COUNTER < 1 )
    return;
    OnRenderedCount++;
    if ( OnRenderedCount > Counter )
    log("OnRendered called"@OnRenderedCount@"times:"@GetMenuPath());
    }

    Delegate OnActivate(); // Called when the component gains focus
    Delegate OnDeActivate(); // Called when the component loses focus
    Delegate OnWatch(); // Called when the component is being watched
    Delegate OnHitTest(float MouseX, float MouseY); // Called when Hit test is performed for mouse input
    Delegate OnMessage(coerce string Msg, float MsgLife); // When a message comes down the line
    Delegate OnHide();
    Delegate OnShow();

    // Called just before OnHover()
    // Controller assigns the value of its MouseOver property to the result of this function
    delegate GUIToolTip OnBeginTooltip()
    {
    if ( ToolTip != None )
    return ToolTip.EnterArea();

    else if ( MenuOwner != None )
    return MenuOwner.OnBeginTooltip();

    return None;
    }

    // Called on the current ActiveControl when the mouse is moved over a new component
    // This is called before OnBeginTooltip is called on the new control
    // Return false if the tooltip will remain visible after leaving this control
    delegate bool OnEndTooltip()
    {
    if ( ToolTip != None )
    return ToolTip.LeaveArea();

    else if ( MenuOwner != None )
    return MenuOwner.OnEndTooltip();

    return true;
    }

    Delegate OnInvalidate(GUIComponent Who); // Called when the background is clicked

    // Return true to override default behavior
    // Called on both the active control & active page
    delegate bool OnHover( GUIComponent Sender ) { return false; }

    // -- Input event delegates
    Delegate bool OnClick(GUIComponent Sender); // The mouse was clicked on this control
    Delegate bool OnDblClick(GUIComponent Sender); // The mouse was double-clicked on this control
    Delegate bool OnRightClick(GUIComponent Sender); // Return false to prevent context menu from appearing

    Delegate OnMousePressed(GUIComponent Sender, bool bRepeat); // Sent when a mouse is pressed (initially)
    Delegate OnMouseRelease(GUIComponent Sender); // Sent when the mouse is released.

    Delegate OnTimer(GUIComponent Sender); // Called from Timer()
    Delegate OnChange(GUIComponent Sender); // Called when a component changes it's value

    Delegate bool OnKeyType(out byte Key, optional string Unicode) // Key Strokes
    {
    return false;
    }

    Delegate bool OnKeyEvent(out byte Key, out byte State, float delta)
    {
    return false;
    }

    delegate bool OnDesignModeKeyEvent( Interactions.EInputKey Key, Interactions.EInputAction State )
    {
    return false;
    }

    Delegate bool OnCapturedMouseMove(float deltaX, float deltaY)
    {
    return false;
    }

    Delegate OnLoadINI(GUIComponent Sender, string s); // Do the actual work here
    Delegate string OnSaveINI(GUIComponent Sender); // Do the actual work here

    // drag-n-drop
    // Called when mouse is released over the DropSource to detemine whether OnClick() should be called
    delegate bool OnMultiSelect( GUIComponent Sender )
    {
    return true;
    }

    delegate bool OnBeginDrag(GUIComponent Sender) // Called on the source component when a drag & drop operation begins
    {
    return bDropSource;
    }

    delegate OnEndDrag(GUIComponent Sender, bool bAccepted);

    // Called on the target component when data is dropped
    // DropStateChange() will be called on the source - DRP_Accept if it returns true, DRP_Reject if it returns false
    delegate bool OnDragDrop(GUIComponent Sender)
    {
    return false;
    }

    delegate OnDragEnter(GUIComponent Sender); // Called on the target component when the mouse enters the components bounds
    delegate OnDragLeave(GUIComponent Sender); // Called on a target component when the mouse leaves the components bounds
    delegate OnDragOver(GUIComponent Sender); // Called when the mouse is moved inside a target's bounds


    native(812) final function PlayerController PlayerOwner();

    native(813) function final SetTimer(float Interval, optional bool bRepeat);
    native(814) function final KillTimer();

    // Auto-positioning - accounts for bBoundToParent & bScaleToParent
    native(815) final function AutoPosition(
    array<GUIComponent> Components,
    float LeftBound, float UpperBound, float RightBound, float LowerBound,
    float LeftPad, float UpperPad, float RightPad, float LowerPad,
    optional int NumberOfColumns, optional float ColumnPadding
    );

    native(816) final function AutoPositionOn(
    array<GUIComponent> Components, GUIComponent Frame,
    float LeftPadPerc, float UpperPadPerc, float RightPadPerc, float LowerPadPerc,
    optional int NumberOfColumns, optional float ColumnPadding
    );

    native(817) final function UpdateOffset(float PosX, float PosY, float PosW, float PosH);
    //native(818) final function DrawSpriteWidget(Canvas C, float ResScaleX, float ResScaleY, out HudBase.SpriteWidget Widget);
    //native(819) final function DrawNumericWidget(Canvas C, float ResScaleX, float ResScaleY, out HudBase.NumericWidget Widget, out HudBase.DigitSet Digit);

    // The ActualXXXX functions are not viable until after the first pre-render so don't
    // use them in inits
    native(820) final function float ActualWidth( optional coerce float Val, optional bool bForce );
    native(821) final function float ActualHeight( optional coerce float Val, optional bool bForce );
    native(822) final function float ActualLeft( optional coerce float Val, optional bool bForce );
    native(823) final function Float ActualTop( optional coerce float Val, optional bool bForce );

    native(824) final function float RelativeLeft( optional coerce float RealLeft, optional bool bForce );
    native(825) final function float RelativeTop( optional coerce float RealTop, optional bool bForce );
    native(826) final function float RelativeWidth( optional coerce float RealWidth, optional bool bForce );
    native(827) final function float RelativeHeight( optional coerce float RealHeight, optional bool bForce );

    event ResolutionChanged( int ResX, int ResY );

    function SetPosition( float NewLeft, float NewTop, float NewWidth, float NewHeight, optional bool bForceRelative )
    {
    if ( bDebugging && (Controller == None || Controller.bModAuthor) )
    log(Name$".SetPosition( "$NewLeft$","@NewTop$","@NewWidth$","@NewHeight$","@bForceRelative,'ModAuthor');

    if ( bForceRelative )
    {
    WinLeft = RelativeLeft(NewLeft);
    WinTop = RelativeTop(NewTop);
    WinWidth = RelativeWidth(NewWidth);
    WinHeight = RelativeHeight(NewHeight);
    }
    else
    {
    WinLeft = NewLeft;
    WinTop = NewTop;
    WinWidth = NewWidth;
    WinHeight = NewHeight;
    }

    if ( bDebugging && bForceRelative && (Controller == None || Controller.bModAuthor) )
    log(Name@"SetPosition() Current L:"$WinLeft$"("$Bounds[0]$") T:"$WinTop$"("$Bounds[1]$") W:"$WinWidth$"("$Bounds[0]+Bounds[2]$") H:"$WinHeight$"("$Bounds[1]+Bounds[3]$")",'ModAuthor');
    }

    // For debugging
    native(828) final function string GetMenuPath();
    // Used only for design mode - performs raw hit detection, without regard to properties that affect
    // hit detection (bAcceptsInput, MenuState, etc.)
    native(829) final function bool SpecialHit( optional bool bForce );

    event string AdditionalDebugString() { return ""; }

    event Timer()
    {
    OnTimer(Self);
    }

    event Opened(GUIComponent Sender) // Called when the Menu Owner is opened
    {
    LoadIni();
    if ( ToolTip != None )
    {
    ToolTip.InitComponent( Controller, Self );
    SetToolTipText( Hint );
    }
    }

    event Closed(GUIComponent Sender, bool bCancelled) // Called when the Menu Owner is closed
    {
    if (!bCancelled)
    SaveIni();
    }

    event Free() // This control is no longer needed
    {
    MenuOwner = None;
    PageOwner = None;
    Controller = None;
    FocusInstead = None;
    FriendlyLabel = None;
    Style = None;
    if ( ToolTip != None )
    ToolTip.Free();

    ToolTip = None;
    }

    function string LoadINI()
    {
    local string s;

    if ( (PlayerOwner()==None) || (INIOption=="") )
    return "";

    if ( IniOption ~= "@Internal" )
    {
    OnLoadIni(Self,"");
    return "";
    }


    s = PlayerOwner().ConsoleCommand("get"@IniOption);
    if (s=="")
    s = IniDefault;

    OnLoadINI(Self,s);
    return s;
    }

    function SaveINI(optional string Value)
    {
    if (PlayerOwner()==None)
    return;

    OnSaveINI(Self);
    }

    // Take a string and strip out colour codes
    static function string StripColorCodes(string InString)
    {
    local int CodePos;

    CodePos = InStr(InString, Chr(27));
    // while(CodePos != -1 && CodePos < Len(InString)-3) // ignore colour codes at the end of the string
    while ( CodePos != -1 ) // do not ignore color codes at the end of the word, or they aren't stripped
    {
    InString = Left(InString, CodePos)$Mid(InString, CodePos+4);
    CodePos = InStr(InString, Chr(27));
    }

    return InString;
    }

    static function string MakeColorCode(color NewColor)
    {
    // Text colours use 1 as 0.
    if(NewColor.R == 0)
    NewColor.R = 1;

    if(NewColor.G == 0)
    NewColor.G = 1;

    if(NewColor.B == 0)
    NewColor.B = 1;

    return Chr(0x1B)$Chr(NewColor.R)$Chr(NewColor.G)$Chr(NewColor.B);
    }

    // Functions

    event MenuStateChange(eMenuState Newstate)
    {
    //log("MenuStateChange:"$NewState@Self.Name);

    if ( MenuState != MSAT_Watched )
    LastMenuState = MenuState;

    bPendingFocus = false;
    MenuState = NewState;
    switch (MenuState)
    {
    case MSAT_Focused:
    if ( !bNeverFocus )
    {
    bHasFocus = true;
    break;
    }

    MenuState = MSAT_Blurry;

    case MSAT_Blurry:
    bHasFocus = false;
    if ( LastMenuState != MSAT_Blurry && LastMenuState != MSAT_Disabled )
    OnDeActivate();
    break;

    case MSAT_Watched:
    if (bFocusOnWatch)
    {
    SetFocus(None);
    return;
    }

    OnWatch();
    break;

    case MSAT_Disabled:
    if (Controller.ActiveControl == Self)
    Controller.ActiveControl = None;

    if (Controller.FocusedControl == Self)
    LoseFocus(None);

    break;
    }

    if ( FriendlyLabel != None )
    FriendlyLabel.MenuState = MenuState;
    }

    event bool IsMultiSelect()
    {
    if ( Controller == None )
    return false;

    return bDropSource && DropState != DRP_Source && Controller.CtrlPressed && OnMultiSelect(Self);
    }

    event DropStateChange(eDropState NewState)
    {
    if (Controller == None)
    return;

    // log( Name$".DropStateChange Current:"$GetEnum(enum'eDropState',DropState)@"New:"$GetEnum(enum'eDropState',NewState)
    // @"DropSource:"$Controller.DropSource == Self@"DropTarget:"$Controller.DropTarget==Self);

    switch (NewState)
    {
    case DRP_None:
    // might be DropTarget with DropState == DRP_Source if we are mousing over the DropSource
    if ( Controller.DropTarget == Self )
    {
    OnDragLeave(Self);
    Controller.DropTarget = None;

    // If this component is also the DropSource, do not alter the DropState
    if ( Controller.DropSource == Self )
    return;
    }

    else if (Controller.DropSource == Self)
    {
    UpdateOffset(0,0,0,0);
    Controller.DropSource = None;
    }

    break;

    case DRP_Source:

    // Don't alter the drop state if component didn't want to begin a drag operation
    if ( !OnBeginDrag(Self) )
    return;

    Controller.DropSource = Self;
    Controller.PlayInterfaceSound(CS_Drag);
    break;

    case DRP_Target:
    Controller.DropTarget = Self;
    if (DropState == DRP_None)
    OnDragEnter(Self);

    break;

    case DRP_Accept:
    Controller.PlayInterfaceSound(CS_Up);

    if ( Controller.DropSource != None )
    Controller.DropSource.OnEndDrag(Self, True);

    Controller.DropTarget = None;
    NewState = DRP_None;

    break;

    case DRP_Reject:
    Controller.PlayInterfaceSound(CS_Down);
    if ( Controller.DropSource != None )
    Controller.DropSource.OnEndDrag(Self, False);

    Controller.DropTarget = None;
    NewState = DRP_None;
    break;
    }

    DropState = NewState;
    }

    event InitComponent(GUIController MyController, GUIComponent MyOwner)
    {
    Controller = MyController;
    MenuOwner = MyOwner;

    PageOwner = OwnerPage();

    if (Style==None)
    Style = Controller.GetStyle(StyleName, FontScale);
    }

    function bool IsInBounds() // Script version of PerformHitTest
    {
    return ( (Controller.MouseX >= Bounds[0] && Controller.MouseX<=Bounds[2]) && (Controller.MouseY >= Bounds[1] && Controller.MouseY <=Bounds[3]) );
    }

    function bool IsInClientBounds()
    {
    return ( (Controller.MouseX >= ClientBounds[0] && Controller.MouseX<=ClientBounds[2]) && (Controller.MouseY >= ClientBounds[1] && Controller.MouseY <=ClientBounds[3]) );
    }

    event bool CanAcceptFocus()
    {
    return MenuState != MSAT_Disabled && bVisible && !bNeverFocus;
    }

    event SetFocus(GUIComponent Who)
    {
    if (Who==None)
    {
    if (bNeverFocus)
    {
    if (FocusInstead != None)
    FocusInstead.SetFocus(Who);

    return;
    }
    bPendingFocus = true;
    if (Controller.FocusedControl!=None)
    {
    if (Controller.FocusedControl == Self) // Already Focused
    return;
    else Controller.FocusedControl.LoseFocus(Self);
    }

    MenuStateChange(MSAT_Focused);
    Controller.FocusedControl = self;
    OnActivate();
    }
    else
    MenuStateChange(MSAT_Focused);


    if (MenuOwner!=None)
    MenuOwner.SetFocus(self);
    }

    event LoseFocus(GUIComponent Sender)
    {
    if (Controller!=None)
    Controller.FocusedControl = None;

    if (MenuState != MSAT_Disabled)
    MenuStateChange(MSAT_Blurry);

    if (MenuOwner!=None)
    MenuOwner.LoseFocus(Self);
    }

    event bool FocusFirst(GUIComponent Sender) // Focus your first child, or yourself if no childrean
    {
    if ( !bTabStop || !CanAcceptFocus() )
    return false;

    SetFocus(None);
    return true;
    }

    event bool FocusLast(GUIComponent Sender) // Focus your last child, or yourself
    {
    if ( !bTabStop || !CanAcceptFocus() )
    return false;

    SetFocus(None);
    return true;
    }

    event bool NextControl(GUIComponent Sender)
    {
    if (MenuOwner!=None)
    return MenuOwner.NextControl(Self);

    return false;
    }

    event bool PrevControl(GUIComponent Sender)
    {
    if (MenuOwner!=None)
    return MenuOwner.PrevControl(Self);

    return false;
    }

    event bool NextPage()
    {
    if (MenuOwner != None)
    return MenuOwner.NextPage();

    return false;
    }

    event bool PrevPage()
    {
    if (MenuOwner != None)
    return MenuOwner.PrevPage();

    return false;
    }

    // Force control to use same area as its MenuOwner.
    function FillOwner()
    {
    WinLeft = 0.0;
    WinTop = 0.0;
    WinWidth = 1.0;
    WinHeight = 1.0;
    bScaleToParent = true;
    bBoundToParent = true;
    }

    event SetVisibility( coerce bool bIsVisible)
    {
    bVisible = bIsVisible;

    if (bVisible)
    OnShow();
    else OnHide();
    }

    function CenterMouse()
    {
    local PlayerController PC;
    local float MidX, MidY;

    PC = PlayerOwner();
    if ( PC != None )
    {
    MidX = ActualLeft() + ActualWidth() / 2;
    MidY = ActualTop() + ActualHeight() / 2;
    PC.ConsoleCommand("SETMOUSE" @ MidX @ MidY);
    }
    }

    event Hide()
    {
    SetVisibility(false);
    }

    event Show()
    {
    SetVisibility(true);
    }

    function SetFocusInstead( GUIComponent InFocusComp )
    {
    if ( InFocusComp != None )
    bNeverFocus = true;

    FocusInstead = InFocusComp;
    }

    function SetFriendlyLabel(GUILabel NewLabel)
    {
    FriendlyLabel = NewLabel;
    }

    function SetHint(string NewHint)
    {
    Hint = NewHint;
    SetToolTipText(Hint);
    }

    function SetToolTipText( string NewToolTipText )
    {
    if ( ToolTip != None )
    ToolTip.SetTip( NewToolTipText );
    }

    function SetTooltip( GUIToolTip InTooltip )
    {
    if ( ToolTip != None )
    ToolTip.LeaveArea();

    ToolTip = InToolTip;
    if ( ToolTip != None )
    ToolTip.InitComponent( Controller, Self );
    }

    function PadLeft( out string Src, int StrLen, optional string PadStr )
    {
    if ( PadStr == "" )
    PadStr = " ";

    while ( Len(Src) < StrLen )
    Src = PadStr $ Src;
    }

    function PadRight( out string Src, int StrLen, optional string PadStr )
    {
    if ( PadStr == "" )
    PadStr = " ";

    while ( Len(Src) < StrLen )
    Src = Src $ PadStr;
    }

    final function DebugFocus( GUIComponent Who, bool bLose )
    {
    return;
    if ( Controller != None && Controller.CtrlPressed )
    {
    if ( bLose )
    {
    if ( Who == None )
    log(Name@"losing focus chain down");
    else log(Name@"losing focus of"@Who);
    }

    else
    {
    if ( Who == None )
    log(Name@"sending focus chain down");
    else log(Name@"setting focus to"@Who);
    }
    }
    }

    final function DebugFocusPosition( GUIComponent Who, bool Last )
    {
    return;
    if ( Controller.CtrlPressed )
    {
    if ( Last )
    {
    if ( Who == None )
    log(Name@"FocusLast going down");
    else log(Name@"FocusLast call from"@Who);
    }

    else
    {
    if ( Who == None )
    log(Name@"FocusFirst going down");
    else log(Name@"FocusFirst call from"@Who);
    }
    }
    }

    event GUIPage OwnerPage()
    {
    local GUIComponent C;

    if ( PageOwner != None )
    return PageOwner;

    C = Self;
    while ( C != None )
    {
    if ( GUIPage(C) != None )
    return GUIPage(C);

    C = C.MenuOwner;
    }

    Warn( "OwnerPage not found!" );
    return None;
    }

    // By default, we don't care which components are animating
    // Input is disabled while bAnimating
    event BeginAnimation( GUIComponent Animating )
    {
    bAnimating = True;
    if ( MenuOwner != None )
    MenuOwner.BeginAnimation(Animating);
    }

    event EndAnimation( GUIComponent Animating, EAnimationType Type )
    {
    bAnimating = False;
    if ( MenuOwner != None )
    MenuOwner.EndAnimation( Animating, Type );

    if ( Animating == Self )
    OnEndAnimation(Animating, Type);
    }

    // If you short circuit these functions (by modifying the animation arrays directly)
    // you must call BeginAnimation() on the owning page for each frame
    function Animate( float NewLeft, float NewTop, optional float Time )
    {
    local int i;

    i = MotionFrame.Length;
    MotionFrame.Length = i + 1;
    MotionFrame[i].X = NewLeft;
    MotionFrame[i].Y = NewTop;
    MotionFrame[i].Z = Time;

    if ( i < 1 )
    BeginAnimation(Self);
    }

    function Resize( float NewWidth, float NewHeight, optional float Time )
    {
    local int i;

    i = SizeFrame.Length;
    SizeFrame.Length = i + 1;
    SizeFrame[i].X = NewWidth;
    SizeFrame[i].Y = NewHeight;
    SizeFrame[i].Z = Time;

    if ( i < 1 )
    BeginAnimation(Self);
    }

    function DAnimate( float NewLeft, float NewTop, float NewWidth, float NewHeight, optional float PositionTime, optional float DimensionTime )
    {
    Animate( NewLeft, NewTop, PositionTime );
    Resize( NewWidth, NewHeight, DimensionTime );
    }

    function KillAnimation()
    {
    if ( MotionFrame.Length > 0 )
    {
    MotionFrame.Remove( 0, MotionFrame.Length );
    EndAnimation( Self, AT_Position );
    }

    if ( SizeFrame.Length > 0 )
    {
    SizeFrame.Remove( 0, SizeFrame.Length );
    EndAnimation( Self, AT_Dimension );
    }
    }

    final function EnableComponent(GUIComponent Comp)
    {
    if ( Comp == None )
    return;

    Comp.EnableMe();
    }

    final function DisableComponent(GUIComponent Comp)
    {
    if ( Comp == None )
    return;

    Comp.DisableMe();
    }

    function EnableMe()
    {
    if ( MenuState != MSAT_Disabled )
    return;

    MenuStateChange(MSAT_Blurry);
    }

    function DisableMe()
    {
    if ( MenuState == MSAT_Disabled )
    return;

    MenuStateChange(MSAT_Disabled);
    }

    function LevelChanged()
    {
    if ( ToolTip != None )
    ToolTip.Free();
    }

    function DebugTabOrder();

    defaultproperties
    {
    FontScale=FNS_Medium
    WinWidth=1.000000
    RenderWeight=0.500000
    TabOrder=-1
    Tag=-1
    bVisible=True
    bInit=True
    TimerIndex=-1
    WhiteColor=(B=244,G=237,R=253,A=255)
    }


    [/i][/i][/i][/i][/i][/i][/spoiler][i][i][i][i][i][i]
    GUI
    [spoiler]

    // ====================================================================
    // Class: UT2K4UI.GUI
    //
    // GUI is an abstract class that holds all of the enums and structs
    // for the UI system
    //
    // Written by Joe Wilcox
    // Updated by Ron Prestenback
    // (c) 2002, Epic Games, Inc. All Rights Reserved
    // ====================================================================

    class GUI extends Object
    abstract
    instanced
    native
    editinlinenew
    config(User);

    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)
    // (cpptext)

    // Number of times each of the rendering functions are allowed to be called on a single component each tick
    // (PreDraw, Draw, and all delegates)
    // Set to 1 to find components that are being rendered (or pre-drawn, or anything) twice each tick
    // Set to 0 to disable render debugging
    const Counter = 0;

    var noexport GUIController Controller; // Callback to the GUIController running the show
    var noexport plane SaveModulation;
    var noexport float SaveX,SaveY;
    var noexport color SaveColor;
    var noexport font SaveFont;
    var noexport byte SaveStyle;


    enum eMenuState // Defines the various states of a component
    {
    MSAT_Blurry, // Component has no focus at all
    MSAT_Watched, // Component is being watched (ie: Mouse is hovering over, etc)
    MSAT_Focused, // Component is Focused (ie: selected)
    MSAT_Pressed, // Component is being pressed
    MSAT_Disabled, // Component is disabled.
    };

    enum eDropState // Defines the state for components allowed to participate in drop operations
    {
    DRP_None, // Not participating in a drop operation
    DRP_Source, // Currently acting as a source
    DRP_Target, // Currently a target
    DRP_Accept, // Accepted dropped data
    DRP_Reject // Reject dropped data
    };

    enum eFontScale // Defines which range of font/fontcolors are used for this component's style
    {
    FNS_Small,
    FNS_Medium,
    FNS_Large
    };

    enum eTextAlign // Used for aligning text in a box
    {
    TXTA_Left,
    TXTA_Center,
    TXTA_Right,
    };

    enum eTextCase // Used for forcing case on text
    {
    TXTC_None,
    TXTC_Upper,
    TXTC_Lower,
    };

    enum eImgStyle // Used to define the style for an image
    {
    ISTY_Normal,
    ISTY_Stretched,
    ISTY_Scaled,
    ISTY_Bound,
    ISTY_Justified,
    ISTY_PartialScaled,
    ISTY_Tiled,
    };

    enum eImgAlign // Used for aligning justified images in a box
    {
    IMGA_TopLeft,
    IMGA_Center,
    IMGA_BottomRight,
    };

    enum eEditMask // Used to define the mask of an input box
    {
    EDM_None,
    EDM_Alpha,
    EDM_Numeric,
    };

    enum EMenuRenderStyle
    {
    MSTY_None,
    MSTY_Normal,
    MSTY_Masked,
    MSTY_Translucent,
    MSTY_Modulated,
    MSTY_Alpha,
    MSTY_Additive,
    MSTY_Subtractive,
    MSTY_Particle,
    MSTY_AlphaZ,
    };

    enum eIconPosition
    {
    ICP_Normal,
    ICP_Center,
    ICP_Scaled,
    ICP_Stretched,
    ICP_Bound,
    };

    enum ePageAlign // Used to Align panels to a form.
    {
    PGA_None,
    PGA_Client,
    PGA_Left,
    PGA_Right,
    PGA_Top,
    PGA_Bottom,
    };

    enum eDrawDirection
    {
    DRD_LeftToRight,
    DRD_RightToLeft,
    DRD_TopToBottom,
    DRD_BottomToTop,
    };

    enum eCellStyle
    {
    CELL_FixedSize,
    CELL_FixedCount
    };

    enum EOrientation
    {
    ORIENT_Vertical, ORIENT_Horizontal
    };

    enum EAnimationType
    {
    AT_Position, AT_Dimension,
    };

    const QBTN_Ok =1;
    const QBTN_Cancel =2;
    const QBTN_Retry =4;
    const QBTN_Continue =8;
    const QBTN_Yes =16;
    const QBTN_No =32;
    const QBTN_Abort =64;
    const QBTN_Ignore =128;
    const QBTN_OkCancel =3;
    const QBTN_AbortRetry =68;
    const QBTN_YesNo =48;
    const QBTN_YesNoCancel =50;


    struct native init GUIListElem
    {
    var string Item;
    var object ExtraData;
    var string ExtraStrData;
    var bool bSection;
    };

    struct APackInfo // OBSOLETE - Use CacheManager.GetAnnouncerList() instead
    {
    var string PackageName;
    var localized string Description;
    };

    struct native init MultiSelectListElem
    {
    var string Item;
    var object ExtraData;
    var string ExtraStrData;
    var bool bSelected;
    var int SelectionIndex; // Used for tracking
    var bool bSection;
    };

    struct native init ImageListElem
    {
    var int Item;
    var Material Image;
    var int Locked;
    };

    struct native init GUITreeNode
    {
    var() string Caption;
    var() string Value;
    var() string ParentCaption;
    var() string ExtraInfo;
    var() int Level;
    var() bool bEnabled;

    cppstruct
    {
    UBOOL operator==( const FGUITreeNode& Other ) const;
    }
    };

    struct AutoLoginInfo
    {
    var() string IP;
    var() string Port;
    var() string Username;
    var() string Password;
    var() bool bAutologin;
    };

    struct GUITabItem
    {
    var() string ClassName;
    var() localized string Caption, Hint;
    };


    // GUI-wide utility functions
    static function bool IsDigit( string Test, optional bool bAllowDecimal )
    {
    if ( Test == "" )
    return false;

    while ( Test != "" )
    {
    if ( Asc(Left(Test,1)) > 57 )
    return false;
    if ( Asc(Left(Test,1)) < 48 && !(bAllowDecimal && Left(Test,1) == ".") )
    return false;
    Test = Mid(Test,1);
    }

    return true;
    }

    // Join together array elements into a single string
    static final function string JoinArray(array<string> StringArray, optional string delim, optional bool bIgnoreBlanks)
    {
    local int i;
    local string s;

    if (delim == "")
    delim = ",";

    for (i = 0; i < StringArray.Length; i++)
    {
    if ((StringArray[i] != "") || (!bIgnoreBlanks))
    {
    if (s != "")
    s $= delim;

    s $= StringArray[i];
    }
    }

    return s;
    }


    // Temp for profiling

    native function Profile(string ProfileName);

    native function GetModList(out array<string> ModDirs, out array<string> ModTitles);
    native function string GetModValue(string ModDir, string ModKey);
    native function material GetModLogo(string ModDir);

    defaultproperties
    {
    }


    [/i][/i][/spoiler][i][i]

    Интересное что если нажать на stats то влезает прилично хоть при 640x480, там же латинскими буквами, надо брать пример с SRTab_MidGameStats[/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i]