Prepare fixtures

This commit is contained in:
dkanus 2026-07-14 20:27:09 +07:00
commit 9c94356263
6021 changed files with 722805 additions and 22 deletions

View file

@ -0,0 +1,89 @@
// ====================================================================
// (C) 2002, Epic Games
// ====================================================================
class AdminPlayerList extends GUIMultiColumnList;
struct PlayerInfo
{
var string PlayerName;
var string PlayerID;
var string PlayerIP;
};
var array<PlayerInfo> MyPlayers;
var GUIStyles SelStyle;
function Clear()
{
MyPlayers.Remove(0,MyPlayers.Length);
Super.Clear();
}
function Add(string PlayerInfo)
{
local string s;
local int i,idx;
idx = MyPlayers.Length;
MyPlayers.Length = MyPlayers.Length+1;
i = instr(PlayerInfo,chr(27));
s = left(PlayerInfo,i);
MyPlayers[idx].PlayerName=s;
PlayerInfo = right(PlayerInfo,Len(PlayerInfo)-i-1);
i = instr(PlayerInfo,chr(27));
s = left(PlayerInfo,i);
MyPlayers[idx].PlayerID=s;
PlayerInfo = right(PlayerInfo,Len(PlayerInfo)-i-1);
MyPlayers[idx].PlayerIP = PlayerInfo;
ItemCount++;
AddedItem();
}
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
OnDrawItem = MyOnDrawItem;
OnKeyEvent = InternalOnKeyEvent;
Super.Initcomponent(MyController, MyOwner);
SelStyle = Controller.GetStyle("SquareButton",FontScale);
}
function MyOnDrawItem(Canvas Canvas, int i, float X, float Y, float W, float H, bool bSelected, bool bPending)
{
local float CellLeft, CellWidth;
if( bSelected )
{
Canvas.SetDrawColor(128,8,8,255);
Canvas.SetPos(x,y-2);
Canvas.DrawTile(Controller.DefaultPens[0],w,h+2,0,0,1,1);
Canvas.SetDrawColor(255,255,255,255);
}
GetCellLeftWidth( 0, CellLeft, CellWidth );
Style.DrawText( Canvas, MenuState, X+CellLeft, Y, CellWidth, H, TXTA_Left, MyPlayers[i].PlayerName, FontScale);
GetCellLeftWidth( 1, CellLeft, CellWidth );
Style.DrawText( Canvas, MenuState, X+CellLeft, Y, CellWidth, H, TXTA_Left, MyPlayers[i].PlayerID, FontScale);
GetCellLeftWidth( 2, CellLeft, CellWidth );
Style.DrawText( Canvas, MenuState, X+CellLeft, Y, CellWidth, H, TXTA_Left, MyPlayers[i].PlayerIP, FontScale);
}
defaultproperties
{
ColumnHeadings(0)="Player Name"
ColumnHeadings(1)="Unique ID"
ColumnHeadings(2)="IP"
InitColumnPerc(0)=0.3
InitColumnPerc(1)=0.4
InitColumnPerc(2)=0.3
SortColumn=-1
WinHeight=1
}

View file

@ -0,0 +1,24 @@
//==============================================================================
// Created on: 10/10/2003
// This class has been setup as a template for GUIImages that should render beneath
// all other components and cover the entire screen
//
// Written by Ron Prestenback
// © 2003, Epic Games, Inc. All Rights Reserved
//==============================================================================
class BackgroundImage extends GUIImage;
DefaultProperties
{
RenderWeight=0
ImageStyle=ISTY_Stretched
ImageRenderStyle=MSTY_Normal
WinLeft=0.0
WinTop=0.0
WinWidth=1.0
WinHeight=1.0
bScaleToParent=False
bBoundToParent=False
}

View file

@ -0,0 +1,104 @@
class Browser_AddBuddy extends UT2K3GUIPage;
var moEditBox MyNewBuddy;
var Browser_ServerListPageBuddy MyBuddyPage;
function InitComponent(GUIController pMyController, GUIComponent MyOwner)
{
Super.InitComponent(pMyController, MyOwner);
MyNewBuddy = moEditBox(Controls[1]);
}
function bool InternalOnClick(GUIComponent Sender)
{
local string buddyName;
if(Sender == Controls[4])
{
buddyName = MyNewBuddy.GetText();
if(buddyName == "")
return true;
MyBuddyPage.Buddies.Length = MyBuddyPage.Buddies.Length + 1;
MyBuddyPage.Buddies[MyBuddyPage.Buddies.Length - 1] = buddyName;
MyBuddyPage.MyBuddyList.ItemCount = MyBuddyPage.Buddies.Length;
MyBuddyPage.SaveConfig();
}
Controller.CloseMenu(false);
return true;
}
defaultproperties
{
Begin Object Class=GUIButton name=VidOKBackground
WinWidth=1.0
WinHeight=1.0
WinTop=0
WinLeft=0
bAcceptsInput=false
bNeverFocus=true
StyleName="SquareBar"
bBoundToParent=true
bScaleToParent=true
End Object
Controls(0)=GUIButton'VidOKBackground'
// EditBox with Limited CharSet for IP address
Begin Object class=moEditBox Name=BuddyEntryBox
Caption="Buddy Name: "
LabelJustification=TXTA_Right
LabelFont="UT2SmallFont"
LabelColor=(R=255,G=255,B=255,A=255)
CaptionWidth=0.55
WinWidth=0.500000
WinHeight=0.050000
WinLeft=0.160000
WinTop=0.466667
End Object
Controls(1)=moEditBox'BuddyEntryBox'
Begin Object Class=GUIButton Name=CancelButton
Caption="CANCEL"
WinWidth=0.2
WinHeight=0.04
WinLeft=0.65
WinTop=0.75
bBoundToParent=true
OnClick=InternalOnClick
End Object
Controls(2)=GUIButton'CancelButton'
Begin Object class=GUILabel Name=AddBuddyDesc
Caption="Add Buddy"
TextALign=TXTA_Center
TextColor=(R=230,G=200,B=0,A=255)
TextFont="UT2HeaderFont"
WinWidth=1
WinLeft=0
WinTop=0.4
WinHeight=32
End Object
Controls(3)=GUILabel'AddBuddyDesc'
Begin Object Class=GUIButton Name=OkButton
Caption="OK"
WinWidth=0.2
WinHeight=0.04
WinLeft=0.125
WinTop=0.75
bBoundToParent=true
OnClick=InternalOnClick
End Object
Controls(4)=GUIButton'OkButton'
WinLeft=0
WinTop=0.375
WinWidth=1
WinHeight=0.25
}

View file

@ -0,0 +1,32 @@
class Browser_BuddyList extends GUIMultiColumnList;
var Browser_ServerListPageBuddy MyBuddyPage;
var GUIStyles SelStyle;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.InitComponent(MyController, MyOwner);
OnDrawItem = MyOnDrawItem;
SelStyle = Controller.GetStyle("SquareButton",FontScale);
}
function MyOnDrawItem(Canvas Canvas, int i, float X, float Y, float W, float H, bool bSelected, bool bPending)
{
local float CellLeft, CellWidth;
if( bSelected )
SelStyle.Draw(Canvas, MSAT_Pressed, X, Y-2, W, H+2 );
GetCellLeftWidth( 0, CellLeft, CellWidth );
Style.DrawText( Canvas, MenuState, CellLeft, Y, CellWidth, H, TXTA_Left, MyBuddyPage.Buddies[i], FontScale );
}
defaultproperties
{
ColumnHeadings(0)="Buddy Name"
InitColumnPerc(0)=1
ExpandLastColumn=True
}

View file

@ -0,0 +1,162 @@
class Browser_IRC extends Browser_Page;
var IRC_System SystemPage;
var GUITabControl ChannelTabs;
var localized string SystemLabel;
var bool bIrcIsInitialised;
var GUIButton LeaveButton;
var GUIButton BackButton;
var GUIButton ChangeNickButton;
var localized string LeaveChannelCaption;
var localized string LeavePrivateCaptionHead;
var localized string LeavePrivateCaptionTail;
var localized string ChooseNewNickText;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.InitComponent(MyController, MyOwner);
// If not already initialised, create system page and add to tabs.
if(!bIrcIsInitialised)
{
ChannelTabs = GUITabControl(Controls[1]);
SystemPage = IRC_System( ChannelTabs.AddTab(SystemLabel, "xinterface.IRC_System", , , true) );
SystemPage.IRCPage = self;
ChannelTabs.OnChange = TabChange;
SystemPage.SetCurrentChannel(-1); // Initially, System page is shown
// Set up buttons
BackButton = GUIButton(GUIPanel(Controls[0]).Controls[0]);
BackButton.OnClick = BackClick;
LeaveButton = GUIButton(GUIPanel(Controls[0]).Controls[1]);
LeaveButton.bVisible = false;
LeaveButton.OnClick = LeaveChannelClick;
ChangeNickButton = GUIButton(GUIPanel(Controls[0]).Controls[2]);
ChangeNickButton.OnClick = ChangeNickClick;
bIrcIsInitialised=true;
}
}
// delegates
function bool BackClick(GUIComponent Sender)
{
Controller.CloseMenu(true);
return true;
}
function bool ChangeNickClick(GUIComponent Sender)
{
local IRC_NewNick NewNickDialog;
if( SystemPage.Controller.OpenMenu("xinterface.IRC_NewNick") )
{
NewNickDialog = IRC_NewNick(SystemPage.Controller.TopPage());
NewNickDialog.NewNickPrompt.Caption = ChooseNewNickText;
NewNickDialog.SystemPage = SystemPage;
}
return true;
}
function TabChange(GUIComponent Sender)
{
local GUITabButton TabButton;
TabButton = GUITabButton(Sender);
if ( TabButton == none )
return;
// If changed to system page - set channel to -1 (ie system)
if( SystemPage == TabButton.MyPanel )
{
SystemPage.SetCurrentChannel(-1);
LeaveButton.bVisible = false;
}
else
{
SystemPage.SetCurrentChannelPage( IRC_Channel( TabButton.MyPanel ) );
// Set caption
if( IRC_Private( TabButton.MyPanel ) != None)
LeaveButton.Caption = LeavePrivateCaptionHead$Caps(TabButton.Caption)$LeavePrivateCaptionTail;
else
LeaveButton.Caption = LeaveChannelCaption;
LeaveButton.bVisible = true;
}
TabButton.bForceFlash=false; // Stop any 'forced' flashing when we switch to a tab
}
function bool LeaveChannelClick(GUIComponent Sender)
{
SystemPage.PartCurrentChannel();
return true;
}
defaultproperties
{
Begin Object Class=GUIButton Name=MyBackButton
Caption="BACK"
StyleName="SquareMenuButton"
WinWidth=0.2
WinLeft=0
WinTop=0
WinHeight=1
End Object
Begin Object Class=GUIButton Name=MyLeaveButton
Caption=""
StyleName="SquareMenuButton"
WinWidth=0.2
WinLeft=0.4
WinTop=0
WinHeight=1
End Object
Begin Object Class=GUIButton Name=MyChangeNickButton
Caption="CHANGE NICK"
StyleName="SquareMenuButton"
WinWidth=0.2
WinLeft=0.2
WinTop=0
WinHeight=1
End Object
Begin Object Class=GUIPanel Name=FooterPanel
Controls(0)=MyBackButton
Controls(1)=MyLeaveButton
Controls(2)=MyChangeNickButton
WinWidth=1
WinHeight=0.05
WinLeft=0
WinTop=0.95
End Object
Controls(0)=GUIPanel'FooterPanel'
Begin Object Class=GUITabControl Name=ChannelTabControl
WinWidth=1.0
WinLeft=0
WinTop=0
WinHeight=48
TabHeight=0.04
bFillSpace=False
bAcceptsInput=true
bDockPanels=true
End Object
Controls(1)=GUITabControl'ChannelTabControl'
LeaveChannelCaption="LEAVE CHANNEL"
LeavePrivateCaptionHead="CLOSE "
LeavePrivateCaptionTail=""
SystemLabel="System"
ChooseNewNickText="Choose A New Chat Nickname"
}

View file

@ -0,0 +1,232 @@
class Browser_IconKey extends UT2K3GUIPage;
function bool InternalOnClick(GUIComponent Sender)
{
Controller.CloseMenu(false);
return true;
}
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
local int i;
Super.InitComponent(MyController, MyOwner);
for(i=0; i<7; i++)
{
GUIImage(Controls[3+2*i]).Image = class'Browser_ServersList'.default.Icons[i];
GUILabel(Controls[4+2*i]).Caption = class'Browser_ServersList'.default.IconDescriptions[i];
}
}
defaultproperties
{
Begin Object Class=GUIButton name=DialogBackground
WinWidth=0.500000
WinHeight=0.556251
WinLeft=0.250000
WinTop=0.256667
bAcceptsInput=false
bNeverFocus=true
StyleName="ListBox"
bBoundToParent=true
bScaleToParent=true
End Object
Controls(0)=GUIButton'DialogBackground'
Begin Object Class=GUIButton Name=OkButton
Caption="OK"
WinWidth=0.200000
WinHeight=0.040000
WinLeft=0.400000
WinTop=0.75
OnClick=InternalOnClick
End Object
Controls(1)=GUIButton'OkButton'
Begin Object class=GUILabel Name=DialogText
Caption="Server Icon Key"
TextALign=TXTA_Center
TextColor=(R=220,G=180,B=0,A=255)
TextFont="UT2HeaderFont"
WinWidth=1.000000
WinHeight=32.000000
WinLeft=0.000000
WinTop=0.278334
End Object
Controls(2)=GUILabel'DialogText'
Begin Object Class=GUIImage name=Icon1
ImageStyle=ISTY_Scaled
ImageRenderStyle=MSTY_Alpha
ImageColor=(R=255,G=255,B=255,A=255)
WinWidth=16
WinHeight=16
WinLeft=0.3
WinTop=0.35
End Object
Controls(3)=GUIImage'Icon1'
Begin Object Class=GUILabel name=Label1
TextALign=TXTA_Left
TextColor=(R=255,G=255,B=255,A=255)
WinWidth=0.350000
WinHeight=32.000000
WinLeft=0.360000
WinTop=0.340000
StyleName="TextLabel"
End Object
Controls(4)=GUILabel'Label1'
Begin Object Class=GUIImage name=Icon2
ImageStyle=ISTY_Scaled
ImageRenderStyle=MSTY_Alpha
ImageColor=(R=255,G=255,B=255,A=255)
WinWidth=16.000000
WinHeight=16.000000
WinLeft=0.300000
WinTop=0.41
End Object
Controls(5)=GUIImage'Icon2'
Begin Object Class=GUILabel name=Label2
TextALign=TXTA_Left
TextColor=(R=255,G=255,B=255,A=255)
WinWidth=0.350000
WinHeight=32.000000
WinLeft=0.36
WinTop=0.40
StyleName="TextLabel"
End Object
Controls(6)=GUILabel'Label2'
Begin Object Class=GUIImage name=Icon3
ImageStyle=ISTY_Scaled
ImageRenderStyle=MSTY_Alpha
ImageColor=(R=255,G=255,B=255,A=255)
WinWidth=16.000000
WinHeight=16.000000
WinLeft=0.300000
WinTop=0.47
End Object
Controls(7)=GUIImage'Icon3'
Begin Object Class=GUILabel name=Label3
TextALign=TXTA_Left
TextColor=(R=255,G=255,B=255,A=255)
WinWidth=0.350000
WinHeight=32.000000
WinLeft=0.36
WinTop=0.46
StyleName="TextLabel"
End Object
Controls(8)=GUILabel'Label3'
Begin Object Class=GUIImage name=Icon4
ImageStyle=ISTY_Scaled
ImageRenderStyle=MSTY_Alpha
ImageColor=(R=255,G=255,B=255,A=255)
WinWidth=16.000000
WinHeight=16.000000
WinLeft=0.300000
WinTop=0.53
End Object
Controls(9)=GUIImage'Icon4'
Begin Object Class=GUILabel name=Label4
TextALign=TXTA_Left
TextColor=(R=255,G=255,B=255,A=255)
WinWidth=0.350000
WinHeight=32.000000
WinLeft=0.36
WinTop=0.52
StyleName="TextLabel"
End Object
Controls(10)=GUILabel'Label4'
Begin Object Class=GUIImage name=Icon5
ImageStyle=ISTY_Scaled
ImageRenderStyle=MSTY_Alpha
ImageColor=(R=255,G=255,B=255,A=255)
WinWidth=16.000000
WinHeight=16.000000
WinLeft=0.300000
WinTop=0.59
End Object
Controls(11)=GUIImage'Icon5'
Begin Object Class=GUILabel name=Label5
TextALign=TXTA_Left
TextColor=(R=255,G=255,B=255,A=255)
WinWidth=0.350000
WinHeight=32.000000
WinLeft=0.36
WinTop=0.58
StyleName="TextLabel"
End Object
Controls(12)=GUILabel'Label5'
Begin Object Class=GUIImage name=Icon6
ImageStyle=ISTY_Scaled
ImageRenderStyle=MSTY_Alpha
ImageColor=(R=255,G=255,B=255,A=255)
WinWidth=16.000000
WinHeight=16.000000
WinLeft=0.300000
WinTop=0.65
End Object
Controls(13)=GUIImage'Icon6'
Begin Object Class=GUILabel name=Label6
TextALign=TXTA_Left
TextColor=(R=255,G=255,B=255,A=255)
WinWidth=0.350000
WinHeight=32.000000
WinLeft=0.36
WinTop=0.64
StyleName="TextLabel"
End Object
Controls(14)=GUILabel'Label6'
Begin Object Class=GUIImage name=Icon7
ImageStyle=ISTY_Scaled
ImageRenderStyle=MSTY_Alpha
ImageColor=(R=255,G=255,B=255,A=255)
WinWidth=16.000000
WinHeight=16.000000
WinLeft=0.300000
WinTop=0.71
End Object
Controls(15)=GUIImage'Icon7'
Begin Object Class=GUILabel name=Label7
TextALign=TXTA_Left
TextColor=(R=255,G=255,B=255,A=255)
WinWidth=0.350000
WinHeight=32.000000
WinLeft=0.36
WinTop=0.70
StyleName="TextLabel"
End Object
Controls(16)=GUILabel'Label7'
WinLeft=0
WinTop=0
WinWidth=1
WinHeight=1
bRequire640x480=false
}

View file

@ -0,0 +1,222 @@
class Browser_MOTD extends Browser_Page;
var MasterServerClient MSC;
var String MOTD;
var GUIScrollTextBox MOTDTextBox;
var GUIButton UpgradeButton;
var bool MustUpgrade;
var bool GotMOTD;
var GUITitleBar StatusBar;
var float ReReadyPause;
var localized string VersionString;
event Timer()
{
StatusBar.SetCaption(ReadyString);
}
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.InitComponent(MyController, MyOwner);
StatusBar = GUITitleBar(GUIPanel(Controls[1]).Controls[3]);
StatusBar.SetCaption(ReadyString);
MSC = PlayerOwner().Level.Spawn( class'MasterServerClient' );
MSC.OnReceivedMOTDData = MyReceivedMOTDData;
MSC.OnQueryFinished = MyQueryFinished;
MOTDTextBox = GUIScrollTextBox(Controls[0]);
GUIButton(GUIPanel(Controls[1]).Controls[0]).OnClick=BackClick;
GUIButton(GUIPanel(Controls[1]).Controls[1]).OnClick=RefreshClick;
UpgradeButton = GUIButton(GUIPanel(Controls[1]).Controls[2]);
UpgradeButton.OnClick=UpgradeClick;
if( !GotMOTD )
{
UpgradeButton.bVisible = false;
MustUpgrade = false;
MSC.StartQuery(CTM_GetMOTD);
StatusBar.SetCaption(StartQueryString);
SetTimer(0, false); // Stop it going back to ready from a previous timer!
}
Controls[2].bBoundToParent=false;
// if _RO_
GUILabel(Controls[2]).Caption = "Killing Floor"@VersionString@PlayerOwner().Level.ROVersion;
//else
//GUILabel(Controls[2]).Caption = "UT2004"@VersionString@PlayerOwner().Level.EngineVersion;
}
function MyReceivedMOTDData( MasterServerClient.EMOTDResponse Command, string Data )
{
switch( Command )
{
case MR_MOTD:
GotMOTD = true;
MOTDTextBox.SetContent(Data, Chr(13));
break;
case MR_OptionalUpgrade:
UpgradeButton.bVisible = true;
break;
case MR_MandatoryUpgrade:
MustUpgrade = true;
UpgradeButton.bVisible = true;
break;
case MR_NewServer:
break;
case MR_IniSetting:
break;
case MR_Command:
break;
}
}
function MyQueryFinished( MasterServerClient.EResponseInfo ResponseInfo, int Info )
{
switch( ResponseInfo )
{
case RI_Success:
StatusBar.SetCaption(QueryCompleteString);
SetTimer(ReReadyPause, false);
if( !MustUpgrade )
Browser.MOTDVerified(true);
break;
case RI_AuthenticationFailed:
StatusBar.SetCaption(AuthFailString);
SetTimer(ReReadyPause, false);
break;
case RI_ConnectionFailed:
StatusBar.SetCaption(ConnFailString);
SetTimer(ReReadyPause, false);
Browser.MOTDVerified(false);
// try again
MSC.StartQuery(CTM_GetMOTD);
break;
case RI_ConnectionTimeout:
StatusBar.SetCaption(ConnTimeoutString);
Browser.MOTDVerified(false);
SetTimer(ReReadyPause, false);
break;
}
}
function OnCloseBrowser()
{
if( MSC != None )
{
MSC.CancelPings();
MSC.Destroy();
MSC = None;
}
}
// delegates
function bool BackClick(GUIComponent Sender)
{
Controller.CloseMenu(true);
return true;
}
function bool RefreshClick(GUIComponent Sender)
{
MustUpgrade = false;
UpgradeButton.bVisible = false;
MSC.Stop();
MSC.StartQuery(CTM_GetMOTD);
StatusBar.SetCaption(StartQueryString);
SetTimer(0, false);
return true;
}
function bool UpgradeClick(GUIComponent Sender)
{
MSC.LaunchAutoUpdate();
return true;
}
defaultproperties
{
Begin Object class=GUIScrollTextBox Name=MyMOTDText
TextAlign=TXTA_Left
WinWidth=0.9
WinHeight=0.8
WinLeft=0.05
WinTop=0.048
CharDelay=0.004
EOLDelay=0.1
bNeverFocus=true
bAcceptsInput=true
End Object
Controls(0)=MyMOTDText
Begin Object Class=GUIButton Name=MyBackButton
Caption="BACK"
StyleName="SquareMenuButton"
WinWidth=0.2
WinLeft=0
WinTop=0
WinHeight=0.5
End Object
Begin Object Class=GUIButton Name=MyRefreshButton
Caption="REFRESH"
StyleName="SquareMenuButton"
WinWidth=0.2
WinLeft=0.2
WinTop=0
WinHeight=0.5
End Object
Begin Object Class=GUIButton Name=MyUpgradeButton
Caption="UPGRADE"
StyleName="SquareMenuButton"
WinWidth=0.2
WinLeft=0.8
WinTop=0
WinHeight=0.5
bVisible=false
End Object
Begin Object class=GUITitleBar name=MyStatus
WinWidth=1
WinHeight=0.5
WinLeft=0
WinTop=0.5
StyleName="SquareBar"
Caption=""
bUseTextHeight=false
Justification=TXTA_Left
End Object
Begin Object Class=GUIPanel Name=FooterPanel
Controls(0)=MyBackButton
Controls(1)=MyRefreshButton
Controls(2)=MyUpgradeButton
Controls(3)=MyStatus
WinWidth=1
WinHeight=0.1
WinLeft=0
WinTop=0.9
End Object
Controls(1)=FooterPanel
Begin Object class=GUILabel Name=VersionNum
Caption=""
TextALign=TXTA_Right
TextColor=(R=100,G=100,B=160,A=255)
WinWidth=0.500000
WinHeight=0.040000
WinLeft=0.495000
WinTop=0.0025
End Object
Controls(2)=GUILabel'VersionNum'
ReReadyPause=2.0
VersionString="Ver."
}

View file

@ -0,0 +1,125 @@
class Browser_OpenIP extends UT2K3GUIPage;
var moEditBox MyIpAddress;
var Browser_ServerListPageFavorites MyFavoritesPage;
function InitComponent(GUIController pMyController, GUIComponent MyOwner)
{
Super.InitComponent(pMyController, MyOwner);
MyIpAddress = moEditBox(Controls[1]);
MyIpAddress.MyEditBox.AllowedCharSet="0123456789.:";
}
function bool InternalOnClick(GUIComponent Sender)
{
local GameInfo.ServerResponseLine S;
local string address, ipString, portString;
local int colonPos, portNum;
if(Sender == Controls[4])
{
address = MyIpAddress.GetText();
if(address == "")
return true;
// Parse text to find IP and possibly port number
colonPos = InStr(address, ":");
if(colonPos < 0)
{
// No colon
ipString = address;
portNum = 7777;
}
else
{
ipString = Left(address, colonPos);
portString = Mid(address, colonPos+1);
portNum = int(portString);
}
S.IP = ipString;
S.Port = portNum;
S.QueryPort = portNum+1;
S.ServerName = "Unknown";
MyFavoritesPage.MyAddFavorite(S);
}
Controller.CloseMenu(false);
return true;
}
defaultproperties
{
Begin Object Class=GUIButton name=VidOKBackground
WinWidth=1.0
WinHeight=1.0
WinTop=0
WinLeft=0
bAcceptsInput=false
bNeverFocus=true
StyleName="SquareBar"
bBoundToParent=true
bScaleToParent=true
End Object
Controls(0)=GUIButton'VidOKBackground'
// EditBox with Limited CharSet for IP address
Begin Object class=moEditBox Name=IpEntryBox
Caption="IP Address: "
LabelJustification=TXTA_Right
LabelFont="UT2SmallFont"
LabelColor=(R=255,G=255,B=255,A=255)
CaptionWidth=0.55
WinWidth=0.500000
WinHeight=0.050000
WinLeft=0.160000
WinTop=0.466667
End Object
Controls(1)=moEditBox'IpEntryBox'
Begin Object Class=GUIButton Name=CancelButton
Caption="CANCEL"
WinWidth=0.2
WinHeight=0.04
WinLeft=0.65
WinTop=0.75
bBoundToParent=true
OnClick=InternalOnClick
End Object
Controls(2)=GUIButton'CancelButton'
Begin Object class=GUILabel Name=OpenIPDesc
Caption="Enter New IP Address"
TextALign=TXTA_Center
TextColor=(R=230,G=200,B=0,A=255)
TextFont="UT2HeaderFont"
WinWidth=1
WinLeft=0
WinTop=0.4
WinHeight=32
End Object
Controls(3)=GUILabel'OpenIPDesc'
Begin Object Class=GUIButton Name=OkButton
Caption="OK"
WinWidth=0.2
WinHeight=0.04
WinLeft=0.125
WinTop=0.75
bBoundToParent=true
OnClick=InternalOnClick
End Object
Controls(4)=GUIButton'OkButton'
WinLeft=0
WinTop=0.375
WinWidth=1
WinHeight=0.25
}

View file

@ -0,0 +1,32 @@
class Browser_Page extends UT2K3TabPanel;
var ServerBrowser Browser;
var localized string StartQueryString;
var localized string AuthFailString;
var localized string ConnFailString;
var localized string ConnTimeoutString;
var localized string QueryCompleteString;
var localized string RefreshCompleteString;
var localized string ReadyString;
var localized string PageCaption;
function OnCloseBrowser();
defaultproperties
{
StartQueryString="Querying Master Server"
AuthFailString="Authentication Failed"
ConnFailString="Connection Failed - Retrying"
ConnTimeoutString="Connection Timed Out"
RefreshCompleteString="Refresh Complete!"
QueryCompleteString="Query Complete!"
ReadyString="Ready"
bFillHeight=True
WinWidth=1.0
WinHeight=0.85
WinTop=0.15
WinLeft=0
}

View file

@ -0,0 +1,67 @@
class Browser_PlayersList extends GUIMultiColumnList;
var Browser_ServerListPageBase MyPage;
var Browser_ServersList MyServersList;
var int listitem;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
OnDrawItem = MyOnDrawItem;
OnKeyEvent = InternalOnKeyEvent;
Super.Initcomponent(MyController, MyOwner);
}
function MyOnDrawItem(Canvas Canvas, int i, float X, float Y, float W, float H, bool bSelected, bool bPending)
{
local float CellLeft, CellWidth;
GetCellLeftWidth( 0, CellLeft, CellWidth );
Style.DrawText( Canvas, MenuState, CellLeft, Y, CellWidth, H, TXTA_Left, MyServersList.Servers[listitem].PlayerInfo[i].PlayerName, FontScale );
GetCellLeftWidth( 1, CellLeft, CellWidth );
Style.DrawText( Canvas, MenuState, CellLeft, Y, CellWidth, H, TXTA_Left, string(MyServersList.Servers[listitem].PlayerInfo[i].Score), FontScale );
if( MyServersList.Servers[listitem].PlayerInfo[i].StatsID != 0 )
{
GetCellLeftWidth( 2, CellLeft, CellWidth );
Style.DrawText( Canvas, MenuState, CellLeft, Y, CellWidth, H, TXTA_Left, string(MyServersList.Servers[listitem].PlayerInfo[i].StatsID), FontScale );
}
GetCellLeftWidth( 3, CellLeft, CellWidth );
Style.DrawText( Canvas, MenuState, CellLeft, Y, CellWidth, H, TXTA_Left, string(MyServersList.Servers[listitem].PlayerInfo[i].Ping), FontScale );
}
function bool InternalOnKeyEvent(out byte Key, out byte State, float delta)
{
if( Super.InternalOnKeyEvent(Key, State, delta) )
return true;
if( State==1 )
{
switch(Key)
{
case 0x0D: //IK_Enter
MyServersList.Connect(false);
return true;
break;
case 0x74: //IK_F5
MyPage.RefreshList();
return true;
break;
}
}
return false;
}
defaultproperties
{
ColumnHeadings(0)="Player Name"
ColumnHeadings(1)="Score"
ColumnHeadings(2)="Stats ID"
ColumnHeadings(3)="Ping"
InitColumnPerc(0)=0.17
InitColumnPerc(1)=0.11
InitColumnPerc(2)=0.11
InitColumnPerc(3)=0.11
}

View file

@ -0,0 +1,551 @@
class Browser_Prefs extends Browser_Page;
var GUITitleBar StatusBar;
var localized string ViewStatsStrings[3];
var localized string MutatorModeStrings[4];
var localized string WeaponStayStrings[3];
var localized string TranslocatorStrings[3];
var bool bIsInitialised;
var array<xUtil.MutatorRecord> MutatorRecords;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
local int i;
Super.InitComponent(MyController, MyOwner);
if(bIsInitialised)
return;
GUIButton(GUIPanel(Controls[0]).Controls[0]).OnClick=BackClick;
// Set options for stats server viewing
moComboBox(Controls[5]).AddItem(ViewStatsStrings[0]);
moComboBox(Controls[5]).AddItem(ViewStatsStrings[1]);
moComboBox(Controls[5]).AddItem(ViewStatsStrings[2]);
moComboBox(Controls[5]).ReadOnly(true);
// Load mutators into combobox
class'xUtil'.static.GetMutatorList(MutatorRecords);
moComboBox(Controls[9]).AddItem(MutatorModeStrings[0]);
moComboBox(Controls[9]).AddItem(MutatorModeStrings[1]);
moComboBox(Controls[9]).AddItem(MutatorModeStrings[2]);
moComboBox(Controls[9]).AddItem(MutatorModeStrings[3]);
moComboBox(Controls[9]).ReadOnly(true);
moComboBox(Controls[13]).AddItem(MutatorModeStrings[0]);
moComboBox(Controls[13]).AddItem(MutatorModeStrings[2]);
moComboBox(Controls[13]).AddItem(MutatorModeStrings[3]);
moComboBox(Controls[13]).ReadOnly(true);
for(i=0; i<MutatorRecords.Length; i++)
{
moComboBox(Controls[6]).AddItem(MutatorRecords[i].FriendlyName, None, MutatorRecords[i].ClassName);
moComboBox(Controls[14]).AddItem(MutatorRecords[i].FriendlyName, None, MutatorRecords[i].ClassName);
}
moComboBox(Controls[6]).ReadOnly(true);
// Weapon stay
moComboBox(Controls[11]).AddItem(WeaponStayStrings[0]);
moComboBox(Controls[11]).AddItem(WeaponStayStrings[1]);
moComboBox(Controls[11]).AddItem(WeaponStayStrings[2]);
moComboBox(Controls[11]).ReadOnly(true);
// Translocator
moComboBox(Controls[12]).AddItem(TranslocatorStrings[0]);
moComboBox(Controls[12]).AddItem(TranslocatorStrings[1]);
moComboBox(Controls[12]).AddItem(TranslocatorStrings[2]);
moComboBox(Controls[12]).ReadOnly(true);
moNumericEdit(Controls[15]).MyNumericEdit.Step = 10;
moNumericEdit(Controls[16]).MyNumericEdit.Step = 10;
for(i=2; i<17; i++)
{
Controls[i].OnLoadINI=MyOnLoadINI;
Controls[i].OnChange=MyOnChange;
}
StatusBar = GUITitleBar(GUIPanel(Controls[0]).Controls[1]);
// Set on click for 'Show Icon Key' button
GUIButton(GUIPanel(Controls[0]).Controls[2]).OnClick = InternalShowIconKey;
bIsInitialised=true;
}
// delegates
function bool BackClick(GUIComponent Sender)
{
Controller.CloseMenu(true);
return true;
}
function UpdateMutatorVisibility()
{
// If first one is 'any' or 'none', don't show any mutator selector boxes
if(Browser.ViewMutatorMode == VMM_AnyMutators || Browser.ViewMutatorMode == VMM_NoMutators)
{
Controls[6].bVisible = false;
Controls[13].bVisible = false;
Controls[14].bVisible = false;
}
else // If its not - show the first mutator selection box, and the second mode box
{
Controls[6].bVisible = true;
Controls[13].bVisible = true;
// And check the second mode drop-down,
if(Browser.ViewMutator2Mode == VMM_AnyMutators)
Controls[14].bVisible = false;
else
Controls[14].bVisible = true;
}
}
function bool InternalShowIconKey(GUIComponent Sender)
{
Controller.OpenMenu("XInterface.Browser_IconKey");
return true;
}
///////////////////// LOAD ///////////////////////
function MyOnLoadINI(GUIComponent Sender, string s)
{
local int i;
if(Sender == Controls[8])
moCheckBox(Controls[8]).Checked(Browser.bOnlyShowStandard);
else if(Sender == Controls[2])
moCheckBox(Controls[2]).Checked(Browser.bOnlyShowNonPassword);
else if(Sender == Controls[3])
moCheckBox(Controls[3]).Checked(Browser.bDontShowFull);
else if(Sender == Controls[4])
moCheckBox(Controls[4]).Checked(Browser.bDontShowEmpty);
else if(Sender == Controls[5])
moComboBox(Controls[5]).SetText(ViewStatsStrings[Browser.StatsServerView]);
else if(Sender == Controls[6])
{
// Find the Mutator with this class name, and put its friendly name in the box
for(i=0; i<MutatorRecords.Length; i++)
{
if( Browser.DesiredMutator == MutatorRecords[i].ClassName )
{
moComboBox(Controls[6]).SetText( MutatorRecords[i].FriendlyName );
return;
}
}
}
else if(Sender == Controls[7])
{
moEditBox(Controls[7]).SetText(Browser.CustomQuery);
}
else if(Sender == Controls[9])
{
moComboBox(Controls[9]).SetText( MutatorModeStrings[Browser.ViewMutatorMode] );
UpdateMutatorVisibility();
}
else if(Sender == Controls[10])
moCheckBox(Controls[10]).Checked(Browser.bDontShowWithBots);
else if(Sender == Controls[11])
moComboBox(Controls[11]).SetText(WeaponStayStrings[Browser.WeaponStayServerView]);
else if(Sender == Controls[12])
moComboBox(Controls[12]).SetText(TranslocatorStrings[Browser.TranslocServerView]);
else if(Sender == Controls[13])
{
moComboBox(Controls[13]).SetText( MutatorModeStrings[Browser.ViewMutator2Mode] );
UpdateMutatorVisibility();
}
else if(Sender == Controls[14])
{
for(i=0; i<MutatorRecords.Length; i++)
{
if( Browser.DesiredMutator2 == MutatorRecords[i].ClassName )
{
moComboBox(Controls[14]).SetText( MutatorRecords[i].FriendlyName );
return;
}
}
}
else if(Sender == Controls[15])
moNumericEdit(Controls[15]).SetValue(Browser.MinGamespeed);
else if(Sender == Controls[16])
moNumericEdit(Controls[16]).SetValue(Browser.MaxGamespeed);
}
///////////////////// SAVE ///////////////////////
function MyOnChange(GUIComponent Sender)
{
local string t;
if(Sender == Controls[8])
Browser.bOnlyShowStandard = moCheckBox(Controls[8]).IsChecked();
else if(Sender == Controls[2])
Browser.bOnlyShowNonPassword = moCheckBox(Controls[2]).IsChecked();
else if(Sender == Controls[3])
Browser.bDontShowFull = moCheckBox(Controls[3]).IsChecked();
else if(Sender == Controls[4])
Browser.bDontShowEmpty = moCheckBox(Controls[4]).IsChecked();
else if(Sender == Controls[5])
{
t = moComboBox(Controls[5]).GetText();
if(t == ViewStatsStrings[0])
Browser.StatsServerView = SSV_Any;
else if(t == ViewStatsStrings[1])
Browser.StatsServerView = SSV_OnlyStatsEnabled;
else if(t == ViewStatsStrings[2])
Browser.StatsServerView = SSV_NoStatsEnabled;
}
else if(Sender == Controls[6])
{
Browser.DesiredMutator = moComboBox(Controls[6]).GetExtra();
}
else if(Sender == Controls[7])
{
Browser.CustomQuery = moEditBox(Controls[7]).GetText();
}
else if(Sender == Controls[9])
{
t = moComboBox(Controls[9]).GetText();
if(t == MutatorModeStrings[0])
Browser.ViewMutatorMode = VMM_AnyMutators;
else if(t == MutatorModeStrings[1])
Browser.ViewMutatorMode = VMM_NoMutators;
else if(t == MutatorModeStrings[2])
Browser.ViewMutatorMode = VMM_ThisMutator;
else if(t == MutatorModeStrings[3])
Browser.ViewMutatorMode = VMM_NotThisMutator;
UpdateMutatorVisibility();
}
else if(Sender == Controls[10])
Browser.bDontShowWithBots = moCheckBox(Controls[10]).IsChecked();
else if(Sender == Controls[11])
{
t = moComboBox(Controls[11]).GetText();
if(t == WeaponStayStrings[0])
Browser.WeaponStayServerView = WSSV_Any;
else if(t == WeaponStayStrings[1])
Browser.WeaponStayServerView = WSSV_OnlyWeaponStay;
else if(t == WeaponStayStrings[2])
Browser.WeaponStayServerView = WSSV_NoWeaponStay;
}
else if(Sender == Controls[12])
{
t = moComboBox(Controls[12]).GetText();
if(t == TranslocatorStrings[0])
Browser.TranslocServerView = TSV_Any;
else if(t == TranslocatorStrings[1])
Browser.TranslocServerView = TSV_OnlyTransloc;
else if(t == TranslocatorStrings[2])
Browser.TranslocServerView = TSV_NoTransloc;
}
else if(Sender == Controls[13])
{
t = moComboBox(Controls[13]).GetText();
if(t == MutatorModeStrings[0])
Browser.ViewMutator2Mode = VMM_AnyMutators;
else if(t == MutatorModeStrings[2])
Browser.ViewMutator2Mode = VMM_ThisMutator;
else if(t == MutatorModeStrings[3])
Browser.ViewMutator2Mode = VMM_NotThisMutator;
UpdateMutatorVisibility();
}
else if(Sender == Controls[14])
{
Browser.DesiredMutator2 = moComboBox(Controls[14]).GetExtra();
}
else if(Sender == Controls[15])
{
if( moNumericEdit(Controls[15]).GetValue() < 0 )
moNumericEdit(Controls[15]).SetValue( 0 );
Browser.MinGamespeed = moNumericEdit(Controls[15]).GetValue();
}
else if(Sender == Controls[16])
{
if( moNumericEdit(Controls[16]).GetValue() > 200 )
moNumericEdit(Controls[16]).SetValue( 200 );
Browser.MaxGamespeed = moNumericEdit(Controls[16]).GetValue();
}
Browser.SaveConfig();
}
defaultproperties
{
Begin Object Class=GUIButton Name=MyBackButton
Caption="BACK"
StyleName="SquareMenuButton"
WinWidth=0.2
WinLeft=0
WinTop=0
WinHeight=0.5
End Object
Begin Object class=GUITitleBar name=MyStatus
WinWidth=1
WinHeight=0.5
WinLeft=0
WinTop=0.5
StyleName="SquareBar"
Caption=""
bUseTextHeight=false
Justification=TXTA_Left
End Object
Begin Object Class=GUIButton Name=MyKeyButton
Caption="ICON KEY"
StyleName="SquareMenuButton"
WinWidth=0.2
WinLeft=0.2
WinTop=0
WinHeight=0.5
End Object
Begin Object Class=GUIPanel Name=FooterPanel
Controls(0)=MyBackButton
Controls(1)=MyStatus
Controls(2)=MyKeyButton
WinWidth=1
WinHeight=0.1
WinLeft=0
WinTop=0.9
End Object
Controls(0)=GUIPanel'FooterPanel'
Begin Object Class=GUILabel Name=FilterTitle
WinWidth=0.720003
WinHeight=0.056250
WinLeft=0.1500000
WinTop=0.05
Caption="Server Filtering Options:"
TextAlign=TXTA_Left
TextColor=(R=230,G=200,B=0,A=255)
TextFont="UT2HeaderFont"
End Object
Controls(1)=GUILabel'FilterTitle'
Begin Object class=moCheckBox Name=NoPasswdCheckBox
WinWidth=0.3400000
WinHeight=0.040000
WinLeft=0.05
WinTop=0.21
Caption="No Passworded Servers"
INIOption="@Internal"
CaptionWidth=0.9
bSquare=true
ComponentJustification=TXTA_Left
End Object
Controls(2)=moCheckbox'NoPasswdCheckBox'
Begin Object class=moCheckBox Name=NoFullCheckBox
WinWidth=0.3400000
WinHeight=0.040000
WinLeft=0.05
WinTop=0.27
Caption="No Full Servers"
INIOption="@Internal"
CaptionWidth=0.9
bSquare=true
ComponentJustification=TXTA_Left
End Object
Controls(3)=moCheckbox'NoFullCheckBox'
Begin Object class=moCheckBox Name=NoEmptyCheckBox
WinWidth=0.34
WinHeight=0.04
WinLeft=0.05
WinTop=0.33
Caption="No Empty Servers"
INIOption="@Internal"
CaptionWidth=0.9
bSquare=true
ComponentJustification=TXTA_Left
End Object
Controls(4)=moCheckbox'NoEmptyCheckBox'
Begin Object class=moComboBox Name=StatsViewCombo
WinWidth=0.76
WinHeight=0.04
WinLeft=0.05
WinTop=0.39
Caption="Stats Servers"
INIOption="@INTERNAL"
CaptionWidth=0.4
ComponentJustification=TXTA_Left
End Object
Controls(5)=moComboBox'StatsViewCombo'
Begin Object class=moComboBox Name=MutatorCombo
WinWidth=0.308750
WinHeight=0.060000
WinLeft=0.675004
WinTop=0.45
Caption=""
INIOption="@INTERNAL"
CaptionWidth=0.0
ComponentJustification=TXTA_Left
End Object
Controls(6)=moComboBox'MutatorCombo'
Begin Object class=moEditBox Name=CustomQuery
WinWidth=0.76
WinHeight=0.04
WinLeft=0.05
WinTop=0.75
Caption="Custom Query"
INIOption="@INTERNAL"
CaptionWidth=0.4
End Object
Controls(7)=moEditBox'CustomQuery'
Begin Object class=moCheckBox Name=OnlyStandardCheckBox
WinWidth=0.3400000
WinHeight=0.040000
WinLeft=0.05
WinTop=0.15
Caption="Only Standard Servers"
INIOption="@Internal"
CaptionWidth=0.9
bSquare=true
ComponentJustification=TXTA_Left
End Object
Controls(8)=moCheckbox'OnlyStandardCheckBox'
Begin Object class=moComboBox Name=MutatorModeCombo
WinWidth=0.61
WinHeight=0.04
WinLeft=0.05
WinTop=0.45
Caption="Mutators"
INIOption="@INTERNAL"
CaptionWidth=0.5
ComponentJustification=TXTA_Left
End Object
Controls(9)=moComboBox'MutatorModeCombo'
Begin Object class=moCheckBox Name=NoBotServersCheckBox
WinWidth=0.34
WinHeight=0.04
WinLeft=0.05
WinTop=0.39
Caption="No Servers With Bots"
INIOption="@Internal"
CaptionWidth=0.9
bSquare=true
ComponentJustification=TXTA_Left
bVisible=false
End Object
Controls(10)=moCheckbox'NoBotServersCheckBox'
Begin Object class=moComboBox Name=WeaponStayCombo
WinWidth=0.76
WinHeight=0.04
WinLeft=0.05
WinTop=0.57
Caption="WeaponStay"
INIOption="@INTERNAL"
CaptionWidth=0.4
ComponentJustification=TXTA_Left
End Object
Controls(11)=moComboBox'WeaponStayCombo'
Begin Object class=moComboBox Name=TranslocatorCombo
WinWidth=0.76
WinHeight=0.04
WinLeft=0.05
WinTop=0.63
Caption="Translocator"
INIOption="@INTERNAL"
CaptionWidth=0.4
ComponentJustification=TXTA_Left
End Object
Controls(12)=moComboBox'TranslocatorCombo'
Begin Object class=moComboBox Name=MutatorModeCombo2
WinWidth=0.61
WinHeight=0.04
WinLeft=0.05
WinTop=0.51
Caption=""
INIOption="@INTERNAL"
CaptionWidth=0.5
ComponentJustification=TXTA_Left
End Object
Controls(13)=moComboBox'MutatorModeCombo2'
Begin Object class=moComboBox Name=MutatorCombo2
WinWidth=0.308750
WinHeight=0.060000
WinLeft=0.675004
WinTop=0.51
Caption=""
INIOption="@INTERNAL"
CaptionWidth=0.0
ComponentJustification=TXTA_Left
End Object
Controls(14)=moComboBox'MutatorCombo2'
Begin Object class=moNumericEdit Name=MinGamespeed
WinWidth=0.433750
WinHeight=0.060000
WinLeft=0.05
WinTop=0.69
Caption="Game Speed Min"
CaptionWidth=0.7
MinValue=0
MaxValue=200
INIOption="@INTERNAL"
ComponentJustification=TXTA_Left
End Object
Controls(15)=moNumericEdit'MinGamespeed'
Begin Object class=moNumericEdit Name=MaxGamespeed
WinWidth=0.235000
WinHeight=0.060000
WinLeft=0.557501
WinTop=0.69
Caption="Max"
CaptionWidth=0.4
MinValue=0
MaxValue=200
INIOption="@INTERNAL"
ComponentJustification=TXTA_Left
End Object
Controls(16)=moNumericEdit'MaxGamespeed'
ViewStatsStrings(0)="Any Servers"
ViewStatsStrings(1)="Only Stats Servers"
ViewStatsStrings(2)="No Stats Servers"
WeaponStayStrings(0)="Any Servers"
WeaponStayStrings(1)="Only Weapon Stay Servers"
WeaponStayStrings(2)="No Weapon Stay Servers"
TranslocatorStrings(0)="Any Servers"
TranslocatorStrings(1)="Only Translocator Servers"
TranslocatorStrings(2)="No Translocator Servers"
MutatorModeStrings(0)="Any Mutators"
MutatorModeStrings(1)="No Mutators"
MutatorModeStrings(2)="This Mutator"
MutatorModeStrings(3)="Not This Mutator"
}

View file

@ -0,0 +1,126 @@
class Browser_RulesList extends GUIMultiColumnList;
var Browser_ServerListPageBase MyPage;
var Browser_ServersList MyServersList;
var int listitem;
var localized string TrueString;
var localized string FalseString;
var localized string ServerModeString;
var localized string DedicatedString;
var localized string NonDedicatedString;
var localized string AdminNameString;
var localized string AdminEmailString;
var localized string PasswordString;
var localized string GameStatsString;
var localized string GameSpeedString;
var localized string MutatorString;
var localized string BalanceTeamsString;
var localized string PlayersBalanceTeamsString;
var localized string FriendlyFireString;
var localized string GoalScoreString;
var localized string TimeLimitString;
var localized string MinPlayersString;
var localized string TranslocatorString;
var localized string WeaponStayString;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
OnDrawItem = MyOnDrawItem;
OnKeyEvent = InternalOnKeyEvent;
Super.Initcomponent(MyController, MyOwner);
}
function MyOnDrawItem(Canvas Canvas, int i, float X, float Y, float W, float H, bool bSelected, bool bPending)
{
local float CellLeft, CellWidth;
GetCellLeftWidth( 0, CellLeft, CellWidth );
Style.DrawText( Canvas, MenuState, CellLeft, Y, CellWidth, H, TXTA_Left, LocalizeRules(MyServersList.Servers[listitem].ServerInfo[i].Key), FontScale );
GetCellLeftWidth( 1, CellLeft, CellWidth );
Style.DrawText( Canvas, MenuState, CellLeft, Y, CellWidth, H, TXTA_Left, LocalizeRules(MyServersList.Servers[listitem].ServerInfo[i].Value), FontScale );
}
function bool InternalOnKeyEvent(out byte Key, out byte State, float delta)
{
if( Super.InternalOnKeyEvent(Key, State, delta) )
return true;
if( State==1 )
{
switch(Key)
{
case 0x0D: //IK_Enter
MyServersList.Connect(false);
return true;
break;
case 0x74: //IK_F5
MyPage.RefreshList();
return true;
break;
}
}
return false;
}
function string LocalizeRules( string code )
{
switch( caps(code) )
{
case "TRUE": return TrueString;
case "FALSE": return FalseString;
case "SERVERMODE": return ServerModeString;
case "DEDICATED": return DedicatedString;
case "NON-DEDICATED": return NonDedicatedString;
case "ADMINNAME": return AdminNameString;
case "ADMINEMAIL": return AdminEmailString;
case "PASSWORD": return PasswordString;
case "GAMESTATS": return GameStatsString;
case "GAMESPEED": return GameSpeedString;
case "MUTATOR": return MutatorString;
case "BALANCETEAMS": return BalanceTeamsString;
case "PLAYERSBALANCETEAMS": return PlayersBalanceTeamsString;
case "FRIENDLYFIRE": return FriendlyFireString;
case "GOALSCORE": return GoalScoreString;
case "TIMELIMIT": return TimeLimitString;
case "MINPLAYERS": return MinPlayersString;
case "TRANSLOCATOR": return TranslocatorString;
case "WEAPONSTAY": return WeaponStayString;
}
return code;
}
defaultproperties
{
ColumnHeadings(0)="Setting"
ColumnHeadings(1)="Value"
InitColumnPerc(0)=0.25
InitColumnPerc(1)=0.25
ExpandLastColumn=True
TrueString="Enabled"
FalseString="Disabled"
ServerModeString="Server Mode"
DedicatedString="Dedicated"
NonDedicatedString="Non-Dedicated"
AdminNameString="Server Admin"
AdminEmailString="Admin Email"
PasswordString="Requires Password"
// if _RO_
GameStatsString="Killing Floor Stats"
// else
// GameStatsString="UT2004 Stats"
// end if _RO_
GameSpeedString="Game Speed"
MutatorString="Mutator"
BalanceTeamsString="Bots Balance Teams"
PlayersBalanceTeamsString="Balance Teams"
FriendlyFireString="Friendly Fire"
GoalScoreString="Goal Score"
TimeLimitString="Time Limit"
MinPlayersString="Minimum Players (bots)"
TranslocatorString="Translocator"
WeaponStayString="Weapons Stay"
}

View file

@ -0,0 +1,264 @@
// ====================================================================
// Class: XInterface.ServerListPage
// Parent: XInterface.GUITabPanel
//
// <Enter a description here>
// ====================================================================
class Browser_ServerListPageBase extends Browser_Page;
// Internal
var Browser_ServersList MyServersList;
var bool ConnectLAN;
var GUITitleBar StatusBar;
var bool bInitialized;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
if( !bInitialized )
{
MyServersList = Browser_ServersList(GUIMultiColumnListBox(GUIPanel(GUISplitter(Controls[0]).Controls[0]).Controls[0]).Controls[0]);
MyServersList.MyPage = Self;
MyServersList.MyRulesList = Browser_RulesList (GUIMultiColumnListBox(GUIPanel(GUISplitter(GUISplitter(Controls[0]).Controls[1]).Controls[0]).Controls[0]).Controls[0]);
MyServersList.MyPlayersList = Browser_PlayersList(GUIMultiColumnListBox(GUIPanel(GUISplitter(GUISplitter(Controls[0]).Controls[1]).Controls[1]).Controls[0]).Controls[0]);
MyServersList.MyRulesList.MyPage = Self;
MyServersList.MyRulesList.MyServersList = MyServersList;
MyServersList.MyPlayersList.MyPage = Self;
MyServersList.MyPlayersList.MyServersList = MyServersList;
StatusBar = GUITitleBar(GUIPanel(Controls[1]).Controls[5]);
}
StatusBar.SetCaption(ReadyString);
Super.Initcomponent(MyController, MyOwner);
if( !bInitialized )
{
GUIButton(GUIPanel(Controls[1]).Controls[0]).OnClick=BackClick;
GUIButton(GUIPanel(Controls[1]).Controls[1]).OnClick=RefreshClick;
GUIButton(GUIPanel(Controls[1]).Controls[2]).OnClick=JoinClick;
GUIButton(GUIPanel(Controls[1]).Controls[3]).OnClick=SpectateClick;
GUIButton(GUIPanel(Controls[1]).Controls[4]).OnClick=AddFavoriteClick;
}
bInitialized = True;
}
// functions
function RefreshList()
{
}
function PingServer( int i, ServerQueryClient.EPingCause PingCause, GameInfo.ServerResponseLine s )
{
}
function CancelPings()
{
}
// delegates
function bool BackClick(GUIComponent Sender)
{
Controller.CloseMenu(true);
return true;
}
function bool RefreshClick(GUIComponent Sender)
{
RefreshList();
return true;
}
function bool JoinClick(GUIComponent Sender)
{
MyServersList.Connect(false);
return true;
}
function bool SpectateClick(GUIComponent Sender)
{
MyServersList.Connect(true);
return true;
}
function bool AddFavoriteClick(GUIComponent Sender)
{
MyServersList.AddFavorite(Browser);
return true;
}
defaultproperties
{
// Server list box
Begin Object Class=Browser_ServersList Name=TheServersList
End Object
Begin Object Class=GUIMultiColumnListBox Name=ServersListBox
WinLeft=0
WinTop=0
WinWidth=1
WinHeight=1
bVisibleWhenEmpty=True
Controls(0)=TheServersList
StyleName="ServerBrowserGrid"
End Object
// Players list box
Begin Object Class=Browser_PlayersList Name=ThePlayersList
End Object
Begin Object Class=GUIMultiColumnListBox Name=PlayersListBox
WinLeft=0
WinTop=0
WinWidth=1
WinHeight=1
bVisibleWhenEmpty=True
Controls(0)=ThePlayersList
StyleName="ServerBrowserGrid"
End Object
// Rules list box
Begin Object Class=Browser_RulesList Name=TheRulesList
End Object
Begin Object Class=GUIMultiColumnListBox Name=RulesListBox
WinLeft=0
WinTop=0
WinWidth=1
WinHeight=1
bVisibleWhenEmpty=True
Controls(0)=TheRulesList
StyleName="ServerBrowserGrid"
End Object
// Servers panel
Begin Object Class=GUIPanel Name=ServersPanel
Controls(0)=ServersListBox
End Object
// Rules panel
Begin Object Class=GUIPanel Name=RulesPanel
Controls(0)=RulesListBox
End Object
// Players panel
Begin Object Class=GUIPanel Name=PlayersPanel
Controls(0)=PlayersListBox;
End Object
// Splitter to divide players and rules horizontally
Begin Object Class=GUISplitter Name=DetailsSplitter
WinWidth=1.0
WinHeight=1.0
WinTop=0
WinLeft=0
Controls(0)=RulesPanel
Controls(1)=PlayersPanel
SplitOrientation=SPLIT_Horizontal
SplitPosition=0.5
Background=DefaultTexture
End Object
// Splitter to divide main window in two: server list and details
Begin Object Class=GUISplitter Name=MainSplitter
WinWidth=1.0
WinHeight=0.9
WinTop=0
WinLeft=0
Controls(0)=ServersPanel
Controls(1)=DetailsSplitter
SplitOrientation=SPLIT_Vertical
SplitPosition=0.5
End Object
Controls(0)=MainSplitter
Begin Object Class=GUIButton Name=BackButton
Caption="BACK"
StyleName="SquareMenuButton"
WinWidth=0.2
WinLeft=0
WinTop=0
WinHeight=0.5
End Object
Begin Object Class=GUIButton Name=RefreshButton
Caption="REFRESH LIST"
StyleName="SquareMenuButton"
WinWidth=0.2
WinLeft=0.2
WinTop=0
WinHeight=0.5
End Object
Begin Object Class=GUIButton Name=JoinButton
Caption="JOIN"
StyleName="SquareMenuButton"
WinWidth=0.2
WinLeft=0.4
WinTop=0
WinHeight=0.5
End Object
Begin Object Class=GUIButton Name=SpectateButton
Caption="SPECTATE"
StyleName="SquareMenuButton"
WinWidth=0.2
WinLeft=0.6
WinTop=0
WinHeight=0.5
End Object
Begin Object Class=GUIButton Name=AddFavoriteButton
Caption="ADD FAVORITE"
StyleName="SquareMenuButton"
WinWidth=0.2
WinLeft=0.8
WinTop=0
WinHeight=0.5
End Object
Begin Object Class=GUIButton Name=UtilButtonA
Caption=""
StyleName="SquareMenuButton"
WinWidth=0.2
WinLeft=0.6
WinTop=0.5
WinHeight=0.5
End Object
Begin Object Class=GUIButton Name=UtilButtonB
Caption=""
StyleName="SquareMenuButton"
WinWidth=0.2
WinLeft=0.8
WinTop=0.5
WinHeight=0.5
End Object
Begin Object class=GUITitleBar name=MyStatus
WinWidth=0.6
WinHeight=0.5
WinLeft=0
WinTop=0.5
StyleName="SquareBar"
Caption=""
bUseTextHeight=false
Justification=TXTA_Left
End Object
Begin Object Class=GUIPanel Name=FooterPanel
Controls(0)=BackButton
Controls(1)=RefreshButton
Controls(2)=JoinButton
Controls(3)=SpectateButton
Controls(4)=AddFavoriteButton
Controls(5)=MyStatus
Controls(6)=UtilButtonA
Controls(7)=UtilButtonB
WinWidth=1
WinHeight=0.1
WinLeft=0
WinTop=0.9
End Object
Controls(1)=FooterPanel
ConnectLAN=False
}

View file

@ -0,0 +1,154 @@
class Browser_ServerListPageBuddy extends Browser_ServerListPageMS;
// Actual list of buddies
var() config array<String> Buddies;
var GUISplitter MainSplit;
var GUISplitter BudSplit;
var Browser_BuddyList MyBuddyList;
var localized string AddBuddyCaption;
var localized string RemoveBuddyCaption;
var bool BuddyInitialized;
function InitComponent(GUIController C, GUIComponent O)
{
Super.InitComponent(C, O);
if( !BuddyInitialized )
{
MainSplit = GUISplitter(Controls[0]);
// Set one half of the buddy splitter to be the servers panel
BudSplit.Controls[1] = MainSplit.Controls[0];
// Set the buddy splitter as one half of the main splitter
MainSplit.Controls[0] = BudSplit;
// Init the budsplit
BudSplit.InitComponent(C, MainSplit);
}
MyBuddyList = Browser_BuddyList( GUIMultiColumnListBox(GUIPanel(BudSplit.Controls[0]).Controls[0]).Controls[0] );
MyBuddyList.MyBuddyPage = self;
MyBuddyList.ItemCount = Buddies.Length;
// Change server list spacing a bit
MyServersList.InitColumnPerc[0]=0.1;
MyServersList.InitColumnPerc[1]=0.25;
MyServersList.InitColumnPerc[2]=0.15;
MyServersList.InitColumnPerc[3]=0.125;
MyServersList.InitColumnPerc[4]=0.125;
// This page has a REFRESH LIST button
GUIButton(GUIPanel(Controls[1]).Controls[6]).OnClick=MyRefreshClick;
GUIButton(GUIPanel(Controls[1]).Controls[6]).Caption=RefreshCaption;
GUIButton(GUIPanel(Controls[1]).Controls[6]).bVisible=true;
// take over the "Add Favorite" button for "Add Buddy".
GUIButton(GUIPanel(Controls[1]).Controls[7]).OnClick=AddBuddyClick;
GUIButton(GUIPanel(Controls[1]).Controls[7]).Caption=AddBuddyCaption;
// add "Remove Buddy" button
GUIButton(GUIPanel(Controls[1]).Controls[4]).OnClick=RemoveBuddyClick;
GUIButton(GUIPanel(Controls[1]).Controls[4]).Caption=RemoveBuddyCaption;
StatusBar.WinWidth=0.6;
BuddyInitialized = True;
}
function bool MyRefreshClick(GUIComponent Sender)
{
Super.MyRefreshClick(Sender);
return true;
}
function RefreshList()
{
local int i;
local MasterServerClient.QueryData QD;
MyServersList.Clear();
// Construct query containing all buddy names
i = Buddies.Length;
MSC.Query.Length = i;
for(i=0; i<Buddies.Length; i++)
{
QD.Key = "buddy";
QD.Value = Buddies[i];
QD.QueryType = QT_Equals;
MSC.Query[i] = QD;
}
// Run query
MSC.StartQuery(CTM_Query);
StatusBar.SetCaption(StartQueryString);
SetTimer(0, false); // Stop it going back to ready from a previous timer!
}
// Add a new buddy to your list
function bool AddBuddyClick(GUIComponent Sender)
{
if ( Controller.OpenMenu("xinterface.Browser_AddBuddy") )
Browser_AddBuddy(Controller.TopPage()).MyBuddyPage = self;
return true;
}
// Remove current buddy from your list
function bool RemoveBuddyClick(GUIComponent Sender)
{
if(MyBuddyList.Index < 0 || MyBuddyList.Index >= Buddies.Length)
return true;
Buddies.Remove(MyBuddyList.Index, 1);
MyBuddyList.ItemCount = Buddies.Length;
SaveConfig();
return true;
}
defaultproperties
{
// Buddy list box
Begin Object Class=Browser_BuddyList Name=TheBuddyList
End Object
Begin Object Class=GUIMultiColumnListBox Name=BuddyListBox
WinLeft=0
WinTop=0
WinWidth=1
WinHeight=1
bVisibleWhenEmpty=True
Controls(0)=TheBuddyList
StyleName="ServerBrowserGrid"
End Object
// Buddy panel
Begin Object Class=GUIPanel Name=BuddyPanel
Controls(0)=BuddyListBox;
End Object
// Splitter to divide buddies and rules horizontally
Begin Object Class=GUISplitter Name=BuddySplitter
WinWidth=1.0
WinHeight=1.0
WinTop=0
WinLeft=0
Controls(0)=BuddyPanel
SplitOrientation=SPLIT_Horizontal
SplitPosition=0.25
Background=DefaultTexture
bBoundToParent=true
bScaleToParent=true
End Object
BudSplit=BuddySplitter
AddBuddyCaption="ADD BUDDY"
RemoveBuddyCaption="REMOVE BUDDY"
}

View file

@ -0,0 +1,192 @@
class Browser_ServerListPageFavorites extends Browser_ServerListPageBase;
struct FavoritesServerInfo
{
var() config int ServerID;
var() config string IP;
var() config int Port;
var() config int QueryPort;
var() config string ServerName;
};
var() config array<FavoritesServerInfo> Favorites;
var localized string RemoveFavoriteCaption;
var localized string AddIPCaption;
var localized string RePingCaption;
var ServerQueryClient SQC;
var GUIButton MyAddIPButton;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
local int i;
local GameInfo.ServerResponseLine Server;
Super.Initcomponent(MyController, MyOwner);
Browser.OnAddFavorite = MyAddFavorite;
if( SQC == None )
{
SQC = PlayerOwner().Level.Spawn( class'ServerQueryClient' );
SQC.OnReceivedPingInfo = MyServersList.MyReceivedPingInfo;
SQC.OnPingTimeout = MyServersList.MyPingTimeout;
}
MyServersList.Clear();
for( i=0;i<default.Favorites.Length;i++ )
{
FavoriteToServer( i, Server );
MyServersList.MyOnReceivedServer( Server );
}
GUIButton(GUIPanel(Controls[1]).Controls[1]).Caption=RePingCaption;
// take over the "Add Favorite" button.
GUIButton(GUIPanel(Controls[1]).Controls[4]).OnClick=RemoveFavoriteClick;
GUIButton(GUIPanel(Controls[1]).Controls[4]).Caption=RemoveFavoriteCaption;
// 'Add IP' button
GUIButton(GUIPanel(Controls[1]).Controls[7]).OnClick=AddIPClick;
GUIButton(GUIPanel(Controls[1]).Controls[7]).Caption=AddIPCaption;
GUIButton(GUIPanel(Controls[1]).Controls[6]).bVisible=false;
StatusBar.WinWidth=0.8;
// Change server list spacing a bit (no icons)
MyServersList.InitColumnPerc[0]=0.0;
MyServersList.InitColumnPerc[1]=0.47;
MyServersList.InitColumnPerc[2]=0.25;
MyServersList.InitColumnPerc[3]=0.13;
MyServersList.InitColumnPerc[4]=0.15;
}
function bool AddIPClick(GUIComponent Sender)
{
if ( Controller.OpenMenu("xinterface.Browser_OpenIP") )
Browser_OpenIP(Controller.TopPage()).MyFavoritesPage = self;
return true;
}
function RefreshList()
{
MyServersList.InvalidatePings();
MyServersList.AutoPingServers();
}
function ShowPanel(bool bShow)
{
Super.ShowPanel(bShow);
if( bShow )
{
// Resume pings
Log(MyButton.Caption$": Resuming pings");
MyServersList.AutoPingServers();
}
else
{
// Pause pings
Log(MyButton.Caption$": Cancelling pings");
MyServersList.StopPings();
}
}
function CancelPings()
{
SQC.CancelPings();
}
function OnCloseBrowser()
{
if( SQC != None )
{
SaveFavorites();
SQC.CancelPings();
SQC.Destroy();
SQC = None;
}
}
function PingServer( int listid, ServerQueryClient.EPingCause PingCause, GameInfo.ServerResponseLine s )
{
if( PingCause == PC_Clicked )
SQC.PingServer( listid, PingCause, s.IP, s.QueryPort, QI_RulesAndPlayers, s );
else
SQC.PingServer( listid, PingCause, s.IP, s.QueryPort, QI_Ping, s );
}
// Called by the Remove Favorite button
function bool RemoveFavoriteClick(GUIComponent Sender)
{
local int i;
i = MyServersList.RemoveCurrentServer();
if( i >= 0 )
{
default.Favorites.Remove(i,1);
SaveFavorites();
}
return true;
}
function SaveFavorites()
{
local int i;
default.Favorites.Length = MyServersList.Servers.Length;
for( i=0;i<MyServersList.Servers.Length;i++ )
{
default.Favorites[i].ServerID = MyServersList.Servers[i].ServerID;
default.Favorites[i].IP = MyServersList.Servers[i].IP;
default.Favorites[i].Port = MyServersList.Servers[i].Port;
default.Favorites[i].QueryPort = MyServersList.Servers[i].QueryPort;
default.Favorites[i].ServerName = MyServersList.Servers[i].ServerName;
}
StaticSaveConfig();
}
function FavoriteToServer( int i, out GameInfo.ServerResponseLine Server )
{
Server.ServerID = default.Favorites[i].ServerID;
Server.IP = default.Favorites[i].IP;
Server.Port = default.Favorites[i].Port;
Server.QueryPort = default.Favorites[i].QueryPort;
Server.ServerName = default.Favorites[i].ServerName;
}
function MyAddFavorite( GameInfo.ServerResponseLine Server )
{
local int i;
for( i=0;i<default.Favorites.Length;i++ )
if( default.Favorites[i].IP==Server.IP && default.Favorites[i].Port==Server.Port )
return;
MyServersList.MyOnReceivedServer( Server );
SaveFavorites();
}
// Add a favorite from anywhere
static function StaticAddFavorite(String IPString, int port, int queryPort)
{
local int numFavorites;
Log("StaticAddFavorite:"@IPString@port@queryPort);
numFavorites = default.Favorites.Length;
default.Favorites.Length = numFavorites + 1;
default.Favorites[numFavorites].IP = IPString;
default.Favorites[numFavorites].Port = port;
default.Favorites[numFavorites].QueryPort = queryPort;
default.Favorites[numFavorites].ServerName = "Unknown";
StaticSaveConfig();
}
defaultproperties
{
RemoveFavoriteCaption="REMOVE FAVORITE"
AddIPCaption="ADD IP"
RePingCaption="RE-PING LIST"
}

View file

@ -0,0 +1,79 @@
class Browser_ServerListPageLAN extends Browser_ServerListPageBase;
var LANQueryClient LQC;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.Initcomponent(MyController, MyOwner);
GUIButton(GUIPanel(Controls[1]).Controls[6]).bVisible = false;
GUIButton(GUIPanel(Controls[1]).Controls[7]).bVisible = false;
StatusBar.WinWidth=1.0;
if( LQC == None )
{
LQC = PlayerOwner().Level.Spawn( class'LANQueryClient' );
LQC.OnReceivedPingInfo = MyReceivedPingInfo;
LQC.OnPingTimeout = MyServersList.MyPingTimeout;
}
// Change server list spacing a bit (no icons)
MyServersList.InitColumnPerc[0]=0.0;
MyServersList.InitColumnPerc[1]=0.47;
MyServersList.InitColumnPerc[2]=0.25;
MyServersList.InitColumnPerc[3]=0.13;
MyServersList.InitColumnPerc[4]=0.15;
RefreshList();
}
function OnCloseBrowser()
{
if( LQC != None )
{
LQC.Destroy();
LQC = None;
}
}
function MyReceivedPingInfo( int ServerID, ServerQueryClient.EPingCause PingCause, GameInfo.ServerResponseLine s )
{
local int i;
if( ServerID < 0 )
{
for( i=0;i<MyServersList.Servers.Length;i++ )
{
// dupe
if( MyServersList.Servers[i].IP==s.IP && MyServersList.Servers[i].Port==s.Port )
return;
}
MyServersList.MyOnReceivedServer( s );
}
else
{
MyServersList.MyReceivedPingInfo( ServerID, PingCause, s );
}
}
function PingServer( int listid, ServerQueryClient.EPingCause PingCause, GameInfo.ServerResponseLine s )
{
LQC.PingServer( listid, PingCause, s.IP, s.QueryPort, QI_RulesAndPlayers, s );
}
function CancelPings()
{
LQC.CancelPings();
}
function RefreshList()
{
MyServersList.Clear();
CancelPings();
LQC.BroadcastPingRequest();
}
defaultproperties
{
ConnectLAN=True
}

View file

@ -0,0 +1,278 @@
class Browser_ServerListPageMS extends Browser_ServerListPageBase;
var() string GameType;
var() MasterServerClient MSC;
var() bool bStarted;
var localized string QueryFinHead;
var localized string QueryFinTail;
var localized string PingRecvString;
var localized string MustUpgradeString;
var localized string RefreshFinHead, RefreshFinMid, RefreshFinTail;
var localized string RePingServersCaption;
var localized string RefreshCaption;
function AddQueryTerm(string Key, string GameType, MasterServerClient.EQueryType QueryType)
{
local MasterServerClient.QueryData QD;
local int i;
//Log("["$Key$"] ["$GameType$"] ["$QueryType$"]");
QD.Key = Key;
QD.Value = GameType;
QD.QueryType = QueryType;
i = MSC.Query.Length;
MSC.Query.Length = i + 1;
MSC.Query[i] = QD;
}
function RefreshList()
{
local int dotPos;
local string TmpString;
MyServersList.Clear();
// Build query
MSC.Query.Length = 0;
AddQueryTerm("gametype", GameType, QT_Equals);
// Add any extra filtering to the query
if(Browser.bOnlyShowStandard)
AddQueryTerm("standard", "true", QT_Equals);
if(Browser.bOnlyShowNonPassword)
AddQueryTerm("password", "false", QT_Equals);
if(Browser.bDontShowFull)
AddQueryTerm("freespace", "0", QT_GreaterThan);
if(Browser.bDontShowEmpty)
AddQueryTerm("currentplayers", "0", QT_GreaterThan);
if(Browser.StatsServerView == SSV_OnlyStatsEnabled)
AddQueryTerm("stats", "true", QT_Equals);
else if(Browser.StatsServerView == SSV_NoStatsEnabled)
AddQueryTerm("stats", "false", QT_Equals);
// MUTATOR 1
// Send only the stuff to the right of the dot...
dotPos = InStr(Browser.DesiredMutator, ".");
if(dotPos < 0)
TmpString = Browser.DesiredMutator;
else
TmpString = Mid(Browser.DesiredMutator, dotPos + 1);
if(Browser.ViewMutatorMode == VMM_NoMutators)
AddQueryTerm("mutator", "", QT_Equals); // Empty string indicates 'no mutators please'
else if(Browser.ViewMutatorMode == VMM_ThisMutator && TmpString != "")
AddQueryTerm("mutator", TmpString, QT_Equals);
else if(Browser.ViewMutatorMode == VMM_NotThisMutator && TmpString != "")
AddQueryTerm("mutator", TmpString, QT_NotEquals);
// MUTATOR2
dotPos = InStr(Browser.DesiredMutator2, ".");
if(dotPos < 0)
TmpString = Browser.DesiredMutator2;
else
TmpString = Mid(Browser.DesiredMutator2, dotPos + 1);
if( Browser.ViewMutatorMode != VMM_AnyMutators )
{
if(Browser.ViewMutator2Mode == VMM_ThisMutator && TmpString != "")
AddQueryTerm("mutator", TmpString, QT_Equals);
else if(Browser.ViewMutator2Mode == VMM_NotThisMutator && TmpString != "")
AddQueryTerm("mutator", TmpString, QT_NotEquals);
}
if(Browser.bDontShowWithBots)
AddQueryTerm("nobots", "true", QT_Equals);
if(Browser.WeaponStayServerView == WSSV_OnlyWeaponStay)
AddQueryTerm("weaponstay", "true", QT_Equals);
else if(Browser.WeaponStayServerView == WSSV_NoWeaponStay)
AddQueryTerm("weaponstay", "false", QT_Equals);
if(Browser.TranslocServerView == TSV_OnlyTransloc)
AddQueryTerm("transloc", "true", QT_Equals);
else if(Browser.TranslocServerView == TSV_NoTransloc)
AddQueryTerm("transloc", "false", QT_Equals);
// If not entire range (and valid), add game speed query
if( (Browser.MinGamespeed != 0 || Browser.MaxGamespeed != 200) && Browser.MaxGamespeed >= Browser.MinGamespeed )
{
// Master Server stores game speed as 1 = 100% etc
AddQueryTerm("gamespeed", string(float(Browser.MinGamespeed)/100.0), QT_GreaterThanEquals);
AddQueryTerm("gamespeed", string(float(Browser.MaxGamespeed)/100.0), QT_LessThanEquals);
}
if(Browser.CustomQuery != "")
{
TmpString = Left(Browser.CustomQuery, 32); // Only send 32 chars max
AddQueryTerm("custom", TmpString, QT_Equals);
}
MSC.StartQuery(CTM_Query);
StatusBar.SetCaption(StartQueryString);
}
function ShowPanel(bool bShow)
{
Super.ShowPanel(bShow);
if( bShow )
{
if( !bStarted )
{
Log(MyButton.Caption$": Initial refresh");
RefreshList();
bStarted = True;
}
else
{
// Resume pings
Log(MyButton.Caption$": Resuming pings");
MyServersList.AutoPingServers();
}
}
else
{
// Pause pings
Log(MyButton.Caption$": Cancelling pings");
MyServersList.StopPings();
}
}
function OnCloseBrowser()
{
if( MSC != None )
{
MSC.CancelPings();
MSC.Destroy();
MSC = None;
}
}
function PingServer( int listid, ServerQueryClient.EPingCause PingCause, GameInfo.ServerResponseLine s )
{
if( PingCause == PC_Clicked )
MSC.PingServer( listid, PingCause, s.IP, s.QueryPort, QI_RulesAndPlayers, s );
else
MSC.PingServer( listid, PingCause, s.IP, s.QueryPort, QI_Ping, s );
}
function CancelPings()
{
MSC.CancelPings();
}
// Caught for status bar updating
function UpdateStatusPingCount()
{
if(MyServersList.NumReceivedPings < MyServersList.Servers.Length)
{
StatusBar.SetCaption(PingRecvString@"("$MyServersList.NumReceivedPings$"/"$MyServersList.Servers.Length$")");
}
else
{
StatusBar.SetCaption(RefreshFinHead@MyServersList.Servers.Length@RefreshFinMid@MyServersList.NumPlayers@RefreshFinTail);
}
}
function MyReceivedPingInfo( int ServerID, ServerQueryClient.EPingCause PingCause, GameInfo.ServerResponseLine s )
{
MyServersList.MyReceivedPingInfo(ServerID, PingCause, s);
if(PingCause == PC_AutoPing)
UpdateStatusPingCount();
}
function MyPingTimeout( int listid, ServerQueryClient.EPingCause PingCause )
{
MyServersList.MyPingTimeout(listid, PingCause);
if(PingCause == PC_AutoPing)
UpdateStatusPingCount();
}
// We have list of servers from master server and are going to start pinging
function MyQueryFinished( MasterServerClient.EResponseInfo ResponseInfo, int Info )
{
MyServersList.MyQueryFinished(ResponseInfo, Info);
switch( ResponseInfo )
{
case RI_Success:
StatusBar.SetCaption(QueryFinHead$MSC.ResultCount$QueryFinTail);
break;
case RI_AuthenticationFailed:
StatusBar.SetCaption(AuthFailString);
break;
case RI_ConnectionFailed:
StatusBar.SetCaption(ConnFailString);
break;
case RI_ConnectionTimeout:
StatusBar.SetCaption(ConnTimeoutString);
break;
case RI_MustUpgrade:
StatusBar.SetCaption(MustUpgradeString);
break;
}
}
function bool MyRePing(GUIComponent Sender)
{
MyServersList.RePingServers();
return true;
}
function bool MyRefreshClick(GUIComponent Sender)
{
Super.RefreshClick(Sender);
return true;
}
function InitComponent(GUIController C, GUIComponent O)
{
Super.InitComponent(C, O);
if( MSC == None )
{
MSC = PlayerOwner().Level.Spawn( class'MasterServerClient' );
MSC.OnReceivedServer = MyServersList.MyOnReceivedServer;
MSC.OnQueryFinished = MyQueryFinished;
MSC.OnReceivedPingInfo = MyReceivedPingInfo;
MSC.OnPingTimeout = MyPingTimeout;
}
StatusBar.WinWidth = 0.8;
GUIButton(GUIPanel(Controls[1]).Controls[6]).bVisible = false;
GUIButton(GUIPanel(Controls[1]).Controls[1]).Caption = RePingServersCaption;
GUIButton(GUIPanel(Controls[1]).Controls[1]).OnClick = MyRePing;
// Set up REFRESH button
GUIButton(GUIPanel(Controls[1]).Controls[7]).Caption = RefreshCaption;
GUIButton(GUIPanel(Controls[1]).Controls[7]).OnClick = MyRefreshClick;
}
defaultproperties
{
QueryFinHead="Query Complete! Received: "
QueryFinTail=" Servers"
PingRecvString="Pinging Servers"
RefreshFinHead="Pinging Complete! "
RefreshFinMid=" Servers, "
RefreshFinTail=" Players"
RePingServersCaption="RE-PING LIST"
MustUpgradeString="Upgrade available. Please refresh the News page."
RefreshCaption="REFRESH LIST"
}

View file

@ -0,0 +1,203 @@
class Browser_ServerListPageMSCustom extends Browser_ServerListPageMS;
var GUISplitter GameTypeSplit;
var GUIComboBox GameTypeCombo;
var GUISplitter MainSplit;
var bool CustomInitialized;
var config string LastGameType;
function ChangeGameType(GUIComponent Sender)
{
Log( "New Game Type:"$GameTypeCombo.GetText()$" ("$GameTypeCombo.GetExtra()$")" );
GameType = GameTypeCombo.GetExtra();
LastGameType = GameType;
SaveConfig();
RefreshList();
}
// Beginning to think this should be somewhere else :)
function string MyParseDescStr(string DescStr, int index)
{
local string temp;
local int p,i;
i = 0;
while (DescStr!="")
{
p = instr(DescStr,"|");
if (p<0)
{
Temp = DescStr;
DescStr = "";
}
else
{
Temp = Left(DescStr,p);
DescStr = Right(DescStr,Len(DescStr)-p-1);
}
if (i==Index)
return Temp;
i++;
}
}
static function bool IsStandardGameType(string Desc)
{
if( InStr(Desc, "xDeathMatch") >= 0 )
return true;
if( InStr(Desc, "xTeamGame") >= 0 )
return true;
if( InStr(Desc, "xCTFGame") >= 0 )
return true;
if( InStr(Desc, "xBombingRun") >= 0 )
return true;
if( InStr(Desc, "xDoubleDom") >= 0 )
return true;
// Bonus pack game types.. 'forward compatibility'
if( InStr(Desc, "xMutantGame") >= 0 )
return true;
if( InStr(Desc, "xLastManStanding") >= 0 )
return true;
if( InStr(Desc, "Invasion") >= 0 )
return true;
return false;
}
// Find the friendly name for this game type class, by searching the dialog box
function string FindGameTypeName(string GameType)
{
local int i;
for(i=0; i<GameTypeCombo.List.ItemCount; i++)
{
if( GameType == GameTypeCombo.List.GetExtraAtIndex(i) )
return GameTypeCombo.List.GetItemAtIndex(i);
}
Log("CustomTab: Could Not Find Game Type '"$GameType$"' In Combo");
return "";
}
function PopulateGameTypes()
{
local string Entry, Desc, MyGameType, TypeName;
local int Index, PeriodPos;
// Find other game types from .int files, and create tabs
Index = 0;
PlayerOwner().GetNextIntDesc("GameInfo",Index,Entry,Desc);
while (Entry != "")
{
Desc = Entry$"|"$Desc;
if ( !IsStandardGameType(Desc) )
{
MyGameType = MyParseDescStr(Desc, 0);
// strip it down to just the stuff after the '.'
PeriodPos = InStr(MyGameType, ".");
if(PeriodPos != -1)
MyGameType = Mid(MyGameType, PeriodPos+1);
TypeName = MyParseDescStr(Desc, 2);
// Add game type to combo box
GameTypeCombo.AddItem(TypeName, None, MyGameType);
}
Index++;
PlayerOwner().GetNextIntDesc("GameInfo", Index, Entry, Desc);
}
// Default to last used game type (if we find it).
GameType = LastGameType;
GameTypeCombo.SetText( FindGameTypeName(LastGameType) );
}
function InitComponent(GUIController C, GUIComponent O)
{
Super.InitComponent(C, O);
if(!CustomInitialized)
{
MainSplit = GUISplitter(Controls[0]);
MainSplit.WinHeight = 1.0;
// Set the main splitter as one half of this game type splitter
GameTypeSplit.Controls[1] = MainSplit;
// The the game type splitter as the main control on the page
Controls[0] = GameTypeSplit;
// (re)initialise the game type splitter as a child of this page
GameTypeSplit.InitComponent(C, self);
// Set up the game type combo box
GameTypeCombo = GUIComboBox(GUIPanel(GameTypeSplit.Controls[0]).Controls[0]);
PopulateGameTypes();
GameTypeCombo.OnChange = ChangeGameType;
// Done Init
CustomInitialized = true;
}
GameTypeCombo.ReadOnly(true);
}
defaultproperties
{
Begin Object class=GUIComboBox Name=MyGameTypeCombo
WinWidth=0.365000
WinHeight=24.000000
WinLeft=0.615740
WinTop=0.250000
End Object
Begin Object class=GUILabel Name=MyGameTypeLabel
Caption="Game Type"
TextALign=TXTA_Left
TextColor=(R=255,G=255,B=255,A=255)
WinWidth=0.400000
WinHeight=24.000000
WinLeft=0.405117
WinTop=0.283333
End Object
// Buddy panel
Begin Object Class=GUIPanel Name=GameTypePanel
Controls(0)=MyGameTypeCombo
Controls(1)=MyGameTypeLabel
End Object
// Splitter to divide buddies and rules horizontally
Begin Object Class=GUISplitter Name=MyGameTypeSplitter
WinWidth=1.0
WinHeight=0.9
WinTop=0
WinLeft=0
Controls(0)=GameTypePanel
SplitOrientation=SPLIT_Vertical
SplitPosition=0.08
Background=DefaultTexture
bBoundToParent=true
bScaleToParent=true
bFixedSplitter=true
bDrawSplitter=false
End Object
GameTypeSplit=MyGameTypeSplitter
}

View file

@ -0,0 +1,498 @@
class Browser_ServersList extends GUIMultiColumnList;
//#exec OBJ LOAD file=..\Textures\Old2k4\ServerIcons.utx
//#exec Texture Import File=textures\UTClassicIcon.tga Name=S_UTClassic Mips=Off Alpha=1
var() array<GameInfo.ServerResponseLine> Servers;
var Browser_ServerListPageBase MyPage;
var Browser_RulesList MyRulesList;
var Browser_PlayersList MyPlayersList;
var GUIStyles SelStyle;
var array<int> OutstandingPings;
var int UseSimultaneousPings;
var int PingStart;
var int NumReceivedPings;
var int NumPlayers;
//ifdef _KF_
var int MaxPingsPerSecond;
//endif _KF_
var() array<Material> Icons;
var() localized array<String> IconDescriptions;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
local int i;
// let rules/players know about us
MyPlayersList.MyServersList = Self;
MyRulesList.MyServersList = Self;
// set delegates
OnDrawItem = MyOnDrawItem;
OnChange = MyOnChange;
OnDblClick = MyOnDblClick;
Super.Initcomponent(MyController, MyOwner);
SelStyle = Controller.GetStyle("SquareButton",FontScale);
if( Controller.MaxSimultaneousPings == 0 )
{
i = class'Player'.default.ConfiguredInternetSpeed;
if (i<=2600)
UseSimultaneousPings = 10;
else if (i<=5000)
UseSimultaneousPings = 15;
else if (i<=10000)
UseSimultaneousPings = 20;
else
UseSimultaneousPings = 35;
}
else
UseSimultaneousPings = Controller.MaxSimultaneousPings;
//ifdef _KF_
MaxPingsPerSecond = Controller.MaxPingsPerSecond;
//endif _KF_
}
function Clear()
{
PingStart = 0;
StopPings();
Servers.Remove(0,Servers.Length);
ItemCount = 0;
Super.Clear();
}
function CopyServerToClipboard()
{
local string URL;
if( Index >= 0 )
{
URL = PlayerOwner().GetURLProtocol()$"://"$Servers[SortData[Index].SortItem].IP$":"$string(Servers[SortData[Index].SortItem].Port);
PlayerOwner().CopyToClipboard(URL);
}
}
function Connect(bool Spectator)
{
local string URL;
if( Index >= 0 )
{
URL = PlayerOwner().GetURLProtocol()$"://"$Servers[SortData[Index].SortItem].IP$":"$string(Servers[SortData[Index].SortItem].Port);
if( Spectator )
URL = URL $ "?SpectatorOnly=1";
if( MyPage.ConnectLAN )
URL = URL $ "?LAN";
Controller.CloseAll(false);
PlayerOwner().ClientTravel( URL, TRAVEL_Absolute, false );
}
}
function AddFavorite( ServerBrowser Browser )
{
if( Index >= 0 )
Browser.OnAddFavorite( Servers[SortData[Index].SortItem] );
}
function bool MyOnDblClick(GUIComponent Sender)
{
Connect(false);
return true;
}
function bool InternalOnKeyEvent(out byte Key, out byte State, float delta)
{
if( Super.InternalOnKeyEvent(Key, State, delta) )
return true;
if( State==1 )
{
switch(Key)
{
case 0x0D: //IK_Enter
Connect(false);
return true;
break;
case 0x74: //IK_F5
MyPage.RefreshList();
return true;
break;
case 0x43: // IK_C
if(Controller.CtrlPressed)
{
// Ctrl-C on the server list copies selected server to clipboard.
CopyServerToClipboard();
return true;
}
break;
}
}
return false;
}
function MyOnReceivedServer( GameInfo.ServerResponseLine s )
{
local int i;
i = Servers.Length;
Servers.Length=i+1;
Servers[i] = s;
if( Servers[i].Ping == 0 )
Servers[i].Ping = 9999;
ItemCount++;
AddedItem();
}
function MyPingTimeout( int listid, ServerQueryClient.EPingCause PingCause )
{
local int i;
if(listid >= Servers.Length)
return;
if( Servers[listid].Ping == 9999 )
{
Servers[listid].Ping = 10000;
UpdatedItem(listid);
}
// remove from the outstanding ping list
for( i=0;i<OutstandingPings.Length;i++ )
if( OutstandingPings[i] == listid )
{
OutstandingPings.Remove(i,1);
break;
}
// continue pinging
if( PingCause == PC_AutoPing )
{
NumReceivedPings++;
NeedsSorting = True;
AutoPingServers();
}
}
function MyReceivedPingInfo( int listid, ServerQueryClient.EPingCause PingCause, GameInfo.ServerResponseLine s )
{
local int i;
if( listid < 0 )
{
PingStart = 0;
return;
}
Servers[listid] = s;
// see if we can move the ping start marker down
for( i=PingStart;i<listid && i<Servers.Length;i++ )
if( Servers[i].Ping == 9999 )
break;
if( i < listid )
PingStart = listid;
// remove from the outstanding ping list
for( i=0;i<OutstandingPings.Length;i++ )
if( OutstandingPings[i] == listid )
{
OutstandingPings.Remove(i,1);
break;
}
UpdatedItem(listid);
// update rules/player info
if( Index>=0 && listid == SortData[Index].SortItem )
MyOnChange(None);
// continue pinging
if( PingCause == PC_AutoPing )
{
NumReceivedPings++;
NumPlayers += s.CurrentPlayers;
NeedsSorting = True;
AutoPingServers();
}
}
function RePingServers()
{
InvalidatePings();
AutoPingServers();
}
function MyQueryFinished( MasterServerClient.EResponseInfo ResponseInfo, int Info )
{
if( ResponseInfo == RI_Success )
{
RePingServers();
}
}
function InvalidatePings()
{
local int i;
StopPings();
PingStart = 0;
NumReceivedPings=0;
NumPlayers=0;
for( i=0;i<Servers.Length;i++ )
{
Servers[i].Ping = 9999;
UpdatedItem(i);
}
}
function AutoPingServers()
{
local int i, j;
for( i=PingStart;i<Servers.Length && OutstandingPings.Length < UseSimultaneousPings;i++ )
{
if( Servers[i].Ping == 9999 )
{
// see if we already have an outstanding ping for this server.
for( j=0;j<OutstandingPings.Length;j++ )
if( OutstandingPings[j] == i )
break;
if( j == OutstandingPings.Length )
{
// ping
MyPage.PingServer( i, PC_AutoPing, Servers[i] );
// add out outstanding ping list
j = OutstandingPings.Length;
OutstandingPings.Length = j+1;
OutstandingPings[j] = i;
}
}
}
if(OutstandingPings.Length == 0)
NumReceivedPings = Servers.Length;
}
function StopPings()
{
OutstandingPings.Remove(0,OutstandingPings.Length);
MyPage.CancelPings();
}
event Timer()
{
if( Index >= 0 )
MyOnChange( Self );
}
function MyOnChange(GUIComponent Sender)
{
MyRulesList.Clear();
MyPlayersList.Clear();
if( Index >= 0 )
{
// when changing selected servers, get their rules
if( Sender != None )
MyPage.PingServer( SortData[Index].SortItem, PC_Clicked, Servers[SortData[Index].SortItem] );
MyRulesList.ItemCount = Servers[SortData[Index].SortItem].ServerInfo.Length;
MyRulesList.ListItem = SortData[Index].SortItem;
MyPlayersList.ItemCount = Servers[SortData[Index].SortItem].PlayerInfo.Length;
MyPlayersList.ListItem = SortData[Index].SortItem;
SetTimer( 5, false );
}
else
{
MyRulesList.ItemCount = 0;
MyPlayersList.ItemCount = 0;
}
}
function int RemoveCurrentServer()
{
local int OldItem;
if( Index >= 0 )
{
OldItem = SortData[Index].SortItem;
Servers.Remove( OldItem, 1 );
ItemCount--;
MyRulesList.ItemCount = 0;
MyPlayersList.ItemCount = 0;
// tell sort lists.
RemovedCurrent();
return OldItem;
}
return -1;
}
function MyOnDrawItem(Canvas Canvas, int i, float X, float Y, float W, float H, bool bSelected, bool bPending)
{
local float CellLeft, CellWidth, DrawX;
local float IconPosX, IconPosY;
local string Ping;
local int k, flags, checkFlag;
// Draw the selection border
if( bSelected )
SelStyle.Draw(Canvas,MSAT_Pressed, X, Y-2, W, H+2 );
//////////////////////////////////////////////////////////////////////
// Here we get the flags for this server.
// Passworded 1 << 30
// Stats 1 << 29
// LatestVersion 1 << 28
// Listen Server 1 << 27
// Instagib 1 << 26
// Standard 1 << 25
// UT CLassic 1 << 24
// flags are encoded at the top of MaxPlayers
flags = Servers[SortData[i].SortItem].MaxPlayers;
//flags = (1 << 30) | (1 << 29) | (1 << 28) | (1 << 27) | (1 << 26) | (1 << 25); // For testing
//////////////////////////////////////////////////////////////////////
GetCellLeftWidth( 0, CellLeft, CellWidth );
IconPosX = CellLeft;
IconPosY = Y;
// First flag is in the second to most sig bit (dont want to mess with sign bit). Then we work down.
checkFlag = 1 << 30;
// While we still have icon, and we can fit another one in.
for(k=0; (k<Icons.Length) && (IconPosX < CellLeft + CellWidth); k++)
{
if((flags & checkFlag) != 0)
{
DrawX = Min(14, (CellLeft + CellWidth) - IconPosX);
Canvas.DrawColor = Canvas.MakeColor(255, 255, 255, 255);
Canvas.SetPos(IconPosX, IconPosY);
Canvas.DrawTile(Icons[k], DrawX, 14, 0, 0, DrawX+1.0, 15.0);
IconPosX += 14;
}
checkFlag = checkFlag >> 1;
}
GetCellLeftWidth( 1, CellLeft, CellWidth );
Style.DrawText( Canvas, MenuState, CellLeft, Y, CellWidth, H, TXTA_Left, Servers[SortData[i].SortItem].ServerName, FontScale );
GetCellLeftWidth( 2, CellLeft, CellWidth );
Style.DrawText( Canvas, MenuState, CellLeft, Y, CellWidth, H, TXTA_Left, Servers[SortData[i].SortItem].MapName, FontScale );
GetCellLeftWidth( 3, CellLeft, CellWidth );
if( Servers[SortData[i].SortItem].CurrentPlayers>0 || Servers[SortData[i].SortItem].MaxPlayers>0 )
Style.DrawText( Canvas, MenuState, CellLeft, Y, CellWidth, H, TXTA_Left, string(Servers[SortData[i].SortItem].CurrentPlayers)$"/"$string((Servers[SortData[i].SortItem].MaxPlayers&255)), FontScale );
GetCellLeftWidth( 4, CellLeft, CellWidth );
if( Servers[SortData[i].SortItem].Ping == 9999 )
Ping = "?";
else
if( Servers[SortData[i].SortItem].Ping == 10000 )
Ping = "N/A";
else
Ping = string(Servers[SortData[i].SortItem].Ping);
Style.DrawText( Canvas, MenuState, CellLeft, Y, CellWidth, H, TXTA_Left, Ping, FontScale );
// GetCellLeftWidth( 4, CellLeft, CellWidth );
// Style.DrawText( Canvas, MenuState, X+CellLeft, Y, CellWidth, H, TXTA_Left, SortData[i].SortString, FontScale );
}
function string GetSortString( int i )
{
local string s, t;
switch( SortColumn )
{
case 0:
case 1:
s = Left(caps(Servers[i].ServerName), 8);
break;
case 2:
s = Left(caps(Servers[i].MapName), 8);
break;
case 3:
s = string(Servers[i].CurrentPlayers);
while(Len(s) < 4 )
s = "0"$s;
t = string((Servers[i].MaxPlayers&255));
while(Len(t) < 4 )
t = "0"$t;
s = s $ t;
break;
case 4:
s = string(Servers[i].Ping);
while(Len(s) < 5 )
s = "0"$s;
break;
default:
s = string(Servers[i].Ping);
while(Len(s) < 5 )
s = "0"$s;
break;
}
return s;
}
defaultproperties
{
ColumnHeadings(0)=""
ColumnHeadings(1)="Server Name"
ColumnHeadings(2)="Map"
ColumnHeadings(3)="Players"
ColumnHeadings(4)="Ping"
InitColumnPerc(0)=0.10
InitColumnPerc(1)=0.37
InitColumnPerc(2)=0.25
InitColumnPerc(3)=0.13
InitColumnPerc(4)=0.15
SortColumn=4
SortDescending=False
// if _RO_
/*
// end if _RO_
Icons(0)=material'ServerIcons.Password'
IconDescriptions(0)="Passworded"
Icons(1)=material'ServerIcons.Stats'
IconDescriptions(1)="Stats Enabled"
Icons(2)=material'ServerIcons.LatestVersion'
IconDescriptions(2)="Latest Version"
Icons(3)=material'ServerIcons.ListenServer'
IconDescriptions(3)="Listen Server"
Icons(4)=material'ServerIcons.Instagib'
IconDescriptions(4)="Instagib"
Icons(5)=material'ServerIcons.Standard'
IconDescriptions(5)="Standard Server"
Icons(6)=material'xInterface.S_UTClassic'
IconDescriptions(6)="UT Classic"
// if _RO_
*/
// end if _RO_
}

View file

@ -0,0 +1,140 @@
// ====================================================================
// (C) 2002, Epic Games
// ====================================================================
class CoolImage extends GUIComponent
native;
cpptext
{
void Draw(UCanvas* Canvas);
}
struct native init AnimInfo
{
var float cX,cY; // Current X,Y;
var float Scale; // How big is the image
var float FadeTime,Alpha, TargetAlpha; // How quick is the fade
var float ResetDelay; // How long before it appears again
var float TravelTime;
};
var() Material Image; // The Material to Render
var array<AnimInfo> Anims;
var int NoAnims;
var float MaxScale, MinScale;
var float MinFadeTime, MaxFadeTime;
var float MinResetDelay, MaxResetDelay;
var int FullAlpha;
event InitComponent(GUIController MyController, GUIComponent MyOwner)
{
local int i;
Super.InitComponent(MyController,MyOwner);
if (Image==None || NoAnims==0)
return;
Anims.Length = NoAnims;
for (i=0;i<NoAnims;i++)
ResetItem(i);
}
function GetPos(float Scale, out float X, out float y)
{
local float AW, AH;
AW = ActualWidth();
AH = ActualHeight();
switch (Rand(2))
{
case 0: // Left Edge
X = 0;
Y = AH * 1.5 * frand();
if ( y > AH )
Y = y - (AH/2);
break;
case 1:
Y = AH;
X = AW * 1.5 * frand();
if ( x>AW )
x = x - AW;
break;
}
}
function bool DoCollisionTest(int i)
{
local int j;
for (j=0;j<NoAnims;j++)
{
if ( j!=i && TestCollision(i,j) )
return true;
}
return false;
}
function bool TestCollision(int i,int j)
{
local float w,h,l1,l2,r1,r2,t1,t2,b1,b2;
w = Image.MaterialUSize();
h = Image.MaterialVSize();
l1 = Anims[i].cX;
t1 = Anims[i].cY;
r1 = l1 + (W*Anims[i].Scale);
b1 = t1 + (H*Anims[i].Scale);
l2 = Anims[j].cX;
t2 = Anims[j].cY;
r2 = l2 + (W*Anims[j].Scale);
b2 = t2 + (H*Anims[j].Scale);
if (t1 > b2) return false;
if (t2 > b1) return false;
if (l1 > r2) return false;
if (l2 > r1) return false;
return true;
}
event ResetItem(int i)
{
local bool Collide;
local int cnt;
Anims[i].Scale = MinScale + (frand()*(MaxScale-MinScale));
Anims[i].FadeTime = MinFadeTime + (frand()*(MaxFadeTime-MinFadeTime));
Anims[i].ResetDelay = 0; // MinResetDelay + ( frand()*(MaxResetDelay - MinResetDelay));
Anims[i].TargetAlpha = FullAlpha;
Anims[i].Alpha = 0;
Anims[i].TravelTime = 0.25 + (0.25*frand());
Collide = true;
while (Collide)
{
GetPos(Anims[i].Scale,Anims[i].cX,Anims[i].cY);
Collide = DoCollisionTest(i);
if (Collide)
{
cnt++;
if (cnt>20) // Setup for a reset in 1/2 a sec
{
Anims[i].ResetDelay=0.5;
Anims[i].FadeTime=0;
Anims[i].Alpha=0;
Anims[i].TargetAlpha=0;
Collide = false;
}
}
}
}
defaultproperties
{
NoAnims=0
}

View file

@ -0,0 +1,30 @@
//==============================================================================
// Example of custom crosshair package. Loads default crosshairs into game.
//
// Written by Ron Prestenback
// © 2003, Epic Games, Inc. All Rights Reserved
//==============================================================================
class DefaultCrosshairs extends CrosshairPack
notplaceable;
DefaultProperties
{
// if _RO_
Crosshair(0)=(FriendlyName="Cross",CrosshairTexture=Texture'InterfaceArt_tex.Cursors.Crosshair_Cross2')
// else
// Crosshair(0)=(FriendlyName="Cross (1)",CrosshairTexture=Texture'Crosshairs.Hud.Crosshair_Cross1')
// Crosshair(1)=(FriendlyName="Cross (2)",CrosshairTexture=Texture'Crosshairs.Hud.Crosshair_Cross2')
// Crosshair(2)=(FriendlyName="Cross (3)",CrosshairTexture=Texture'Crosshairs.Hud.Crosshair_Cross3')
// Crosshair(3)=(FriendlyName="Cross (4)",CrosshairTexture=Texture'Crosshairs.Hud.Crosshair_Cross4')
// Crosshair(4)=(FriendlyName="Cross (5)",CrosshairTexture=Texture'Crosshairs.Hud.Crosshair_Cross5')
// Crosshair(5)=(FriendlyName="Dot",CrosshairTexture=Texture'Crosshairs.Hud.Crosshair_Dot')
// Crosshair(6)=(FriendlyName="Pointer",CrosshairTexture=Texture'Crosshairs.Hud.Crosshair_Pointer')
// Crosshair(7)=(FriendlyName="Triad (1)",CrosshairTexture=Texture'Crosshairs.Hud.Crosshair_Triad1')
// Crosshair(8)=(FriendlyName="Triad (2)",CrosshairTexture=Texture'Crosshairs.Hud.Crosshair_Triad2')
// Crosshair(9)=(FriendlyName="Triad (3)",CrosshairTexture=Texture'Crosshairs.Hud.Crosshair_Triad3')
// Crosshair(10)=(FriendlyName="Bracket (1)",CrosshairTexture=Texture'Crosshairs.Hud.Crosshair_Bracket1')
// Crosshair(11)=(FriendlyName="Bracket (2)",CrosshairTexture=Texture'Crosshairs.Hud.Crosshair_Bracket2')
// Crosshair(12)=(FriendlyName="Circle (1)",CrosshairTexture=Texture'Crosshairs.Hud.Crosshair_Circle1')
// Crosshair(13)=(FriendlyName="Circle (2)",CrosshairTexture=Texture'Crosshairs.Hud.Crosshair_Circle2')
// end if _RO_
}

View file

@ -0,0 +1,60 @@
class DrawOpBase extends Object;
var float Top, Lft, Height, Width; // Location/size is always range 0.0 to 1.0
var byte RenderStyle; // Render Style to use for this particular Image
var byte Justification; // 0 - Left/Top 1 - Centered 2 - Right/Bottom
var Color DrawColor; // Color to set Canvas to.
function SetPos(float T, float L)
{
Top = T;
Lft = L;
}
function SetSize(float H, float W)
{
Height = H;
Width = W;
}
function Draw(Canvas Canvas)
{
Canvas.SetPos(Lft * Canvas.SizeX, Top * Canvas.SizeY);
Canvas.Style = RenderStyle;
Canvas.DrawColor = DrawColor;
}
simulated function Font GetFont(string FontClassName, float ResX)
{
local Font fnt;
fnt = GetGUIFont(FontClassName, ResX);
if ( fnt == None )
fnt = Font(DynamicLoadObject(FontClassName, class'Font'));
if ( fnt == None )
log(Name$" - FONT NOT FOUND '"$FontClassName$"'",'Error');
return fnt;
}
simulated function Font GetGUIFont( string FontClassName, float ResX )
{
local class<GUIFont> FntCls;
local GUIFont Fnt;
FntCls = class<GUIFont>(DynamicLoadObject(FontClassName, class'Class',True));
if (FntCls != None)
Fnt = new(None) FntCls;
if ( Fnt == None )
return None;
return Fnt.GetFont(ResX);
}
defaultproperties
{
DrawColor=(R=255,G=255,B=255,A=255)
RenderStyle=1
}

View file

@ -0,0 +1,78 @@
class DrawOpImage extends DrawOpBase
DependsOn(GUI);
var Material Image;
var byte ImageStyle;
var float SubX, SubY, SubXL, SubYL; // coordinates on Image
var deprecated bool bStretch; // Stretch the picture;
function Draw(Canvas Canvas)
{
local float X, Y, XL, YL, U, V, UL, VL;
if ( Image == None )
return;
Canvas.Style = RenderStyle;
Canvas.DrawColor = DrawColor;
X = Lft * Canvas.SizeX;
Y = Top * Canvas.SizeY;
if ( Width < 0 )
XL = Image.MaterialUSize();
else XL = Width * Canvas.SizeX;
if ( Height < 0 )
YL = Image.MaterialVSize();
else YL = Height * Canvas.SizeY;
U = FMax(0, SubX);
V = FMax(0, SubY);
if ( SubXL < 0 )
UL = Image.MaterialUSize();
else
UL = SubXL;
if ( SubYL < 0 )
VL = Image.MaterialVSize();
else
VL = SubYL;
if ( Justification == 1 )
{
X -= XL / 2;
Y -= YL / 2;
}
else if ( Justification == 2 )
{
X -= XL;
Y -= YL;
}
Canvas.SetPos(X,Y);
switch ( ImageStyle )
{
case 0: // Normal (scaled to fit)
Canvas.DrawTile( Image, XL, YL, U, V, UL, VL );
break;
case 1: // Stretched
Canvas.DrawTileStretched(Image,XL,YL);
break;
case 2: // Bound
Canvas.DrawTileClipped( Image, XL, YL, U, V, UL, VL );
break;
}
//Log("DrawOpImage.Draw Called");
}
defaultproperties
{
SubX=-1
SubY=-1
SubXL=-1
SubYL=-1
}

View file

@ -0,0 +1,78 @@
class DrawOpText extends DrawOpBase;
var localized string Text;
var string FontName; // Font to use
var int MaxLines; // In case a multiline is too tall.
/** set to true to wrap text on "|" */
var bool bWrapText;
var byte VertAlign;
function Draw(Canvas Canvas)
{
local Font Fnt;
local int i;
local float X, Y, XL, YL, TextHeight, StrHeight, StrWidth;
local array<string> Lines;
Super.Draw(Canvas);
if (FontName != "")
{
Fnt = GetFont(FontName, Canvas.SizeX);
if (Fnt != None)
Canvas.Font = Fnt;
}
Canvas.FontScaleX = 0.9;
Canvas.FontScaleY = 0.9;
X = Lft * Canvas.SizeX;
Y = Top * Canvas.SizeY;
XL = Width * Canvas.SizeX;
YL = Height * Canvas.SizeY;
Canvas.StrLen(Text, StrWidth, StrHeight);
if (bWrapText) Canvas.WrapStringToArray(Text, Lines, XL, "|");
else Lines[0] = Text;
TextHeight = StrHeight * Lines.length;
switch ( VertAlign )
{
case 1: // Center
Y = Y + (YL - TextHeight) / 2;
break;
case 2: // Bottom
Y = Y + YL - TextHeight;
break;
}
for ( i = 0; i < Lines.Length; i++ )
{
Canvas.StrLen(Lines[i], StrWidth, StrHeight);
switch ( Justification )
{
case 0: // left
Canvas.SetPos(X, Y);
break;
case 1: // center
Canvas.SetPos(X + (XL - StrWidth) / 2, Y);
break;
case 2: // right
Canvas.SetPos(X + XL - StrWidth, Y);
break;
}
Canvas.DrawText(Lines[i]);
Y += StrHeight;
}
}
defaultproperties
{
bWrapText=true
MaxLines=99
FontName="XInterface.UT2DefaultFont"
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,27 @@
//==============================================================================
// Created on: 10/10/2003
// This is a GUIImage that is not full screen, but should render beneath everything else
//
// Written by Ron Prestenback
// © 2003, Epic Games, Inc. All Rights Reserved
//==============================================================================
class FloatingImage extends GUIImage;
DefaultProperties
{
RenderWeight=0.000001
WinTop=0.375
WinHeight=0.35
WinWidth=0.5
WinLeft=0.25
ImageStyle=ISTY_PartialScaled
DropShadow=Texture'InterfaceArt_tex.Menu.changeme_texture' //Material'2K4Menus.Floating.FloatingShadow'
DropShadowX=6
DropShadowY=6
bBoundToParent=True
bScaleToParent=True
}

View file

@ -0,0 +1,285 @@
// ====================================================================
// 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
{
virtual void SaveCanvasState(UCanvas* Canvas); // Save the current state of the canvas
virtual void RestoreCanvasState(UCanvas* Canvas); // Restores the state of the canvas
}
// 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);

View file

@ -0,0 +1,40 @@
//==============================================================================
// Created on: 01/06/2004
// Base class for header and footers
//
// Written by Ron Prestenback
// © 2003, Epic Games, Inc. All Rights Reserved
//==============================================================================
class GUIBorder extends GUIMultiComponent
native;
cpptext
{
void Draw(UCanvas* Canvas);
}
var() localized string Caption; // The caption that get's displayed in here
var() eTextAlign Justification; // How to draw
var() int TextIndent; // Indent caption by this much
function SetCaption( string NewCaption )
{
Caption = NewCaption;
}
function string GetCaption()
{
return Caption;
}
DefaultProperties
{
Justification=TXTA_Center
TextIndent=20
StyleName="Footer"
bNeverFocus=True
PropagateVisibility=True
bRequiresStyle=True
}

View file

@ -0,0 +1,78 @@
// ====================================================================
// Class: UT2K4UI.GUIButton
//
// GUIButton - The basic button class
//
// Written by Joe Wilcox
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIButton extends GUIComponent
Native;
cpptext
{
void PreDraw(UCanvas* Canvas);
void Draw(UCanvas* Canvas);
}
var() eTextAlign CaptionAlign;
var() editconst GUIStyles CaptionEffectStyle;
var() string CaptionEffectStyleName;
var() localized string Caption;
var() struct native PaddingPercent
{ var() float HorzPerc, VertPerc; } AutoSizePadding; // Padding (space) to insert around caption if autosizing
// When multiple buttons should be the same size, set this value to the longest caption of the group
// and all buttons will be sized using this caption instead
var() string SizingCaption;
var() bool bAutoSize; // Size according to caption size.
var() bool bAutoShrink; // Reduce size of button if bAutoSize & caption is smaller than WinWidth
var() bool bWrapCaption; // Wrap the caption if its too long - ignored if bAutoSize = true
var() bool bUseCaptionHeight; // Get the Height from the caption
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
local eFontScale x;
Super.InitComponent(MyController, MyOwner);
if (CaptionEffectStyleName!="")
CaptionEffectStyle = Controller.GetStyle(CaptionEffectStyleName,x);
}
function bool InternalOnKeyEvent(out byte Key, out byte State, float delta)
{
if ((key==0x0D || Key == 0x20) && State==1) // ENTER or Space Pressed
{
OnClick(self);
return true;
}
return false;
}
defaultproperties
{
OnKeyEvent=InternalOnKeyEvent
StyleName="SquareButton"
bAcceptsInput=true
bCaptureMouse=True
bNeverFocus=false
bTabStop=true
WinHeight=0.04
bMouseOverSound=true
OnClickSound=CS_Click
CaptionEffectStyleName=""
CaptionAlign=TXTA_Center
AutoSizePadding=(HorzPerc=0.125)
StandardHeight=0.04
bAutoShrink=true
Begin Object Class=GUIToolTip Name=GUIButtonToolTip
End Object
ToolTip=GUIButtonToolTip
bUseCaptionHeight=false
}

View file

@ -0,0 +1,328 @@
// ====================================================================
// Class: UT2K4UI.GUICharacterList
// Parent: UT2K4UI.GUIHorzList
//
// <Enter a description here>
// ====================================================================
class GUICharacterList extends GUICircularList
Native;
cpptext
{
void PreDraw(UCanvas* Canvas);
protected:
void DrawItem(UCanvas* Canvas, INT Item, FLOAT X, FLOAT Y, FLOAT XL, FLOAT YL, UBOOL bSelected, UBOOL bPending);
public:
}
var() array<xUtil.PlayerRecord> PlayerList;
var() bool bLocked;
var() Material DefaultPortrait; // Image used for unused entries
var() array<xUtil.PlayerRecord> SelectedElements;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.Initcomponent(MyController, MyOwner);
InitList();
}
function InitList()
{
local int i;
local array<xUtil.PlayerRecord> AllPlayerList;
class'xUtil'.static.GetPlayerList(AllPlayerList);
// Filter out 'duplicate' characters - only used in single player
for(i=0; i<AllPlayerList.Length; i++)
{
if(AllPlayerList[i].Menu != "DUP")
PlayerList[PlayerList.Length] = AllPlayerList[i];
}
ItemCount = PlayerList.Length;
}
// Accessor function for the items.
function string SelectedText()
{
if ( (Index >=0) && (Index <ItemCount) )
return PlayerList[Index].DefaultName;
return "";
}
function bool ValidIndex(int i)
{
return i >= 0 && i < PlayerList.Length;
}
function Add(string NewItem, optional Object obj)
{
return; // GUICharacterLists can not be modifed at runtime
}
function Remove(int i, optional int Count)
{
return; // GUICharacterLists can not be modifed at runtime
}
function Clear()
{
return; // GUICharacterLists can not be modifed at runtime
}
function Find(string Text, optional bool bExact)
{
local int i;
for (i=0;i<ItemCount;i++)
{
if (bExact)
{
if (Text == PlayerList[i].DefaultName)
{
Index = i;
Top = i;
OnChange(self);
return;
}
}
else
{
if (Text ~= PlayerList[i].DefaultName)
{
Index = i;
Top = i;
OnChange(self);
return;
}
}
}
}
function material GetPortrait()
{
return PlayerList[Index].Portrait;
}
function Material GetPortraitAt(int i)
{
if (ValidIndex(i))
return PlayerList[i].Portrait;
return None;
}
function string GetName()
{
return PlayerList[Index].DefaultName;
}
function string GetNameAt(int i)
{
if (ValidIndex(i))
return PlayerList[i].DefaultName;
return "";
}
function string GetGender()
{
return PlayerList[Index].Sex;
}
function string GetGenderAt(int i)
{
if ( ValidIndex(i) )
return PlayerList[i].Sex;
return "";
}
function xUtil.PlayerRecord GetRecord()
{
return PlayerList[Index];
}
function xUtil.PlayerRecord GetRecordAt(int i)
{
local xUtil.PlayerRecord Rec;
if (ValidIndex(i))
Rec = PlayerList[i];
return Rec;
}
function string GetDecoText()
{
return GetDecoTextAt(Index);
}
function string GetDecoTextAt(int AtIndex)
{
local string S;
if (ValidIndex(AtIndex))
S = PlayerList[AtIndex].TextName;
return S;
}
function sound GetSound()
{
local sound NameSound;
local string SoundName;
SoundName = "AnnouncerNames." $ Repl(PlayerList[Index].DefaultName, ".", "_");
/* // Use the player name, with periods replaced with underscores, as sound name
DefName = PlayerList[Index].DefaultName;
PeriodPos = InStr(DefName, ".");
while(PeriodPos != -1)
{
DefName = Left(DefName, PeriodPos)$"_"$Mid(DefName, PeriodPos+1);
PeriodPos = InStr(DefName, ".");
}
SoundName = "AnnouncerNames."$DefName; // TODO Is this still applicable?
*/
NameSound = sound(DynamicLoadObject(SoundName, class'Sound'));
if(NameSound == None)
Log("Could not find player name sound for: "$PlayerList[Index].DefaultName);
return NameSound;
}
function Sound GetSoundAt(int i)
{
local sound NameSound;
local string SoundName;
if (ValidIndex(i))
{
SoundName = "AnnouncerNames." $ Repl(PlayerList[i].DefaultName, ".", "_");
NameSound = Sound(DynamicLoadObject(SoundName, class'Sound'));
if (NameSound == None)
log("Could not find player name sound for:"@PlayerList[i].DefaultName);
}
return NameSound;
}
function ScrollRight()
{
MoveRight();
}
function ScrollLeft()
{
MoveLeft();
}
function bool MoveLeft()
{
if (bLocked)
{
if ( Index > 0 )
{
Index--;
OnChange(Self);
}
return true;
}
else return Super.MoveLeft();
}
function bool MoveRight()
{
if (bLocked)
{
if (Index<ItemsPerPage-1)
{
Index++;
OnChange(Self);
}
return true;
}
else return Super.MoveRight();
}
function End()
{
if (bLocked)
{
Index = ItemsPerPage-1;
OnChange(Self);
}
else
Super.End();
}
function ClearPendingElements()
{
Super.ClearPendingElements();
if ( SelectedItems.Length == 0 )
SelectedElements.Remove(0, SelectedElements.Length);
}
function array<xUtil.PlayerRecord> GetPendingElements( optional bool bGuarantee )
{
local int i;
if ( (DropState == DRP_Source && Controller.DropSource == Self) || bGuarantee )
{
if ( SelectedElements.Length == 0 )
{
for (i = 0; i < SelectedItems.Length; i++)
if (ValidIndex(SelectedItems[i]))
SelectedElements[SelectedElements.Length] = PlayerList[SelectedItems[i]];
if ( SelectedElements.Length == 0 && IsValid() )
SelectedElements[0] = PlayerList[Index];
}
return SelectedElements;
}
}
function bool InternalOnBeginDrag(GUIComponent Sender)
{
if ( Super.InternalOnBeginDrag(Sender) )
{
SelectedElements = GetPendingElements();
return true;
}
return false;
}
// Called on the drop source when when an Item has been dropped. bAccepted tells it whether
// the operation was successful or not.
function InternalOnEndDrag(GUIComponent Accepting, bool bAccepted)
{
// Pending items were dropped somewhere - list cannot be modified at runtime
if (bAccepted && Accepting != None)
bRepeatClick = False;
// If the drag-n-drop wasn't accepted, set bRepeatClick to True so that ClearPendingElements()
// won't clear the SelectedItems array - we may want to retry to drag-n-drop
if (Accepting == None)
bRepeatClick = True;
SetOutlineAlpha(255);
if ( bNotify )
CheckLinkedObjects(Self);
}
// Cannot add to CharacterList at runtime
function bool InternalOnDragDrop(GUIComponent Sender)
{
InternalOnMouseRelease(Sender);
return false;
}

View file

@ -0,0 +1,137 @@
// ====================================================================
// Class: UT2K4UI.GUICharacterListTeam
// Parent: UT2K4UI.GUICharacterList
//
// Specialized version of charlist that allows manual addition/
// removal of players.
// author: capps 8/25/02
// ====================================================================
class GUICharacterListTeam extends GUICharacterList;
function InitList()
{
ItemCount = 0;
}
/** Include only those players described with Menu=s */
function InitListInclusive(string s) {
local int i,j;
local array<xUtil.PlayerRecord> AllPlayerList;
class'xUtil'.static.GetPlayerList(AllPlayerList);
// Filter out to only characters with the 's' menu setting
j=0;
for(i=0; i<AllPlayerList.Length; i++)
{
if(AllPlayerList[i].Menu == s)
PlayerList[j++] = AllPlayerList[i];
}
ItemCount = j;
Index = 0;
}
/** Include all players except those described with Menu=s */
function InitListIncl(array<string> menus, optional string Race) {
local int i,j;
local array<xUtil.PlayerRecord> AllPlayerList;
local string menulist;
menulist = ";"$JoinArray(menus, ";")$";";
class'xUtil'.static.GetPlayerList(AllPlayerList);
// Filter out to only characters without the 's' menu setting
j=0;
for(i=0; i<AllPlayerList.Length; i++)
{
if ( InStr(menulist, ";"$AllPlayerList[i].Menu$";") != -1 && (Race=="" || (Caps(AllPlayerList[i].Species.default.SpeciesName)==Race)) )
PlayerList[j++] = AllPlayerList[i];
}
ItemCount = j;
Index = 0;
}
/** Include all players except those described with Menu=s */
function InitListExclusive(string s, optional string s2) {
local int i,j;
local array<xUtil.PlayerRecord> AllPlayerList;
class'xUtil'.static.GetPlayerList(AllPlayerList);
// Filter out to only characters without the 's' menu setting
j=0;
for(i=0; i<AllPlayerList.Length; i++)
{
if( (AllPlayerList[i].Menu != s) &&
( (s2 == "") ||
(s2 != "" && AllPlayerList[i].Menu != s2))) // if s2 isn't empty, use it as a filter too
PlayerList[j++] = AllPlayerList[i];
}
ItemCount = j;
Index = 0;
}
/** Include all players except those described with Menu=s */
function InitListExcl(array<string> menus, optional string Race) {
local int i,j;
local array<xUtil.PlayerRecord> AllPlayerList;
local string menulist;
menulist = ";"$JoinArray(menus, ";")$";";
class'xUtil'.static.GetPlayerList(AllPlayerList);
// Filter out to only characters without the 's' menu setting
j=0;
for(i=0; i<AllPlayerList.Length; i++)
{
if ( InStr(menulist, ";"$AllPlayerList[i].Menu$";") == -1 && (Race=="" || (Caps(AllPlayerList[i].Species.default.SpeciesName)==Race)) )
PlayerList[j++] = AllPlayerList[i];
}
ItemCount = j;
Index = 0;
}
/** Populate list with Player team members */
function ResetList(array<xUtil.PlayerRecord> PlayerTeam, int numchars)
{
local int i;
if ( PlayerTeam.Length < numchars ) {
Log("GUICharacterListTeam::ResetList() could not reset list; invalid team.");
return;
}
for ( i=0; i < numchars; i++ ) {
PlayerList[i] = PlayerTeam[i];
}
ItemCount = numchars;
}
/** populate the player list based on default player names */
function PopulateList(array<string> PlayerNames)
{
local int i, j;
local array<xUtil.PlayerRecord> PRlist;
PlayerList.length = PlayerNames.length;
class'xUtil'.static.GetPlayerList(PRlist);
for (i = 0; i < PlayerNames.length; i++)
{
for (j = 0; j < PRlist.length; j++)
{
if (PlayerNames[i] ~= PRlist[j].DefaultName)
{
PlayerList[i] = PRlist[j];
break;
}
}
}
ItemCount = PlayerNames.length;
}

View file

@ -0,0 +1,46 @@
// ====================================================================
// Class: UT2K4UI.GUIGFXButton
//
// Written by Joe Wilcox
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUICheckBoxButton extends GUIGFXButton
Native;
cpptext
{
void Draw(UCanvas* Canvas);
}
var() Material CheckedOverlay[10];
var() bool bAllOverlay;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
local int i;
Super.InitComponent(MyController, MyOwner);
for ( i = 0; i < ArrayCount(CheckedOverlay); i++ )
{
if ( CheckedOverlay[i] == None )
CheckedOverlay[i] = Graphic;
}
}
defaultproperties
{
CheckedOverlay(0)=Texture'KF_InterfaceArt_tex.Menu.CheckBox'
CheckedOverlay(1)=Texture'KF_InterfaceArt_tex.Menu.checkbox_highlight'
CheckedOverlay(2)=Texture'KF_InterfaceArt_tex.Menu.CheckBox'
CheckedOverlay(3)=Texture'KF_InterfaceArt_tex.Menu.CheckBox'
CheckedOverlay(4)=Texture'KF_InterfaceArt_tex.Menu.CheckBox'
bCheckBox=true
Position=ICP_Scaled
bRepeatClick=false
bTabStop=true
StyleName="CheckBox"
ImageIndex=4
}

View file

@ -0,0 +1,409 @@
//==============================================================================
// Created on: 09/16/2003
// Support for creating circular lists like the character lists, using other materials
//
// Written by Ron Prestenback
// © 2003, Epic Games, Inc. All Rights Reserved
//==============================================================================
class GUICircularImageList extends GUICircularList
native;
cpptext
{
void PreDraw(UCanvas* Canvas);
protected:
void DrawItem(UCanvas* Canvas, INT Item, FLOAT X, FLOAT Y, FLOAT W, FLOAT HT, UBOOL bSelected, UBOOL bPending);
public:
}
var() editconst editconstarray protected array<GUIListElem> Elements;
function Add( Material Img, optional string Str )
{
local int NewIndex;
if ( !bAllowEmptyItems && Img == None && Str == "" )
return;
if (bSorted && Elements.Length > 0)
{
while (NewIndex < Elements.Length && Elements[NewIndex].Item < Str)
NewIndex++;
}
else NewIndex = Elements.Length;
Elements.Insert(NewIndex, 1);
Elements[NewIndex].Item = Str;
Elements[NewIndex].ExtraData = Img;
ItemCount = Elements.Length;
if (Elements.Length == 1 && bInitializeList)
SetIndex(0);
else CheckLinkedObjects(Self);
}
function Replace(int i, Material Img, optional string Str)
{
if ( !IsValidIndex(i) )
Add(img,Str);
else
{
if ( !bAllowEmptyItems && img == None && Str == "" )
return;
Elements[i].Item = Str;
Elements[i].ExtraData = img;
if ( bNotify )
OnChange(self);
}
}
function Insert(int i, Material Img, optional string Str)
{
if ( !IsValidIndex(i) )
Add(Img,Str);
else
{
if ( !bAllowEmptyItems && Img == None && Str == "" )
return;
Elements.Insert(i,1);
Elements[i].Item=Str;
Elements[i].ExtraData=Img;
ItemCount=Elements.Length;
if ( bNotify )
OnChange(self);
}
}
event Swap(int IndexA, int IndexB)
{
local GUI.GUIListElem elem;
if ( IsValidIndex(IndexA) && IsValidIndex(IndexB) )
{
elem = Elements[IndexA];
Elements[IndexA] = Elements[IndexB];
Elements[IndexB] = elem;
}
}
function LoadFrom(GUICircularImageList Source, optional bool bClearFirst)
{
local string t1,t2;
local object obj;
local int i;
if (bClearfirst)
Clear();
for (i=0;i<Source.Elements.Length;i++)
{
Source.GetAtIndex(i,t1,obj,t2);
Add(material(obj),t1);
}
}
function int RemoveSilent(int i, optional int Count)
{
bNotify = False;
i = Remove(i, Count);
bNotify = True;
return i;
}
function int Remove(int i, optional int Count)
{
Count = Max( Count, 1 );
if (!IsValidIndex(i))
return Index;
Elements.Remove(i, Min(Count, Elements.Length - i));
ItemCount = Elements.Length;
// In case we now have an invalid index
SetIndex(Index);
return Index;
}
function int RemoveElement(GUIListElem Elem, optional int Count)
{
local int i;
Count = Max(Count, 1);
for ( i = 0; i < Elements.Length; i++ )
{
if ( Elements[i] == Elem )
{
Elements.Remove(i, Min(Count, Elements.Length - i));
break;
}
}
ItemCount = Elements.Length;
// In case we now have an invalid index
SetIndex(Index);
return Index;
}
function Clear()
{
if (Elements.Length == 0)
return;
Elements.Remove(0,Elements.Length);
ItemCount = 0;
Super.Clear();
}
//##############################################################################
//
// Query functions
//
// Current listitem
function string Get(optional bool bGuarantee)
{
if ( !IsValid() )
{
if (bGuarantee && Elements.Length > 0)
return Elements[0].Item;
return "";
}
return Elements[Index].Item;
}
function Material GetImage(optional bool bGuarantee)
{
if ( !IsValid() )
{
if ( bGuarantee && Elements.Length > 0 )
return Material(Elements[0].ExtraData);
return none;
}
return Material(Elements[Index].ExtraData);
}
// Arbitrary list Item
function string GetItemAtIndex(int i)
{
if (!IsValidIndex(i))
return "";
return Elements[i].Item;
}
function Material GetImageAtIndex(int i)
{
if (!IsValidIndex(i))
return None;
return Material(Elements[i].ExtraData);
}
function GetAtIndex(int i, out string ItemStr, out Object Img, out string ExtraStr)
{
if (!IsValidIndex(i))
return;
ItemStr = Elements[i].Item;
Img = Elements[i].ExtraData;
ExtraStr = Elements[i].ExtraStrData;
}
// Specify true for bGuarantee to receive the selected item if there are no "pending" items
function array<string> GetPendingItems(optional bool bGuarantee)
{
local int i;
local array<string> Items;
if ( (DropState == DRP_Source && Controller.DropSource == Self ) || bGuarantee )
{
for ( i = 0; i < SelectedItems.Length; i++ )
if ( IsValidIndex(SelectedItems[i]) )
Items[Items.Length] = Elements[SelectedItems[i]].Item;
if ( Items.Length == 0 && IsValid() )
Items[0] = Get();
}
return Items;
}
function array<GUIListElem> GetPendingElements(optional bool bGuarantee)
{
local int i;
local array<GUIListElem> PendingItem;
if ( (DropState == DRP_Source && Controller.DropSource == Self) || bGuarantee )
{
for (i = 0; i < SelectedItems.Length; i++)
if (IsValidIndex(SelectedItems[i]))
PendingItem[PendingItem.Length] = Elements[SelectedItems[i]];
if ( PendingItem.Length == 0 && IsValid() )
{
PendingItem.Length = PendingItem.Length + 1;
GetAtIndex(Index, PendingItem[0].Item, PendingItem[0].ExtraData, PendingItem[0].ExtraStrData);
}
}
return PendingItem;
}
//##############################################################################
//
// Assignment functions
//
function SetItemAtIndex(int i, string NewItem)
{
if (!IsValidIndex(i))
return;
Elements[i].Item = NewItem;
}
function SetImageAtIndex(int i, Material Img)
{
if (!IsValidIndex(i))
return;
Elements[i].ExtraData = Img;
}
function RemoveItem(string Item)
{
local int i;
// Work through array. If we find it, remove it (will reduce Elements.Length).
// If we don't, move on to next one.
while( i < Elements.Length)
{
if(Item ~= Elements[i].Item)
Elements.Remove(i, 1);
else
i++;
}
ItemCount = Elements.Length;
SetIndex(-1);
}
function RemoveImage(Material Img)
{
local int i;
while (i < Elements.Length)
{
if (Img == Elements[i].ExtraData)
Elements.Remove(i, 1);
else i++;
}
ItemCount = Elements.Length;
SetIndex(-1);
}
//##############################################################################
//
// Search functions
//
function int FindIndex(Material Img, optional string Test)
{
local int i;
if (Img != None)
{
for (i = 0; i < Elements.Length; i++)
if ( Img == Elements[i].ExtraData )
return i;
}
else if (Test != "")
{
for ( i = 0; i < Elements.Length; i++)
if ( Elements[i].Item ~= Test )
return i;
}
return -1;
}
// Called on the drop source when when an Item has been dropped. bAccepted tells it whether
// the operation was successful or not.
function InternalOnEndDrag(GUIComponent Accepting, bool bAccepted)
{
local int i;
local array<GUIListElem> TempElem;
if (bAccepted && Accepting != None)
{
for (i = 0; i < SelectedItems.Length; i++)
TempElem[TempElem.Length] = Elements[SelectedItems[i]];
for (i = 0; i < TempElem.Length; i++)
RemoveElement(TempElem[i]);
bRepeatClick = False;
// InternalOnMouseRelease(Accepting);
}
// Simulate repeat click if the operation was a failure to prevent InternalOnMouseRelease from clearing
// the SelectedItems array
// This way we don't lose the items we clicked on
if (Accepting == None)
bRepeatClick = True;
SetOutlineAlpha(255);
if ( bNotify )
CheckLinkedObjects(Self);
}
// Called on the drop target when the mouse is released - Sender is always DropTarget
function bool InternalOnDragDrop(GUIComponent Sender)
{
local array<GUIListElem> NewItem;
local int i;
if (Controller.DropTarget == Self)
{
if (Controller.DropSource != None && GUIList(Controller.DropSource) != None)
{
NewItem = GUIList(Controller.DropSource).GetPendingElements();
if (DropIndex >= 0 && DropIndex < ItemCount)
{
for (i = NewItem.Length - 1; i >= 0; i--)
Insert(DropIndex, Material(NewItem[i].ExtraData), NewItem[i].Item);
}
else
{
DropIndex = ItemCount;
for (i = 0; i < NewItem.Length; i++)
Add(Material(NewItem[i].ExtraData), NewItem[i].Item);
}
SetIndex(DropIndex);
// InternalOnMouseRelease(Self);
return true;
}
}
return false;
}

View file

@ -0,0 +1,369 @@
// ====================================================================
// Class: UT2K4UI.GUICircularList
// Parent: UT2K4UI.GUIListBase
//
// <Enter a description here>
// ====================================================================
class GUICircularList extends GUIListBase
Native;
cpptext
{
void Draw(UCanvas* Canvas);
}
var() bool bCenterInBounds; // Center the list in the bounding box
var() bool bFillBounds; // If true, the list will take up the whole bounding box
var() bool bIgnoreBackClick; // If true, will ignore any click on back region
var() bool bAllowSelectEmpty; // If true, allows selection of empty slots
var() int FixedItemsPerPage; // There are a fixed number of items in the list
var() bool bWrapItems; // If itemcount < ItemsPerPage, should items be wrapped?
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.Initcomponent(MyController, MyOwner);
// Sanity
if (bFillBounds)
bCenterInBounds=false;
if (!bAllowSelectEmpty && ItemCount == 0)
Index = -1;
}
function float CalculateOffset(float MouseX)
{
local float x,x1,x2,Width,xMod;
local int i;
x1 = ClientBounds[0];
x2 = ClientBounds[2];
if ( (MouseX<x1) || (MouseX>x2) )
return -1.0;
width = x2-x1;
if ( (bCenterInBounds) && (ItemsPerPage*ItemWidth<Width) )
{
xMod = (Width - (ItemsPerPage*ItemWidth)) / 2;
x1+=xMod;
x2-=xMod;
if ( (MouseX>=x1) && (MouseX<=x2) )
return (MouseX-x1) / ItemWidth;
else
return -1;
}
if ( (bFillBounds) && (ItemsPerPage*ItemWidth<Width) )
{
xMod = (Width - (ItemsPerPage*ItemWidth)) / ItemsPerPage;
i = 0;
x = x1;
while (x<=x2)
{
if ((MouseX>=x) && (MouseX<=x+ItemWidth) )
return i;
i++;
x+= ItemWidth+xmod;
}
return -1;
}
return (MouseX-x1)/ItemWidth;
}
event int CalculateIndex( optional bool bRequireValidIndex )
{
local int i, NewIndex;
i = (Top + CalculateOffset(Controller.MouseX)) % ItemCount;
if ( bRequireValidIndex && !IsValidIndex(i) )
i = -1;
NewIndex = Min( i, ItemCount - 1 );
return NewIndex;
}
function bool InternalOnClick(GUIComponent Sender)
{
local int NewIndex;
if ( ( !IsInClientBounds() ) || (ItemsPerPage==0) )
return false;
// Get the Col
NewIndex = CalculateIndex(True);
// Keep selected index in range
if (NewIndex < 0 && bIgnoreBackClick)
return false;
// check if allowed to go out of range
if ( !bAllowSelectEmpty && !IsValidIndex(NewIndex) )
return false;
SetIndex(NewIndex);
return true;
}
function WheelUp()
{
MoveLeft();
}
function WheelDown()
{
MoveRight();
}
function bool MoveLeft()
{
local int last;
if (ItemCount<2) return true;
Last = Index;
if (Index==0)
Index=ItemCount-1;
else
Index--;
if (Last==Top)
Top=Index;
OnChange(self);
return true;
}
function bool MoveRight()
{
local int last;
if (ItemCount<2) return true;
Last = Index;
Index++;
if (Index==ItemCOunt)
Index = 0;
if (Last==(Top+ItemsPerPage-1)%ItemCount)
{
Top++;
if (Top==ItemCount)
Top=0;
}
OnChange(self);
return true;
}
function Home()
{
if (ItemCount<2) return;
SetIndex(0);
Top = 0;
OnChange(self);
}
function End()
{
if (ItemCount<2) return;
Top = ItemCount - ItemsPerPage;
if (Top<0)
Top = 0;
SetIndex(ItemCount-1);
}
function PgUp()
{
local int moveCount, Last;
if (ItemCount<2) return;
for(moveCount=0; moveCount<ItemsPerPage-1; moveCount++)
{
Last = Index;
if (Index==0)
Index=ItemCount-1;
else
Index--;
if (Last==Top)
Top=Index;
}
OnChange(self);
}
function PgDown()
{
local int moveCount, Last;
if (ItemCount<2) return;
for(moveCount=0; moveCount<ItemsPerPage-1; moveCount++)
{
Last = Index;
Index++;
if (Index==ItemCOunt)
Index = 0;
if (Last==(Top+ItemsPerPage-1)%ItemCount)
{
Top++;
if (Top==ItemCount)
Top=0;
}
}
OnChange(self);
}
function bool IsValid()
{
return Index != -1;
}
// We've received a mouse click in the drop source
function InternalOnMousePressed(GUIComponent Sender, bool IsRepeat)
{
local int NewIndex, i, j, k;
if ( !IsInClientBounds() || ItemsPerPage == 0 )
return;
// If not holding down the mouse
if (!IsRepeat && ItemCount > 0)
{
NewIndex = CalculateIndex( True );
if (NewIndex == -1 && bIgnoreBackClick)
return;
LastPressX = Controller.MouseX;
LastPressY = Controller.MouseY;
if (NewIndex >= ItemCount)
NewIndex = ItemCount - 1;
// If we had an Item selected, go ahead and add it to the drag-n-drop list
if ( Controller.CtrlPressed && bMultiSelect && SelectedItems.Length == 0 && NewIndex != Index )
SelectedItems[SelectedItems.Length] = Index;
// If shift is pressed, do shift selection
if ( Controller.ShiftPressed && IsMultiSelect() )
{
if ( LastSelected == -1 )
LastSelected = 0;
// If not pressing Ctrl, clear out the SelectedItems array
if ( !Controller.CtrlPressed )
for ( j = SelectedItems.Length - 1; j >= 0; j-- )
if ( SelectedItems[j] != Index )
SelectedItems.Remove(j,1);
for ( j = Min(LastSelected, NewIndex); j <= Max(LastSelected, NewIndex); j++ )
{
for ( k = 0; k < SelectedItems.Length; k++ )
if ( SelectedItems[k] == j )
break;
if ( k == SelectedItems.Length )
SelectedItems[k] = j;
}
return;
}
else
{
LastSelected = NewIndex;
if ( IsMultiSelect() )
Index = NewIndex;
}
// Find out if the this index is already in our selected list
for (i = 0; i < SelectedItems.Length; i++)
if (SelectedItems[i] == NewIndex)
break;
// If it was found, remove it (allows toggling an Item's selectedness)
// don't remove it immediately, but set MightRemove. This way, if the user drags
// the selected Item, instead of releasing the mouse, we won't deselect it.
if (i < SelectedItems.Length)
MightRemove = i;
else if (Controller.CtrlPressed && bMultiSelect)
SelectedItems[i] = NewIndex;
else if (SelectedItems.Length > 0 && MightRemove == -1)
SelectedItems.Remove(0, SelectedItems.Length);
}
}
// Find out if we were clicking on any Item - if so, add it to SelectedItems
function CheckDragSelect()
{
local int i;
i = CalculateIndex(True);
if (i < 0 && bIgnoreBackClick)
return;
if (i >= ItemCount)
i = ItemCount - 1;
SetIndex(i);
SelectedItems[SelectedItems.Length] = i;
}
// Called on whatever component the data is being dragged over
function InternalOnDragOver(GUIComponent Sender)
{
local int NewIndex;
if (Controller.DropTarget == Self)
{
NewIndex = CalculateIndex(True);
// Keep selected index in range
if (NewIndex == -1 && bIgnoreBackClick)
return;
if (NewIndex >= ItemCount)
{
DropIndex = -1;
return;
}
if (Controller.DropSource != Self && SelectedItems.Length > 0)
SelectedItems.Remove(0, SelectedItems.Length);
DropIndex = NewIndex;
}
}
defaultproperties
{
OnClick=InternalOnClick
bWrapItems=True
bCenterInBounds=true
bIgnoreBackClick=true
FixedItemsPerPage=0
bAllowSelectEmpty=true
bRequiresStyle=True
}

View file

@ -0,0 +1,476 @@
// ====================================================================
// Class: UT2K4UI.GUIComboBox
//
// A Combination of an EditBox, a Down Arrow Button and a ListBox
//
// Written by Michel Comeau
// Updated by Ron Prestenback
// (c) 2002, 2003 Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIComboBox extends GUIMultiComponent
Native;
cpptext
{
void PreDraw(UCanvas* Canvas);
}
var() bool bReadOnly;
var() bool bValueReadOnly;
var() bool bIgnoreChangeWhenTyping; // If not read-only, only accept OnChange when Enter is pressed
var() bool bShowListOnFocus;
var() int MaxVisibleItems;
var() editconst int Index;
var() editconst string TextStr;
var() editconst GUIList List;
var Automated GUIEditBox Edit;
var Automated GUIScrollButtonBase MyShowListBtn;
var Automated GUIListBox MyListBox;
delegate OnShowList(); // Called when the list is shown
delegate OnHideList(); // Called when the list is hidden
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.Initcomponent(MyController, MyOwner);
List = MyListBox.List;
List.OnChange = ItemChanged;
List.bHotTrack = true;
List.bHotTrackSound = false;
List.OnClickSound = CS_Click;
List.OnClick = InternalListClick;
List.OnInvalidate = InternalOnInvalidate;
List.TextAlign = TXTA_Left;
MyListBox.Hide();
Edit.OnChange = TextChanged;
Edit.OnMousePressed = InternalEditPressed;
Edit.INIOption = INIOption;
Edit.INIDefault = INIDefault;
Edit.bReadOnly = bReadOnly;
List.OnDeActivate = InternalListDeActivate;
MyShowListBtn.OnClick = ShowListBox;
MyShowListBtn.FocusInstead = List;
SetHint(Hint);
}
function SetHint(string NewHint)
{
Super.SetHint(NewHint);
MyShowListBtn.SetHint(NewHint);
Edit.SetHint(NewHint);
}
function bool InternalOnKeyEvent(out byte Key, out byte State, float Delta)
{
local Interactions.EInputKey iKey;
if ( State == 3 )
{
iKey = EInputKey(Key);
if (iKey == IK_Down && Controller.ShiftPressed)
{
ShowListBox(Self);
return true;
}
if ( iKey == IK_Enter && !bReadOnly && !bValueReadOnly && bIgnoreChangeWhenTyping && TextStr != Edit.GetText() )
{
TextStr = Edit.TextStr;
OnChange(self);
}
}
return false;
}
function InternalListDeActivate()
{
if ( bDebugging )
log(Name@"ListDeactivate Edit.bPendingFocus: "$Edit.bPendingFocus);
if (!Edit.bPendingFocus)
HideListBox();
}
function InternalOnInvalidate(GUIComponent Who)
{
if ( bDebugging )
log(Name@"Invalidate Who:"$Who);
if ( Who != Controller.ActivePage )
return;
Edit.SetFocus(None);
HideListBox();
}
function InternalEditPressed(GUIComponent Sender, bool bRepeat)
{
if ( bDebugging )
log(Name@"EditPressed MyListBox.bVisible:"@MyListBox.bVisible);
if ( Edit.bReadOnly && !bRepeat )
{
if ( !MyListBox.bVisible )
{
Controller.bIgnoreNextRelease = true;
ShowListBox(Self);
}
else
HideListBox();
}
return;
}
function bool InternalListClick(GUIComponent Sender)
{
if ( bDebugging )
log(Name@"ListClick");
if ( !bValueReadOnly )
List.InternalOnClick(Sender);
Edit.SetFocus(none);
HideListBox();
return true;
}
function string InternalOnSaveIni(GUIComponent Sender)
{
return OnSaveIni(Sender);
}
function InternalOnLoadIni(GUIComponent Sender, string S)
{
OnLoadIni(Sender, S);
}
function HideListBox()
{
if ( bDebugging )
log(Name@"HideListBox");
OnHideList();
if ( Controller != None )
MyShowListBtn.Graphic = Controller.ImageList[7];
MyListBox.Hide();
List.SilentSetIndex( List.FindIndex(TextStr) );
}
event SetVisibility(bool bIsVisible)
{
local bool bTemp;
Super(GUIComponent).SetVisibility(bIsVisible);
bTemp = bDebugging;
bDebugging = False;
HideListBox();
MyShowListBtn.SetVisibility(bIsVisible);
Edit.SetVisibility(bIsVisible);
bDebugging = bTemp;
}
function bool ShowListBox(GUIComponent Sender)
{
if ( bDebugging )
log(Name@"ShowListBox MyListBox.bVisible:"$MyListBox.bVisible);
OnShowList();
MyListBox.SetVisibility(!MyListBox.bVisible);
if (MyListBox.bVisible)
MyShowListBtn.Graphic = Controller.ImageList[2];
else
MyShowListBtn.Graphic = Controller.ImageList[7];
if (MyListBox.bVisible)
{
List.SetFocus(none);
List.SetTopItem(List.Index);
}
return true;
}
function ItemChanged(GUIComponent Sender)
{
Index = List.Index;
SetText(List.Get());
if ( !bReadOnly && !bValueReadOnly && bIgnoreChangeWhenTyping )
{
TextStr = Edit.TextStr;
OnChange(Self);
}
}
function TextChanged(GUIComponent Sender)
{
if ( bValueReadOnly )
Edit.TextStr = TextStr;
else if ( bReadOnly || !bIgnoreChangeWhenTyping )
{
TextStr = Edit.TextStr;
OnChange(self);
}
}
function SetText(string NewText, optional bool bListItemsOnly)
{
local int i;
i = List.FindIndex(NewText);
if ( (bReadOnly || bListItemsOnly) && i < 0 )
return;
Edit.SetText(NewText);
TextStr = Edit.TextStr;
}
function SetExtra(string NewExtra, optional bool bListItemsOnly)
{
local int i;
i = FindExtra(NewExtra);
if (( bReadOnly || bListItemsOnly ) && i < 0 )
return;
Edit.SetText( List.GetItemAtIndex(i) );
}
function string Get()
{
return Edit.GetText();
}
function string GetText()
{
return Get();
}
function object GetObject()
{
local string temp;
temp = List.Get();
if ( temp~=Edit.GetText() )
return List.GetObject();
return none;
}
function string GetExtra()
{
local string temp;
temp = List.Get();
if ( temp~=Edit.GetText() )
return List.GetExtra();
return "";
}
function SetIndex(int I)
{
List.SetIndex(i);
}
function int GetIndex()
{
return List.Index;
}
function AddItem(string Item, Optional object Extra, Optional string Str)
{
List.Add(Item,Extra,Str);
}
function RemoveItem(int Item, optional int Count)
{
List.Remove(Item, Count);
}
function string GetItem(int index)
{
return List.GetItemAtIndex(index);
}
function object GetItemObject(int index)
{
return List.GetObjectAtIndex(index);
}
function string find(string Text, optional bool bExact, optional bool bExtra)
{
return List.Find(Text,bExact, bExtra);
}
function int FindExtra(string Text, optional bool bExact)
{
return List.FindExtra(Text, bExact);
}
function int FindIndex(string Test, optional bool bExact, optional bool bExtra, optional Object Obj)
{
return List.FindIndex(Test, bExact, bExtra, Obj);
}
function int ItemCount()
{
return List.ItemCount;
}
function ReadOnly(bool b)
{
Edit.bReadOnly = b;
}
function InternalOnMousePressed(GUIComponent Sender, bool bRepeat)
{
if (!bRepeat)
{
if ( bDebugging )
log(Name@"MousePressed");
ShowListBox(Sender);
}
}
function Clear()
{
List.Clear();
if ( bReadOnly )
Edit.SetText("");
// Set my values directly, in case component's state prevented OnChange() events from being passed upwards
TextStr = "";
Index = -1;
}
function CenterMouse()
{
if ( MyShowListBtn != None )
MyShowListBtn.CenterMouse();
else Super.CenterMouse();
}
function SetFriendlyLabel( GUILabel NewLabel )
{
Super.SetFriendlyLabel(NewLabel);
if ( Edit != None )
Edit.SetFriendlyLabel(NewLabel);
if ( MyShowListBtn != None )
MyShowListBtn.SetFriendlyLabel(NewLabel);
if ( MyListBox != None )
MyListBox.SetFriendlyLabel(NewLabel);
}
function LoseFocus(GUIComponent Sender)
{
if ( bDebugging )
log(Name@"LoseFocus Sender:"$Sender);
Super.LoseFocus(Sender);
}
function bool FocusFirst( GUIComponent Sender )
{
if ( Edit != None )
{
HideListBox();
Edit.SetFocus(None);
return true;
}
if ( bAcceptsInput )
{
Super(GUIComponent).SetFocus(None);
return true;
}
return false;
}
function bool FocusLast( GUIComponent Sender )
{
if ( Edit != None )
{
HideListBox();
Edit.SetFocus(None);
return true;
}
if ( bAcceptsInput )
{
Super(GUIComponent).SetFocus(None);
return true;
}
return false;
}
defaultproperties
{
OnKeyEvent=InternalOnKeyEvent
Begin Object Class=GUIToolTip Name=GUIComboBoxToolTip
End Object
ToolTip=GUIComboBoxToolTip
Begin Object Class=GUIEditBox Name=EditBox1
bNeverScale=True
TextStr=""
RenderWeight=0.5
End Object
Begin Object Class=GUIComboButton Name=ShowList
bNeverScale=True
bRepeatClick=false
bTabStop=False
RenderWeight=0.6
End Object
Begin Object Class=GUIListBox Name=ListBox1
bNeverScale=True
StyleName="ComboListBox"
bVisible=false
FontScale=FNT_Medium
bTabStop=False
RenderWeight=0.7
End Object
Edit=EditBox1
MyShowListBtn=ShowList
MyListBox=ListBox1
MaxVisibleItems=8
WinHeight=0.06
bAcceptsInput=True
PropagateVisibility=true
Index = -1
}

View file

@ -0,0 +1,22 @@
// ====================================================================
// Class: XInterface.GUIComboButton
//
// Written by Joe Wilcox
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIComboButton extends GUIVertScrollButton;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super(GUIScrollButtonBase).Initcomponent(MyController, MyOwner);
}
defaultproperties
{
ImageIndex=7
bRepeatClick=false
OnClickSound=CS_Edit
StyleName="ComboButton"
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,100 @@
//====================================================================
// Parent: GUI
// Class: UT2K4UI.GUIContextMenu
// Date: 05-01-2003
//
// Right-click context menu.
//
// Written by Joe Wilcox
// (c) 2003, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIContextMenu extends GUIComponent
native;
cpptext
{
virtual void PreDraw(UCanvas *Canvas);
virtual void Draw(UCanvas* Canvas);
virtual void UpdateIndex(INT MouseX, INT MouseY); // Check to see if a mouse press affects the control
virtual UBOOL Close();
virtual UBOOL KeyEvent(BYTE& iKey, BYTE& State, FLOAT Delta); // Handle key events
}
var localized array<string> ContextItems; // List of menu items
var int ItemIndex; // Selected item
var string SelectionStyleName; // Name of the Style to use
var GUIStyles SelectionStyle; // Holds the style
var int ItemHeight;
delegate bool OnOpen(GUIContextMenu Sender); // Return false to prevent menu from appearing
delegate bool OnClose(GUIContextMenu Sender); // Return false to prevent menu from closing
delegate OnSelect(GUIContextMenu Sender, int ClickIndex);
// Return false to override default behavior
// ( here is where an item is selected & highlighted )
delegate bool OnContextHitTest(float MouseX, float MouseY);
function int AddItem(string NewItem)
{
local int Index;
Index = ContextItems.Length;
ContextItems[Index] = NewItem;
return Index;
}
function int InsertItem(string NewItem, int Index)
{
if (Index >= ContextItems.Length)
return AddItem(NewItem);
if (Index <0)
return -1;
ContextItems.Insert(Index, 1);
ContextItems[Index] = NewItem;
return Index;
}
function bool RemoveItemByName(string ItemName)
{
local int Index;
for (Index=0;Index<ContextItems.Length;Index++)
if (ContextItems[Index] ~= ItemName)
{
ContextItems.Remove(Index,1);
return true;
}
return false;
}
function bool RemoveItemByIndex(int Index)
{
if (Index>=0 && Index<ContextItems.Length)
{
ContextItems.Remove(Index,1);
return true;
}
return false;
}
function bool ReplaceItem( int Index, string NewItem )
{
if ( RemoveItemByIndex(Index) )
return InsertItem(NewItem, Index) > 0;
return false;
}
defaultproperties
{
StyleName="ContextMenu"
SelectionStyleName="ListSelection"
FontScale=FNS_Small
bRequiresStyle=True
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,340 @@
// ====================================================================
// Class: XInterface.GUIEditBox
//
// GUIEditBox - The basic text edit control. I've merged Normal
// edit, restricted edit, numeric edit and password edit in to 1 control.
//
// Written by Joe Wilcox
// Updated by Ron Prestenback
// (c) 2002, 2003, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIEditBox extends GUIButton
Native;
// if _RO_
// else
//#exec OBJ LOAD FILE=InterfaceContent.utx
// end if _RO_
cpptext
{
void Draw(UCanvas* Canvas);
}
var() string TextStr; // Holds the current string
var() string AllowedCharSet; // Only Allow these characters
var() bool bMaskText; // Displays the text as a *
var() bool bIntOnly; // Only Allow Interger Numeric entry
var() bool bFloatOnly; // Only Allow Float Numeric entry
var() bool bIncludeSign; // Do we need to allow a -/+ sign
var() bool bConvertSpaces; // Do we want to convert Spaces to "_"
var() int MaxWidth; // Holds the maximum width (in chars) of the string - 0 = No Max
var() eTextCase TextCase; // Controls forcing case, etc
var() int BorderOffsets[4]; // How far in from the edit is the edit area
var() bool bReadOnly; // Can't actually edit this box
var() bool bAlwaysNotify; // If true, send OnChange event when receive SetText(), even if text is identical
var int CaretPos; // Where is the cursor within the string
var int FirstVis; // Position of the first visible character;
var int LastSizeX; // Used to detect resolution changes
var int LastCaret,LastLength; // Used to make things quick
var bool bAllSelected;
var byte LastKey;
var() float DelayTime;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.InitComponent(MyController, MyOwner);
if ( bIntOnly || bFloatOnly )
{
AllowedCharSet = "0123456789";
if (bFloatOnly)
AllowedCharSet $= ".";
}
bAllSelected=true;
}
event SetText(string NewText)
{
local bool bChanged;
bChanged = bAlwaysNotify || TextStr != NewText;
TextStr = NewText;
CaretPos=len(TextStr);
if (bChanged)
TextChanged();
bAllSelected=true;
}
function DeleteChar()
{
if (CaretPos==len(TextStr))
return;
else if (CaretPos==Len(TextStr)-1)
{
TextStr = left(TextStr,CaretPos);
CaretPos=len(TextStr);
}
else
TextStr = left(TextStr,CaretPos)$Mid(TextStr,CaretPos+1);
TextChanged();
}
function bool InternalOnKeyType(out byte Key, optional string Unicode)
{
local string temp,st;
if (bReadOnly)
return false;
if (UniCode!="")
st = Unicode;
else
st = chr(Key);
// Handle cut/paste/copy keys
if (key<32)
{
if (!Controller.CtrlPressed || key == 9)
return false; // old code captured any keys under 32
switch (key)
{
case 3: // ctrl-c, copy to console
PlayerOwner().CopyToClipboard(TextStr);
bAllSelected=true;
break;
case 22: // ctrl-v, paste at position
if ( (TextStr=="") || ( CaretPos==len(TextStr) ) ) // At the end of the string, just add
{
if (bAllSelected)
TextStr="";
TextStr = ConvertIllegal(TextStr$PlayerOwner().PasteFromClipboard());
CaretPos=len(TextStr);
}
else
{
// We are somewhere inside the string, insert.
temp = ConvertIllegal(left(TextStr,CaretPos)$PlayerOwner().PasteFromClipboard()$Mid(TextStr,CaretPos));
TextStr = temp;
}
break;
case 24: // ctrl-x, clear and copy
PlayerOwner().CopyToClipboard(TextStr);
TextStr="";
CaretPos=0;
}
TextChanged();
return true;
}
if(bAllSelected)
{
TextStr="";
CaretPos=0;
bAllSelected=false;
}
if ( (AllowedCharSet=="") || ( (bIncludeSign) && ( (st=="-") || (st=="+") ) && (TextStr=="") ) || (InStr(AllowedCharSet,St)>=0) )
{
if ( (MaxWidth==0) || (Len(TextStr)<MaxWidth) )
{
if ( (bConvertSpaces) && ((st==" ") || (st=="?") || (st=="\\")) )
st = "_";
if ( (TextStr=="") || ( CaretPos==len(TextStr) ) ) // At the end of the string, just add
{
TextStr = TextStr$st;
CaretPos=len(TextStr);
}
else
{
// We are somewhere inside the string, insert it.
temp = left(TextStr,CaretPos)$st$Mid(TextStr,CaretPos);
TextStr = temp;
CaretPos++;
}
TextChanged();
return true;
}
}
return false;
}
function bool InternalOnKeyEvent(out byte Key, out byte State, float delta)
{
if (bReadOnly || State != 1)
return false;
if( Key==8 ) // Process Backspace
{
if (CaretPos>0)
{
if ( bAllSelected )
{
TextStr = "";
CaretPos = 0;
bAllSelected = False;
TextChanged();
}
else
{
CaretPos--;
DeleteChar();
}
}
return true;
}
if ( Key==0x2E ) // Delete key
{
if(bAllSelected)
{
TextStr="";
CaretPos = 0;
bAllSelected=false;
TextChanged();
}
else
DeleteChar();
return true;
}
//if ( (Key==0x64 || Key==0x25) && (State==1) ) // Left Arrow
if ( Key==0x25 ) // Left Arrow
{
if(bAllSelected)
{
CaretPos = 0;
bAllSelected=false;
}
else if (CaretPos>0)
CaretPos--;
return true;
}
//if ( (Key==0x66 || Key==0x27) && (State==1) ) // Right Arrow
if (Key==0x27) // Right Arrow
{
if(bAllSelected)
{
CaretPos = len(TextStr);
bAllSelected=false;
}
else if ( CaretPos<Len(TextStr) )
CaretPos++;
return true;
}
//if ( (Key==0x24 || Key==0x67) && (State==1) ) // Home
if (Key==0x24) // Home
{
CaretPos=0;
bAllSelected=false;
return true;
}
//if ( (Key==0x23 || Key==0x61) && (State==1) ) // End
if (Key==0x23) // End
{
CaretPos=len(TextStr);
bAllSelected=false;
return true;
}
if ( Key == 0x41 && Controller.CtrlPressed )
{
bAllSelected=true;
return true;
}
return false;
}
// converts space-characters and chars not in the allowed char array
// ensure string stays within max bounds
function string ConvertIllegal(string inputstr)
{
local int i, max;
local string retval;
local string c;
i = 0;
max = Len(inputstr);
while ( i < max )
{
c = Mid(inputstr,i,1);
if ( AllowedCharSet != "" && InStr(AllowedCharSet,c) < 0 )
{
c = "";
}
if ( bConvertSpaces &&
((c == " ") || (c =="?") || (c=="\\") ))
{
c = "_";
}
retval = retval $ c;
i++;
}
if (MaxWidth > 0)
return Left(retval,MaxWidth);
return retval;
}
function string GetText()
{
return TextStr;
}
function TextChanged()
{
OnChange(Self);
}
function InternalActivate()
{
CaretPos = Len(TextStr);
bAllSelected = True;
}
function InternalDeactivate()
{
CaretPos = 0;
bAllSelected = False;
}
defaultproperties
{
OnKeyType = InternalOnKeyType
OnKeyEvent = InternalOnKeyEvent
OnActivate=InternalActivate
OnDeactivate=InternalDeactivate
StyleName="EditBox"
MaxWidth=768
TextCase=TXTC_None
LastCaret=-1
LastLength=-1
WinHeight=0.06
bCaptureMouse=False
bTabStop=True
OnClickSound=CS_Edit
bRequiresStyle=True
}

View file

@ -0,0 +1,190 @@
// ====================================================================
// (C) 2002, Epic Games
// ====================================================================
class GUIFloatEdit extends GUIMultiComponent
Native;
cpptext
{
void PreDraw(UCanvas* Canvas);
}
var Automated GUIEditBox MyEditBox;
var Automated GUISpinnerButton MySpinner;
var() string Value;
var() bool bLeftJustified;
var() float MinValue;
var() float MaxValue;
var() float Step;
var() bool bReadOnly;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
if ( MinValue < 0 )
MyEditBox.bIncludeSign = True;
Super.Initcomponent(MyController, MyOwner);
MyEditBox.OnChange = EditOnChange;
MyEditBox.SetText(Value);
MyEditBox.OnKeyEvent = EditKeyEvent;
MyEditBox.OnDeActivate = CheckValue;
MyEditBox.INIOption = INIOption;
MyEditBox.INIDefault = INIDefault;
CalcMaxLen();
MySpinner.bNeverFocus = true;
MySpinner.FocusInstead = MyEditBox;
MySpinner.OnPlusClick = SpinnerPlusClick;
MySpinner.OnMinusClick = SpinnerMinusClick;
SetReadOnly(bReadOnly);
SetHint(Hint);
}
function SetHint(string NewHint)
{
local int i;
Super.SetHint(NewHint);
for (i=0;i<Controls.Length;i++)
Controls[i].SetHint(NewHint);
}
function CalcMaxLen()
{
local int digitcount,x;
digitcount=1;
x=10;
while (x<MaxValue)
{
digitcount++;
x*=10;
}
MyEditBox.MaxWidth = DigitCount+4;
}
function SetValue(float V)
{
MyEditBox.SetText( string(FClamp(V, MinValue, MaxValue)) );
}
function bool SpinnerPlusClick(GUIComponent Sender)
{
SetValue(float(Value) + Step);
return true;
}
function bool SpinnerMinusClick(GUIComponent Sender)
{
SetValue(float(Value) - Step);
return true;
}
function bool EditKeyEvent(out byte Key, out byte State, float delta)
{
if ( (key==0xEC) && (State==3) )
{
SpinnerPlusClick(none);
return true;
}
if ( (key==0xED) && (State==3) )
{
SpinnerMinusClick(none);
return true;
}
return MyEditBox.InternalOnKeyEvent(Key,State,Delta);
}
function CheckValue()
{
SetValue(float(Value));
}
function EditOnChange(GUIComponent Sender)
{
Value = string( FClamp(float(MyEditBox.TextStr), MinValue, MaxValue) );
OnChange(Sender);
}
function SetReadOnly(bool b)
{
bReadOnly = b;
MyEditBox.bReadOnly = b;
if ( b )
{
DisableComponent(MySpinner);
}
else
{
EnableComponent(MySpinner);
}
}
function SetFriendlyLabel( GUILabel NewLabel )
{
Super.SetFriendlyLabel(NewLabel);
if ( MyEditBox != None )
MyEditbox.SetFriendlyLabel(NewLabel);
if ( MySpinner != None )
MySpinner.SetFriendlyLabel(NewLabel);
}
function ValidateValue()
{
local float f;
f = float(MyEditBox.TextStr);
MyEditBox.TextStr = string(FClamp(f, MinValue, MaxValue));
MyEditBox.bHasFocus = False;
}
defaultproperties
{
OnDeactivate=ValidateValue
Begin Object Class=GUIEditBox Name=cMyEditBox
bNeverScale=True
TextStr=""
bFloatOnly=true
End Object
Begin Object Class=GUISpinnerButton Name=cMySpinner
bTabStop=false
bNeverScale=True
End Object
Begin object Class=GUIToolTip Name=GUIFloatEditToolTip
End Object
ToolTip=GUIFloatEditToolTip
MyEditBox=cMyEditBox
MySpinner=cMySpinner
Value="0.0"
Step=0.1
MinValue=-9999
MaxValue=9999
bAcceptsInput=true
bLeftJustified=false
WinHeight=0.06
PropagateVisibility=true
}

View file

@ -0,0 +1,52 @@
// ====================================================================
// Class: UT2K4UI.GUIFont
//
// GUIFont is used to give a single pipeline for handling fonts at
// multiple resolutions while at the same time supporting resolution
// independant fonts (for browsers, etc).
//
// Written by Joe Wilcox
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIFont extends GUI
Abstract
Native;
var(Menu) string KeyName;
var(Menu) bool bFixedSize; // If true, only FontArray[0] is used
var(Menu) bool bScaled; // This font is scaled
var(Menu) int NormalXRes; // If Scaled, this is it's default resolution
var(Menu) int FallBackRes; // If the Resolution is <= this value, it will use the fallback font.
var(Menu) localized array<string> FontArrayNames; // Holds all of the names of the fonts
var(Menu) array<Font> FontArrayFonts; // Holds all of the fonts
native event Font GetFont(int XRes); // Returns the font for the current resolution
// Dynamically load font.
static function Font LoadFontStatic(int i)
{
if( i>=default.FontArrayFonts.Length || default.FontArrayFonts[i] == None )
{
default.FontArrayFonts[i] = Font(DynamicLoadObject(default.FontArrayNames[i], class'Font'));
if( default.FontArrayFonts[i] == None )
Log("Warning: "$default.Class$" Couldn't dynamically load font "$default.FontArrayNames[i]);
}
return default.FontArrayFonts[i];
}
function Font LoadFont(int i)
{
if( i>=FontArrayFonts.Length || FontArrayFonts[i] == None )
{
FontArrayFonts[i] = Font(DynamicLoadObject(FontArrayNames[i], class'Font'));
if( FontArrayFonts[i] == None )
Log("Warning: "$Self$" Couldn't dynamically load font "$FontArrayNames[i]);
}
return FontArrayFonts[i];
}
defaultproperties
{
}

View file

@ -0,0 +1,20 @@
//====================================================================
// Class: XInterface.GUIFooter
// Date: 04-28-2003
//
// Base class for page footer panels.
//
// Written by Ron Prestenback
// (c) 2003, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIFooter extends GUIBorder;
defaultproperties
{
WinTop=0.9
WinHeight=0.1
WinWidth=1.0
bBoundToParent=True
bScaleToParent=True
}

View file

@ -0,0 +1,73 @@
//==============================================================================
// NumericEdit component with custom formatting
//
// Written by Michiel Hendriks
// (c) 2003, 2004, Epic Games, Inc. All Rights Reserved
//==============================================================================
class GUIFormatNumEdit extends GUINumericEdit;
var protected bool bUnformated;
delegate string FormatValue(int NewValue)
{
return "$ "$NewValue; // test
}
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.InitComponent(MyController, MyOwner);
MyEditBox.OnActivate = FormatToValue;
MyEditBox.OnDeActivate = ValueToFormat;
MySpinner.bNeverFocus = false;
MySpinner.FocusInstead = none;
}
function CalcMaxLen(); // don't limit size
function EditOnChange(GUIComponent Sender); // no longer needed
function ValidateValue();
function ValueToFormat()
{
if (!bUnformated) return;
SetValue(int(MyEditBox.GetText()));
}
function FormatToValue()
{
MyEditBox.SetText(Value);
bUnformated = true;
}
function SetValue(int V)
{
if (v<MinValue)
v=MinValue;
if (v>MaxValue)
v=MaxValue;
Value = string(V);
MyEditBox.SetText(FormatValue(int(Value)));
bUnformated = false;
OnChange(Self);
}
function bool SpinnerPlusClick(GUIComponent Sender)
{
local int v;
v = int(Value) + Step;
SetValue(v);
return true;
}
function bool SpinnerMinusClick(GUIComponent Sender)
{
local int v;
v = int(Value) - Step;
SetValue(v);
return true;
}

View file

@ -0,0 +1,68 @@
// ====================================================================
// Class: UT2K4UI.GUIButton
//
// GUIGFXButton - The basic button class. It can be used for icon buttons
// or Checkboxes
//
// Written by Joe Wilcox
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIGFXButton extends GUIButton
Native;
// if _RO_
// else
//#exec OBJ LOAD FILE=InterfaceContent.utx
// end if _RO_
cpptext
{
void Draw(UCanvas* Canvas);
}
var() Int ImageIndex;
var() Material Graphic; // The graphic to display
var() eIconPosition Position; // How do we draw the Icon
var() bool bCheckBox; // Is this a check box button (ie: supports 2 states)
var() bool bClientBound; // Graphic is drawn using clientbounds if true
var bool bChecked;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.Initcomponent(MyController, MyOwner);
if ( bCheckBox )
OnClick = InternalOnClick;
if (Graphic==none && ImageIndex>=0 && ImageIndex < MyController.ImageList.Length)
Graphic=MyController.ImageList[ImageIndex];
}
function SetChecked(bool bNewChecked)
{
if (bCheckBox)
{
bChecked = bNewChecked;
OnChange(Self);
}
}
function bool InternalOnClick(GUIComponent Sender)
{
if (bCheckBox)
bChecked = !bChecked;
OnChange(Self);
return true;
}
defaultproperties
{
Position=ICP_Normal
bCheckBox=false
bChecked=false
bTabStop=false
}

View file

@ -0,0 +1,19 @@
//==============================================================================
// Created on: 08/23/2003
// Base class for scroll zone grip buttons
//
// Written by Ron Prestenback
// © 2003, Epic Games, Inc. All Rights Reserved
//==============================================================================
class GUIGripButtonBase extends GUIGFXButton
native;
defaultproperties
{
StyleName="RoundButton"
Position=ICP_Bound
bNeverFocus=true
bCaptureMouse=true
OnClickSound=CS_None
bRequireReleaseClick=true
}

View file

@ -0,0 +1,17 @@
//====================================================================
// Date: 04-28-2003
// Base class for header panels.
//
// Written by Ron Prestenback
// (c) 2003, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIHeader extends GUITitleBar;
DefaultProperties
{
StyleName="Header"
bDockTop=false
FontScale=FNS_Small
DockAlign=PGA_Top
bUseTextHeight=false
}

View file

@ -0,0 +1,7 @@
class GUIHorzGripButton extends GUIGripButtonBase;
defaultproperties
{
ImageIndex=1
}

View file

@ -0,0 +1,190 @@
// ====================================================================
// Class: UT2K4UI.GUIHorzList
// Parent: UT2K4UI.GUIListBase
//
// <Enter a description here>
// ====================================================================
class GUIHorzList extends GUIListBase
Native;
cpptext
{
void Draw(UCanvas* Canvas);
}
event int CalculateIndex(optional bool bRequireValidIndex)
{
local int i, NewIndex;
i = Top + ((Controller.MouseX - ClientBounds[0]) / ItemWidth);
if ( i >= ItemCount && bRequireValidIndex )
i = -1;
NewIndex = Min( i, ItemCount - 1 );
return NewIndex;
}
function bool InternalOnClick(GUIComponent Sender)
{
local int NewIndex;
if ( !IsInClientBounds() || ItemsPerPage == 0 )
return false;
NewIndex = CalculateIndex();
SetIndex(NewIndex);
return true;
}
function bool InternalOnKeyType(out byte Key, optional string Unicode)
{
// Add code to jump to next line with Char
return false;
}
function WheelUp()
{
if (MyScrollBar!=None)
GUIHorzScrollBar(MyScrollBar).WheelUp();
else
{
if (!Controller.CtrlPressed)
ScrollLeft();
else
PgUp();
}
}
function WheelDown()
{
if (MyScrollBar!=None)
GUIHorzScrollBar(MyScrollBar).WheelDown();
else
{
if (!Controller.CtrlPressed)
ScrollRight();
else
PgDn();
}
}
function bool MoveLeft()
{
if ( (ItemCount<2) || (Index==0) ) return true;
Index = max(0,Index-1);
if ( (Index<Top) || (Index>Top+ItemsPerPage) )
{
Top = Index;
MyScrollBar.AlignThumb();
}
return true;
}
function bool MoveRight()
{
if ( (ItemCount<2) || (Index==ItemCount-1) ) return true;
Index = min(Index+1,ItemCount-1);
if (Index<Top)
{
Top = Index;
MyScrollBar.AlignThumb();
}
else if (Index>=Top+ItemsPerPage)
{
Top = Index-ItemsPerPage+1;
MyScrollBar.AlignThumb();
}
return true;
}
function ScrollLeft()
{
MoveLeft();
}
function ScrollRight()
{
MoveRight();
}
function Home()
{
if (ItemCount<2) return;
SetIndex(0);
Top = 0;
MyScrollBar.AlignThumb();
}
function End()
{
if (ItemCount<2) return;
Top = ItemCount - ItemsPerPage;
if (Top<0)
Top = 0;
SetIndex(ItemCount-1);
MyScrollBar.AlignThumb();
}
function PgUp()
{
if (ItemCount<2) return;
Index -= ItemsPerPage;
// Adjust to bounds
if (Index < 0)
Index = 0;
// If new index
if (Top + ItemsPerPage <= Index) // If index is forward but not visible, jump to it
Top = Index;
else if (Index + ItemsPerPage < Top) // Item is way too far
Top = Index;
else if (Index < Top) // Item is 1 page or less away
SetTopItem(Top - ItemsPerPage);
SetIndex(Index);
MyScrollBar.AlignThumb();
}
function PgDn()
{
if (ItemCount<2) return;
// Select item 1 page away from current selection
Index += ItemsPerPage;
// Adjust to bounds
if (Index >= ItemCount)
Index = ItemCount-1;
if (Index < Top) // If item is still before Top Item, go to it
Top = Index;
else if (Index - Top - ItemsPerPage >= ItemsPerPage) // Too far away
SetTopItem(Index);
else if (Index - Top >= ItemsPerPage) // Just 1 page away
SetTopItem(Top + ItemsPerPage);
SetIndex(Index);
MyScrollBar.AlignThumb();
}
defaultproperties
{
OnClick=InternalOnClick
bRequiresStyle=True
}

View file

@ -0,0 +1,73 @@
// ====================================================================
// Class: XInterface.GUIHorzScrollBar
// Parent: XInterface.GUIScrollBarBase
//
// Scrollbar assembly for horizontal lists.
// ====================================================================
class GUIHorzScrollBar extends GUIScrollBarBase;
// Record location you grabbed the grip
function GripPressed( GUIComponent Sender, bool IsRepeat )
{
if ( !IsRepeat )
GrabOffset = Controller.MouseX - MyGripButton.ActualLeft();
}
function bool GripPreDraw( GUIComponent Sender )
{
local float NewPerc;
if ( MyGripButton.MenuState != MSAT_Pressed )
return false;
// Calculate the new Grip Top using the mouse cursor location.
NewPerc = FClamp(
(Controller.MouseX - GrabOffset - MyScrollZone.ActualLeft()) / (MyScrollZone.ActualWidth() - GripSize),
0.0, 1.0 );
UpdateGripPosition(NewPerc);
return false;
}
function ZoneClick(float Delta)
{
if ( Controller.MouseX < MyGripButton.Bounds[0] )
MoveGripBy(-BigStep);
else if ( Controller.MouseX > MyGripButton.Bounds[2] )
MoveGripBy(BigStep);
return;
}
defaultproperties
{
Begin Object Class=GUIHorzScrollZone Name=HScrollZone
OnScrollZoneClick=ZoneClick
End Object
Begin Object Class=GUIHorzScrollButton Name=HLeftBut
OnClick=DecreaseClick
End Object
Begin Object Class=GUIHorzScrollButton Name=HRightBut
OnClick=IncreaseClick
bIncreaseButton=True
End Object
Begin Object Class=GUIHorzGripButton Name=HGrip
OnMousePressed=GripPressed
End Object
OnPreDraw=GripPreDraw
MyScrollZone=HScrollZone
MyDecreaseButton=HLeftBut
MyIncreaseButton=HRightBut
MyGripButton=HGrip
bAcceptsInput=true
WinWidth=0.0375
Orientation=ORIENT_Horizontal
MinGripPixels=12
}

View file

@ -0,0 +1,17 @@
class GUIHorzScrollButton extends GUIScrollButtonBase;
var() bool LeftButton;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
if (bIncreaseButton)
ImageIndex = 3;
Super.Initcomponent(MyController, MyOwner);
}
defaultproperties
{
ImageIndex=2
}

View file

@ -0,0 +1,21 @@
// ====================================================================
// Class: XInterface.GUIHorzScrollZone
// Parent: XInterface.GUIComponent
//
// Scrollzone implementation for horizontal lists.
// ====================================================================
class GUIHorzScrollZone extends GUIScrollZoneBase;
function bool InternalOnClick(GUIComponent Sender)
{
local float perc;
if (!IsInBounds())
return false;
perc = ( Controller.MouseX - ActualLeft() ) / ActualWidth();
OnScrollZoneClick(perc);
return true;
}

View file

@ -0,0 +1,74 @@
/* ====================================================================
Class: UT2K4UI.GUIImage
GUIImage - A graphic image used by the menu system. It encapsulates
Material.
Written by Joe Wilcox
(c) 2002, Epic Games, Inc. All Rights Reserved
Notes about draw styles:
Some things to know about using ISTY_Stretched -
If X1, X2, Y1, and Y2 are all -1, draws normally.
If specify values for any of those (i.e. you are drawing only a portion of another texture),
the image is scaled instead of streched. In effect, it is the same as ISTY_Scaled, with one exception:
If using ImageAlign other than IMGA_Left, then position calculation is done based from the
original material's size with ISTY_Stretched, whereas it is done with size of the GUIImage with
ISTY_Scaled.
ImageAlign is ignored if ImageStyle is ISTY_Bound.
===================================================================*/
class GUIImage extends GUIComponent
Native;
cpptext
{
void UpdateBounds();
void Draw(UCanvas* Canvas);
}
var() Material Image; // The Material to Render
var() Material DropShadow; // The Materinal used for a drop shadow
var() color ImageColor; // What color should we set
var() eImgStyle ImageStyle; // How should the image be displayed
var() EMenuRenderStyle ImageRenderStyle; // How should we display this image
var() eImgAlign ImageAlign; // If ISTY_Justified, how should image be aligned
var() int X1,Y1,X2,Y2; // If set, it will pull a subimage from inside the image
var() int DropShadowX; // Offset for a drop shadow
var() int DropShadowY; // Offset for a drop shadow
var() float BorderOffsets[4]; // How thick is the border (in percentage)
// Only used for ISTY_PartialScaled
// Essentially, ISTY_PartialScaled means the material is stretched if the bounds are larger than the material
// and scaled if the bounds are smaller than the material
// X3 and Y3 are used to specify how far into each side (must be symmetric) of the image
// will be stretched *instead of* scaled if the material is smaller than the bounds
// This is mainly used for textures which contain combinations of gradients and detailed borders or bevels,
// where the gradient should be scaled to maintain color distribution, but the border needs to maintain a
// minimum size. Also used to preserve "bevelled" appearance of materials (editbox)
var() float X3, Y3;
event string AdditionalDebugString()
{
return " IS:"$GetEnum(enum'EImgStyle', ImageStyle);
}
defaultproperties
{
ImageColor=(R=255,G=255,B=255,A=255)
ImageStyle=ISTY_Normal
ImageRenderStyle=MSTY_Alpha
ImageAlign=IMGA_TopLeft
X1=-1
X2=-1
X3=-1
Y1=-1
Y2=-1
Y3=-1
RenderWeight=0.1
DropShadowX=0
DropShadowY=0
}

View file

@ -0,0 +1,133 @@
// GUIImageList is simply a GUIImage that has its current image selected from an array
// It rotates using mouse wheel/arrow keys
class GUIImageList extends GUIImage;
// Native;
var() editinline array<string> MatNames;
var() array<Material> Materials;
var() editconst int CurIndex;
var() bool bWrap;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.Initcomponent(MyController, MyOwner);
OnKeyEvent=internalKeyEvent;
}
function AddMaterial(string MatName, out Material Mat)
{
local int i;
if (Mat != None)
{
i = Materials.Length;
Materials[i]=Mat;
MatNames[i]=MatName;
}
}
function string GetCurMatName()
{
if (CurIndex >= 0 && CurIndex < Materials.Length)
return MatNames[CurIndex];
return "";
}
function SetIndex(int index)
{
if (index >= 0 && index < Materials.Length)
{
CurIndex = index;
Image = Materials[index];
}
else
{
Image = None;
CurIndex = -1;
}
}
function bool internalKeyEvent(out byte Key, out byte State, float delta)
{
if ( State != 3 )
return false;
switch ( Key )
{
case 0x25: // Up/Left/MouseWheelUp
case 0x26:
case 0x64:
case 0x68:
case 0xEC:
PrevImage();
return true;
case 0x27: // Down/Right/MouseWheelDn
case 0x28:
case 0x62:
case 0x66:
case 0xED:
NextImage();
return true;
case 0x24: // Home
case 0x67:
FirstImage();
return true;
case 0x23: // End
case 0x61:
LastImage();
return true;
}
return false;
}
function PrevImage()
{
if (CurIndex < 1)
{
if (bWrap)
SetIndex(Materials.Length - 1);
}
else
SetIndex(CurIndex - 1);
}
function NextImage()
{
if (CurIndex < 0)
SetIndex(0);
else if ((CurIndex + 1) >= Materials.Length)
{
if (bWrap)
SetIndex(0);
}
else
SetIndex(CurIndex + 1);
}
function FirstImage()
{
if (Materials.Length > 0)
SetIndex(0);
}
function LastImage()
{
if (Materials.Length > 0)
SetIndex(Materials.Length - 1);
}
defaultproperties
{
StyleName="NoBackground"
bAcceptsInput=true
bCaptureMouse=True
bNeverFocus=false;
bTabStop=true
}

View file

@ -0,0 +1,60 @@
// ======================================================================================================
// GUILabel - A text label that get's displayed. By default, it
// uses the default font, however you can override it if you wish.
//
// By default, labels will never be focused, since bAcceptsInput is false
// for GUILabel. This means that GUILabel will never be put into the MSAT_Focused
// state (thus changing the color of the text to FocusedTextColor) unless the GUILabel
// is associated with a component that manually sets the label's state, such as a GUIMenuOption.
//
// The easiest way to override this default behavior, if desired, is by setting StyleName to "TextLabel".
//
// Written by Joe Wilcox
// Updated by Ron Prestenback
// (c) 2002 - 2003, Epic Games, Inc. All Rights Reserved
// ======================================================================================================
class GUILabel extends GUIComponent
Native;
cpptext
{
void Draw(UCanvas* Canvas);
}
var() localized string Caption; // The text to display
var() eTextAlign TextAlign; // How is the text aligned in it's bounding box
var() color TextColor; // The Color to display this in.
var() color FocusedTextColor; // The Color to display this in.
var() EMenuRenderStyle TextStyle; // What canvas style to use
var() string TextFont; // The Font to display it in
var() bool bTransparent; // Draw a Background for this label
var() bool bMultiLine; // Will cut content to display on multiple lines when too long
var() eTextAlign VertAlign; // Vertical alignment (only if bMultiLine) - Left = Top
var() color BackColor; // Background color for this label
var() color ShadowColor; // Shadow Color
var() float ShadowOffsetX; // if > 0 draw shadow
var() float ShadowOffsetY; // if > 0 draw shadow
var() color HilightColor; // Shadow Color
var() float HilightOffsetX; // if > 0 draw shadow
var() float HilightOffsetY; // if > 0 draw shadow
defaultproperties
{
TextAlign=TXTA_Left
TextColor=(R=0,G=0,B=64,A=255)
FocusedTextColor=(R=32,G=32,B=80,A=255)
TextStyle=MSTY_Normal
TextFont="UT2MenuFont"
bTransparent=true
BackColor=(R=0,G=0,B=0,A=255)
RenderWeight=0.4
WinHeight=0.06
VertAlign=TXTA_Left
ShadowColor=(R=0,G=0,B=0,A=196)
ShadowOffsetX=0
ShadowOffsetY=0
HilightColor=(R=255,G=255,B=255,A=196)
HilightOffsetX=0
HilightOffsetY=0
}

View file

@ -0,0 +1,581 @@
// ====================================================================
// The GUIList is a basic list component.
//
// Written by Joe Wilcox
// Updated by Ron Prestenback
// (c) 2002, 2003, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIList extends GUIVertList
Native;
// if _RO_
// else
//#exec OBJ LOAD FILE=InterfaceContent.utx
// end if _RO_
cpptext
{
protected:
virtual void DrawItem(UCanvas* Canvas, INT Item, FLOAT X, FLOAT Y, FLOAT W, FLOAT HT, UBOOL bSelected, UBOOL bPending);
public:
}
var() eTextAlign TextAlign; // How is text Aligned in the control
var() editconstarray editconst array<GUIListElem> Elements;
var() editconstarray editconst array<GUIListElem> SelectedElements; // Used to easily support drag-n-drop between the same list
var() color OfficialColor; // Used to signify items standard in UT2003
var() color Official2004Color; // Used to signify items standard in UT2004
var() color BonusPackColor; // Used to signify items standard in BonusPacks
native final function SortList();
function Sort()
{
Super.Sort();
SortList();
}
// Used by SortList.
delegate int CompareItem(GUIListElem ElemA, GUIListElem ElemB)
{
return StrCmp(ElemA.Item, ElemB.Item);
}
// Accessor function for the items.
// Functions for manipulating entire list elements
function Add(string NewItem, optional Object obj, optional string Str, optional bool bSection)
{
local int NewIndex;
local GUIListElem E;
if ( !bAllowEmptyItems && NewItem == "" && Obj == None && Str == "" )
return;
E.Item = NewItem;
E.ExtraData = Obj;
E.ExtraStrData = Str;
E.bSection = bSection;
if (bSorted && Elements.Length > 0)
{
while (NewIndex < Elements.Length && CompareItem(Elements[NewIndex], E) < 0)
NewIndex++;
}
else NewIndex = Elements.Length;
Elements.Insert(NewIndex, 1);
Elements[NewIndex] = E;
ItemCount = Elements.Length;
if (Elements.Length == 1 && bInitializeList)
SetIndex(0);
else if ( bNotify )
CheckLinkedObjects(Self);
if (MyScrollBar != None)
MyScrollBar.AlignThumb();
}
function AddElement( GUIListElem NewElem )
{
Add( NewElem.Item, NewElem.ExtraData, NewElem.ExtraStrData );
}
function Replace(int i, string NewItem, optional Object obj, optional string Str, optional bool bNoSort)
{
if ( !IsValidIndex(i) )
Add(NewItem,Obj,Str);
else
{
if ( !bAllowEmptyItems && NewItem == "" && Obj == None && Str == "" )
return;
Elements[i].Item = NewItem;
Elements[i].ExtraData = obj;
Elements[i].ExtraStrData = Str;
if ( bSorted && !bNoSort )
Sort();
SetIndex(Index);
}
}
function Insert(int i, string NewItem, optional Object obj, optional string Str, optional bool bNoSort, optional bool bSection )
{
if ( !IsValidIndex(i) )
Add(NewItem,Obj,Str, bSection);
else
{
if ( !bAllowEmptyItems && NewItem == "" && Obj == None && Str == "" )
return;
Elements.Insert(i,1);
Elements[i].Item=NewItem;
Elements[i].ExtraData=obj;
Elements[i].ExtraStrData=Str;
Elements[i].bSection=bSection;
ItemCount = Elements.Length;
if ( bSorted && !bNoSort )
Sort();
SetIndex(Index);
if (MyScrollBar != None)
MyScrollBar.AlignThumb();
}
}
function InsertElement( int i, GUIListElem NewElem, optional bool bNoSort )
{
Insert( i, NewElem.Item, NewElem.ExtraData, NewElem.ExtraStrData, bNoSort );
}
event Swap(int IndexA, int IndexB)
{
local GUI.GUIListElem elem;
if ( IsValidIndex(IndexA) && IsValidIndex(IndexB) )
{
elem = Elements[IndexA];
Elements[IndexA] = Elements[IndexB];
Elements[IndexB] = elem;
if (bSorted)
Sort();
if ( bNotify )
CheckLinkedObjects(Self);
}
}
function LoadFrom(GUIList Source, optional bool bClearFirst)
{
local string t1,t2;
local object t;
local int i;
if (bClearfirst)
Clear();
for (i=0;i<Source.Elements.Length;i++)
{
Source.GetAtIndex(i,t1,t,t2);
Add(t1,t,t2);
}
}
function int Remove(int i, optional int Count, optional bool bNoSort)
{
Count = Max( Count, 1 );
if (!IsValidIndex(i))
return Index;
Elements.Remove(i, Min(Count, Elements.Length - i));
ItemCount = Elements.Length;
if ( bSorted && !bNoSort )
Sort();
// In case we now have an invalid index
SetIndex(Index);
if (MyScrollBar != None)
MyScrollBar.AlignThumb();
return Index;
}
function int RemoveSilent(int i, optional int Count)
{
bNotify = False;
i = Remove(i, Count, True);
bNotify = True;
return i;
}
function int RemoveElement(GUIListElem Elem, optional int Count, optional bool bNoSort)
{
local int i;
Count = Max( Count, 1 );
for ( i = 0; i < Elements.Length; i++ )
{
if ( Elements[i] == Elem )
{
Elements.Remove(i, Min(Count, Elements.Length - i));
break;
}
}
ItemCount = Elements.Length;
if ( bSorted && !bNoSort )
Sort();
// In case we now have an invalid index
SetIndex(Index);
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
return Index;
}
function Clear()
{
if (Elements.Length == 0)
return;
Elements.Remove(0,Elements.Length);
ItemCount = 0;
Super.Clear();
}
// =====================================================================================================================
// =====================================================================================================================
// Query Functions
// =====================================================================================================================
// =====================================================================================================================
// Backwards compatibility
function string SelectedText()
{
return Get();
}
// Current listitem
function string Get(optional bool bGuarantee)
{
if ( !IsValid() )
{
if (bGuarantee && Elements.Length > 0)
return Elements[0].Item;
return "";
}
return Elements[Index].Item;
}
function object GetObject()
{
if ( !IsValid() )
return none;
return Elements[Index].ExtraData;
}
function string GetExtra()
{
if ( !IsValid() )
return "";
return Elements[Index].ExtraStrData;
}
function bool IsSection()
{
if ( !IsValid() )
return false;
return Elements[Index].bSection;
}
// Arbitrary list Item
function string GetItemAtIndex(int i)
{
if (!IsValidIndex(i))
return "";
return Elements[i].Item;
}
function object GetObjectAtIndex(int i)
{
if (!IsValidIndex(i))
return None;
return Elements[i].ExtraData;
}
function string GetExtraAtIndex(int i)
{
if (!IsValidIndex(i))
return "";
return Elements[i].ExtraStrData;
}
function GetAtIndex(int i, out string ItemStr, out object ExtraObj, out string ExtraStr)
{
if (!IsValidIndex(i))
return;
ItemStr = Elements[i].Item;
ExtraObj = Elements[i].ExtraData;
ExtraStr = Elements[i].ExtraStrData;
}
// =====================================================================================================================
// =====================================================================================================================
// Assignment functions
// =====================================================================================================================
// =====================================================================================================================
function SetItemAtIndex(int i, string NewItem)
{
if (!IsValidIndex(i))
return;
Elements[i].Item = NewItem;
if ( bNotify )
CheckLinkedObjects(Self);
}
function SetObjectAtIndex(int i, Object NewObject)
{
if (!IsValidIndex(i))
return;
Elements[i].ExtraData = NewObject;
if ( bNotify )
CheckLinkedObjects(Self);
}
function SetExtraAtIndex(int i, string NewExtra)
{
if (!IsValidIndex(i))
return;
Elements[i].ExtraStrData = NewExtra;
if ( bNotify )
CheckLinkedObjects(Self);
}
function RemoveItem(string Item)
{
local int i;
// Work through array. If we find it, remove it (will reduce Elements.Length).
// If we don't, move on to next one.
while( i < Elements.Length)
{
if(Item ~= Elements[i].Item)
Elements.Remove(i, 1);
else
i++;
}
ItemCount = Elements.Length;
SetIndex(-1);
if (MyScrollBar != None)
MyScrollBar.AlignThumb();
}
function RemoveObject(Object Obj)
{
local int i;
while (i < Elements.Length)
{
if (Obj == Elements[i].ExtraData)
Elements.Remove(i, 1);
else i++;
}
ItemCount = Elements.Length;
SetIndex(-1);
if (MyScrollBar != None)
MyScrollBar.AlignThumb();
}
function RemoveExtra(string Str)
{
local int i;
while (i < Elements.Length)
{
if (Str ~= Elements[i].ExtraStrData)
Elements.Remove(i, 1);
else i++;
}
ItemCount = Elements.Length;
SetIndex(-1);
if (MyScrollBar != None)
MyScrollBar.AlignThumb();
}
// =====================================================================================================================
// =====================================================================================================================
// Search functions
// =====================================================================================================================
// =====================================================================================================================
function string Find(string Text, optional bool bExact, optional bool bExtra)
{
local int i;
i = FindIndex(Text, bExact, bExtra);
if (i != -1)
{
SetIndex(i);
return Elements[i].Item;
}
return "";
}
function int FindExtra(string Text, optional bool bExact)
{
return FindIndex(Text, bExact, True);
}
function int FindItemObject(Object Obj)
{
return FindIndex("",,,Obj);
}
function int FindIndex(string Test, optional bool bExact, optional bool bExtra, optional Object TestObject)
{
local int i;
if (TestObject != None)
{
for (i = 0; i < Elements.Length; i++)
if ( TestObject == Elements[i].ExtraData )
return i;
}
else if (Test != "")
{
if (bExtra)
{
for (i = 0; i < Elements.Length; i++)
if ( (bExact && Elements[i].ExtraStrData == Test) || (!bExact && Elements[i].ExtraStrData ~= Test) )
return i;
}
else
{
for ( i = 0; i < Elements.Length; i++)
if ( (bExact && Elements[i].Item == Test) || (!bExact && Elements[i].Item ~= Test) )
return i;
}
}
return -1;
}
// =====================================================================================================================
// =====================================================================================================================
// Drag-n-drop interface
// =====================================================================================================================
// =====================================================================================================================
// Called on the drop source when when an Item has been dropped. bAccepted tells it whether
// the operation was successful or not.
function InternalOnEndDrag(GUIComponent Accepting, bool bAccepted)
{
local int i;
// log(Name@"InternalOnEndDrag Accepting:"$Accepting@"bAccepted:"$bAccepted);
if (bAccepted && Accepting != None)
{
GetPendingElements();
if ( Accepting != Self )
{
for ( i = 0; i < SelectedElements.Length; i++ )
RemoveElement(SelectedElements[i]);
}
bRepeatClick = False;
}
// Simulate repeat click if the operation was a failure to prevent InternalOnMouseRelease from clearing
// the SelectedItems array
// This way we don't lose the items we clicked on
if (Accepting == None)
bRepeatClick = True;
SetOutlineAlpha(255);
if ( bNotify )
CheckLinkedObjects(Self);
}
// Called on the drop target when the mouse is released - Sender is always DropTarget
function bool InternalOnDragDrop(GUIComponent Sender)
{
local array<GUIListElem> NewItem;
local int i;
// log(Name@"InternalOnDragDrop Sender:"$ Sender);
if (Controller.DropTarget == Self)
{
if (Controller.DropSource != None && GUIList(Controller.DropSource) != None)
{
NewItem = GUIList(Controller.DropSource).GetPendingElements();
// Special case for drag-n-drop between the same list.
if ( Controller.DropSource == Self )
{
for ( i = NewItem.Length - 1; i >= 0; i-- )
RemoveElement(NewItem[i],,True);
}
if ( !IsValidIndex(DropIndex) )
DropIndex = ItemCount;
for (i = NewItem.Length - 1; i >= 0; i--)
Insert(DropIndex, NewItem[i].Item, NewItem[i].ExtraData, NewItem[i].ExtraStrData);
SetIndex(DropIndex);
return true;
}
}
return false;
}
function ClearPendingElements()
{
Super.ClearPendingElements();
if ( SelectedItems.Length == 0 )
SelectedElements.Remove(0, SelectedElements.Length);
}
function array<GUIListElem> GetPendingElements(optional bool bGuarantee)
{
local int i;
if ( (DropState == DRP_Source && Controller.DropSource == Self) || bGuarantee )
{
if ( SelectedElements.Length == 0 )
{
for (i = 0; i < SelectedItems.Length; i++)
if (IsValidIndex(SelectedItems[i]))
SelectedElements[SelectedElements.Length] = Elements[SelectedItems[i]];
if ( SelectedElements.Length == 0 && IsValid() )
{
SelectedElements.Length = SelectedElements.Length + 1;
GetAtIndex(Index, SelectedElements[0].Item, SelectedElements[0].ExtraData, SelectedElements[0].ExtraStrData);
}
}
return SelectedElements;
}
}
defaultproperties
{
TextAlign=TXTA_Center
}

View file

@ -0,0 +1,645 @@
// ====================================================================
// Class: UT2K4UI.GUIListBase
//
// Abstract GUIList list box component.
//
// Written by Joe Wilcox
// Made abstract by Jack Porter
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIListBase extends GUIComponent
Native
Abstract;
// if _RO_
// else
//#exec OBJ LOAD FILE=InterfaceContent.utx
// end if _RO_
cpptext
{
protected:
virtual void DrawItem(UCanvas* Canvas, INT Item, FLOAT X, FLOAT Y, FLOAT W, FLOAT HT, UBOOL bSelected, UBOOL bPending) {}
public:
}
var() bool bSorted; // Should we sort this list
var() bool bHotTrack; // Use the Mouse X/Y to always hightlight something
var() bool bHotTrackSound; // Whether to make the mouse over sound when hottracking
var() bool bDrawSelectionBorder; // Should we draw a selection border around the selected item
var() bool bVisibleWhenEmpty; // List is still drawn when there are no items in it.
var() bool bNotify; // Used to abort OnChange notification in list
var() bool bInitializeList; // If true, set index to 0 when adding first item
var() bool bMultiSelect; // allow multiple selections (where implemented)
var() bool bAllowEmptyItems;
var() noexport GUIScrollBarBase MyScrollBar;
// Styles
var(Style) string SelectedStyleName; // Name of the style to use for the selected item
var(Style) string SectionStyleName; // Name of the style to use for header items
var(Style) string OutlineStyleName;
var(Style) noexport GUIStyles SelectedStyle;
var(Style) noexport GUIStyles SectionStyle;
var(Style) noexport GUIStyles OutlineStyle; // Used for outlining a pending drag-n-drop
var() ETextAlign SectionJustification;
var() Material SelectedImage; // Image to use when displaying
var() color SelectedBKColor; // Color for a selection background
var() noexport editconst int Top,Index; // Pointers in to the list
var() noexport editconst const int ItemsPerPage; // # of items per Page. Is set natively
var() noexport editconst const float ItemHeight; // Size of each row. Subclass should set in PreDraw.
var() noexport editconst const float ItemWidth; // Width of each row.. Subclass should set in PreDraw.
var() noexport editconst int ItemCount; // # of items in this list
// Drag-n-drop
// You must set these to enable drag-n-drop
var() noexport editconst array<int> SelectedItems;
var() noexport editconst int LastSelected; // Last selected item
var() noexport editconst int LastPressX, LastPressY; // Last position of mouse press
var() noexport editconst int DropIndex; // Indicates the insertion position for the drag-n-drop operation
var() noexport editconst int MightRemove; // Indicates an item that will be de-selected unless a drag operation begins
var() noexport editconstarray array<GUIComponent> LinkedObjects; // Objects state is changed based on whether this list has a valid index
// Not yet implemented (drag-n-drop)
// This will eventually allow you to auto-scroll a list while holding the cursor
// on the top or bottom item of the target list when moving items
delegate OnScrollBy(GUIComponent Sender);
// Owner-draw.
delegate OnDrawItem(Canvas Canvas, int Item, float X, float Y, float W, float HT, bool bSelected, bool bPending);
delegate OnAdjustTop(GUIComponent Sender);
// Called when hot tracking, and a new item is highlighted
delegate OnTrack(GUIComponent Sender, int LastIndex);
delegate CheckLinkedObjects( GUIListBase List )
{
if ( IsValid() )
EnableLinkedObjects();
else DisableLinkedObjects();
}
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.InitComponent(MyController,MyOwner);
if (SectionStyleName != "" && SectionStyle == None)
SectionStyle = MyController.GetStyle(SectionStyleName,FontScale);
if (SelectedStyleName != "" && SelectedStyle == None)
SelectedStyle = MyController.GetStyle(SelectedStyleName,FontScale);
if (OutlineStyleName != "" && OutlineStyle == None)
OutlineStyle = MyController.GetStyle(OutlineStyleName,FontScale);
}
function Sort(); // Add in a bit
function int SilentSetIndex(int NewIndex)
{
local int i;
bNotify = False;
i = SetIndex(NewIndex);
bNotify = True;
return i;
}
// Should be subclassed
event int CalculateIndex(optional bool bRequireValidIndex) { return -1; }
function int SetIndex(int NewIndex)
{
if ( !IsValidIndex(NewIndex) )
Index = -1;
else
Index = NewIndex;
if ( index >= 0 && ItemsPerPage > 0 )
{
if ( Index < Top )
SetTopItem(Index);
else if ( Index >= Top + ItemsPerPage )
SetTopItem(Index - ItemsPerPage + 1);
else if ( bNotify )
CheckLinkedObjects(Self);
}
else
{
if ( bNotify )
CheckLinkedObjects(Self);
if ( Top >= ItemCount )
Home();
}
IndexChanged(self);
return Index;
}
function IndexChanged(GUIComponent Sender)
{
if ( bNotify )
OnChange(Sender);
LastSelected = Index;
}
function ClearPendingElements()
{
// log(Name@"ClearPendingElements()");
if (bRepeatClick)
{
bRepeatClick = False;
return;
}
SelectedItems.Remove(0, SelectedItems.Length);
DropIndex = -1;
}
function Clear()
{
Top = 0;
ItemCount=0;
SetIndex(-1);
MyScrollBar.AlignThumb();
}
function MakeVisible(float Perc)
{
SetTopItem(int((ItemCount-ItemsPerPage) * Perc));
}
function SetTopItem(int Item)
{
//log("GUIListBase::SetTopItem"@Item@"ItemsPerPage:"$ItemsPerPage);
Top = Item;
if (Top+ItemsPerPage>=ItemCount)
Top = ItemCount - ItemsPerPage;
if (Top<0)
Top=0;
if ( bNotify )
CheckLinkedObjects(Self);
OnAdjustTop(Self);
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
}
function int AddLinkObject( GUIComponent NewObj, optional bool bNoCheck )
{
local int i;
if ( NewObj != None )
{
if ( !bNoCheck )
{
for (i = 0; i < LinkedObjects.Length; i++)
if ( LinkedObjects[i] == NewObj )
return i;
}
i = LinkedObjects.Length;
LinkedObjects[i] = NewObj;
return i;
}
return -1;
}
function InitLinkObjects( array<GUIComponent> NewObj, optional bool bNoCheck )
{
local int i;
if ( !bNoCheck )
{
for (i = NewObj.Length - 1; i >= 0; i--)
if ( NewObj[i] == None )
NewObj.Remove(i,1);
}
LinkedObjects = NewObj;
if ( bNotify )
CheckLinkedObjects(Self);
}
function EnableLinkedObjects()
{
local int i;
for (i = 0; i < LinkedObjects.Length; i++)
if ( LinkedObjects[i] != None )
EnableComponent(LinkedObjects[i]);
}
function DisableLinkedObjects()
{
local int i;
for (i = 0; i < LinkedObjects.Length; i++)
if ( LinkedObjects[i] != None )
DisableComponent(LinkedObjects[i]);
}
function bool IsValid()
{
if (Index < 0 || Index >= ItemCount)
return false;
return true;
}
function bool IsValidIndex( int i )
{
if ( i < 0 || i >= ItemCount )
return false;
return true;
}
event string AdditionalDebugString()
{
return " SelectedItems:"@ SelectedItems.Length;
}
function string GetItemAtIndex( int idx ) { return ""; }
// Specify true for bGuarantee to receive the selected item if there are no "pending" items
function array<string> GetPendingItems(optional bool bGuarantee)
{
local int i;
local array<string> Items;
if ( (DropState == DRP_Source && Controller.DropSource == Self) || bGuarantee )
{
for ( i = 0; i < SelectedItems.Length; i++ )
if ( IsValidIndex(SelectedItems[i]) )
Items[Items.Length] = GetItemAtIndex(SelectedItems[i]);
if ( Items.Length == 0 && IsValid() )
Items[0] = GetItemAtIndex(Index);
}
return Items;
}
function bool InternalOnKeyEvent( out byte Key, out byte KeyState, float Delta )
{
local int i;
local Interactions.EInputKey iKey;
if ( ItemsPerPage == 0 || ItemsPerPage == 0 ) return false;
iKey = EInputKey(Key);
if ( KeyState == 3 && ikey == IK_MouseWheelUp ) { WheelUp(); return true; }
if ( KeyState == 3 && ikey == IK_MouseWheelDown ) { WheelDown(); return true; }
if ( KeyState != 1 ) return false;
switch ( iKey )
{
case IK_Up:
if ( Up() )
return true;
break;
case IK_Down:
if ( !Controller.ShiftPressed && Down() )
return true;
break;
case IK_Left:
if ( MoveLeft() )
return true;
break;
case IK_Right:
if ( MoveRight() )
return true;
break;
case IK_Home:
Home();
return true;
case IK_End:
End();
return true;
case IK_PageUp:
PgUp();
return true;
case IK_PageDown:
PgDn();
return true;
case IK_A:
if ( Controller.CtrlPressed && bMultiSelect )
{
SelectedItems.Length = ItemCount;
for ( i = 0; i < ItemCount; i++ )
SelectedItems[i] = i;
return true;
}
}
return false;
}
function bool Up() { return false; }
function bool Down() { return false; }
function bool MoveRight() { return false; }
function bool MoveLeft() { return false; }
function WheelUp();
function WheelDown();
function PgUp();
function PgDn();
function Home();
function End();
// We've received a mouse press in the drop source
function InternalOnMousePressed(GUIComponent Sender, bool IsRepeat)
{
local int i, j, k, NewIndex;
if ( !IsInClientBounds() || ItemsPerPage == 0 )
return;
// If not holding down the mouse
if (!IsRepeat && ItemCount > 0)
{
// log(Name@"InternalOnMousePressed");
NewIndex = CalculateIndex(True);
if ( NewIndex == -1 )
return;
LastPressX = Controller.MouseX;
LastPressY = Controller.MouseY;
// If we had an Item selected, go ahead and add it to the drag-n-drop list
if ( Controller.CtrlPressed && bMultiSelect && SelectedItems.Length == 0 && NewIndex != Index )
SelectedItems[SelectedItems.Length] = Index;
// If shift is pressed, do shift selection
if ( Controller.ShiftPressed && IsMultiSelect() )
{
if ( LastSelected == -1 )
LastSelected = 0;
// If not pressing Ctrl, clear out the SelectedItems array
if ( !Controller.CtrlPressed )
for ( j = SelectedItems.Length - 1; j >= 0; j-- )
if ( SelectedItems[j] != Index )
SelectedItems.Remove(j,1);
for ( j = Min(LastSelected, NewIndex); j <= Max(LastSelected, NewIndex); j++ )
{
for ( k = 0; k < SelectedItems.Length; k++ )
{
if ( j == SelectedItems[k] )
break;
if ( j < SelectedItems[k] )
{
SelectedItems.Insert(k, 1);
SelectedItems[k] = j;
break;
}
}
if ( k == SelectedItems.Length )
SelectedItems[k] = j;
}
return;
}
else
{
LastSelected = NewIndex;
if ( IsMultiSelect() )
Index = NewIndex;
}
// Find out if the this index is already in our selected list
for (i = 0; i < SelectedItems.Length; i++)
if (SelectedItems[i] == NewIndex)
break;
// If it was found, remove it (allows toggling an Item's selectedness)
// don't remove it immediately, but set MightRemove. This way, if the user drags
// the selected Item, instead of releasing the mouse, we won't deselect it.
if (i < SelectedItems.Length)
MightRemove = i;
else if (Controller.CtrlPressed && bMultiSelect)
{
for ( i = 0; i < SelectedItems.Length; i++ )
if ( NewIndex < SelectedItems[i] )
{
SelectedItems.Insert(i, 1);
SelectedItems[i] = NewIndex;
break;
}
if ( i == SelectedItems.Length )
SelectedItems[i] = NewIndex;
}
else if (SelectedItems.Length > 0 && MightRemove == -1)
SelectedItems.Remove(0, SelectedItems.Length);
}
}
// Called on both the source and target when mouse is released.
function InternalOnMouseRelease(GUIComponent Sender)
{
// log(Name@"InternalOnMouseRelease Sender:"$Sender.Name);
if ( MightRemove >= 0 && MightRemove < SelectedItems.Length )
SelectedItems.Remove(MightRemove, 1);
MightRemove = -1;
// Stop here if we aren't doing a multi-selection
if ( !IsMultiSelect() )
ClearPendingElements();
}
// Called when mouse is pressed and user begins to move mouse while items are selected.
function bool InternalOnBeginDrag(GUIComponent Sender)
{
if ( Controller == None )
return false;
// Must move the mouse more than 3 pixels in order to begin a drag operation
// to account for accidentally moving the mouse a little while clicking
if ( (Abs(LastPressX - Controller.MouseX) < 3) && (Abs(LastPressY - Controller.MouseY) < 3) )
return false;
// log(Name@"InternalOnBeginDrag");
MightRemove = -1;
if ( SelectedItems.Length == 0 )
CheckDragSelect();
// Assign the offset that native rendering will use to draw the hovering selection
UpdateOffset(ClientBounds[0], ClientBounds[1], ClientBounds[2], ClientBounds[3]);
SetOutlineAlpha(128);
return true;
}
// Find out if we were clicking on any Item - if so, add it to SelectedItems
function CheckDragSelect()
{
local int i;
i = CalculateIndex(True);
if ( i < 0 )
return;
SetIndex(i);
SelectedItems[SelectedItems.Length] = i;
}
function bool InternalOnRightClick( GUIComponent Sender )
{
if ( bDropSource && bMultiSelect && SelectedItems.Length > 0 )
Controller.bIgnoreNextRelease = True;
return true;
}
// Called on the drop source when when an Item has been dropped. bAccepted tells it whether
// the operation was successful or not.
// Should be subclassed
function InternalOnEndDrag(GUIComponent Accepting, bool bAccepted);
// Called on the drop target when the mouse is released - Sender is always DropTarget
// Should be subclassed
function bool InternalOnDragDrop(GUIComponent Sender)
{
return false;
}
// Called on whatever component the data is being dragged over
function InternalOnDragOver(GUIComponent Sender)
{
local int NewIndex;
if ( Controller == None )
return;
if (Controller.DropTarget == Self)
{
NewIndex = CalculateIndex(True);
if (NewIndex == -1)
{
DropIndex = -1;
return;
}
// Remove any items that were selected in this list
if ( Controller.DropSource != Self && SelectedItems.Length > 0 )
SelectedItems.Remove(0, SelectedItems.Length);
DropIndex = NewIndex;
}
}
function InternalOnDragEnter(GUIComponent Sender)
{
/*
Uncomment to add special mouse cursor
MouseCursorIndex = -- "OK to drop here" mouse cursor -- ;
*/
SetOutlineAlpha(255);
}
function InternalOnDragLeave(GUIComponent Sender)
{
/* Uncomment to add special mouse cursor
MouseCursorIndex = -- "Cannot drop here" mouse cursor --;
*/
SetOutlineAlpha(128);
if (DropIndex >= 0)
DropIndex = -1;
}
event bool IsMultiSelect()
{
if ( Controller == None )
return false;
return bDropSource && bMultiSelect && DropState != DRP_Source && (Controller.CtrlPressed || Controller.ShiftPressed) && OnMultiSelect(Self);
}
function SetOutlineAlpha(int NewAlpha)
{
local int i;
if (OutlineStyle == None)
return;
for (i = 0; i < 5; i++)
OutlineStyle.ImgColors[i].A = NewAlpha;
}
defaultproperties
{
bAcceptsInput=true
FontScale=FNS_Small
StyleName="NoBackground"
SelectedStyleName="ListSelection"
SelectedBKColor=(R=255,G=255,B=200,A=255)
SectionJustification=TXTA_Left
Top=0
Index=-1
ItemsPerPage=0
bTabStop=true
bVisibleWhenEmpty=false
bBoundToParent=false
bScaleToParent=false
bDrawSelectionBorder=True
bNotify=True
bInitializeList=True
bMultiSelect=true
bHotTrackSound=True
OutlineStyleName="ItemOutline"
OnBeginDrag=InternalOnBeginDrag
OnEndDrag=InternalOnEndDrag
OnDragDrop=InternalOnDragDrop
OnDragEnter=InternalOnDragEnter
OnDragLeave=InternalOnDragLeave
OnDragOver=InternalOnDragOver
OnRightClick=InternalOnRightClick
OnKeyEvent=InternalOnKeyEvent
OnMousePressed=InternalOnMousePressed
OnMouseRelease=InternalOnMouseRelease
LastSelected=-1
MightRemove=-1
DropIndex=-1
SectionStyleName="ListSection"
}

View file

@ -0,0 +1,93 @@
// ====================================================================
// Class: UT2K4UI.GUIListBox
//
// The GUIListBoxBase is a wrapper for a GUIList and it's ScrollBar
//
// Written by Joe Wilcox
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIListBox extends GUIListBoxBase
native;
var GUIList List; // For Quick Access;
function InitBaseList(GUIListBase LocalList)
{
if ((List == None || List != LocalList) && GUIList(LocalList) != None)
List = GUIList(LocalList);
List.OnClick=InternalOnClick;
List.OnClickSound=CS_Click;
List.OnDblClick=InternalOnDblClick;
List.OnChange=InternalOnChange;
Super.InitBaseList(LocalList);
}
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.Initcomponent(MyController, MyOwner);
if (DefaultListClass != "")
{
List = GUIList(AddComponent(DefaultListClass));
if (List == None)
{
log(Class$".InitComponent - Could not create default list ["$DefaultListClass$"]");
return;
}
}
if (List == None)
{
Warn("Could not initialize list!");
return;
}
InitBaseList(List);
}
function bool InternalOnClick(GUIComponent Sender)
{
List.InternalOnClick(Sender);
OnClick(Self);
return true;
}
function bool InternalOnDblClick(GUIComponent Sender)
{
// List.InternalOnDblClick(Sender);
// OnDblClick(Self);
// ifdef _RO_
OnDblClick(Self);
// endif
return true;
}
function InternalOnChange(GUIComponent Sender)
{
if (Controller != None && Controller.bCurMenuInitialized)
OnChange(Self);
}
function int ItemCount()
{
return List.ItemCount;
}
function bool MyOpen(GUIContextMenu Menu)
{
return HandleContextMenuOpen(self, Menu, Menu.MenuOwner);
}
function bool MyClose(GUIContextMenu Sender)
{
return HandleContextMenuClose(Sender);
}
defaultproperties
{
DefaultListClass="XInterface.GUIList"
}

View file

@ -0,0 +1,122 @@
// ====================================================================
// Class: UT2K4UI.GUIListBoxBase
//
// The GUIListBoxBase is a wrapper for a GUIList and it's ScrollBar
//
// Written by Joe Wilcox
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIListBoxBase extends GUIMultiComponent
Native;
cpptext
{
void PreDraw(UCanvas* Canvas);
void Draw(UCanvas* Canvas); // Handle drawing of the component natively
}
// Styles
var() string SelectedStyleName; // For propagating selected style to the list
var() string SectionStyleName; // For propagating section style to the list
var() string OutlineStyleName; // For propagating outline styles to the list
var() string DefaultListClass;
var automated GUIScrollBarBase MyScrollBar;
var() editconst GUIListBase MyList;
var() bool bVisibleWhenEmpty; // List box is visible when empty.
var() bool bSorted;
var() bool bInitializeList; // Propagated to list
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
local bool bTemp;
// Delay propagation until InitBaseList
bTemp = PropagateVisibility;
PropagateVisibility = False;
Super.InitComponent(MyController, MyOwner);
PropagateVisibility = bTemp;
}
function InitBaseList(GUIListBase LocalList)
{
MyList = LocalList;
LocalList.bNeverScale = True;
LocalList.StyleName = StyleName;
LocalList.bVisibleWhenEmpty = bVisibleWhenEmpty;
LocalList.MyScrollBar = MyScrollBar;
LocalList.bInitializeList = bInitializeList;
LocalList.bSorted = bSorted;
LocalList.FontScale = FontScale;
MyScrollBar.bTabStop = false;
MyScrollBar.SetList(LocalList);
SetVisibility(bVisible);
SetHint(Hint);
}
function SetHint(string NewHint)
{
local int i;
Super.SetHint(NewHint);
for (i=0;i<Controls.Length;i++)
Controls[i].SetHint(NewHint);
}
function InternalOnCreateComponent(GUIComponent NewComp, GUIComponent Sender)
{
if (GUIListBase(NewComp) != None)
{
GUIListBase(NewComp).bInitializeList = bInitializeList;
if (StyleName != "")
NewComp.StyleName = StyleName;
if (SelectedStyleName != "")
GUIListBase(NewComp).SelectedStyleName = SelectedStyleName;
if (SectionStyleName != "")
GUIListBase(NewComp).SectionStyleName = SectionStyleName;
if (OutlineStyleName != "")
GUIListBase(NewComp).OutlineStyleName = OutlineStyleName;
}
}
function SetFriendlyLabel( GUILabel NewLabel )
{
Super.SetFriendlyLabel(NewLabel);
if ( MyList != None )
MyList.SetFriendlyLabel(NewLabel);
if ( MyScrollBar != None )
MyScrollBar.SetFriendlyLabel(NewLabel);
}
defaultproperties
{
OnCreateComponent=InternalOnCreateComponent
Begin Object Class=GUIVertScrollBar Name=TheScrollbar
bVisible=false
End Object
MyScrollBar=TheScrollbar
Begin object Class=GUIToolTip Name=GUIListBoxBaseToolTip
End Object
ToolTip=GUIListBoxBaseToolTip
bAcceptsInput=true
StyleName="NoBackground"
bVisibleWhenEmpty=False
bInitializeList=True
PropagateVisibility=true
FontScale=FNS_Small
SectionStyleName="ListSection"
}

View file

@ -0,0 +1,15 @@
//==============================================================================
// Description
//
// Created by Ron Prestenback
// © 2003, Epic Games, Inc. All Rights Reserved
//==============================================================================
class GUIListHeader extends GUIListSpacer;
DefaultProperties
{
StyleName="ListSection"
LabelStyleName="ListSection"
Tag=-3
FontScale=FNS_Large
}

View file

@ -0,0 +1,27 @@
//==============================================================================
// Description
//
// Created by Ron Prestenback
// © 2003, Epic Games, Inc. All Rights Reserved
//==============================================================================
class GUIListSpacer extends GUIMenuOption;
function InternalOnCreateComponent(GUIComponent NewComp, GUIComponent Sender)
{
if ( Sender == self && GUILabel(NewComp) != None )
NewComp.FontScale = FontScale;
Super.InternalOnCreateComponent(NewComp, Sender);
}
DefaultProperties
{
ComponentClassName="XInterface.GUILabel"
CaptionWidth=1.0
ComponentWidth=0.0
StyleName="NoBackground"
LabelStyleName="TextLabel"
Tag=-2
OnClickSound=CS_None
bNeverFocus=true
}

View file

@ -0,0 +1,218 @@
// ====================================================================
// Class: UT2K4UI.GUIMultiComponent
//
// MenuOptions combine a label and any other component in to 1 single
// control. The Label is left justified, the control is right.
//
// Written by Joe Wilcox
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIMenuOption extends GUIMultiComponent
Native;
cpptext
{
void PreDraw(UCanvas* Canvas);
UBOOL MousePressed(UBOOL IsRepeat);
UBOOL MouseReleased();
}
var(Option) editconst bool bIgnoreChange; // Don't want an OnChange event
var(Option) bool bValueReadOnly; // Value of this option cannot be modified by input
var(Option) bool bAutoSizeCaption; // Extend CaptionWidth if caption is too long
var(Option) bool bHeightFromComponent; // Get the Height of this component from the Component
var(Option) bool bFlipped; // Draw the Component to the left of the caption
var(Option) bool bSquare; // Use the Height for the Width
var(Option) bool bVerticalLayout; // Layout controls vertically
var(Option) eTextAlign LabelJustification; // How do we justify the label
var(Option) eTextAlign ComponentJustification; // How do we justify the label
var(Option) float CaptionWidth; // How big should the Caption be
var(Option) float ComponentWidth; // How big should the Component be (-1 = 1-CaptionWidth)
var(Option) localized string Caption; // Caption for the label
var(Option) string ComponentClassName; // Name of the component to spawn
var(Option) string LabelFont; // Name of the Font for the label
var(Option) string LabelStyleName; // The Style for the label
var(Option) Color LabelColor; // Color for the label
var(Option) editconst noexport GUILabel MyLabel; // Holds the label
var(Option) editconst noexport GUIComponent MyComponent; // Holds the component
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
if (bVerticalLayout) StandardHeight *= 2;
Super.Initcomponent(MyController, MyOwner);
// Create the two components
MyLabel = GUILabel(AddComponent("XInterface.GUILabel"));
if (MyLabel==None)
{
log("Failed to create "@self@" due to problems creating GUILabel");
return;
}
if (bFlipped)
{
if (LabelJustification==TXTA_Left)
LabelJustification=TXTA_Right;
else if (LabelJustification==TXTA_Right)
LabelJustification=TXTA_Left;
if (ComponentJustification==TXTA_Left)
ComponentJustification=TXTA_Right;
else if (ComponentJustification==TXTA_Right)
ComponentJustification=TXTA_Left;
}
MyLabel.Caption = Caption;
if ( LabelStyleName == "" )
{
MyLabel.TextColor = LabelColor;
MyLabel.TextFont = LabelFont;
}
else MyLabel.Style = Controller.GetStyle(LabelStyleName,MyLabel.FontScale);
MyLabel.FontScale = FontScale;
MyLabel.TextAlign = LabelJustification;
MyLabel.IniOption = IniOption;
MyLabel.bNeverScale = True;
if (ComponentClassName == "")
return;
MyComponent = AddComponent(ComponentClassName);
// Check for errors
if (MyComponent == None)
{
log("Could not create requested menu component"@ComponentClassName);
return;
}
SetHint(Hint);
MyComponent.IniOption = IniOption;
if (bHeightFromComponent && !bVerticalLayout)
WinHeight = MyComponent.WinHeight;
else
MyComponent.WinHeight = WinHeight;
MyComponent.OnChange = InternalOnChange;
MyComponent.bTabStop = true;
MyComponent.TabOrder = 1;
MyComponent.bNeverScale = True;
MyComponent.bNeverFocus = bNeverFocus;
SetFriendlyLabel(MyLabel);
if ( MenuState == MSAT_Disabled )
{
MenuState = MSAT_Blurry;
DisableMe();
}
}
// Used for MultiOptionLists
function SetComponentValue(coerce string NewValue, optional bool bNoChange);
function string GetComponentValue()
{
return "";
}
// Reset component to default state
function ResetComponent()
{
SetComponentValue(IniDefault);
}
function SetReadOnly( bool bValue )
{
bValueReadOnly = bValue;
}
function SetHint(string NewHint)
{
Super.SetHint(NewHint);
MyLabel.SetHint(NewHint);
MyComponent.SetHint(NewHint);
}
function SetCaption(string NewCaption)
{
Caption = NewCaption;
MyLabel.Caption = NewCaption;
}
// This is the function that the GUIMultiOptionList will call when this component has been clicked on,
// since it overrides the component's OnClick() delegate
// Return false to prevent the GUIMultiOptionList from passing the OnClick notification upwards
function bool MenuOptionClicked(GUIComponent Sender)
{
return true;
}
function InternalOnChange(GUIComponent Sender)
{
if (Controller != None && Controller.bCurMenuInitialized)
{
if ( !bIgnoreChange )
OnChange(Self);
}
bIgnoreChange = False;
}
function InternalOnCreateComponent(GUIComponent NewComp, GUIComponent Sender);
function CenterMouse()
{
if ( MyComponent != None )
MyComponent.CenterMouse();
else Super.CenterMouse();
}
function SetFriendlyLabel( GUILabel NewLabel )
{
Super.SetFriendlyLabel(NewLabel);
if ( MyComponent != None )
MyComponent.SetFriendlyLabel(NewLabel);
}
defaultproperties
{
OnCreateComponent=InternalOnCreateComponent
Begin object Class=GUIToolTip Name=GUIMenuOptionToolTip
End Object
ToolTip=GUIMenuOptionToolTip
CaptionWidth=0.5
ComponentWidth=-1
WinWidth=0.500000
WinHeight=0.03
WinLeft=0.496094
WinTop=0.347656
LabelFont="UT2MenuFont"
LabelColor=(R=0,G=0,B=64,A=255)
LabelStyleName="TextLabel"
bFlipped=false
LabelJustification=TXTA_Left
ComponentJustification=TXTA_Right
bSquare=false
bTabStop=true
bAcceptsInput=True
PropagateVisibility=true
OnClickSound=CS_Click
bAutoSizeCaption=true
bStandardized=true
StandardHeight=0.03
}

View file

@ -0,0 +1,194 @@
class GUIMultiColumnList extends GUIVertList
native;
cpptext
{
INT FindSortIndex( INT YourArrayIndex ) const;
}
struct native init MultiColumnSortData
{
var() editconst const string SortString; // Set by GetSortString()
var() editconst const int SortItem; // Should be the index into your array for the corresponding SortString
cppstruct
{
FMultiColumnSortData( INT InSortItem = INDEX_NONE, const TCHAR* InString = TEXT("") );
}
};
// There should always be the same number of ColumnHeadings as InitColumnPerc
var() localized array<string> ColumnHeadings;
var() array<float> InitColumnPerc;
var() localized array<string> ColumnHeadingHints;
// Set natively, for speed
var const array<MultiColumnSortData> SortData; // Filled with results of GetSortString()
var const array<int> InvSortData; // Used for keeping same item selected after sorting
var() const editconst array<float> ColumnWidths;
// sorting stuff
var() float CellSpacing;
var() int SortColumn; // Column that is currently used for sorting ( -1 for no sorting )
var() bool NeedsSorting; // Will automatically sort when this is true
var() bool SortDescending; // Used by native sorting to determine which direction to sort
var() bool ExpandLastColumn; // If true & columns widths do not add up to 100%, last column will be stretched
// notification
delegate OnColumnSized(int column);
native final function int GetListIndex( int YourArrayIndex );
native final function ChangeSortOrder();
native final function SortList();
native final function UpdatedItem( int YourArrayIndex ); // should be called when we update an item's data
native final function RemovedItem( int YourArrayIndex );
// must be called when we add an item to the list.
// If your data is contained in a single array, but is represented as multiple multicolumn lists,
// pass in your array index (see UT2K4Tab_PlayerLoginControls for an example of this)
native final function AddedItem(optional int YourArrayIndex);
delegate string GetSortString( int YourArrayIndex );
function int CurrentListId()
{
if (Index < 0)
return -1;
return SortData[Index].SortItem;
}
event OnSortChanged()
{
if (SortData.Length <= 0)
return;
ChangeSortOrder();
// resort list
SortList();
// remap the selection item back again to keep the same item selected
if ( IsValid() )
Index = InvSortData[Index];
}
function Clear()
{
SortData.Remove(0,SortData.Length);
InvSortData.Remove(0,InvSortData.Length);
Super.Clear();
}
function RemovedCurrent()
{
if ( IsValid() )
{
RemovedItem(CurrentListId());
SetIndex(Index);
}
}
function ResolutionChanged( int ResX, int ResY )
{
if ( !bInit )
bInit = True;
Super.ResolutionChanged(ResX,ResY);
}
event InitializeColumns(Canvas C)
{
local int i;
local float AW;
if ( bDebugging )
log(Name@"#### InitializeColumns ActualWidth() = "@ActualWidth()@"WinWidth:"$WinWidth);
AW = ActualWidth();
for(i=0; i<InitColumnPerc.Length; i++)
{
if ( bDebugging )
log(Name@"#### InitColumnPerc["$i$"]:"$InitColumnPerc[i]);
ColumnWidths[i] = AW * InitColumnPerc[i];
}
bInit = false;
}
function bool InternalOnPreDraw(Canvas C)
{
local float x;
local int i;
if (bInit)
return false;
if( NeedsSorting )
{
SortList();
if ( IsValid() )
Index = InvSortData[Index];
}
if( ExpandLastColumn )
{
for( i=0;i<ColumnWidths.Length-1;i++ )
x += ColumnWidths[i];
ColumnWidths[i] = ActualWidth() - x;
}
return false;
}
function GetCellLeftWidth( int Column, out float Left, out float Width )
{
local int i;
Left = ClientBounds[0];
for( i=0;i<Column && i<ColumnWidths.Length;i++ )
Left += ColumnWidths[i];
if( i<ColumnWidths.Length )
Width = ColumnWidths[i];
else
Width = 0;
Left += CellSpacing;
Width -= 2*CellSpacing;
if ( Left >= Bounds[2] )
Width = 0;
if (Left + Width >= Bounds[2])
Width = Bounds[2] - Left;
if ( Width < 0 )
Width = 0;
}
function Sort()
{
SortList();
}
function Dump()
{
local int i;
log("Dumping multicolumn list contents '"$Name$"'");
for ( i = 0; i < SortData.Length; i++ )
{
if ( i < InvSortData.Length )
log(" " $ i $ ")" @ "'" $ SortData[i].SortString $ "'" @ SortData[i].SortItem @ "InvSortData:"$InvSortData[i]);
else log(" " $ i $ ")" @ "'" $ SortData[i].SortString $ "'" @ SortData[i].SortItem @ "InvSortData: Invalid");
}
}
defaultproperties
{
OnPreDraw=InternalOnPreDraw
CellSpacing=1.0
}

View file

@ -0,0 +1,116 @@
//====================================================================
// Parent: GUIListBoxBase
// Class: UT2K4UI.GUIMultiColumnListBox
// Date: 05-01-2003
//
// Base class for listboxes which use multiple columns for showing data.
//
// Updated by Ron Prestenback
// TODO: Update all panels that use this component to save the header column perc's
// (c) 2003, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIMultiColumnListBox extends GUIListBoxBase
native;
cpptext
{
void PreDraw(UCanvas* Canvas);
void Draw(UCanvas* Canvas);
}
var Automated GUIMultiColumnListHeader Header;
var() bool bDisplayHeader;
var() editconst GUIMultiColumnList List;
var() array<float> HeaderColumnPerc;
var() localized array<string> ColumnHeadings;
var() bool bFullHeightStyle;
function InitBaseList(GUIListBase LocalList)
{
if ((List == None || List != LocalList) && GUIMultiColumnList(LocalList) != None)
List = GUIMultiColumnList(LocalList);
if ( ColumnHeadings.Length > 0 )
List.ColumnHeadings = ColumnHeadings;
Header.MyList = List;
Super.InitBaseList(LocalList);
}
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.InitComponent(MyController, MyOwner);
if (DefaultListClass!="")
{
List = GUIMultiColumnList(AddComponent(DefaultListClass));
if (List==None)
{
log(Class$".InitComponent - Could not create default list ["$DefaultListClass$"]");
return;
}
}
if (List == None)
{
Warn("Could not initialize list!");
return;
}
InitBaseList(List);
if (bFullHeightStyle)
List.Style=None;
}
function InternalOnLoadIni(GUIComponent Sender, string S)
{
local int i;
if (GUIMultiColumnList(Sender) != None)
{
if (HeaderColumnPerc.Length == GUIMultiColumnList(Sender).InitColumnPerc.Length)
GUIMultiColumnList(Sender).InitColumnPerc = HeaderColumnPerc;
else
{
if (GUIMultiColumnList(Sender).InitColumnPerc.Length == 0)
GUIMultiColumnList(Sender).InitColumnPerc.Length = HeaderColumnPerc.Length;
for (i = 0; i < HeaderColumnPerc.Length && i < GUIMultiColumnList(Sender).InitColumnPerc.Length; i++)
GUIMultiColumnList(Sender).InitColumnPerc[i] = HeaderColumnPerc[i];
}
}
}
function InternalOnCreateComponent(GUIComponent NewComp, GUIComponent Sender)
{
if (GUIMultiColumnList(NewComp) != None)
{
GUIMultiColumnList(NewComp).OnColumnSized = InternalOnColumnSized;
NewComp.IniOption = "@Internal";
NewComp.OnLoadINI = InternalOnLoadIni;
}
Super.InternalOnCreateComponent(NewComp, Sender);
}
function InternalOnColumnSized(int Column)
{
HeaderColumnPerc[Column] = List.ColumnWidths[Column] / ActualWidth();
}
defaultproperties
{
bDisplayHeader=true
Begin Object Class=GUIMultiColumnListHeader Name=MyHeader
End Object
DefaultListClass="Xinterface.GUIMultiColumnList"
Header=MyHeader
bVisible=True
bRequiresStyle=True
}

View file

@ -0,0 +1,43 @@
class GUIMultiColumnListHeader extends GUIComponent
native;
cpptext
{
UBOOL MousePressed(UBOOL IsRepeat);
UBOOL MouseReleased();
UBOOL MouseMove(INT XDelta, INT YDelta);
UBOOL MouseHover();
void Draw(UCanvas* Canvas);
void PreDraw(UCanvas* Canvas);
}
var() GUIMultiColumnList MyList;
var() editconst const int SizingCol;
var() editconst const int ClickingCol;
var GUIStyles BarStyle;
var string BarStyleName;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
local eFontScale x;
Super.InitComponent(MyController, MyOwner);
if (BarStyleName!="")
BarStyle = Controller.GetStyle(BarStyleName,x);
}
defaultproperties
{
StyleName="SectionHeaderTop"
BarStyleName="SectionHeaderBar"
bCaptureTabs=False
bNeverFocus=False
bTabStop=False
bAcceptsInput=True
SizingCol=-1
ClickingCol=-1
bRequiresStyle=True
}

View file

@ -0,0 +1,528 @@
// ====================================================================
// 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
{
void PreDraw(UCanvas* Canvas); // Do any size/postitioning
void Draw(UCanvas* Canvas); // Draw the component
void PreDrawControls(UCanvas* Canvas);
void DrawControls(UCanvas* Canvas);
virtual void InitializeControls(); // Takes all GUIComponent members and assigns them to the controls array
virtual void RemapComponents();
UGUIComponent* UnderCursor(FLOAT MouseX, FLOAT MouseY);
UBOOL NativeKeyType(BYTE& iKey, TCHAR Unicode ); // A Key or Mouse button has pressed
UBOOL NativeKeyEvent(BYTE& iKey, BYTE& State, FLOAT Delta ); // A Key/Mouse event occured
void NativeInvalidate(UGUIComponent* Who);
UBOOL SpecialHit( UBOOL bForce );
UBOOL PerformHitTest(INT MouseX, INT MouseY);
UBOOL MousePressed(UBOOL IsRepeat); // The left mouse button was pressed
UBOOL MouseReleased(); // The mouse button was released
UGUIComponent* GetFocused() const { return FocusedControl; }
UBOOL IsFocusedOn( const UGUIComponent* Comp ) const { return Comp && Comp == GetFocused(); }
void NotifyResolutionChange( INT NewResX, INT NewResY );
#ifdef UCONST_Counter
virtual void ResetCounter();
#endif
}
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[i] == None)
{
if ( Controller.bModAuthor )
log(Name@"- Invalid control found in"@GetMenuPath()$"!! (Control"@i$")",'ModAuthor');
Controls.Remove(i--,1);
continue;
}
OnCreateComponent(Controls[i], Self);
Controls[i].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[i] == 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[i].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[i].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[i].FocusFirst(Sender) )
return true;
}
}
for (i=0;i<Controls.Length;i++)
{
if ( Controls[i].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[i].FocusLast(Sender))
return true;
}
}
for (i=Controls.Length-1;i>=0;i--)
{
if ( Controls[i].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[i]);
}
singular function DisableMe()
{
local int i;
Super.DisableMe();
for ( i = 0; i < Controls.Length; i++ )
DisableComponent(Controls[i]);
}
event SetVisibility(bool bIsVisible)
{
local int i;
Super.SetVisibility(bIsVisible);
if ( !PropagateVisibility )
return;
for (i=0;i<Controls.Length;i++)
Controls[i].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
PropagateVisibility=false
}

View file

@ -0,0 +1,847 @@
/*==============================================================================
Vertical list containing multiple GUIMenuOptions
The inherent problem with GUIMultiOptionList is that is actually a GUIMultiComponent, in that it is a component
that will be the MenuOwner for other components. However, it is a list, which is not a subclass of GUIMultiComponent.
When designing this class, I had to choose whether to derive it from GUIListBase, thus inheriting all the behavior
of GUIListBase, but requiring the behavior of GUIMultiComponent to be reimplemented, or vice versa. I decided to
go with subclassing GUIListBase, since all other components of the menu should see this class as a list, and treat
it as such. Having to deal with passing input, focus and drawing to all its inner components is something that only
concerns GUIMultiOptionList, while having an interface consistent with other lists is very much a concern for the
rest of the GUI.
Since we do not have the benefits of the FocusedControl property of GUIMultiComponent, among which are things like:
always drawn last to ensure that it is always on top, chance to process input first, etc., I need some other method
to represent which of the elements are currently my "FocusedControl".
GUI lists normally use the Index property to indicate the element which is currently selected, and this would work
really well for the most part. However, this is not 100% reliable for indicating which of the elements of the
GUIMultiOptionList should be the "FocusedControl". If the list has hot tracking enabled, this index will be changed
constantly, meaning that the user would always need to have the mouse over the element that they are interacting
with in order for that element to correctly receive input and focus.
To solve this, I use the FocusInstead property to represent the list element that is the "FocusedControl" (receiving
input, being drawn last, etc.). Index is used in the same manner as it is used in other GUI lists, with the exception
that for rendering, the "selected" item is always the one that corresponds to FocusInstead, rather than the element
at Index.
Created by Ron Prestenback
© 2003, Epic Games, Inc. All Rights Reserved
==============================================================================*/
class GUIMultiOptionList extends GUIVertList
native;
cpptext
{
protected:
void DrawItem(UCanvas* Canvas, INT Item, FLOAT X, FLOAT Y, FLOAT W, FLOAT HT, UBOOL bSelected, UBOOL bPending);
public:
UBOOL MousePressed(UBOOL IsRepeat);
UBOOL MouseReleased();
void PreDraw(UCanvas* Canvas);
void Draw(UCanvas* Canvas);
UBOOL NativeKeyType(BYTE& iKey, TCHAR Unicode );
UBOOL NativeKeyEvent(BYTE& iKey, BYTE& State, FLOAT Delta );
void NativeInvalidate(UGUIComponent* Who);
UBOOL SpecialHit( UBOOL bForce );
UGUIComponent* GetFocused() const;
UGUIComponent* UnderCursor( FLOAT MouseX, FLOAT MouseY );
INT CalculateIndex( UBOOL bRequireValidIndex = 0 );
#ifdef UCONST_Counter
virtual void ResetCounter();
#endif
}
var() editconst editconstarray array<GUIMenuOption> Elements;
var() float ItemScaling; // Used to scale the total item height of the list elements
// Controls amount of border drawn around each item
// ItemHeight (after ItemScaling is applied) is further reduced by this value, and elements are centered vertically
var() float ItemPadding;
// Support for multiple columns
var() float ColumnWidth;
var() int NumColumns;
var() editconst int ItemsPerColumn;
// Only DRD_LefttoRight & DRD_TopToBottom supported - indicates direction of increment
// LeftToRight - TopToBottom
// 1 2 3 4 1 3 5 7
// 5 6 7 8 2 4 6 8
var() bool bVerticalLayout;
delegate OnCreateComponent(GUIMenuOption NewComp, GUIMultiOptionList Sender);
function InitComponent(GUIController InController, GUIComponent InOwner)
{
Super.InitComponent(InController, InOwner);
MyScrollBar.AlignThumb = ScrollAlignThumb;
}
event int CalculateIndex( optional bool bRequireValidIndex )
{
local int NewIndex, i;
local float X, Y;
NewIndex = -1;
if ( IsInClientBounds() )
{
X = ClientBounds[0];
Y = ClientBounds[1];
NewIndex = Top;
if ( bVerticalLayout )
i = 1;
while ( NewIndex < ItemCount )
{
if ( !ElementVisible(NewIndex) )
{
NewIndex++;
continue;
}
if ( Controller.MouseX >= X && Controller.MouseX <= X + ItemWidth &&
Controller.MouseY >= Y && Controller.MouseY <= Y + ItemHeight )
break;
if ( bVerticalLayout )
{
NewIndex += ItemsPerColumn;
X += ItemWidth;
if ( NewIndex >= ItemCount )
{
X = ClientBounds[0];
Y += ItemHeight;
NewIndex = Top + i++;
if ( NewIndex >= Top + Min(ItemsPerPage, ItemCount) / NumColumns )
{
if ( bRequireValidIndex )
NewIndex = -1;
break;
}
}
}
else
{
X += ItemWidth;
if ( ++i >= NumColumns )
{
i = 0;
X = ClientBounds[0];
Y += ItemHeight;
}
}
NewIndex++;
}
}
if ( NewIndex >= ItemCount && bRequireValidIndex )
NewIndex = -1;
return Min(NewIndex, ItemCount - 1);
}
event bool ElementVisible( int Idx )
{
local int i;
if ( bVerticalLayout )
{
i = Idx - (ItemsPerColumn * (Idx / ItemsPerColumn));
return i >= Top && i < Min(Top + ItemsPerPage / NumColumns, ItemCount - 1);
}
else return Idx >= Top && Idx < Top + ItemsPerPage;
}
function bool InternalOnClick(GUIComponent Sender)
{
local int NewIndex;
if ( ItemsPerPage==0 )
return false;
NewIndex = CalculateIndex();
if ( !IsValidIndex(NewIndex) )
return false;
SilentSetIndex(NewIndex);
// We must intercept the menu options's OnClick delegate, since most don't handle the click event unless
// the click was on their component
// However, we need to know when the option is clicked, so that I can send the notification upwards
// Using the normal OnChange() chain of events is no good here, since GUIMultiOptionList passes OnChange()
// to indicate that a component's value has changed
// But I still need to allow a way for modders MenuOption subclasses to receive the OnClick as well
if ( GUIMenuOption(Sender) != None && !GUIMenuOption(Sender).MenuOptionClicked(Sender) )
return true;
if ( Sender != Self )
OnClick(Self);
return true;
}
protected function GenerateMenuOption(out string NewOptionClass, out GUIMenuOption NewComp, out string Caption)
{
local class<GUIMenuOption> MOClass;
if (NewOptionClass == "" && NewComp == None)
{
Warn("Must specify a menu option class to add item to list!");
return;
}
else if (NewComp == None)
{
MOClass = class<GUIMenuOption>(Controller.AddComponentClass(NewOptionClass));
if (MOClass == None)
{
Warn("Could not create new menu option for list:"@NewOptionClass);
return;
}
NewComp = new(None) MOClass;
}
else NewOptionClass = string(NewComp.Class);
if (Caption != "")
NewComp.Caption = Caption;
else Caption = NewComp.Caption;
NewComp.ComponentJustification = TXTA_Left;
NewComp.LabelJustification = TXTA_Center;
NewComp.bAutoSizeCaption = true;
if (NewComp.LabelStyleName == "")
NewComp.LabelStyleName = StyleName;
// NewComp.OnClick = InternalOnClick;
NewComp.OnChange = InternalOnChange;
NewComp.bHeightFromComponent = False;
OnCreateComponent(NewComp, Self);
NewComp.InitComponent(Controller, Self);
NewComp.OnClick = InternalOnClick;
// If hot tracking is enabled, set the friendly label of the component so that the label's
// state gets updated correctly when we mouse over the component
// if ( bHotTrack )
// NewComp.SetFriendlyLabel(NewComp.MyLabel);
}
function GUIMenuOption AddItem(string NewOptionClass, optional GUIMenuOption NewComp, optional string Caption, optional bool bUnique)
{
local int i;
if (Caption != "" && bUnique)
{
for (i = 0; i < Elements.Length; i++)
if (Elements[i].Caption == Caption)
return None;
}
GenerateMenuOption(NewOptionClass, NewComp, Caption);
if (NewComp != None)
{
Elements[Elements.Length] = NewComp;
NewComp.Opened(Self);
if (MyScrollBar != None)
MyScrollBar.AlignThumb();
}
ItemCount = Elements.Length;
CheckLinkedObjects(Self);
return NewComp;
}
function GUIMenuOption ReplaceItem(int idx, string NewOptionClass, optional GUIMenuOption NewComp, optional string Caption, optional bool bUnique)
{
local int i;
if ( !ValidIndex(Idx) )
return AddItem(NewOptionClass, NewComp, Caption, bUnique);
if (Caption != "" && bUnique)
for (i = 0; i < Elements.Length; i++)
if (Caption == Elements[i].Caption)
return None;
GenerateMenuOption(NewOptionClass, NewComp, Caption);
if (NewComp != None)
{
if (NewComp != Elements[Index])
{
NewComp.TabOrder = Elements[Index].TabOrder;
Elements[Index].Free();
Elements[Index] = NewComp;
NewComp.Opened(Self);
if (Controller.bCurMenuInitialized)
OnChange(Self);
}
}
return NewComp;
}
function GUIMenuOption InsertItem(int Idx, string NewOptionClass, optional GUIMenuOption NewComp, optional string Caption, optional bool bUnique)
{
local int i;
if ( !ValidIndex(Idx) )
return AddItem(NewOptionClass, NewComp, Caption, bUnique);
if (Caption != "" && bUnique)
for (i = 0; i < Elements.Length; i++)
if (Caption == Elements[i].Caption)
return None;
GenerateMenuOption(NewOptionClass, NewComp, Caption);
if (NewComp != None)
{
NewComp.TabOrder = Idx;
Elements.Insert(Idx, 1);
Elements[Idx] = NewComp;
NewComp.Opened(Self);
while (++Idx < Elements.Length)
Elements[Idx].TabOrder = Idx;
if (MyScrollBar != None)
MyScrollBar.AlignThumb();
if (Controller.bCurMenuInitialized)
OnChange(Self);
}
ItemCount = Elements.Length;
return NewComp;
}
function RemoveItem(int Idx)
{
if ( ValidIndex(Idx) )
{
Elements[Idx].Free();
Elements.Remove(Idx, 1);
// Run through the remaining items and update their tab orders.
while (Idx < Elements.Length)
Elements[Idx].TabOrder = Idx++;
SetIndex(-1);
if (MyScrollBar != None)
MyScrollBar.AlignThumb();
}
ItemCount = Elements.Length;
}
function Clear()
{
local int i;
for (i = 0; i < Elements.Length; i++)
Elements[i].Free();
Elements.Remove(0, Elements.Length);
Super.Clear();
}
event bool ValidIndex(int Idx)
{
if (Idx < 0 || Idx >= Elements.Length)
return false;
return true;
}
function GUIMenuOption Get()
{
if (ValidIndex(Index))
return Elements[Index];
return none;
}
function GUIMenuOption GetItem(int Idx)
{
if (ValidIndex(Idx))
return Elements[Idx];
return None;
}
function int Find(string Caption)
{
local int i;
for (i = 0; i < Elements.Length; i++)
if (Elements[i].Caption ~= Caption)
return i;
return -1;
}
function int FindComp(GUIMenuOption Comp)
{
local int i;
for (i = 0; i < Elements.Length; i++)
if (Elements[i] == Comp)
return i;
return -1;
}
function InternalOnChange(GUIComponent Sender)
{
if (Controller.bCurMenuInitialized)
{
if (GUIMenuOption(Sender) != None)
SilentSetIndex(FindComp(GUIMenuOption(Sender)));
OnChange(Self);
}
}
function ShowList()
{
local int i;
for (i = 0; i < Elements.Length; i++)
Elements[i].Show();
}
function HideList()
{
local int i;
for (i = 0; i < Elements.Length; i++)
Elements[i].Hide();
}
// Hack to prevent recursion
function int SetIndex(int NewIndex)
{
if (NewIndex == Index)
{
if (ValidIndex(NewIndex) && CanFocusElement(Elements[NewIndex]))
Elements[NewIndex].SetFocus(None);
return NewIndex;
}
if (NewIndex < 0 || NewIndex >= ItemCount)
Index = -1;
else
Index = NewIndex;
if ( Index >= 0 && ItemsPerPage > 0 && !ElementVisible(Index) )
SetTopItem(Index);
// if (ItemsPerPage > 0 && !ElementVisible(Index))
// SetTopItem( (Index - (ItemsPerPage / NumColumns)) + 1);
// }
IndexChanged(Self);
bNotify = True;
if ( ElementVisible(Index) && Index < ItemCount && CanFocusElement(Elements[NewIndex]) )
Elements[Index].SetFocus(None);
return Index;
}
event SetFocus(GUIComponent Who)
{
if (Who==None)
{
Super.SetFocus(None);
return;
}
MenuStateChange(MSAT_Focused);
FocusInstead = Who;
Index = FindComp(GUIMenuOption(Who));
if (MenuOwner != None)
MenuOwner.SetFocus(Self);
}
event LoseFocus(GUIComponent Sender)
{
if ( bHotTrack )
FocusInstead = None;
Super.LoseFocus(Sender);
}
function ScrollAlignThumb()
{
local float NewPos;
if (ItemCount==0)
NewPos = 0;
else
{
if ( bVerticalLayout )
NewPos = float(Top) / (float(ItemsPerColumn) - (ItemsPerPage / NumColumns));
else NewPos = float(Top) / float(ItemCount-ItemsPerPage);
}
MyScrollBar.GripPos = FClamp(NewPos,0.0,1.0);
}
function MakeVisible(float Perc)
{
local float MaxTop, ModResult;
local int NewTop, Change;
if ( !bVerticalLayout )
{
MaxTop = ItemCount - ItemsPerPage;
ModResult = MaxTop % NumColumns;
if ( ModResult > 0 )
MaxTop = (MaxTop - ModResult) + NumColumns;
// NewItem is number of hidden items * Perc we want to show
// Round off result before adjusting top to prevent constant flipping back and forth between two items
// or if we're attempting to view the last row
NewTop = Round(MaxTop * Perc);
Change = Abs(Top - NewTop);
if ( Change < NumColumns && Perc < 1.0)
return;
}
else
{
MaxTop = ItemsPerColumn - (ItemsPerPage / NumColumns);
NewTop = Round(MaxTop * Perc);
}
SetTopItem(NewTop);
}
function SetTopItem(int Item)
{
local int ModResult;
if ( bVerticalLayout )
{
while ( Item > ItemsPerColumn )
Item -= ItemsPerColumn;
Item = Clamp( Item, 0, ItemsPerColumn - (ItemsPerPage / NumColumns) );
// Adjust the result to fall on the first column - otherwise, elements might get shifted to a different column
}
else
{
// clamp new top to prevent displaying space below last items of list
// Item = Clamp(Item, 0, ItemCount - ItemsPerPage);
Item = Clamp(Item, 0, ItemCount - 1);
// Adjust the result to fall on the first column - otherwise, elements might get shifted to a different column
ModResult = Item % NumColumns;
if ( ModResult > 0 )
{
// If we had leftover items, we'll need another row
if ( Item > Top )
Item += NumColumns;
Item -= ModResult;
}
// But if we went too far (more than itemcount + numcolumns), then back it up
while ( (Item + ItemsPerPage > ItemCount + NumColumns) && Item >= 0)
Item -= NumColumns;
}
Top = Max( 0, Item );
OnAdjustTop(Self);
}
function InternalOnAdjustTop(GUIComponent Sender)
{
if ( !bHotTrack && !ElementVisible(Index) )
FocusInstead = None;
else if (bHotTrack && ElementVisible(Index) && Index < Elements.Length && CanFocusElement(Elements[Index]) )
FocusInstead = Elements[Index];
}
function WheelDown()
{
if (MyScrollBar!=None)
{
if (Controller.CtrlPressed)
MyScrollBar.MoveGripBy(ItemsPerPage);
else MyScrollBar.MoveGripBy(NumColumns);
}
else
{
if (!Controller.CtrlPressed)
Down();
else
PgDn();
}
}
function PgUp()
{
if (ItemCount<2) return;
if ( bVerticalLayout )
SetIndex( Max(0, Index - ItemsPerPage / NumColumns) );
else Super.PgUp();
}
function PgDn()
{
if (ItemCount<2) return;
if ( bVerticalLayout )
SetIndex( Min(Index + ItemsPerPage / NumColumns, ItemCount - 1) );
else Super.PgDn();
}
function bool Up()
{
local int NewIndex;
if ( bVerticalLayout )
{
if ( Index > 0 && Index % ItemsPerColumn > 0 )
{
NewIndex = Index - 1;
while ( NewIndex > 0 && !CanFocusElement(Elements[NewIndex]) && NewIndex % ItemsPerColumn > 0 )
NewIndex--;
NewIndex = Max(0, NewIndex);
// Check once more that element can accept focus, in case we're at 0 and 0 is a title bar
if ( CanFocusElement(Elements[NewIndex]) )
SetIndex( NewIndex );
}
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
return true;
}
if ( Index - NumColumns >= 0 )
{
NewIndex = Index - NumColumns;
while ( NewIndex - NumColumns >= 0 && !CanFocusElement(Elements[NewIndex]) )
NewIndex -= NumColumns;
NewIndex = Max(0, NewIndex);
// Check once more that element can accept focus, in case we're at 0 and 0 is a title bar
if ( CanFocusElement(Elements[NewIndex]) )
SetIndex( NewIndex );
}
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
return true;
}
function bool Down()
{
local int NewIndex;
if ( bVerticalLayout )
{
NewIndex = Index + 1;
if ( NewIndex % ItemsPerColumn > 0 && NewIndex < ItemCount )
{
while ( NewIndex < ItemCount && NewIndex % ItemsPerColumn > 0 && !CanFocusElement(Elements[NewIndex]) )
NewIndex++;
NewIndex = Min(NewIndex, ItemCount - 1);
if ( CanFocusElement(Elements[NewIndex]) )
SetIndex( NewIndex );
}
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
return true;
}
if ( Index + NumColumns < ItemCount )
{
NewIndex = Index + NumColumns;
while ( NewIndex + NumColumns < ItemCount && !CanFocusElement(Elements[NewIndex]) )
NewIndex += NumColumns;
NewIndex = Min(NewIndex, ItemCount - 1);
if ( CanFocusElement(Elements[NewIndex]) )
SetIndex( NewIndex );
}
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
return true;
}
function bool MoveRight()
{
local int NewIndex, Avail;
if ( bVerticalLayout )
{
NewIndex = Index + ItemsPerColumn;
if ( Index + ItemsPerColumn >= ItemCount )
return true;
while ( NewIndex + ItemsPerColumn < ItemCount && !CanFocusElement(Elements[NewIndex]) )
NewIndex += ItemsPerColumn;
NewIndex = Min(NewIndex, ItemCount - 1);
if ( CanFocusElement(Elements[NewIndex]) )
SetIndex(NewIndex);
return true;
}
Avail = NumColumns - (Index % NumColumns) - 1;
NewIndex = Index + 1;
if ( Avail > 0 && NewIndex < ItemCount && ItemCount > 0 )
{
while ( NewIndex - Index <= Avail && NewIndex < ItemCount && !CanFocusElement(Elements[NewIndex]) )
NewIndex++;
NewIndex = Min(NewIndex, ItemCount - 1);
if ( CanFocusElement(Elements[NewIndex]) )
SetIndex( NewIndex );
return true;
}
return true;
}
function bool MoveLeft()
{
local int NewIndex, Avail;
if ( bVerticalLayout )
{
NewIndex = Index - ItemsPerColumn;
if ( NewIndex < 0 )
return true;
while ( NewIndex - ItemsPerColumn >= 0 && !CanFocusElement(Elements[NewIndex]) )
NewIndex -= ItemsPerColumn;
NewIndex = Max(0, NewIndex);
if ( CanFocusElement(Elements[NewIndex]) )
SetIndex(NewIndex);
return true;
}
Avail = Index % NumColumns;
if ( Avail > 0 && Index > 0 && ItemCount > 0 )
{
NewIndex = Index - 1;
while ( Index - NewIndex <= Avail && NewIndex > 0 && !CanFocusElement(Elements[NewIndex]) )
NewIndex--;
NewIndex = Max(0, NewIndex);
if ( CanFocusElement(Elements[NewIndex]) )
SetIndex( NewIndex );
return true;
}
return true;
}
event bool NextControl(GUIComponent Sender)
{
if (Controller.CtrlPressed ||
Controller.AltPressed ||
Controller.ShiftPressed ||
(ItemCount > 1 && Index == ItemCount - 1) )
{
if (MenuOwner != None)
return MenuOwner.NextControl(Self);
}
if ( bVerticalLayout )
return Down();
return MoveRight();
}
event bool PrevControl(GUIComponent Sender)
{
if (Controller.CtrlPressed ||
Controller.AltPressed ||
Controller.ShiftPressed ||
(ItemCount > 1 && Index <= 0) )
{
if (MenuOwner != None)
return MenuOwner.PrevControl(Self);
}
if ( bVerticalLayout )
return Up();
else return MoveLeft();
}
protected event bool CanFocusElement( GUIMenuOption Elem )
{
return Elem != None && Elem.MenuState != MSAT_Disabled && GUIListSpacer(Elem) == None;
}
function CenterMouse()
{
local GUIMenuOption mo;
mo = Get();
if ( CanFocusElement(mo) )
{
mo.CenterMouse();
return;
}
Super.CenterMouse();
}
DefaultProperties
{
OnAdjustTop=InternalOnAdjustTop
NumColumns=1
ItemScaling=0.045
ItemPadding=0.1
SectionStyleName="ListSection"
bNotify=True
ColumnWidth=1.0
}

View file

@ -0,0 +1,150 @@
//==============================================================================
// Listbox for GUIMultiOptionLists
//
// Created by Ron Prestenback
// © 2003, Epic Games, Inc. All Rights Reserved
//==============================================================================
class GUIMultiOptionListBox extends GUIListBoxBase;
var() editconst GUIMultiOptionList List;
var() int NumColumns;
function InitBaseList(GUIListBase LocalList)
{
local GUIMultiOptionList L;
L = GUIMultiOptionList(LocalList);
if ( L == None || L == List )
return;
Super.InitBaseList(LocalList);
if ( List != None )
{
List.KillTimer();
List.OnClick = None;
List.OnChange = None;
List.OnCreateComponent = None;
List.OnSaveIni = None;
List.OnLoadIni = None;
RemoveComponent(List,true);
List = GUIMultiOptionList(AppendComponent(L));
}
else List = GUIMultiOptionList(AppendComponent(L));
if ( List != None )
{
List.OnClick=InternalOnClick;
List.OnClickSound=CS_Click;
List.OnChange=InternalOnChange;
List.OnCreateComponent=ListCreateComponent;
List.OnSaveINI=ListSaveIni;
List.OnLoadINI=ListLoadIni;
}
}
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
local GUIMultiOptionList L;
local class<GUIMultiOptionList> ListClass;
Super.InitComponent(MyController, MyOwner);
MyScrollBar.Step = NumColumns;
if (DefaultListClass != "")
{
ListClass = class<GUIMultiOptionList>(Controller.AddComponentClass(DefaultListClass));
if ( ListClass != None )
L = new(None) ListClass;
if (L == None)
{
log(Class$".InitComponent - Could not create default list ["$DefaultListClass$"]");
return;
}
if (L == None)
{
Warn("Could not initialize list!");
return;
}
InitBaseList(L);
}
}
function bool InternalOnClick(GUIComponent Sender)
{
OnClick(Self);
return true;
}
function InternalOnChange(GUIComponent Sender)
{
//log(Name@"InternalonChange:"$Sender);
OnChange(Sender);
}
function int ItemCount()
{
return List.ItemCount;
}
function ListLoadIni(GUIComponent Sender, string S)
{
OnLoadIni(Sender, S);
}
function string ListSaveIni(GUIComponent Sender)
{
return OnSaveIni(Sender);
}
function ListCreateComponent(GUIMenuOption NewComp, GUIMultiOptionList Sender)
{
NewComp.IniOption = "@Internal";
NewComp.OnSaveINI = ListSaveINI;
NewComp.OnLoadINI = ListLoadINI;
OnCreateComponent(NewComp, Sender);
}
function InternalOnCreateComponent(GUIComponent NewComp, GUIComponent Sender)
{
Super.InternalOnCreateComponent(NewComp, Sender);
if (GUIMultiOptionList(NewComp) != None)
GUIMultiOptionList(NewComp).NumColumns = NumColumns;
}
function InternalOnScrollRelease(GUIComponent Sender)
{
MyScrollBar.GripPreDraw(MyScrollBar.MyGripButton);
}
singular function EnableMe()
{
local int i;
Super.EnableMe();
for ( i = 0; i < List.ItemCount; i++ )
EnableComponent(List.GetItem(i));
}
singular function DisableMe()
{
local int i;
Super.DisableMe();
for ( i = 0; i < List.ItemCount; i++ )
DisableComponent(List.GetItem(i));
}
DefaultProperties
{
NumColumns=1
DefaultListClass="XInterface.GUIMultiOptionList"
}

View file

@ -0,0 +1,194 @@
// ====================================================================
// Class: UT2K4UI. UT2NumericEdit
//
// A Combination of an EditBox and 2 spinners
//
// Written by Joe Wilcox
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUINumericEdit extends GUIMultiComponent
Native;
cpptext
{
void PreDraw(UCanvas* Canvas);
}
var Automated GUIEditBox MyEditBox;
var Automated GUISpinnerButton MySpinner;
var() string Value;
var() bool bLeftJustified;
var() int MinValue;
var() int MaxValue;
var() int Step;
var() bool bReadOnly;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
if ( MinValue < 0 )
MyEditBox.bIncludeSign = True;
Super.InitComponent(MyController, MyOwner);
MyEditBox.OnChange = EditOnChange;
MyEditBox.SetText(Value);
MyEditBox.OnKeyEvent = EditKeyEvent;
MyEditBox.OnDeActivate = CheckValue;
CalcMaxLen();
MyEditBox.INIOption = INIOption;
MyEditBox.INIDefault = INIDefault;
MySpinner.bNeverFocus = True;
MySpinner.FocusInstead = MyEditBox;
MySpinner.OnPlusClick = SpinnerPlusClick;
MySpinner.OnMinusClick = SpinnerMinusClick;
SetReadOnly(bReadOnly);
SetHint(Hint);
}
function CalcMaxLen()
{
local int digitcount,x;
digitcount=1;
x=10;
while (x <= MaxValue)
{
digitcount++;
x*=10;
}
MyEditBox.MaxWidth = DigitCount;
}
function SetValue(int V)
{
if (v<MinValue)
v=MinValue;
if (v>MaxValue)
v=MaxValue;
MyEditBox.SetText( string(Clamp(V, MinValue, MaxValue)) );
}
function bool SpinnerPlusClick(GUIComponent Sender)
{
SetValue(int(Value) + Step);
return true;
}
function bool SpinnerMinusClick(GUIComponent Sender)
{
SetValue(int(Value) - Step);
return true;
}
function bool EditKeyEvent(out byte Key, out byte State, float delta)
{
if ( (key==0xEC) && (State==3) )
{
SpinnerPlusClick(none);
return true;
}
if ( (key==0xED) && (State==3) )
{
SpinnerMinusClick(none);
return true;
}
return MyEditBox.InternalOnKeyEvent(Key,State,Delta);
}
function EditOnChange(GUIComponent Sender)
{
Value = string(Clamp(int(MyEditBox.TextStr), MinValue, MaxValue));
OnChange(Self);
}
function SetHint(string NewHint)
{
local int i;
Super.SetHint(NewHint);
for (i=0;i<Controls.Length;i++)
Controls[i].SetHint(NewHint);
}
function SetReadOnly(bool b)
{
bReadOnly = b;
MyEditBox.bReadOnly = b;
if ( b )
{
DisableComponent(MySpinner);
}
else
{
EnableComponent(MySpinner);
}
}
function CheckValue()
{
SetValue(int(Value));
}
function SetFriendlyLabel( GUILabel NewLabel )
{
Super.SetFriendlyLabel(NewLabel);
if ( MyEditBox != None )
MyEditbox.SetFriendlyLabel(NewLabel);
if ( MySpinner != None )
MySpinner.SetFriendlyLabel(NewLabel);
}
function ValidateValue()
{
local int i;
i = int(MyEditBox.TextStr);
MyEditBox.TextStr = string(Clamp(i, MinValue, MaxValue));
MyEditBox.bHasFocus = False;
}
defaultproperties
{
OnDeactivate=ValidateValue
Begin Object Class=GUIEditBox Name=cMyEditBox
bNeverScale=True
TextStr=""
bIntOnly=true
End Object
MyEditBox=cMyEditBox
Begin Object Class=GUISpinnerButton Name=cMySpinner
bTabStop=False
bNeverScale=True
End Object
MySpinner=cMySpinner
Begin object Class=GUIToolTip Name=GUINumericEditToolTip
End Object
ToolTip=GUINumericEditToolTip
Value="0"
MinValue=-9999
MaxValue=9999
Step=1
bAcceptsInput=true
bLeftJustified=false
WinHeight=0.06
PropagateVisibility=true
}

View file

@ -0,0 +1,222 @@
// ====================================================================
// 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
{
void Draw(UCanvas* Canvas);
UBOOL NativeKeyEvent(BYTE& iKey, BYTE& State, FLOAT Delta );
void UpdateTimers(float DeltaTime);
UGUIComponent* UnderCursor( FLOAT MouseX, FLOAT MouseY );
UBOOL MousePressed(UBOOL IsRepeat); // The Mouse was pressed
UBOOL MouseReleased(); // The Mouse was released
UBOOL MouseHover();
}
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[i]=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
{
bAcceptsInput=true
InactiveFadeColor=(R=64,G=64,B=64,A=255)
BackgroundColor=(R=255,G=255,B=255,A=255)
BackgroundRStyle=MSTY_Normal
bRequire640x480=true
bPersistent=false
bTabStop=false
RenderWeight=0.0001
bCaptureInput=True
}

View file

@ -0,0 +1,44 @@
// ====================================================================
// Class: XInterface.GUIPanel
//
// The GUI panel is a visual control that holds components. All
// components who are children of the GUIPanel are bound to the panel
// by default.
//
// Written by Joe Wilcox
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIPanel extends GUIMultiComponent
Native;
cpptext
{
void Draw(UCanvas* Canvas);
UBOOL PerformHitTest(INT MouseX, INT MouseY);
}
var(Panel) Material Background;
Delegate bool OnPostDraw(Canvas Canvas);
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
local int i;
Super.Initcomponent(MyController, MyOwner);
for (i=0;i<Controls.length;i++)
{
Controls[i].bBoundToParent=true;
Controls[i].bScaleToParent=true;
}
}
defaultproperties
{
PropagateVisibility=True
bTabStop=False
}

View file

@ -0,0 +1,53 @@
class GUIProgressBar extends GUIComponent
Native;
cpptext
{
void Draw(UCanvas* Canvas);
}
var Material BarBack; // The unselected portion of the bar
var Material BarTop; // The selected portion of the bar
var Color BarColor; // The Color of the Bar
var float Low; // The minimum value we should see
var float High; // The maximum value we should see
var float Value; // The current value (not clamped)
var float CaptionWidth; // The space reserved to the Caption
var eTextAlign CaptionAlign; // How align the text
var eTextAlign ValueRightAlign; //
var localized string Caption; // The Caption itself
var string FontName; // Which font to use for display
var string ValueFontName; // Font to use for displaying values, use FontName if ValueFontName==""
var float GraphicMargin; // How Much margin to trim from graphic (X Margin only)
var float ValueRightWidth; // Space to leave free on right side
var bool bShowLow; // Show Low(Minimum) left of Bar
var bool bShowHigh; // Show High (Maximum) right of Bar
var bool bShowValue; // Show the value right of the Bar (like 75 or 75/100)
var int NumDecimals; // Number of decimals to display
// ifdef _RO_
var float BorderSize; // Width/Height of the Border built into the background image
// endif
var eDrawDirection BarDirection;
defaultproperties
{
BarBack=Texture'InterfaceArt_tex.Menu.changeme_texture' //Material'InterfaceContent.Menu.BorderBoxD'
BarTop=Texture'InterfaceArt_tex.Menu.changeme_texture' //Material'InterfaceContent.Menu.StatusBarInner'
BarColor=(R=255,G=203,B=0,A=255)
Low=0.0
High=100.0
Value=0.0
bShowLow=false
bShowHigh=false
bShowValue=true
CaptionWidth=0.45
ValueRightWidth=0.2
ValueRightAlign=TXTA_Right
NumDecimals=0
FontName="UT2MenuFont"
BarDirection=DRD_LeftToRight
}

View file

@ -0,0 +1,231 @@
class GUIQuestionPage extends GUIPage;
var GUILabel lMessage;
var Material MessageIcon; // Like Warning/Question/Exclamation
var localized array<string> ButtonNames; // Buttons Names: Ok, Cancel, Retry, Continue, Yes, No, Abort, Ignore. Clamped [0,7].
var array<GUIButton> Buttons;
var GUIButton DefaultButton, CancelButton;
delegate OnButtonClick(byte bButton);
delegate bool NewOnButtonClick(byte bButton) { return true; }
function InitComponent(GUIController pMyController, GUIComponent MyOwner)
{
Super.Initcomponent(pMyController, MyOwner);
lMessage=GUILabel(Controls[1]);
ParentPage.InactiveFadeColor=class'Canvas'.static.MakeColor(128,128,128,255);
}
function bool InternalOnPreDraw(Canvas C)
{
local float XL, YL;
local int i;
local array<string> MsgArray;
// Organize the layout for the Label and the Buttons Top
if (lMessage.TextFont != "")
C.Font = Controller.GetMenuFont(lMessage.TextFont).GetFont(C.SizeX);
C.TextSize("W", XL, YL);
C.WrapStringToArray(lMessage.Caption, MsgArray, lMessage.ActualWidth(), "|");
YL *= MsgArray.Length;
if (lMessage.Style != None)
YL += lMessage.Style.BorderOffsets[1] + lMessage.Style.BorderOffsets[3];
// transform YL to a %
lMessage.WinHeight = (YL +1 )/ C.SizeY;
WinHeight = (YL + Buttons[0].ActualHeight() + 60) / C.SizeY ;
WinTop = (C.SizeY - ActualHeight())/2;
lMessage.WinTop = WinTop + 20;
for (i = 0; i<Buttons.Length; i++)
{
Buttons[i].WinTop = WinTop + 40 + YL;
}
OnPreDraw=None;
return false;
}
function SetupQuestion(string Question, coerce byte bButtons, optional byte ActiveButton, optional bool bClearFirst )
{
if ( lMessage != None )
lMessage.Caption = Question;
if ( bClearFirst )
RemoveButtons();
// Create Buttons Based on Buttons parameter
AddButton(bButtons & QBTN_Yes);
AddButton(bButtons & QBTN_No);
AddButton(bButtons & QBTN_Ok);
AddButton(bButtons & QBTN_Abort);
AddButton(bButtons & QBTN_Retry);
AddButton(bButtons & QBTN_Continue);
CancelButton = AddButton(bButtons & QBTN_Cancel);
AddButton(bButtons & QBTN_Ignore);
/*
if ( bool(bButtons & QBTN_Abort) )
AddButton(6);
if ( bool(bButtons & QBTN_Retry) )
AddButton(2);
if ( bool(bButtons & QBTN_Cancel) )
CancelButton = AddButton(1);
if ( bool(bButtons & QBTN_Continue) )
AddButton(3);
if ( bool(bButtons & QBTN_Ignore) )
AddButton(7);
if ( bool(bButtons & QBTN_Ok) )
AddButton(0);
if ( bool(bButtons & QBTN_Yes) )
AddButton(4);
if ( bool(bButtons & QBTN_No) )
AddButton(5);
*/
LayoutButtons(ActiveButton);
}
function GUIButton AddButton(coerce byte idesc)
{
local GUIButton btn;
local byte mask;
local int cnt;
if ( idesc == 0 )
return None;
mask = 1;
while ( !bool(mask & idesc) )
{
cnt++;
mask = mask << 1;
}
if ( cnt >= ButtonNames.Length )
{
log("GUIQuestionPage.AddButton() button mask was larger than button name array!");
return None;
}
btn = GUIButton(AddComponent("XInterface.GUIButton"));
if ( btn == None )
return None;
btn.Tag = idesc;
btn.TabOrder = Components.Length;
btn.Caption = ButtonNames[cnt];
btn.OnClick = ButtonClick;
Buttons[Buttons.Length] = btn;
return btn;
}
function LayoutButtons(byte ActiveButton)
{
local int i;
local float left, colw, btnw;
// Simply center the button(s)
colw = 1/(Buttons.Length + 1);
btnw = colw * 0.66;
left = colw - btnw/2;
for (i = 0; i<Buttons.Length; i++)
{
Buttons[i].WinLeft = left;
Buttons[i].WinWidth = btnw;
Buttons[i].WinHeight = 0.042773;
Buttons[i].WinTop = 0.6;
left += colw;
if ( bool(Buttons[i].Tag & ActiveButton) )
Buttons[i].SetFocus(None);
}
}
function bool ButtonClick(GUIComponent Sender)
{
local int T;
local GUIController C;
C = Controller;
T = GUIButton(Sender).Tag;
ParentPage.InactiveFadeColor=ParentPage.Default.InactiveFadeColor;
OnButtonClick(T);
if ( NewOnButtonClick(T) )
C.CloseMenu( bool(T & (QBTN_Cancel|QBTN_Abort)) );
return true;
}
function string Replace(string Src, string Tag, string Value)
{
if ( Left(Tag,1) != "%" )
Tag = "%" $ Tag;
if ( Right(Tag,1) != "%" )
Tag $= "%";
return Repl(Src,Tag,Value);
}
function RemoveButtons()
{
local int i;
for ( i = 0; i < Buttons.Length; i++ )
RemoveComponent(Buttons[i], True);
if ( Buttons.Length > 0 )
Buttons.Remove(0,Buttons.Length);
RemapComponents();
}
defaultproperties
{
OnPreDraw=InternalOnPreDraw
Begin Object Class=GUIImage Name=imgBack
Image=Texture'InterfaceArt_tex.Menu.changeme_texture' //Material'InterfaceContent.Menu.SquareBoxA'
ImageStyle=ISTY_Stretched
WinTop=0.0
WinLeft=0.0
WinHeight=1.0
WinWidth=1.0
bScaleToParent=true
bBoundToParent=true
End Object
Begin Object Class=GUILabel Name=lblQuestion
WinTop=0.2
WinLeft=0.1
WinHeight=0.4
WinWidth=0.8
bMultiLine=true
End Object
Controls(0)=imgBack
Controls(1)=lblQuestion
bCaptureInput=True
bRequire640x480=False
bRenderWorld=True
WinTop=0.25
WinHeight=0.5
BackgroundColor=(R=64,G=64,B=64,A=255)
BackgroundRStyle=MSTY_Alpha
ButtonNames(0)="Ok"
ButtonNames(1)="Cancel"
ButtonNames(2)="Retry"
ButtonNames(3)="Continue"
ButtonNames(4)="Yes"
ButtonNames(5)="No"
ButtonNames(6)="Abort"
ButtonNames(7)="Ignore"
// if add more buttonnames, make sure to expand size of array declaration
}

View file

@ -0,0 +1,205 @@
// ====================================================================
// Class: XInterface.GUIScrollBarBase
// Parent: XInterface.GUIMultiComponent
//
// Base class for scroll bar assemblies
// ====================================================================
class GUIScrollBarBase extends GUIMultiComponent
Native;
cpptext
{
void PreDraw( UCanvas* Canvas );
}
var() EOrientation Orientation;
var() int Step; // How many elements to consider a single line
var float GripPos; // Where in the ScrollZone is the grip - Set Natively
var float GripSize; // How big is the grip - Set Natively
var float GrabOffset; // distance from top of button that the user started their drag. Set natively.
var() int MinGripPixels; // Minimum size (in pixels) to draw the grip.
var GUIListBase MyList; // The list this Scrollbar is attached to
// only to be used when MyList == none
var() int BigStep; // big step, by default one page
var() int ItemCount; // total number of items
var() int ItemsPerPage; // number of visible items per page
var int CurPos; // current possition
var Automated GUIScrollZoneBase MyScrollZone;
var Automated GUIScrollButtonBase MyIncreaseButton;
var Automated GUIScrollButtonBase MyDecreaseButton;
var Automated GUIGripButtonBase MyGripButton;
delegate PositionChanged(int NewPos);
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.InitComponent(MyController, MyOwner);
if (MyList != none)
{
ReFocus(MyList);
BigStep = MyList.ItemsPerPage * Step;
ItemCount = MyList.ItemCount;
CurPos = MyList.Top;
}
MyScrollZone.bNeverScale = True;
MyIncreaseButton.bNeverScale = True;
MyDecreaseButton.bNeverScale = True;
MyGripButton.bNeverScale = True;
}
function SetList( GUIListBase List )
{
MyList = List;
Refocus(List);
if ( List != None )
{
BigStep = List.ItemsPerPage;
ItemCount = List.ItemCount;
CurPos = MyList.Top;
}
else
{
BigStep = 0;
ItemCount = 0;
CurPos = 0;
}
}
function UpdateGripPosition(float NewPos)
{
if (MyList != none)
{
MyList.MakeVisible(NewPos);
ItemCount = MyList.ItemCount;
}
GripPos = NewPos;
CurPos = (ItemCount-ItemsPerPage)*GripPos;
PositionChanged(CurPos);
}
delegate MoveGripBy(int items)
{
local int NewItem;
if (MyList != none)
{
NewItem = MyList.Top + items;
ItemCount = MyList.ItemCount;
if (MyList.ItemCount > 0)
{
MyList.SetTopItem(NewItem);
AlignThumb();
}
}
CurPos += items;
if (CurPos < 0) CurPos = 0;
if (CurPos > ItemCount-ItemsPerPage) CurPos = ItemCount-ItemsPerPage;
if (MyList == none) if (ItemCount > 0) AlignThumb();
PositionChanged(CurPos);
}
function bool DecreaseClick(GUIComponent Sender)
{
WheelUp();
return true;
}
function bool IncreaseClick(GUIComponent Sender)
{
WheelDown();
return true;
}
function WheelUp()
{
if (!Controller.CtrlPressed)
MoveGripBy(-Step);
else
MoveGripBy(-BigStep);
}
function WheelDown()
{
if (!Controller.CtrlPressed)
MoveGripBy(Step);
else
MoveGripBy(BigStep);
}
delegate AlignThumb()
{
local float NewPos;
if (MyList != none)
{
BigStep = MyList.ItemsPerPage * Step;
if (MyList.ItemCount==0)
NewPos = 0;
else
NewPos = float(MyList.Top) / float(MyList.ItemCount-MyList.ItemsPerPage);
}
else {
if (ItemCount==0)
NewPos = 0;
else
NewPos = CurPos / float(ItemCount-ItemsPerPage);
}
GripPos = FClamp(NewPos, 0.0, 1.0);
}
function Refocus(GUIComponent Who)
{
local int i;
if (Who != None && Controls.Length > 0)
for (i=0;i<Controls.Length;i++)
{
Controls[i].FocusInstead = Who;
Controls[i].bNeverFocus=true;
}
}
// Stub
function bool GripPreDraw( GUIComponent Sender ) { return false; }
function SetFriendlyLabel( GUILabel NewLabel )
{
Super.SetFriendlyLabel(NewLabel);
if ( MyScrollZone != None )
MyScrollZone.SetFriendlyLabel(NewLabel);
if ( MyIncreaseButton != None )
MyIncreaseButton.SetFriendlyLabel(NewLabel);
if ( MyDecreaseButton != None )
MyDecreaseButton.SetFriendlyLabel(NewLabel);
if ( MyGripButton != None )
MyGripButton.SetFriendlyLabel(NewLabel);
}
/*
function bool FocusFirst(GUIComponent Sender)
{
}
function bool FocusLast(GUIComponent Sender)
{
}
*/
defaultproperties
{
bTabStop=false
PropagateVisibility=true
Step=1
}

View file

@ -0,0 +1,20 @@
//==============================================================================
// Created on: 08/23/2003
// Base class for the buttons on either side of a scroll zone
//
// Written by Ron Prestenback
// © 2003, Epic Games, Inc. All Rights Reserved
//==============================================================================
class GUIScrollButtonBase extends GUIGFXButton
native;
var() bool bIncreaseButton; // Whether this button should increase the value or decrease the value.
DefaultProperties
{
StyleName="RoundScaledButton"
Position=ICP_Scaled
bNeverFocus=true
bCaptureMouse=true
bRepeatClick=True
}

View file

@ -0,0 +1,255 @@
class GUIScrollText extends GUIList
native;
cpptext
{
UBOOL WrapURL( FString& Text ) const;
void PreDraw(UCanvas *Canvas);
void Draw(UCanvas* Canvas);
protected:
void DrawItem(UCanvas* Canvas, INT Item, FLOAT X, FLOAT Y, FLOAT W, FLOAT HT, UBOOL bSelected, UBOOL bPending);
public:
}
enum eScrollState
{
STS_None,
STS_Initial,
STS_Char,
STS_EOL,
STS_Repeat,
};
var() editconst int MaxHistory; // Maximum number of rows. Only used in conjunction with NewText. 0 indicates no limit.
var() editconst string NewText; // New text to add the end of
var() editconst string ClickedString; // Filled in (if bClickText is true) when user clicks on a word
// private set of vars
var() editconst protected string Content; // This is the content to display in 1 single string
var() editconst string Separator; // Separator to use
var() editconst protected int VisibleLines; // This is the number of visible lines
var() editconst protected int VisibleChars; // How Many chars in the last displayed line are visible
var() editconst protected float oldWidth; // Last width of the diplay area
var() editconst protected eScrollState ScrollState; // What was the last action we did
var() editconst protected bool bNewContent; // This is set when new text content has been set for the control
var() editconst protected bool bStopped; // Tells when the sequence has stopped animating (can be rushed by clicking ?)
var const editconst private bool bReceivedNewContent;
// Public set of vars
var() bool bRepeat; // Should the sequence be repeated ?
var() bool bNoTeletype; // Dont do the teletyping effect at all
var() bool bClickText; // Upon clicking on this text box, fill in ClickedString field
var() float InitialDelay; // Initial delay after new content was set
var() float CharDelay; // This is the delay between each char
var() float EOLDelay; // This is the delay to use when reaching end of line
var() float RepeatDelay; // This is used after all the text has been displayed and bRepeat is true
var() editconst editconstarray array<string> StringElements;
native final function string GetWordUnderCursor();
delegate OnEndOfLine();
function Dump()
{
local int i;
for (i = 0; i < StringElements.Length; i++)
log(Name@"ScrollText Elements["$i$"]:"$StringElements[i]);
}
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.InitComponent(MyController, MyOwner);
if(bNoTeletype)
EndScrolling();
}
function SetContent(string NewContent, optional string sep)
{
if (sep == "")
Separator = default.Separator;
else
Separator = sep;
Content = NewContent;
bNewContent = true;
if(bNoTeletype)
EndScrolling();
else
Restart();
}
function Stop()
{
bStopped = true;
ScrollState = STS_None;
TimerInterval = 0;
}
function Restart()
{
VisibleLines = 0;
VisibleChars = 0;
if (InitialDelay <= 0.0)
{
ScrollState = STS_None;
SetTimer(0.001, true);
}
else
{
ScrollState = STS_Initial;
SetTimer(InitialDelay, true);
}
bStopped = false;
}
function bool SkipChar()
{
if (ItemCount > 0 && !bStopped && VisibleLines >= 0 && VisibleLines < ItemCount)
{
if (VisibleChars == Len(StringElements[VisibleLines]))
{
if (VisibleLines+1 < ItemCount)
{
VisibleLines++;
VisibleChars = 0;
TimerInterval = EOLDelay;
ScrollState = STS_EOL;
OnEndOfLine();
return true;
}
}
else
{
VisibleChars++;
TimerInterval = CharDelay;
ScrollState = STS_Char;
return true;
}
}
return false;
}
event Timer()
{
if (ItemCount == 0)
{
if (!bNewContent)
TimerInterval=0;
return;
}
if (ScrollState == STS_Repeat)
{
Restart();
}
else if (ScrollState == STS_EOL)
{
if (!SkipChar())
{
if (bRepeat)
{
if (RepeatDelay > 0)
{
TimerInterval = RepeatDelay;
ScrollState = STS_Repeat;
}
else
Restart();
}
else
{
bStopped = true;
ScrollState = STS_None;
TimerInterval = 0;
}
}
}
else if (ScrollState == STS_None)
{
ScrollState = STS_Initial;
SetTimer(CharDelay, true);
}
else
{
if (!SkipChar())
{
ScrollState=STS_EOL;
TimerInterval=EOLDelay;
OnEndOfLine();
}
}
}
function bool InternalOnClick(GUIComponent Sender)
{
local bool retval;
if(bClickText)
{
ClickedString = GetWordUnderCursor();
return true;
}
retval = Super.InternalOnClick(Sender);
if (retval)
EndScrolling();
return retval;
}
function bool InternalOnKeyType(out byte Key, optional string Unicode)
{
//local bool retval;
// retval = Super.InternalOnKeyType(Key, Unicode);
// if (retval)
EndScrolling();
// return retval;
return false;
}
function bool InternalOnKeyEvent(out byte Key, out byte State, float delta)
{
local bool retval;
retval = Super.InternalOnKeyEvent(Key, State, delta);
if (retval)
EndScrolling();
return retval;
}
function EndScrolling()
{
bStopped = true;
if(MyScrollBar != None)
MyScrollBar.AlignThumb();
KillTimer();
}
function bool IsValid()
{
return true;
}
defaultproperties
{
OnKeyType=InternalOnKeyType
OnKeyEvent=InternalOnKeyEvent
OnClick=InternalOnClick
ScrollState=STS_None
Separator="|"
TextAlign=TXTA_Left
InitialDelay=0.0
CharDelay=0.25
EOLDelay=0.75
RepeatDelay=3.0
VisibleLines=-1
}

View file

@ -0,0 +1,191 @@
//====================================================================
// Parent: GUIListBoxBase
// Class: UT2K4UI.GUIScrollTextBox
// Date: 05-01-2003
//
// ListBox container for a scrolling text list
//
// Updated by Ron Prestenback
// (c) 2003, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIScrollTextBox extends GUIListBoxBase
native;
var GUIScrollText MyScrollText;
var(GUIScrollText) bool bRepeat; // Should the sequence be repeated ?
var(GUIScrollText) bool bNoTeletype; // Dont do the teletyping effect at all
var(GUIScrollText) bool bStripColors; // Strip out IRC-style colour characters (^C)
var(GUIScrollText) float InitialDelay; // Initial delay after new content was set
var(GUIScrollText) float CharDelay; // This is the delay between each char
var(GUIScrollText) float EOLDelay; // This is the delay to use when reaching end of line
var(GUIScrollText) float RepeatDelay; // This is used after all the text has been displayed and bRepeat is true
var(GUIScrollText) eTextAlign TextAlign; // How is text Aligned in the control
var(GUIScrollText) string Separator; // Propagate to GUIScrollText
var() string ESC, COMMA; // fake const's
event Created()
{
ESC = Chr(3);
COMMA = Chr(44);
}
function InternalOnCreateComponent(GUIComponent NewComp, GUIComponent Sender)
{
if (GUIScrollText(NewComp) != None && Sender == Self)
GUIScrollText(NewComp).bNoTeleType = bNoTeleType;
Super.InternalOnCreateComponent(NewComp, Sender);
}
function InitBaseList(GUIListBase LocalList)
{
if ((MyScrollText == None || MyScrollText != LocalList) && GUIScrollText(LocalList) != None)
MyScrollText = GUIScrollText(LocalList);
Super.InitBaseList(LocalList);
MyScrollText.Separator = Separator;
MyScrollText.InitialDelay = InitialDelay;
MyScrollText.CharDelay = CharDelay;
MyScrollText.EOLDelay = EOLDelay;
MyScrollText.RepeatDelay = RepeatDelay;
MyScrollText.TextAlign = TextAlign;
MyScrollText.bRepeat = bRepeat;
MyScrollText.bNoTeletype = bNoTeletype;
MyScrollText.OnAdjustTop = InternalOnAdjustTop;
}
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.InitComponent(MyController, MyOwner);
if (DefaultListClass != "")
{
MyScrollText = GUIScrollText(AddComponent(DefaultListClass));
if (MyScrollText == None)
{
log(Class$".InitComponent - Could not create default list ["$DefaultListClass$"]");
return;
}
}
if (MyScrollText == None)
{
Warn("Could not initialize list!");
return;
}
InitBaseList(MyScrollText);
}
function SetContent(string NewContent, optional string sep)
{
MyScrollText.SetContent(NewContent, sep);
}
function Restart()
{
MyScrollText.Restart();
}
function Stop()
{
MyScrollText.Stop();
}
function InternalOnAdjustTop(GUIComponent Sender)
{
MyScrollText.EndScrolling();
}
function bool IsNumber(string Num)
{
if ( Num > Chr(47) && Num < Chr(58) )
return true;
return false;
}
function string StripColors(string MyString)
{
local int EscapePos, RemCount, LenFromEscape;
EscapePos = InStr(MyString, ESC); // Chr(3) == ^C
while(EscapePos != -1)
{
LenFromEscape = Len(MyString) - (EscapePos + 1); // how far after the escape character the string goes on for
// Now we have to work out how many characters follow the ^C and should be removed. This is rather unpleasant..!
for (RemCount = 0; RemCount < LenFromEscape && RemCount < 7; RemCount++)
{
if ( Mid(MyString, EscapePos+RemCount, 1) == ESC ||
IsNumber(Mid(MyString, EscapePos + RemCount, 1)) ||
Mid(MyString, EscapePos + RemCount, 1) == COMMA )
RemCount++;
else break;
}
/* RemCount = 1; // strip the ctrl-C regardless
if( LenFromEscape >= 1 && IsNumber(Mid(MyString, EscapePos+1, 1)) ) // If a digit follows the ctrl-C, strip that
{
RemCount = 2; // #
if( LenFromEscape >= 3 && Mid(MyString, EscapePos+2, 1) == Chr(44) && IsNumber(Mid(MyString, EscapePos+3, 1)) ) // If we have a comma and another digit, strip those
{
RemCount = 4; // #,#
if( LenFromEscape >= 4 && IsNumber(Mid(MyString, EscapePos+4, 1)) ) // if there is another digit after that, strip it
RemCount = 5; // #,##
}
else if( LenFromEscape >= 2 && IsNumber(Mid(MyString, EscapePos+2, 1)) )// if there is a second digit, strip that
{
RemCount = 3; // ##
if( LenFromEscape >= 4 && Mid(MyString, EscapePos+3, 1) == Chr(44) && IsNumber(Mid(MyString, EscapePos+4, 1)) ) // If we have a comma and another digit, strip those
{
RemCount = 5; // ##,#
if( LenFromEscape >= 5 && IsNumber(Mid(MyString, EscapePos+5, 1)) ) // if there is another digit after that, strip it
RemCount = 6; // ##,##
}
}
}
*/
MyString = Left(MyString, EscapePos)$Mid(MyString, EscapePos+RemCount);
EscapePos = InStr(MyString, Chr(3));
}
return MyString;
}
function AddText(string NewText)
{
local string StrippedText;
if(NewText == "")
return;
if(bStripColors)
StrippedText = StripColors(NewText);
else
StrippedText = NewText;
if ( MyScrollText.NewText != "" )
MyScrollText.NewText $= MyScrollText.Separator;
MyScrollText.NewText $= StrippedText;
}
defaultproperties
{
TextAlign=TXTA_Left
InitialDelay=0.0
CharDelay=0.25
EOLDelay=0.75
RepeatDelay=3.0
bVisibleWhenEmpty=False
DefaultListClass="XInterface.GUIScrollText"
FontScale=FNS_Medium
Separator="|"
}

View file

@ -0,0 +1,32 @@
//==============================================================================
// Created on: 08/23/2003
// Base class for scroll zones
//
// The ScrollZone is the background area for a scrollbar.
// When the user clicks on the zone, it caculates it's percentage.
//
// Written by Joe Wilcox
// © 2003, Epic Games, Inc. All Rights Reserved
//==============================================================================
class GUIScrollZoneBase extends GUIComponent
native;
cpptext
{
void Draw(UCanvas* Canvas);
}
delegate OnScrollZoneClick(float Delta); // Should be overridden
function bool InternalOnClick(GUIComponent Sender) { return false; }
DefaultProperties
{
OnClick=InternalOnClick
StyleName="ScrollZone"
bNeverFocus=true
bAcceptsInput=true
bCaptureMouse=true
bRepeatClick=true
RenderWeight=0.25
bRequiresStyle=True
}

View file

@ -0,0 +1,220 @@
// ====================================================================
// (C) 2002, Epic Games
// ====================================================================
class GUISectionBackground extends GUIImage
Native;
var(Style) editconst noexport GUIStyles CaptionStyle; // must have a CaptionStyle to be drawn
var(Style) string CaptionStyleName;
var(Style) int AltCaptionOffset[4];
var(Style) eTextAlign AltCaptionAlign;
var(Style) bool bAltCaption;
var() bool bRemapStack; // When components are added to the alignment stack, they are inserted based on their tab order
var() bool bFillClient; // Adjust WinHeight of components so that they fill the client area
// if _RO_
var() bool bNoCaption; // Set to true to prevent caption from being drawn
var() eTextAlign CaptionAlign;
// else
// end if _RO_
var() editinlinenotify noexport array<GUIComponent> AlignStack;
var() material HeaderTop,HeaderBar,HeaderBase; // Top, Bar and base
var() localized string Caption;
var() float ColPadding, // Padding between columns
LeftPadding,
RightPadding,
TopPadding,
BottomPadding; // range is 0 - 1.0
var() float ImageOffset[4];
var() int NumColumns; // Number of columns to divide the managed components into
var() int MaxPerColumn; // Applicable only when NumColumns > 0
cpptext
{
void AutoPosition( TArray<UGUIComponent*>& Components, float PosL, float PosT, float PosR, float PosB, INT Col = 1, float ColSpace = 0.f );
void PreDraw(UCanvas* Canvas);
void Draw(UCanvas* Canvas); // Should be overridden in a subclass
}
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.InitComponent(MyController, MyOwner);
if (CaptionStyleName!="")
CaptionStyle = Controller.GetStyle(CaptionStyleName,FontScale);
}
event SetVisibility(bool bIsVisible)
{
local int i;
Super.SetVisibility(bIsVisible);
for (i=0;i<AlignStack.Length;i++)
AlignStack[i].SetVisibility(bIsVisible);
}
// if _RO_
function EnableMe()
{
local int i;
super.EnableMe();
for (i = 0; i < AlignStack.Length; i++)
AlignStack[i].EnableMe();
}
function DisableMe()
{
local int i;
super.EnableMe();
for (i = 0; i < AlignStack.Length; i++)
AlignStack[i].DisableMe();
}
// else
// end if _RO_
// Components that are manage by the section background are auto aligned and placed
function bool ManageComponent(GUIComponent Component)
{
local int i;
if ( Component == None )
return false;
i = FindComponentIndex(Component);
if ( i == -1 )
{
if ( bRemapStack )
{
for (i=0;i<AlignStack.Length;i++)
{
if (AlignStack[i].TabOrder > Component.TabOrder)
break;
}
}
else i = AlignStack.Length;
AlignStack.Insert(i, 1);
AlignStack[i]=Component;
return true;
}
return false;
}
function bool UnmanageComponent( GUIComponent Comp )
{
local int i;
i = FindComponentIndex(Comp);
if ( i != -1 && i >= 0 && i < AlignStack.Length )
{
AlignStack.Remove(i,1);
return true;
}
return false;
}
function int FindComponentIndex( GUIComponent Comp )
{
local int i;
if ( Comp == None )
return -1;
for ( i = 0; i < AlignStack.Length; i++ )
if ( AlignStack[i] == Comp )
return i;
return -1;
}
function Reset()
{
AlignStack.Remove( 0, AlignStack.Length );
bInit = true;
}
function bool InternalPreDraw(Canvas C)
{
local float AL, AT, AW, AH, LPad, RPad, TPad, BPad;
if ( AlignStack.Length == 0 )
return false;
AL = ActualLeft();
AT = ActualTop();
AW = ActualWidth();
AH = ActualHeight();
LPad = (LeftPadding * AW) + ImageOffset[0];
TPad = (TopPadding * AH) + ImageOffset[1];
RPad = (RightPadding * AW) + ImageOffset[2];
BPad = (BottomPadding * AH) + ImageOffset[3];
if ( Style != none )
{
LPad += BorderOffsets[0];
TPad += BorderOffsets[1];
RPad += BorderOffsets[2];
BPad += BorderOffsets[3];
}
AutoPosition( AlignStack,
AL, AT, AL + AW, AT + AH,
LPad, TPad, RPad, BPad,
NumColumns, ColPadding );
return false;
}
event ResolutionChanged(int ResX, int ResY)
{
Super.ResolutionChanged(ResX, ResY);
bInit = True;
}
function SetPosition( float NewLeft, float NewTop, float NewWidth, float NewHeight, optional bool bRelative )
{
Super.SetPosition(NewLeft,NewTop,NewWidth,NewHeight,bRelative);
bInit = true;
}
defaultproperties
{
OnPreDraw=InternalPreDraw
CaptionStyleName="TextLabel"
FontScale=FNS_Small
HeaderTop=Texture'InterfaceArt_tex.Menu.empty'
HeaderBar=Texture'InterfaceArt_tex.Menu.empty'
HeaderBase=Texture'KF_InterfaceArt_tex.Menu.Med_border_SlightTransparent'
TopPadding=0.05
LeftPadding=0.05
RightPadding=0.05
BottomPadding=0.05
ColPadding=0.05
ImageOffset(0)=20
ImageOffset(1)=35
ImageOffset(2)=10
ImageOffset(3)=10
NumColumns=1
bFillClient=false
RenderWeight=0.09
bRemapStack=True
CaptionAlign=TXTA_Left
}

View file

@ -0,0 +1,259 @@
// ====================================================================
// Class: UT2K4UI.GUISlider
//
// Written by Joe Wilcox
// (c) 2002, Epic Games, Inc. All Rights Reserved
// Sliders will not be drawn if both MinValue & MaxValue are both 0
// ====================================================================
class GUISlider extends GUIComponent
Native;
cpptext
{
void Draw(UCanvas* Canvas);
}
var() float MinValue, MaxValue;
var() float Value;
var() float MarkerWidth;
var() bool bIntSlider;
var() bool bShowMarker;
var() bool bShowCaption;
var() bool bDrawPercentSign;
var() bool bReadOnly;
var() bool bShowValueTooltip; // Show the current value as a tooltip while dragging
var() material FillImage;
var() string CaptionStyleName, BarStyleName;
var GUIStyles CaptionStyle;
var GUIStyles BarStyle;
// Return true to prevent caption from being drawn
delegate bool OnPreDrawCaption( out float X, out float Y, out float XL, out float YL, out ETextAlign Justification );
delegate string OnDrawCaption()
{
if (bIntSlider)
return "("$int(Value)$ Eval(bDrawPercentSign, " %", "") $ ")";
return "("$Value$Eval(bDrawPercentSign, " %", "") $ ")";
}
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.Initcomponent(MyController, MyOwner);
CaptionStyle = Controller.GetStyle(CaptionStyleName,FontScale);
BarStyle = Controller.GetStyle(BarStyleName,FontScale);
}
function bool InternalCapturedMouseMove(float deltaX, float deltaY)
{
local float Perc;
if ( bReadOnly )
return true;
if ( (Controller.MouseX >= Bounds[0]) && (Controller.MouseX<=Bounds[2]) )
{
Perc = FClamp( ((Controller.MouseX - (ActualLeft() + (MarkerWidth/2))) / (ActualWidth()-MarkerWidth)), 0.0, 1.0 );
Value = ((MaxValue - MinValue) * Perc) + MinValue;
if (bIntSlider)
Value = round(Value);
}
else if (Controller.MouseX < Bounds[0])
Value = MinValue;
else if (Controller.MouseX > Bounds[2])
Value = MaxValue;
Value = FClamp(Value,MinValue,MaxValue);
if ( bShowValueTooltip )
ToolTip.SetTip( GetValueString() );
return true;
}
function bool InternalOnKeyEvent(out byte Key, out byte State, float delta)
{
if ( bReadOnly )
return false;
if ( (Key==0x25) && (State==1) ) // Left
{
if (bIntSlider)
Adjust(-1);
else
Adjust(-0.01);
return true;
}
if ( (Key==0x27) && (State==1) ) // Right
{
if (bIntSlider)
Adjust(1);
else
Adjust(0.01);
return true;
}
return false;
}
function float SetValue(float NewValue)
{
Value = FClamp(NewValue, MinValue, MaxValue);
if (bIntSlider)
Value = Round(Value);
return Value;
}
function Adjust(float amount)
{
local float Perc;
Perc = (Value-MinValue) / (MaxValue-MinValue);
Perc += amount;
Perc = FClamp(Perc,0.0,1.0);
Value = FClamp( ((MaxValue - MinValue) * Perc) + MinValue, MinValue, MaxValue );
OnChange(self);
}
function bool InternalOnClick(GUIComponent Sender)
{
if ( bShowValueToolTip )
RevertTooltipToNormal();
OnChange(self);
return true;
}
function InternalOnMousePressed(GUIComponent Sender,bool RepeatClick)
{
if ( bShowValueTooltip )
ModifyTooltipForDragging();
InternalCapturedMouseMove(0,0);
}
function InternalOnMouseRelease(GUIComponent Sender)
{
InternalCapturedMouseMove(0,0);
}
function SetReadOnly(bool b)
{
bReadOnly = b;
}
event float GetMarkerPosition()
{
local float Perc;
Perc = (Value - MinValue) / (MaxValue - MinValue);
return ActualLeft() + ((ActualWidth() - MarkerWidth) * Perc);
}
function CenterMouse()
{
if ( PlayerOwner() != None )
PlayerOwner().ConsoleCommand( "SETMOUSE" @ GetMarkerPosition() @ (ActualTop() + ActualHeight() / 2) );
}
function string GetValueString()
{
local string ValueStr;
if ( bIntSlider )
ValueStr = string( int(Value) );
else ValueStr = string(Value);
if ( bDrawPercentSign )
ValueStr @= "%";
return ValueStr;
}
function ModifyTooltipForDragging()
{
ToolTip.bTrackMouse = True;
ToolTip.bTrackInput = False;
ToolTip.bMultiLine = False;
ToolTip.HideToolTip = HideToolTip;
ToolTip.LeaveArea = ToolTipLeaveArea;
SetTooltipText( GetValueString() );
ShowToolTip();
}
function RevertTooltipToNormal()
{
ToolTip.bTrackMouse = ToolTip.default.bTrackMouse;
ToolTip.bTrackInput = ToolTip.default.bTrackInput;
ToolTip.bMultiLine = ToolTip.default.bMultiLine;
ToolTip.HideToolTip = None;
ToolTip.LeaveArea = None;
ToolTip.LeaveArea();
SetTooltipText( Hint );
}
function ShowToolTip()
{
Controller.MouseOver = ToolTip.InternalEnterArea();
ToolTip.SetVisibility(True);
}
function HideToolTip()
{
if ( MenuState != MSAT_Pressed )
{
log("HideToolTip MenuState:"$GetEnum(enum'EMenuState', MenuState));
ToolTip.SetVisibility(False);
}
}
function bool ToolTipLeaveArea()
{
return False;
}
defaultproperties
{
OnCapturedMouseMove=InternalCapturedMouseMove
OnKeyEvent=InternalOnKeyEvent
OnClick=InternalOnClick
OnMousePressed=InternalOnMousePressed
OnMouseRelease=InternalOnMouseRelease
Begin object Class=GUIToolTip Name=GUISliderToolTip
End Object
ToolTip=GUISliderToolTip
StyleName="SliderKnob"
bAcceptsInput=true
bCaptureMouse=True
bNeverFocus=false
bTabStop=true
WinHeight=0.03
bRequireReleaseClick=true
CaptionStyleName="SliderCaption"
bIntSlider=false;
OnClickSound=CS_Click
BarStyleName="SliderBar"
MinValue=0
MaxValue=100
bShowMarker=true
bShowCaption=false
MarkerWidth=0
// if _RO_
FillImage=Texture'InterfaceArt_tex.Menu.SliderFillBlurry'
// else
// FillImage=material'2K4Menus.NewControls.SliderFillBlurry'
// end if _RO_
bRequiresStyle=True
bDrawPercentSign=false
bShowValueTooltip=true
}

View file

@ -0,0 +1,42 @@
// ====================================================================
// Class: UT2K4UI.UT2SpinnerButton
//
// Written by Joe Wilcox
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUISpinnerButton extends GUIButton
Native;
cpptext
{
void Draw(UCanvas* Canvas);
}
delegate bool OnPlusClick(GUIComponent Sender) { return false; }
delegate bool OnMinusClick(GUIComponent Sender) { return false; }
function bool InternalOnClick(GUIComponent Sender)
{
local float x,y;
x = Controller.MouseX - ActualLeft();
y = Controller.MouseY - ActualTop();
if (y <= (ActualHeight()/2) )
return OnPlusClick(Sender);
else
return OnMinusClick(Sender);
}
defaultproperties
{
OnClick=InternalOnClick
StyleName="SpinnerButton"
bNeverFocus=true
bRepeatClick=true
bCaptureMouse=true
bRequiresStyle=True
}

View file

@ -0,0 +1,84 @@
// ====================================================================
// Class: UT2K4UI.GUISplitter
//
// GUISplitters allow the user to size two other controls (usually Panels)
//
// Written by Jack Porter
// Updated by Ron Prestenback
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUISplitter extends GUIPanel
native;
cpptext
{
void PreDraw(UCanvas* Canvas);
void Draw(UCanvas* Canvas);
UBOOL MouseMove(INT XDelta, INT YDelta);
UBOOL MousePressed(UBOOL IsRepeat);
UBOOL MouseReleased();
UBOOL MouseHover();
void SplitterUpdatePositions();
}
enum EGUISplitterType
{
SPLIT_Vertical,
SPLIT_Horizontal,
};
var() EGUISplitterType SplitOrientation;
var() float SplitPosition; // 0.0 - 1.0
var() bool bFixedSplitter; // Can splitter be moved?
var() bool bDrawSplitter; // Draw the actual splitter bar
var() float SplitAreaSize; // size of splitter thing
var() string DefaultPanels[2]; // Names of the default panels
var() GUIComponent Panels[2]; // Quick Reference
var() float MaxPercentage; // How big can any 1 panel get
delegate OnReleaseSplitter(GUIComponent Sender, float NewPosition); // Notification that finished resizing splitter
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.Initcomponent(MyController, MyOwner);
if (DefaultPanels[0]!="")
{
Panels[0] = AddComponent(DefaultPanels[0], DefaultPanels[1] != "");
if (DefaultPanels[1]!="")
Panels[1] = Addcomponent(DefaultPanels[1]);
}
}
event GUIComponent AppendComponent(GUIComponent NewComp, optional bool SkipRemap)
{
OnCreateComponent(NewComp, Self);
Controls[Controls.Length] = NewComp;
NewComp.InitComponent(Controller, Self);
NewComp.bBoundToParent = true;
NewComp.bScaleToParent = true;
if (!SkipRemap)
RemapComponents();
return NewComp;
}
native function SplitterUpdatePositions();
defaultproperties
{
StyleName="SquareButton"
SplitOrientation=SPLIT_Vertical
bCaptureTabs=False
bNeverFocus=True
bTabStop=False
bAcceptsInput=True
SplitPosition=0.5
SplitAreaSize=8
bDrawSplitter=True
MaxPercentage=0.0
bRequiresStyle=True
}

View file

@ -0,0 +1,147 @@
// ====================================================================
// Class: UT2K4UI.GUIStyles
//
// The GUIStyle is an object that is used to describe common visible
// components of the interface.
//
// Written by Joe Wilcox
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIStyles extends GUI
Abstract
Native
noteditinlinenew;
cpptext
{
void Draw(UCanvas* Canvas, BYTE MenuState, FLOAT Left, FLOAT Top, FLOAT Width, FLOAT Height);
void DrawText(UCanvas* Canvas, BYTE MenuState, FLOAT Left, FLOAT Top, FLOAT Width, FLOAT Height, BYTE Just, const TCHAR* Text, BYTE FontScale);
void TextSize(UCanvas* Canvas, BYTE MenuState, const TCHAR* Test, FLOAT& XL, FLOAT& YL, BYTE FontScale);
}
var(Style) const string KeyName; // This is the name of the style used for lookup
// If the desired keyname is one of these, FontScale will be adjusted
// For backwards compatibility - 0 - Smaller 1 - Larger
var(Style) const string AlternateKeyName[2];
/* Each style contains 5 values for each font, per size
Small 0 - 4
Medium 5 - 9
Large 10 - 14
*/
var(Style) noexport string FontNames[15]; // Holds the names of the 5 fonts to use
var(Style) noexport GUIFont Fonts[15]; // Holds the fonts for each state
var(Style) noexport color FontColors[5]; // This array holds 1 font color for each state
var(Style) noexport color FontBKColors[5]; // This holds the Background Colors for each state
var(Style) noexport color ImgColors[5]; // This array holds 1 image color for each state
var(Style) noexport EMenuRenderStyle RStyles[5]; // The render styles for each state
var(Style) noexport Material Images[5]; // This array holds 1 material for each state (Blurry, Watched, Focused, Pressed, Disabled)
var(Style) noexport eImgStyle ImgStyle[5]; // How should each image for each state be drawed
var(Style) noexport float ImgWidths[5]; // -1 if full image
var(Style) noexport float ImgHeights[5]; // -1 if full image
var(Style) noexport int BorderOffsets[4]; // How thick is the border
var(style) noexport bool bTemporary; // This style should be cleaned up
// the OnDraw delegate Can be used to draw. Return true to skip the default draw method
delegate bool OnDraw(Canvas Canvas, eMenuState MenuState, float left, float top, float width, float height);
delegate bool OnDrawText(Canvas Canvas, eMenuState MenuState, float left, float top, float width, float height, eTextAlign Align, string Text, eFontScale FontScale);
native static final function Draw(Canvas Canvas, eMenuState MenuState, float left, float top, float width, float height);
native static final function DrawText(Canvas Canvas, eMenuState MenuState, float left, float top, float width, float height, eTextAlign Align, string Text, eFontScale FontScale);
native static final function TextSize(Canvas Canvas, eMenuState MenuState, string Text, out float XL, out float YL, eFontScale FontScale);
event Initialize()
{
local int i;
// Preset all the data if needed
for ( i = 0; i < ArrayCount(FontNames) && i < ArrayCount(Fonts); i++)
{
if (FontNames[i] != "")
Fonts[i] = Controller.GetMenuFont(FontNames[i]);
}
}
defaultproperties
{
RStyles(0)=MSTY_Normal
RStyles(1)=MSTY_Normal
RStyles(2)=MSTY_Normal
RStyles(3)=MSTY_Normal
RStyles(4)=MSTY_Normal
ImgStyle(0)=ISTY_Stretched
ImgStyle(1)=ISTY_Stretched
ImgStyle(2)=ISTY_Stretched
ImgStyle(3)=ISTY_Stretched
ImgStyle(4)=ISTY_Stretched
ImgColors(0)=(R=255,G=255,B=255,A=255)
ImgColors(1)=(R=255,G=255,B=255,A=255)
ImgColors(2)=(R=255,G=255,B=255,A=255)
ImgColors(3)=(R=255,G=255,B=255,A=255)
ImgColors(4)=(R=128,G=128,B=128,A=255)
ImgWidths(0)=-1.0
ImgWidths(1)=-1.0
ImgWidths(2)=-1.0
ImgWidths(3)=-1.0
ImgWidths(4)=-1.0
ImgHeights(0)=-1.0
ImgHeights(1)=-1.0
ImgHeights(2)=-1.0
ImgHeights(3)=-1.0
ImgHeights(4)=-1.0
// if _RO_
/*
// end if _RO_
FontColors(0)=(R=0,G=0,B=64,A=255)
FontColors(1)=(R=0,G=0,B=64,A=255)
FontColors(2)=(R=32,G=32,B=80,A=255)
FontColors(3)=(R=32,G=32,B=80,A=255)
FontColors(4)=(R=0,G=0,B=128,A=255)
// if _RO_
*/
FontColors(0)=(R=225,G=225,B=225,A=255)
FontColors(1)=(R=255,G=255,B=255,A=255)
FontColors(2)=(R=225,G=225,B=225,A=255)
FontColors(3)=(R=225,G=225,B=225,A=255)
FontColors(4)=(R=125,G=125,B=125,A=255)
// end if _RO_
FontBKColors(0)=(R=0,G=0,B=0,A=255)
FontBKColors(1)=(R=0,G=0,B=0,A=255)
FontBKColors(2)=(R=0,G=0,B=0,A=255)
FontBKColors(3)=(R=0,G=0,B=0,A=255)
FontBKColors(4)=(R=0,G=0,B=0,A=255)
FontNames(0)="UT2SmallFont"
FontNames(1)="UT2SmallFont"
FontNames(2)="UT2SmallFont"
FontNames(3)="UT2SmallFont"
FontNames(4)="UT2SmallFont"
FontNames(5)="UT2MenuFont"
FontNames(6)="UT2MenuFont"
FontNames(7)="UT2MenuFont"
FontNames(8)="UT2MenuFont"
FontNames(9)="UT2MenuFont"
FontNames(10)="UT2LargeFont"
FontNames(11)="UT2LargeFont"
FontNames(12)="UT2LargeFont"
FontNames(13)="UT2LargeFont"
FontNames(14)="UT2LargeFont"
BorderOffsets(0)=10
BorderOffsets(1)=10
BorderOffsets(2)=10
BorderOffsets(3)=10
}

View file

@ -0,0 +1,164 @@
//==============================================================================
// A timed label used to display subtitles
//
// Written by Michiel Hendriks
// (c) 2003, Epic Games, Inc. All Rights Reserved
//==============================================================================
class GUISubtitleText extends GUILabel;
/** each subtitle on a diffirent line */
var() array<string> SubTitles;
/**
Visible is the time this subtitle is vissible
Delay is the time to wait to display the next sub title
*/
struct VisibleDelay
{
var float Visible;
var float Delay;
};
/** time to show a single subtitle */
var() array<VisibleDelay> SubTitleTiming;
/** default subtitle visibility, if <= 0 remain visible */
var() float VisibleTime;
/** default delay time */
var() float DelayTime;
/** initial delay */
var() float InitialDelay;
/** use by SetSubTitles to guess the delay, delay = guess time * no. chars */
var() float GuessCharTime;
/** default seperator */
var string Separator;
var protected int CurLine;
var protected enum eDisplayState {
DS_Delay,
DS_Visibility,
DS_Stopped,
} DisplayState;
delegate OnStopped();
function Restart()
{
CurLine = 0;
Caption = "";
DisplayState = DS_Delay;
if (InitialDelay <= 0.0) SetTimer(0.001, true);
else SetTimer(InitialDelay, true);
}
function Stop()
{
Caption="";
TimerInterval = 0;
DisplayState = DS_Stopped;
OnStopped();
}
/**
Set the subtitles, using default timing
if bDontGuess == true lengthdata will be used (uses the same seperator)
Return the number of items added
*/
function int SetSubtitles(string alldata, optional string sep, optional bool bDontGuess, optional string lengthdata)
{
local array<string> newdata, datalength;
local int i;
if (sep == "") sep = Separator;
split(alldata, sep, newdata);
if (bDontGuess)
{
split(lengthdata, sep, datalength);
datalength.length = newdata.length;
}
ClearSubtitles();
for (i = 0; i < newdata.length; i++)
{
if (bDontGuess) AddSubtitle(newdata[i], float(datalength[i]));
else AddSubtitle(newdata[i], GuessCharTime*Len(newdata[i]));
}
Restart();
return i;
}
/**
Add a subtitle
if delay/visible is omitted or 0 the default value is used
to have an actual 0 as visible/delay use a negative value
*/
function int AddSubtitle(string NewTitle, optional float delay, optional float Visible)
{
return InsertSubtitle(SubTitles.length, NewTitle, delay, Visible);
}
/**
Insert a subtitle
If the position is invalid -1 is returned
*/
function int InsertSubtitle(int position, string NewTitle, optional float delay, optional float Visible)
{
if (position > SubTitles.Length) return -1;
if (position < 0) return -1;
SubTitles.Insert(position, 1);
SubTitleTiming.Insert(position, 1);
SubTitles[position] = NewTitle;
if (delay == 0) delay = DelayTime;
SubTitleTiming[position].Delay = Max(delay, 0);
if (visible == 0) visible = VisibleTime;
if (visible >= delay) visible = 0;
SubTitleTiming[position].Visible = Max(visible, 0);
//Log(":::: Added new subtitle: '"$NewTitle$"'"@delay@Visible@position);
return position;
}
function ClearSubtitles()
{
SubTitles.length = 0;
SubTitleTiming.length = 0;
}
event Timer()
{
if (CurLine >= SubTitles.length)
{
Caption="";
TimerInterval = 0;
DisplayState = DS_Stopped;
OnStopped();
return;
}
if (DisplayState == DS_Delay)
{
Caption = SubTitles[CurLine];
if (SubTitleTiming[CurLine].Visible > 0)
{
DisplayState = DS_Visibility;
TimerInterval = SubTitleTiming[CurLine].Visible;
}
else {
TimerInterval = SubTitleTiming[CurLine].delay;
CurLine++;
}
}
else if (DisplayState == DS_Visibility) {
Caption = "";
DisplayState = DS_Delay;
TimerInterval = SubTitleTiming[CurLine].delay-SubTitleTiming[CurLine].Visible;
CurLine++;
}
}
defaultproperties
{
TextAlign=TXTA_Center
InitialDelay=0
GuessCharTime=0.06
DelayTime=2
VisibleTime=0
bTransparent=true
bMultiLine=true
Separator="|"
StyleName="TextLabel"
}

View file

@ -0,0 +1,78 @@
// ====================================================================
// GUITabButton - A Tab Button has an associated Tab Control, and
// TabPanel.
//
// Written by Joe Wilcox
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUITabButton extends GUIButton
Native;
var bool bForceFlash; // Lets you get a tab to flash even if its not focused
var bool bActive; // Is this the active tab
var GUITabPanel MyPanel; // This is the panel I control
cpptext
{
UBOOL MousePressed(UBOOL IsRepeat); // The Mouse was pressed
UBOOL MouseReleased(); // The Mouse was released
void Draw(UCanvas* Canvas);
UGUIComponent* UnderCursor(FLOAT MouseX, FLOAT MouseY);
}
event SetFocus(GUIComponent Who)
{
}
function bool ChangeActiveState(bool IsActive, bool bFocusPanel)
{
if ( MyPanel == None)
return false;
if ( IsActive )
{
if ( !CanShowPanel() )
return false;
MyPanel.ShowPanel(true);
if ( bFocusPanel )
{
if ( !MyPanel.FocusFirst(None) )
{
MyPanel.ShowPanel(bActive);
return false;
}
bActive = true;
return true;
}
bActive = true;
return true;
}
MyPanel.ShowPanel(false);
bActive = false;
return true;
}
function bool CanShowPanel()
{
// Only return false if tabbutton is disabled, but allow it if only !bVisible
if ( MenuState == MSAT_Disabled || MyPanel == None )
return false;
return MyPanel.CanShowPanel();
}
defaultproperties
{
StyleName="TabButton"
bActive=false
bBoundToParent=True
bNeverFocus=true
WinHeight=0.075
OnClickSound=CS_Edit
FontScale=FNS_Medium
}

View file

@ -0,0 +1,652 @@
// ====================================================================
// GUITabControl - This control has a number of tabs
//
// Written by Joe Wilcox
// (c) 2003, Epic Games, Inc. All Rights Reserved
//
// Updated by Ron Prestenback
// ====================================================================
class GUITabControl extends GUIMultiComponent
Native;
cpptext
{
void PreDraw(UCanvas* Canvas);
void Draw(UCanvas* Canvas);
UGUIComponent* UnderCursor(FLOAT MouseX, FLOAT MouseY);
UBOOL SpecialHit( UBOOL bForce );
UBOOL MousePressed(UBOOL IsRepeat); // The Mouse was pressed
UBOOL MouseReleased(); // The Mouse was released
UBOOL IsFocusedOn( const UGUIComponent* Comp ) const;
#ifdef UCONST_Counter
virtual void ResetCounter();
#endif
}
var() bool bFillSpace; // Tab buttons should be resized if cumulative width is smaller than WinWidth
var() bool bDockPanels; // If true, associated panels will dock vertically with this control
var() bool bDrawTabAbove; // If true, tabs are drawn above the tab panels
var() bool bFillBackground;
var() color FillColor;
var() float FadeInTime;
var() float TabHeight;
var() string BackgroundStyleName;
var() Material BackgroundImage;
var() editconst noexport array<GUITabButton> TabStack;
var() editconst noexport GUITabButton ActiveTab, PendingTab;
var() editconst noexport GUIStyles BackgroundStyle;
var() editconst noexport GUIBorder MyFooter;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.InitComponent(MyController, MyOwner);
if (BackgroundStyleName != "")
BackgroundStyle = Controller.GetStyle(BackgroundStyleName,FontScale);
OnKeyEvent = InternalOnKeyEvent;
}
event Opened( GUIComponent Sender )
{
local int i;
Super.Opened(Sender);
for ( i = 0; i < TabStack.Length; i++ )
{
if ( TabStack[i] != None )
TabStack[i].Opened(Self);
}
if ( !bInit && bVisible && ActiveTab != None && ActiveTab.MyPanel != None )
ActivateTab(ActiveTab, True);
bInit = false;
}
event Closed( GUIComponent Sender, bool bCancelled )
{
local int i;
Super.Closed(Sender,bCancelled);
for ( i = 0; i < TabStack.Length; i++ )
if ( TabStack[i] != None )
TabStack[i].Closed(Sender,bCancelled);
}
function bool InternalOnKeyEvent(out byte Key, out byte State, float delta)
{
local int i,aTabIndex, StartIndex;
if ( (FocusedControl!=None) || (TabStack.Length<=0) )
return false;
if (ActiveTab == None)
return false;
for(i=0;i<TabStack.Length;i++)
{
if (TabStack[i]==ActiveTab)
{
aTabIndex = i;
break;
}
}
if ( Key==0x25 && State == 1 ) // Left
{
StartIndex = aTabIndex;
while (true)
{
if (aTabIndex==0)
aTabIndex=TabStack.Length-1;
else
aTabIndex--;
// Send false for bFocusPanel to ActivateTab here to continue using left/right
if (aTabIndex == StartIndex || ActivateTab(TabStack[aTabIndex], False))
break;
}
return true;
}
if ( Key==0x27 && State == 1 ) // Right
{
StartIndex = aTabIndex;
while (true)
{
aTabIndex++;
if (aTabIndex==TabStack.Length)
aTabIndex=0;
// Send false for bFocusPanel to ActivateTab here to continue using left/right
if (StartIndex == aTabIndex || ActivateTab(TabStack[aTabIndex], False))
break;
}
return true;
}
return false;
}
function GUITabPanel AddTabItem( GUITabItem Item )
{
return AddTab( Item.Caption, Item.ClassName, ,Item.Hint );
}
function GUITabPanel AddTab(string InCaption, string PanelClass, optional GUITabPanel ExistingPanel, optional string InHint, optional bool bForceActive)
{
local class<GUITabPanel> NewPanelClass;
local GUITabButton NewTabButton;
local GUITabPanel NewTabPanel;
local int i;
// Make sure this doesn't exist first
for (i=0;i<TabStack.Length;i++)
{
if (TabStack[i].Caption ~= InCaption)
{
log("A tab with the caption"@InCaption@"already exists.");
return none;
}
}
if (ExistingPanel==None)
NewPanelClass = class<GUITabPanel>(Controller.AddComponentClass(PanelClass));
if ( (ExistingPanel!=None) || (NewPanelClass != None) )
{
if (ExistingPanel != None)
NewTabPanel = GUITabPanel(AppendComponent(ExistingPanel,True));
else if (NewPanelClass != None)
NewTabPanel = GUITabPanel(AddComponent(PanelClass,True));
if (NewTabPanel == None)
{
log("Could not create panel for"@NewPanelClass);
return None;
}
if (NewTabPanel.MyButton != None)
NewTabButton = NewTabPanel.MyButton;
else
{
NewTabButton = new class'GUITabButton';
if (NewTabButton==None)
{
log("Could not create tab for"@NewPanelClass);
return None;
}
NewTabButton.InitComponent(Controller, Self);
NewTabButton.Opened(Self);
NewTabPanel.MyButton = NewTabButton;
if (!bDrawTabAbove)
{
NewTabPanel.MyButton.bBoundToParent = False;
NewTabPanel.MyButton.Style = Controller.GetStyle("FlippedTabButton",NewTabPanel.FontScale);
}
}
NewTabPanel.MyButton.Hint = Eval(InHint != "", InHint, NewTabPanel.Hint);
NewTabPanel.MyButton.Caption = Eval(InCaption != "", InCaption, NewTabPanel.PanelCaption);
NewTabPanel.MyButton.OnClick = InternalTabClick;
NewTabPanel.MyButton.MyPanel = NewTabPanel;
NewTabPanel.MyButton.FocusInstead = self;
NewTabPanel.MyButton.bNeverFocus = true;
NewTabPanel.InitPanel();
// Add the tab to controls
TabStack[TabStack.Length] = NewTabPanel.MyButton;
if ( (TabStack.Length==1 && bVisible) || (bForceActive) )
ActivateTab(NewTabPanel.MyButton,true);
else NewTabPanel.Hide();
return NewTabPanel;
}
return none;
}
function GUITabPanel InsertTab(int Pos, string Caption, string PanelClass, optional GUITabPanel ExistingPanel, optional string InHint, optional bool bForceActive)
{
local class<GUITabPanel> NewPanelClass;
local GUITabPanel NewTabPanel;
local GUITabButton NewTabButton;
if (ExistingPanel == None)
NewPanelClass = class<GUITabPanel>(Controller.AddComponentClass(PanelClass));
if ( ExistingPanel != None || NewPanelClass != None)
{
if (ExistingPanel != None)
NewTabPanel = GUITabPanel(AppendComponent(ExistingPanel,True));
else if (NewPanelClass != None)
NewTabPanel = GUITabPanel(AddComponent(PanelClass,True));
if (NewTabPanel == None)
{
log("Could not create panel for"@NewPanelClass);
return None;
}
if (NewTabPanel.MyButton != None)
NewTabButton = NewTabPanel.MyButton;
else
{
NewTabButton = new class'GUITabButton';
if (NewTabButton==None)
{
log("Could not create tab for"@NewPanelClass);
return None;
}
NewTabButton.InitComponent(Controller, Self);
NewTabButton.Opened(Self);
NewTabPanel.MyButton = NewTabButton;
}
NewTabPanel.MyButton.Caption = Caption;
NewTabPanel.MyButton.Hint = InHint;
NewTabPanel.MyButton.OnClick = InternalTabClick;
NewTabPanel.MyButton.MyPanel = NewTabPanel;
NewTabPanel.MyButton.FocusInstead = self;
NewTabPanel.MyButton.bNeverFocus = true;
NewTabPanel.InitPanel();
TabStack.Insert(Pos, 1);
TabStack[Pos] = NewTabPanel.MyButton;
if (TabStack.Length==1 || bForceActive)
ActivateTab(NewTabPanel.MyButton,true);
else NewTabPanel.Hide();
return NewTabPanel;
}
return None;
}
function GUITabPanel ReplaceTab(GUITabButton Which, string Caption, string PanelClass, optional GUITabPanel ExistingPanel, optional string InHint, optional bool bForceActive)
{
local class<GUITabPanel> NewPanelClass;
local GUITabPanel NewTabPanel, OldTabPanel;
if (ExistingPanel==None)
NewPanelClass = class<GUITabPanel>(Controller.AddComponentClass(PanelClass));
if ( (ExistingPanel!=None) || (NewPanelClass != None) )
{
OldTabPanel = Which.MyPanel;
if (ExistingPanel==None)
NewTabPanel = GUITabPanel(AddComponent(PanelClass, True));
else
NewTabPanel = GUITabPanel(AppendComponent(ExistingPanel, True));
if (NewTabPanel==None)
{
log("Could not create panel"@NewPanelClass);
return none;
}
Which.Caption = Caption;
Which.Hint = InHint;
Which.MyPanel = NewTabPanel;
NewTabPanel.MyButton = Which;
// Init new panel
NewTabPanel.InitPanel();
// Make sure to notify old tab - so use ActivateTab
if ( bForceActive )
ActivateTab(NewTabPanel.MyButton, True);
else NewTabPanel.Hide();
// Notify old panel
RemoveComponent(OldTabPanel);
OldTabPanel.Free();
return NewTabPanel;
}
return none;
}
function RemoveTab(optional string Caption, optional GUITabButton who)
{
local int i;
local bool bActive;
local GUITabPanel OldPanel;
if ( (caption=="") && (Who==None) )
return;
if (Who==None)
i = TabIndex(Caption);
else i = TabIndex(Who.Caption);
if (i < 0)
return;
OldPanel = TabStack[i].MyPanel;
bActive = TabStack[i] == ActiveTab;
TabStack[i].OnClick = None;
TabStack[i].Free();
TabStack.Remove(i, 1);
RemoveComponent(OldPanel,True);
OldPanel.Free();
if (bActive)
LostActiveTab();
}
function bool LostActiveTab()
{
local int i;
if (!Controller.bCurMenuInitialized)
return false;
for (i = 0; i < TabStack.Length; i++)
if (ActivateTab(TabStack[i],true))
return true;
return false;
}
event MakeTabActive(GUITabButton Who)
{
if (ActiveTab!=None)
ActiveTab.ChangeActiveState(false,false);
PendingTab = None;
ActiveTab = Who;
OnChange(Who);
}
function bool ActivateTab(GUITabButton Who, bool bFocusPanel)
{
if (Who == none || PendingTab != None || !Who.CanShowPanel()) // null or not selectable
return false;
Who.bForceFlash = False;
if (Who==ActiveTab) // Same Tab, just accept
{
if ( ActiveTab.ChangeActiveState(True, bFocusPanel) )
return true;
return false;
}
PendingTab = Who;
if ( PendingTab.ChangeActiveState(True, bFocusPanel) )
{
if (PendingTab.MyPanel.FadeInTime==0.0 || TabStack.Length<2)
MakeTabActive(Who);
else
{
FadeInTime = PendingTab.MyPanel.FadeInTime;
if (!Controller.bQuietMenu)
PlayerOwner().PlayOwnedSound(Controller.FadeSound,SLOT_Interface,1.0);
}
return true;
}
PendingTab = None;
return false;
}
function bool ActivateTabByName(string tabname, bool bFocusPanel)
{
local int i;
i = TabIndex(TabName);
if (i < 0 || i >= TabStack.Length) return false;
return ActivateTab(TabStack[i], bFocusPanel);
}
function bool ActivateTabByPanel( GUITabPanel Panel, bool bFocusPanel )
{
local int i;
if ( Panel == None || !Panel.CanShowPanel() )
return false;
for ( i = 0; i < TabStack.Length; i++ )
if ( TabStack[i] != None && TabStack[i].MyPanel == Panel )
return ActivateTab(TabStack[i], bFocusPanel);
return false;
}
function bool InternalTabClick(GUIComponent Sender)
{
local GUITabButton But;
But = GUITabButton(Sender);
if (But==None)
return false;
ActivateTab(But,true);
return true;
}
event bool NextPage()
{
local int i;
// If 1 or no tabs in the stack, then query parents
if (TabStack.Length < 2)
return Super.NextPage();
if (ActiveTab == None)
i = 0;
else
{
i = TabIndex(ActiveTab.Caption) + 1;
if ( i >= TabStack.Length )
i = 0;
}
return ActivateTab(TabStack[i], true);
}
event bool PrevPage()
{
local int i;
if (TabStack.Length < 2)
return Super.PrevPage();
if (ActiveTab == None)
i = TabStack.Length - 1;
else
{
i = TabIndex(ActiveTab.Caption) - 1;
if ( i < 0 )
i = TabStack.Length - 1;
}
return ActivateTab(TabStack[i], true);
}
event bool NextControl(GUIComponent Sender)
{
if (Sender != None)
{
Super(GUIComponent).SetFocus(None);
return true;
}
else
{
if ( Super(GUIComponent).NextControl(Self) )
return true;
else FocusFirst(None);
return true;
}
return false;
}
event bool PrevControl(GUIComponent Sender)
{
if ( Sender != None )
{
Super(GUIComponent).SetFocus(None);
return true;
}
else
{
if ( Super(GUIComponent).PrevControl(Self) )
return true;
else FocusLast(None);
}
return false;
}
function int TabIndex(string TabName)
{
local int i;
for (i = 0; i < TabStack.Length; i++)
if (TabStack[i].Caption ~= TabName)
return i;
return -1;
}
function GUITabPanel FindPanelClass( class<GUITabPanel> PanelClass )
{
local int i;
if ( PanelClass == None )
return None;
for ( i = 0; i < TabStack.Length; i++ )
{
if ( TabStack[i] != None && TabStack[i].MyPanel != None &&
ClassIsChildOf(TabStack[i].MyPanel.Class, PanelClass) )
return TabStack[i].MyPanel;
}
return None;
}
function GUITabPanel BorrowPanel(string Caption)
{
local int i;
if (Caption == "") return None;
i = TabIndex(Caption);
if (i < 0) return None;
return TabStack[i].MyPanel;
}
function SetVisibility(bool bIsVisible)
{
Super.SetVisibility(bIsVisible);
if (ActiveTab != None)
ActiveTab.ChangeActiveState(bIsVisible, False);
}
function InternalOnActivate()
{
if (ActiveTab == None)
LostActiveTab();
}
function bool FocusFirst(GUIComponent Sender)
{
if ( ActiveTab != None && ActiveTab.MyPanel != None && ActiveTab.MyPanel.CanAcceptFocus() && ActiveTab.MyPanel.FocusFirst(None) )
return true;
else if (!Super.FocusFirst(Sender))
Super(GUIComponent).SetFocus(None);
return true;
}
function bool FocusLast(GUIComponent Sender)
{
if ( ActiveTab != None && ActiveTab.MyPanel != None && ActiveTab.MyPanel.CanAcceptFocus() && ActiveTab.MyPanel.FocusLast(None) )
return true;
else if ( !Super.FocusLast(Sender) )
Super(GUIComponent).SetFocus(None);
return true;
}
function CenterMouse()
{
if ( ActiveTab != None )
ActiveTab.CenterMouse();
else Super.CenterMouse();
}
event Free()
{
local int i;
for ( i = 0; i < TabStack.Length; i++ )
{
if ( TabStack[i] != None )
TabStack[i].Free();
}
Super.Free();
}
function LevelChanged()
{
local int i;
for ( i = 0; i < TabStack.Length; i++ )
{
if ( TabStack[i] != None )
TabStack[i].LevelChanged();
}
Super.LevelChanged();
}
defaultproperties
{
OnActivate=InternalOnActivate
bDrawTabAbove=true
TabHeight=0.0350
bFillSpace=false
bTabStop=true
bDockPanels=false
bFillBackground=true
}

View file

@ -0,0 +1,49 @@
// ====================================================================
// GUITabButton - A Tab Button has an associated Tab Control, and
// TabPanel.
//
// Written by Joe Wilcox
// Updated by Ron Prestenback
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUITabPanel extends GUIPanel
native
abstract;
var(Panel) localized string PanelCaption;
var(Panel) bool bFillHeight; // If true, the panel will set it's height = Top - ClipY
var(Panel) float FadeInTime;
var noexport GUITabButton MyButton;
function Refresh(); // this function is used by all tab panels
function InitPanel(); // Should be Subclassed
function OnDestroyPanel(optional bool bCancelled) // Always call Super.OnDestroyPanel()
{
MyButton = None;
}
event Free()
{
OnDestroyPanel(True);
Super.Free();
}
function ShowPanel(bool bShow) // Show Panel should be subclassed if any special processing is needed
{
if ( Controller != None && Controller.bModAuthor )
log("# # # #"@MyButton.Caption@"ShowPanel() "@bShow,'ModAuthor');
SetVisibility(bShow);
}
function bool CanShowPanel() // Subclass this function to change selection behavior of the tab
{
return true;
}
defaultproperties
{
bInit=True
FadeInTime=0.0
}

View file

@ -0,0 +1,32 @@
// ====================================================================
// Base class for header / footer bars
//
// Written by Joe Wilcox
// Updated by Ron Prestenback
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUITitleBar extends GUIBorder
Native;
cpptext
{
void PreDraw(UCanvas* Canvas);
}
var GUITabControl DockedTabs; // Set this to a Tab control and that control will be centered undeneath
var() ePageAlign DockAlign; // How to Align the tabs.. only Left, Center and right work
var() bool bUseTextHeight; // Should this control scale to the text height
var() bool bDockTop; // If True, dock the control ON TOP of this one
var const Material Effect; // obsolete
defaultproperties
{
bUseTextHeight=True
bTabStop=False
bNeverFocus=True
bVisible=True
DockAlign=PGA_None
StyleName="TextLabel"
}

View file

@ -0,0 +1,226 @@
//==============================================================================
// Created on: 01/19/2004
// Tooltip that appears when this component is moused over
//
// Written by Ron Prestenback
// © 2003, Epic Games, Inc. All Rights Reserved
//==============================================================================
class GUIToolTip extends GUIComponent
native;
cpptext
{
void PreDraw( UCanvas* C );
void Draw( UCanvas* C );
void SetTip( FString& NewTip );
}
var() bool bResetPosition; // Position of this component needs to be updated
var() bool bTrackMouse; // This tooltip will follow the mouse as it moves
var() bool bMultiLine; // Allow hint text to be wrapped if it's too long
var() bool bTrackInput; // Should this tooltip disappear when input is received
var() const string Text; // Entire tooltip
var() const array<string> Lines; // If multiline == true, contains the tooltip lines
var() noexport float StartTime;
var() noexport float CurrentTime;
var() globalconfig float MaxWidth; // Max width of the tooltip area, in percent of the screen width
var() globalconfig float InitialDelay; // Number of seconds of inactivity before appearing
var() globalconfig float ExpirationSeconds; // Number of seconds to display before fading out
// Return true to override default behavior
// SetPosition() is called at the end of the native PreDraw(), if (bResetPosition || bTrackMouse),
// which means SetPosition() will NOT be called if you return true from OnPreDraw()
// delegate bool OnPreDraw( Canvas C );
// Draw will NOT be called if bResetPosition == true
// delegate bool OnDraw( Canvas C );
// called when the mouse is first moved over the component associated with this tooltip
delegate GUIToolTip EnterArea()
{
return InternalEnterArea();
}
function GUIToolTip InternalEnterArea()
{
if (Controller==None)
{
if ( class'GUIController'.default.bModAuthor )
log("ToolTip ("$self$") not initialized");
return none;
}
StartTime = PlayerOwner().Level.TimeSeconds;
// if there was a hint currently being displayed, bypass the initial delay
if ( Controller != None && Controller.MouseOver != None && Controller.MouseOver != Self && Controller.MouseOver.bVisible )
CurrentTime = InitialDelay;
else CurrentTime = 0.0;
bResetPosition = true;
return self;
}
// Called when the mouse is moved away from the component associated with this tooltip
// Return false to keep displaying the tooltip - though sometimes controller will force the tooltip to disappear
// (for instance, if opening a context menu, etc.)
delegate bool LeaveArea()
{
return InternalLeaveArea();
}
function bool InternalLeaveArea()
{
StartTime = -1;
CurrentTime = -1;
SetVisibility(false);
if ( Controller != None && Controller.MouseOver == Self )
Controller.MouseOver = None;
return true;
}
// Only received when active
delegate Tick( float RealSeconds )
{
CurrentTime += RealSeconds;
if ( !bVisible && CurrentTime > InitialDelay && (ExpirationSeconds == 0.0 || CurrentTime <= ExpirationSeconds) )
ShowToolTip();
if ( bVisible && CurrentTime > ExpirationSeconds && ExpirationSeconds > 0.0 )
HideToolTip();
}
delegate ShowToolTip()
{
SetVisibility(true);
}
delegate HideToolTip()
{
SetVisibility(false);
}
// This is normally called at the end of PreDraw().
event UpdatePosition( Canvas C )
{
WinWidth = GetWidth(C);
WinHeight = GetHeight(C);
WinLeft = GetLeft(C);
WinTop = GetTop(C);
bResetPosition = false;
}
delegate float GetLeft( Canvas C )
{
local float X;
if ( C == None || MenuOwner == None || Style == None )
return -1.0;
X = FMin(Controller.MouseX, Controller.MouseCursorBounds.X1);
if ( X + WinWidth > C.SizeX )
X -= WinWidth + 10;
return X;
}
delegate float GetTop( Canvas C )
{
local float TargetTop;
if ( C == None || MenuOwner == None || Style == None )
return -1.0;
if ( Controller.MouseY > C.SizeY / 8 )
TargetTop = GetTopAboveCursor(C);
else TargetTop = GetTopBelowCursor(C);
if ( TargetTop < 0 )
TargetTop = GetTopBelowCursor(C);
return TargetTop;
}
delegate float GetWidth( Canvas C )
{
local int i;
local float MaxLineWidth, XL, YL;
if ( C == None || Lines.Length == 0 || MenuOwner == None || Style == None )
return 0.0;
for ( i = 0; i < Lines.Length; i++ )
{
Style.TextSize(C, MenuOwner.MenuState, Lines[i], XL, YL, FontScale);
if ( XL > MaxLineWidth )
MaxLineWidth = XL;
}
return FMin( MaxLineWidth, MaxWidth * C.SizeX ) + Style.BorderOffsets[0] + Style.BorderOffsets[2];
}
delegate float GetHeight( Canvas C )
{
local float XL, YL;
if ( C == None || Lines.Length == 0 || MenuOwner == None || Style == None )
return 0.0;
Style.TextSize( C, MenuOwner.MenuState, Lines[0], XL, YL, FontScale );
return (YL * Lines.Length) + Style.BorderOffsets[1] + Style.BorderOffsets[3];
}
singular function float GetTopAboveCursor( Canvas C )
{
local float TargetY, TempY;
if ( MenuOwner == None || C == None || Controller == None )
return -1.0;
TargetY = FMin(Controller.MouseCursorBounds.Y1, Controller.MouseY) - (WinHeight + 10);
if ( TargetY < 0 )
TempY = GetTopBelowCursor(C);
return FMax(TempY, TargetY);
}
singular function float GetTopBelowCursor( Canvas C )
{
local float TargetY, TempY;
if ( MenuOwner == None || C == None || Controller == None )
return -1.0;
TargetY = FMax(Controller.MouseCursorBounds.Y2, Controller.MouseY) + 10;
if ( TargetY + WinHeight > C.SizeY )
TempY = GetTopAboveCursor(C);
return FMax(TargetY, TempY);
}
native final function SetTip( coerce string NewTip );
DefaultProperties
{
bRequiresStyle=True
bVisible=false
bTrackMouse=false
bMultiLine=true
bTrackInput=true
MaxWidth=0.3
ExpirationSeconds=3.0
InitialDelay=0.25
StyleName="MouseOver"
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,96 @@
// ====================================================================
// Class: GUITreeListBox
//
// Written by Bruce Bickar
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUITreeListBox extends GUIListBoxBase native;
cpptext
{
void PreDraw(UCanvas* Canvas);
}
var GUITreeList List;
function InitBaseList(GUIListBase LocalList)
{
if ((List == None || List != LocalList) && GUITreeList(LocalList) != None)
List = GUITreeList(LocalList);
List.OnClick=InternalOnClick;
List.OnClickSound=CS_Click;
List.OnChange=InternalOnChange;
List.OnDblClick = InternalDblClick;
Super.InitBaseList(LocalList);
}
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.Initcomponent(MyController, MyOwner);
if (DefaultListClass != "")
{
List = GUITreeList(AddComponent(DefaultListClass));
if (List == None)
{
log(Class$".InitComponent - Could not create default list ["$DefaultListClass$"]");
return;
}
}
if (List == None)
{
Warn("Could not initialize list!");
return;
}
InitBaseList(List);
}
function bool InternalOnClick(GUIComponent Sender)
{
List.InternalOnClick(Sender);
OnClick(Self);
return true;
}
function InternalOnChange(GUIComponent Sender)
{
if (Controller != None && Controller.bCurMenuInitialized)
OnChange(Self);
}
function bool InternalDblClick( GUIComponent Sender )
{
List.InternalDblClick(Sender);
OnDblClick(Self);
return True;
}
function int ItemCount()
{
return List.ItemCount;
}
function bool MyOpen(GUIContextMenu Menu)
{
return HandleContextMenuOpen(self, Menu, Menu.MenuOwner);
}
function bool MyClose(GUIContextMenu Sender)
{
return HandleContextMenuClose(Sender);
}
defaultproperties
{
Begin Object Class=GUITreeScrollBar Name=TreeScrollbar
bVisible=false
End Object
MyScrollBar=TreeScrollbar
DefaultListClass="XInterface.GUITreeList"
}

View file

@ -0,0 +1,84 @@
// ====================================================================
// Class: GUITreeScrollBar
//
// The GUITreeScrollBar is used with the GUITreeListBox.
//
// Written by Bruce Bickar
// (c) 2002, 2003, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUITreeScrollBar extends GUIVertScrollBar;
var() editconst noexport GUITreeList List;
function SetList( GUIListBase InList )
{
Super.SetList(InList);
List = GUITreeList(InList);
if ( List != None )
ItemCount = List.VisibleCount;
}
function UpdateGripPosition(float NewPos)
{
if (List != none)
{
List.MakeVisible(NewPos);
ItemCount = List.VisibleCount;
}
GripPos = NewPos;
CurPos = (ItemCount-ItemsPerPage)*GripPos;
PositionChanged(CurPos);
}
delegate MoveGripBy(int items)
{
local int NewItem;
if (List != none)
{
NewItem = List.Top + items;
ItemCount = List.VisibleCount;
if (ItemCount > 0)
{
List.SetTopItem(NewItem);
// AlignThumb();
}
}
CurPos += items;
if (CurPos < 0)
CurPos = 0;
if (CurPos > ItemCount-ItemsPerPage)
CurPos = ItemCount-ItemsPerPage;
if ( List == None && ItemCount > 0 )
AlignThumb();
PositionChanged(CurPos);
}
delegate AlignThumb()
{
local float NewPos;
if (List != none)
{
BigStep = List.ItemsPerPage * Step;
if (List.ItemCount==0)
NewPos = 0;
else
NewPos = float(List.Top) / float(List.VisibleCount-List.ItemsPerPage);
}
else {
if (ItemCount==0)
NewPos = 0;
else
NewPos = CurPos / float(ItemCount-ItemsPerPage);
}
GripPos = FClamp(NewPos, 0.0, 1.0);
}
defaultproperties
{
}

View file

@ -0,0 +1,36 @@
// ====================================================================
// (C) 2002, Epic Games
//
//
// The GUIUSerKeyBinding is a class tha allows mod authors to add keys
// to the control menu. It works as follows:
//
// Mod authors subclass this actor in their package. They then need
// to add the following line to their .INT file
//
// Object=(Class=Class,MetaClass=XInterface.GUIUserKeyBinding,Name=ModPackageName.CustomKeyBindClassName)
//
// The controller config menu will preload all of these on startup and
// add them to it's list.
//
// Alias is the actual alias you wish to bind.
// KeyLabel is the text description that will be displayed in the list
// bIsSection if set, will cause the menu to add it as a section label
//
// ====================================================================
class GUIUserKeyBinding extends GUI
Abstract;
struct KeyInfo
{
var string Alias; // The Alias used for this binding
var string KeyLabel; // The text label for this binding
var bool bIsSection; // Is this a section label
};
var array<KeyInfo> KeyData;
defaultproperties
{
}

View file

@ -0,0 +1,11 @@
class GUIVertGripButton extends GUIGripButtonBase;
function InitComponent(GUIController MyController, GUIComponent MyComponent)
{
Super(GUIButton).InitComponent(MyController, MyComponent);
}
defaultproperties
{
StyleName="VertGrip"
}

View file

@ -0,0 +1,672 @@
// ====================================================================
// (C) 2002, Epic Games
// ====================================================================
class GUIVertImageList extends GUIVertList
Native;
cpptext
{
void PreDraw(UCanvas* Canvas);
void Draw(UCanvas* Canvas);
void DrawItem( UCanvas* Canvas, INT Item, FLOAT X, FLOAT Y, FLOAT XL, FLOAT YL, UBOOL bSelected, UBOOL bPending );
}
var() eCellStyle CellStyle;
var() float ImageScale; // Scale value for the images
var() int NoVisibleRows; // How many rows of visible images are there
var() int NoVisibleCols; // How many cols of visible images are there
var() int HorzBorder, VertBorder; // How much white space
var() editconstarray editconst array<ImageListElem> Elements;
var() editconstarray editconst array<ImageListElem> SelectedElements;
var() material LockedMat;
event int CalculateIndex( optional bool bRequireValidIndex )
{
local int i;
local int HitCol, HitRow;
HitCol = (Controller.MouseX - ClientBounds[0]) / ItemWidth;
HitRow = (Controller.MouseY - ClientBounds[1]) / ItemHeight;
i = Top + HitCol + (HitRow * NoVisibleCols);
if ( (i < 0 || i >= ItemCount) && bRequireValidIndex )
return -1;
return i;
}
function bool InternalOnClick(GUIComponent Sender)
{
local int NewIndex;
if ( !IsInClientBounds() || ItemsPerPage==0 )
return false;
NewIndex = CalculateIndex();
if ( !IsValidIndex(NewIndex) )
return false;
SetIndex(NewIndex);
return true;
}
function int SetIndex(int NewIndex)
{
if (Elements[NewIndex].Locked==1)
return Index;
return super.SetIndex(NewIndex);
}
function bool Up()
{
local int TargetIndex;
if ( Index - NoVisibleCols < 0 )
return true;
TargetIndex = Index-NoVisibleCols;
if ( Elements[TargetIndex].Locked==1 )
{
TargetIndex = TargetIndex-NoVisibleCols;
if ( TargetIndex<0 || Elements[TargetIndex].Locked==1 )
return true;
}
SetIndex(TargetIndex);
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
return true;
}
function bool Down()
{
local int TargetIndex;
if ( Index + NoVisibleCols >= ItemCount )
return true;
TargetIndex = Index + NoVisibleCols;
if ( Elements[TargetIndex].Locked==1 )
{
TargetIndex = TargetIndex + NoVisibleCols;
if ( TargetIndex >= ItemCount || Elements[TargetIndex].Locked==1 )
return true;
}
SetIndex(TargetIndex);
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
return true;
}
function bool MoveRight()
{
local int TargetIndex;
TargetIndex = ( Index + 1 );
if ( TargetIndex % NoVisibleCols == 0 )
return true;
if (Elements[TargetIndex].Locked==1)
{
TargetIndex++;
if ( (TargetIndex % NoVisibleCols == 0 ) || (Elements[TargetIndex].Locked==1) )
return true;
}
if ( TargetIndex < ItemCount )
SetIndex(TargetIndex);
return true;
}
function bool MoveLeft()
{
local int TargetIndex;
if ( Index % NoVisibleCols == 0 )
return true;
TargetIndex = Index - 1;
if (Elements[TargetIndex].Locked==1)
{
TargetIndex--;
if (TargetIndex<0 || TargetIndex%NoVisibleCols==NoVisibleCols-1 || Elements[TargetIndex].Locked==1)
return true;
}
if ( Index > 0 )
SetIndex(TargetIndex);
return true;
}
function Home()
{
local int i;
if ( ItemCount < 2 )
return;
for (i=0;i<Index;i++)
if (Elements[i].Locked!=1)
{
SetIndex(i);
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
return;
}
}
function End()
{
local int i;
if ( ItemCount < 2 )
return;
for (i=ItemCount-1;i>0;i--)
if (Elements[i].Locked!=1)
{
SetIndex( i );
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
return;
}
}
function PgUp()
{
local int newtop;
if (Top > 0)
{
NewTop = max(0,Top-NoVisibleRows);
SetTopItem(NewTop);
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
}
return;
}
function PgDn()
{
local int newtop;
if ( Top < (ItemCount / NoVisibleCols) - NoVisibleRows)
{
NewTop = Max(0, Top+NoVisibleRows);
SetTopItem(NewTop);
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
}
return;
}
function MakeVisible(float Perc)
{
local float MaxTop, ModResult;
local int NewTop, Change;
MaxTop = ItemCount - ItemsPerPage;
ModResult = MaxTop % NoVisibleCols;
if ( ModResult > 0 )
MaxTop = (MaxTop - ModResult) + NoVisibleCols;
// NewItem is number of hidden items * Perc we want to show
// Round off result before adjusting top to prevent constant flipping back and forth between two items
// or if we're attempting to view the last row
NewTop = Round(MaxTop * Perc);
Change = Abs(Top - NewTop);
if ( Change < NoVisibleCols && Perc < 1.0)
return;
SetTopItem(NewTop);
}
function SetTopItem(int Item)
{
local int ModResult;
// clamp new top to prevent displaying space below last items of list
Item = Clamp(Item, 0, ItemCount - 1);
// Adjust the result to fall on the first column - otherwise, elements might get shifted to a different column
ModResult = Item % NoVisibleCols;
if ( ModResult > 0 )
{
// If we had leftover items, we'll need another row
if ( Item > Top )
Item += NoVisibleCols;
Item -= ModResult;
}
// But if we went too far (more than itemcount + numcolumns), then back it up
while ( (Item + ItemsPerPage > ItemCount + NoVisibleCols) && Item >= 0)
Item -= NoVisibleCols;
Top = Max( 0, Item );
OnAdjustTop(Self);
}
function Add(Material Image, optional int Item, optional int Locked)
{
local int i;
if ( Image == None && !bAllowEmptyItems )
return;
i = Elements.Length;
Elements.Length = i + 1;
Elements[i].Image = Image;
Elements[i].Item = Item;
Elements[i].Locked = Locked;
ItemCount = Elements.Length;
if (ItemCount == 1 && bInitializeList)
SetIndex(0);
else CheckLinkedObjects(Self);
if (MyScrollBar != None)
MyScrollBar.AlignThumb();
}
function AddImage( ImageListElem NewElem, optional int Locked)
{
Add(NewElem.Image, NewElem.Item, Locked);
}
function Replace(int i, Material NewImage, optional int NewItem, optional int Locked)
{
if ( !IsValidIndex(i) )
Add(NewImage, NewItem);
else
{
if ( !bAllowEmptyItems && NewImage == None )
return;
Elements[i].Item = NewItem;
Elements[i].Image = NewImage;
Elements[i].Locked = Locked;
SetIndex(Index);
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
}
}
function Insert(int i, Material NewImage, optional int NewItem, optional int Locked)
{
if ( !IsValidIndex(i) )
Add(NewImage,NewItem);
else
{
if ( !bAllowEmptyItems && NewImage == None )
return;
Elements.Insert(i,1);
Elements[i].Item=NewItem;
Elements[i].Image = NewImage;
Elements[i].Locked = Locked;
ItemCount = Elements.Length;
SetIndex(Index);
if (MyScrollBar != None)
MyScrollBar.AlignThumb();
}
}
function InsertElement( int i, ImageListElem NewElem, optional int Locked )
{
Insert( i, NewElem.Image, NewElem.Item, Locked );
}
event Swap(int IndexA, int IndexB)
{
local ImageListElem elem;
if ( IsValidIndex(IndexA) && IsValidIndex(IndexB) )
{
elem = Elements[IndexA];
Elements[IndexA] = Elements[IndexB];
Elements[IndexB] = elem;
}
}
function LoadFrom(GUIVertImageList Source, optional bool bClearFirst)
{
local int i, item;
local Material mat;
local int l;
if (bClearfirst)
Clear();
for ( i = 0; i < Source.ItemCount; i++ )
{
Source.GetAtIndex(i,mat,item,l);
Add(mat,item,l);
}
}
function int Remove(int i, optional int Count)
{
Count = Max( Count, 1 );
if (!IsValidIndex(i))
return Index;
Elements.Remove(i, Min(Count, Elements.Length - i));
ItemCount = Elements.Length;
// In case we now have an invalid index
SetIndex(Index);
if (MyScrollBar != None)
MyScrollBar.AlignThumb();
return Index;
}
function int RemoveSilent(int i, optional int Count)
{
bNotify = False;
i = Remove(i, Count);
bNotify = True;
return i;
}
function int RemoveElement(ImageListElem Elem, optional int Count)
{
local int i;
Count = Max( Count, 1 );
for ( i = 0; i < Elements.Length; i++ )
{
if ( Elements[i] == Elem )
{
Elements.Remove(i, Min(Count, Elements.Length - i));
break;
}
}
ItemCount = Elements.Length;
// In case we now have an invalid index
SetIndex(Index);
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
return Index;
}
function Clear()
{
if (ItemCount == 0)
return;
Elements.Remove(0,Elements.Length);
Super.Clear();
}
// =====================================================================================================================
// =====================================================================================================================
// Query Functions
// =====================================================================================================================
// =====================================================================================================================
function Material Get(optional bool bGuarantee)
{
if ( !IsValid() )
{
if (bGuarantee && ItemCount > 0)
return Elements[0].Image;
return None;
}
return Elements[Index].Image;
}
function int GetItem()
{
if ( !IsValid() )
return -1;
return Elements[Index].Item;
}
// Arbitrary list Item
function Material GetImageAtIndex(int i)
{
if (!IsValidIndex(i))
return None;
return Elements[i].Image;
}
function string GetItemAtIndex(int i)
{
return string(GetItemIntAtIndex(i));
}
function int GetItemIntAtIndex(int i)
{
if (!IsValidIndex(i))
return -1;
return Elements[i].Item;
}
function GetAtIndex(int i, out Material Image, out int Item, out int Locked)
{
if (!IsValidIndex(i))
return;
Image = Elements[i].Image;
Item = Elements[i].Item;
Locked = Elements[i].Locked;
}
function bool IndexLocked(int i)
{
return Elements[i].Locked==1;
}
function bool IsLocked()
{
return Elements[Index].Locked==1;
}
function ClearPendingElements()
{
Super.ClearPendingElements();
SelectedElements.Remove(0, SelectedElements.Length);
}
function array<ImageListElem> GetPendingElements(optional bool bGuarantee)
{
local int i;
if ( (DropState == DRP_Source && Controller.DropSource == Self) || bGuarantee )
{
if ( SelectedElements.Length == 0 )
{
for (i = 0; i < SelectedItems.Length; i++)
if (IsValidIndex(SelectedItems[i]))
SelectedElements[SelectedElements.Length] = Elements[SelectedItems[i]];
if ( SelectedElements.Length == 0 && IsValid() )
{
SelectedElements.Length = SelectedElements.Length + 1;
GetAtIndex(Index, SelectedElements[0].Image, SelectedElements[0].Item, SelectedElements[0].Locked);
}
}
return SelectedElements;
}
}
//##############################################################################
//
// Assignment functions
//
function SetImageAtIndex(int i, Material NewImage)
{
if ( !IsValidIndex(i) )
return;
Elements[i].Image = NewImage;
}
function SetItemAtIndex(int i, int NewItem)
{
if (!IsValidIndex(i))
return;
Elements[i].Item = NewItem;
}
function RemoveImage( Material Image )
{
local int i;
i = FindImage(Image);
if ( IsValidIndex(i) )
Remove(i);
}
function RemoveItem(int Item)
{
local int i;
for ( i = Elements.Length -1; i >= 0; i-- )
if ( Elements[i].Item == Item )
Remove(i);
ItemCount = Elements.Length;
SetIndex(Index);
if (MyScrollBar != None)
MyScrollBar.AlignThumb();
}
//##############################################################################
//
// Search functions
//
function int FindImage( Material Image )
{
local int i;
if ( Image == None && !bAllowEmptyItems )
return -1;
for ( i = 0; i < Elements.Length; i++ )
if ( Elements[i].Image == Image )
return i;
return -1;
}
function int FindItem( int Item )
{
local int i;
for ( i = 0; i < Elements.Length; i++ )
if ( Elements[i].Item == Item )
return i;
return -1;
}
// Called on the drop source when when an Item has been dropped. bAccepted tells it whether
// the operation was successful or not.
function InternalOnEndDrag(GUIComponent Accepting, bool bAccepted)
{
local int i;
// log(Name@"InternalOnEndDrag Accepting:"$Accepting@"bAccepted:"$bAccepted);
if (bAccepted && Accepting != None)
{
GetPendingElements();
if ( Accepting != Self )
{
for ( i = 0; i < SelectedElements.Length; i++ )
RemoveElement(SelectedElements[i]);
}
bRepeatClick = False;
}
// Simulate repeat click if the operation was a failure to prevent InternalOnMouseRelease from clearing
// the SelectedItems array
// This way we don't lose the items we clicked on
if (Accepting == None)
bRepeatClick = True;
SetOutlineAlpha(255);
if ( bNotify )
CheckLinkedObjects(Self);
}
// Called on the drop target when the mouse is released - Sender is always DropTarget
function bool InternalOnDragDrop(GUIComponent Sender)
{
local array<ImageListElem> NewItem;
local int i;
// log(Name@"InternalOnDragDrop Sender:"$ Sender);
if (Controller.DropTarget == Self)
{
if (Controller.DropSource != None && GUIVertImageList(Controller.DropSource) != None)
{
NewItem = GUIVertImageList(Controller.DropSource).GetPendingElements();
// Special case for drag-n-drop between the same list.
if ( Controller.DropSource == Self )
{
for ( i = NewItem.Length - 1; i >= 0; i-- )
RemoveElement(NewItem[i]);
}
if ( !IsValidIndex(DropIndex) )
DropIndex = ItemCount;
for (i = NewItem.Length - 1; i >= 0; i--)
Insert(DropIndex, NewItem[i].Image, NewItem[i].Item);
SetIndex(DropIndex);
return true;
}
}
return false;
}
defaultproperties
{
OnClick=InternalOnClick
CellStyle=Cell_FixedSize
ImageScale=1.0
StyleName=""
HorzBorder=5
VertBorder=5
NoVisibleRows=4
NoVisibleCols=3
}

View file

@ -0,0 +1,109 @@
// ====================================================================
// (C) 2002, Epic Games
// ====================================================================
class GUIVertImageListBox extends GUIListBoxBase;
var GUIVertImageList List;
var() eCellStyle CellStyle;
var() float ImageScale; // Scale value for the images
var() int NoVisibleRows; // How many rows of visible images are there
var() int NoVisibleCols; // How many cols of visible images are there
var() int HorzBorder, VertBorder; // How much white space
function InitBaseList(GUIListBase LocalList)
{
List = GUIVertImageList(LocalList);
List.CellStyle = CellStyle;
List.ImageScale = ImageScale;
List.NoVisibleRows = NoVisibleRows;
List.NoVisibleCols = NoVisibleCols;
List.HorzBorder = HorzBorder;
List.VertBorder = VertBorder;
LocalList.OnClick=InternalOnClick;
LocalList.OnClickSound=CS_Click;
LocalList.OnChange=InternalOnChange;
MyScrollBar.SetVisibility(true);
MyScrollBar.Step = List.NoVisibleCols;
Super.InitBaseList(LocalList);
}
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
Super.Initcomponent(MyController, MyOwner);
if (DefaultListClass != "")
{
MyList = GUIListBase(AddComponent(DefaultListClass));
if (MyList == None)
{
log(Class$".InitComponent - Could not create default list ["$DefaultListClass$"]");
return;
}
}
if (MyList == None)
{
Warn("Could not initialize list!");
return;
}
InitBaseList(MyList);
}
function bool InternalOnClick(GUIComponent Sender)
{
List.InternalOnClick(Sender);
OnClick(Sender);
return true;
}
function InternalOnChange(GUIComponent Sender)
{
if (Controller != None && Controller.bCurMenuInitialized)
OnChange(Self);
}
function int ItemCount()
{
return List.ItemCount;
}
function AddImage(material Image, optional int Item)
{
List.Add(Image, Item);
}
function bool MyOpen(GUIContextMenu Menu, GUIComponent ContextMenuOwner)
{
return HandleContextMenuOpen(self, Menu, ContextMenuOwner);
}
function bool MyClose(GUIContextMenu Sender)
{
return HandleContextMenuClose(Sender);
}
function Clear()
{
List.Clear();
}
defaultproperties
{
DefaultListClass="XInterface.GUIVertImageList"
CellStyle=Cell_FixedSize
ImageScale=1.0
HorzBorder=2
VertBorder=2
}

View file

@ -0,0 +1,156 @@
class GUIVertList extends GUIListBase
Native;
cpptext
{
void PreDraw(UCanvas* Canvas);
void Draw(UCanvas* Canvas);
}
delegate float GetItemHeight(Canvas C);
function CenterMouse()
{
local PlayerController PC;
local float X, Y;
if ( IsValid() )
{
PC = PlayerOwner();
if ( PC != None )
{
SetTopItem(Index);
X = ActualLeft() + ActualWidth() / 2;
Y = (Index - Top) * ItemHeight;
PC.ConsoleCommand("SETMOUSE" @ X @ Y);
}
return;
}
Super.CenterMouse();
}
event int CalculateIndex( optional bool bRequireValidIndex )
{
local int i, NewIndex;
// Figure out which Item we're clicking on
i = Top + ((Controller.MouseY - ClientBounds[1]) / ItemHeight);
if ( i >= ItemCount && bRequireValidIndex )
i = -1;
NewIndex = Min( i, ItemCount - 1 );
return NewIndex;
}
function bool InternalOnClick(GUIComponent Sender)
{
local int NewIndex;
if ( !IsInClientBounds() || ItemsPerPage==0 )
return false;
// Get the Row..
NewIndex = CalculateIndex();
SetIndex(NewIndex);
return true;
}
function bool InternalOnKeyType(out byte Key, optional string Unicode)
{
// Add code to jump to next line with Char
return false;
}
function WheelUp()
{
if (MyScrollBar!=None)
GUIVertScrollBar(MyScrollBar).WheelUp();
else
{
if (!Controller.CtrlPressed)
Up();
else
PgUp();
}
}
function WheelDown()
{
if (MyScrollBar!=None)
GUIVertScrollBar(MyScrollBar).WheelDown();
else
{
if (!Controller.CtrlPressed)
Down();
else
PgDn();
}
}
function bool Up()
{
if ( (ItemCount<2) || (Index==0) ) return true;
SetIndex(Max(0,Index-1));
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
return true;
}
function bool Down()
{
if ( (ItemCount<2) || (Index==ItemCount-1) ) return true;
SetIndex( Min(Index+1, ItemCount - 1) );
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
return true;
}
function Home()
{
if (ItemCount<2) return;
SetIndex(0);
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
}
function End()
{
if (ItemCount<2) return;
SetIndex(ItemCount-1);
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
}
function PgUp()
{
if (ItemCount<2) return;
SetIndex( Max(0, Index - ItemsPerPage) );
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
}
function PgDn()
{
if (ItemCount<2) return;
SetIndex( Min(Index + ItemsPerPage, ItemCount - 1) );
if ( MyScrollBar != None )
MyScrollBar.AlignThumb();
}
defaultproperties
{
OnClick=InternalOnClick
bRequiresStyle=True
}

View file

@ -0,0 +1,74 @@
// ====================================================================
// Class: XInterface.GUIVertScrollBar
// Parent: Xinterface.GUIScrollBarBase
//
// Custom scrollbar for vertical lists
// ====================================================================
class GUIVertScrollBar extends GUIScrollBarBase;
// Record location you grabbed the grip
function GripPressed( GUIComponent Sender, bool IsRepeat )
{
if ( !IsRepeat )
GrabOffset = Controller.MouseY - MyGripButton.ActualTop();
}
function bool GripPreDraw( GUIComponent Sender )
{
local float NewPerc;
if ( MyGripButton.MenuState != MSAT_Pressed )
return false;
// Calculate the new Grip Top using the mouse cursor location.
NewPerc = FClamp(
(Controller.MouseY - GrabOffset - MyScrollZone.ActualTop()) / (MyScrollZone.ActualHeight() - GripSize),
0.0, 1.0 );
UpdateGripPosition(NewPerc);
return true;
}
function ZoneClick(float Delta)
{
if ( Controller.MouseY < MyGripButton.Bounds[1] )
MoveGripBy(-BigStep);
else if ( Controller.MouseY > MyGripButton.Bounds[3] )
MoveGripBy(BigStep);
return;
}
defaultproperties
{
Orientation=ORIENT_Vertical
Begin Object Class=GUIVertScrollZone Name=ScrollZone
OnScrollZoneClick=ZoneClick
End Object
Begin Object Class=GUIVertScrollButton Name=UpBut
OnClick=DecreaseClick
End Object
Begin Object Class=GUIVertScrollButton Name=DownBut
OnClick=IncreaseClick
bIncreaseButton=true
End Object
Begin Object Class=GUIVertGripButton Name=Grip
OnMousePressed=GripPressed
End Object
OnPreDraw=GripPreDraw
MyScrollZone=ScrollZone
MyDecreaseButton=UpBut
MyIncreaseButton=DownBut
MyGripButton=Grip
bAcceptsInput=true
WinWidth=0.020
MinGripPixels=12
}

View file

@ -0,0 +1,18 @@
class GUIVertScrollButton extends GUIScrollButtonBase;
function InitComponent(GUIController MyController, GUIComponent MyOwner)
{
if (bIncreaseButton)
{
StyleName="VertDownButton";
ImageIndex = 7;
}
Super.Initcomponent(MyController, MyOwner);
}
defaultproperties
{
ImageIndex=6
StyleName="VertUpButton"
}

View file

@ -0,0 +1,24 @@
// ====================================================================
// Class: XInterface.GUIVertScrollZone
// Parent: XInterface.GUIScrollZoneBase
//
// Scrollzone implementation for vertical lists.
// Written by Joe Wilcox
// (c) 2002, Epic Games, Inc. All Rights Reserved
// ====================================================================
class GUIVertScrollZone extends GUIScrollZoneBase;
function bool InternalOnClick(GUIComponent Sender)
{
local float perc;
if (!IsInBounds())
return false;
perc = ( Controller.MouseY - ActualTop() ) / ActualHeight();
OnScrollZoneClick(perc);
return true;
}

Some files were not shown because too many files have changed in this diff Show more