//============================================================================== // Base class for tab panels which access playinfo information // // Created by Ron Prestenback // © 2003, Epic Games, Inc. All Rights Reserved //============================================================================== class UT2K4PlayInfoPanel extends UT2K4TabPanel abstract; var() int NumColumns; var array InfoRules; var automated GUIMultiOptionListBox lb_Rules; var GUIMultiOptionList li_Rules; var() config bool bVerticalLayout; var() editconst noexport PlayInfo GamePI; var() noexport bool bRefresh, bUpdate; var() localized string EditText; function InitComponent(GUIController MyC, GUIComponent MyO) { lb_Rules.NumColumns = NumColumns; Super.InitComponent(MyC, MyO); li_Rules = lb_Rules.List; li_Rules.OnCreateComponent = InternalOnCreateComponent; li_Rules.bHotTrack = True; } function bool CanShowPanel() { if (GamePI == None) return false; return Super.CanShowPanel(); } // Called from the owning page when GameType has been changed or PlayInfo settings have been reloaded function Refresh() { GamePI.GetSettings(MyButton.Caption, InfoRules); ClearRules(); LoadRules(); } // This function is used to initialize the GUIMultiOptionList with the settings in PlayInfo function LoadRules() { if (bUpdate) UpdateRules(); } // This function updates the values of the menu options of the GUIMultiOptionList // with the correct values from PlayInfo function UpdateRules() { local int i, j; for (i = 0; i < li_Rules.Elements.Length; i++) { if ( GUIListSpacer(li_Rules.Elements[i]) != None ) continue; j = li_Rules.Elements[i].Tag; // The index got corrupted - dump the contents of the our list to see what's going on // then crash the game to get our attention :> if (InfoRules[j].DisplayName != li_Rules.Elements[i].Caption) DumplistElements(i, j); Assert(InfoRules[j].DisplayName == li_Rules.Elements[i].Caption); li_Rules.Elements[i].SetHint(InfoRules[j].Description); // Update the value of the GUIMenuOption with the actual value in PlayInfo if (j < InfoRules.Length) li_Rules.Elements[i].SetComponentValue(InfoRules[j].Value, True); // Assign the TabOrder so that user can tab properly between list elements li_Rules.Elements[i].TabOrder = i; } bRefresh = False; bUpdate = False; } function DumpListElements(int BadListIndex, int BadPlayInfoIndex) { local int i; log("** DumpListElements **"); log("Element["$BadListIndex$"] caption:"$li_Rules.Elements[BadListIndex].Caption@"Setting["$BadPlayInfoIndex$"] caption:"$GamePI.Settings[BadPlayInfoIndex].DisplayName); for (i = 0; i < li_Rules.Elements.Length; i++) { log(i$")"@li_Rules.Elements[i].Caption@li_Rules.Elements[i].Tag); } GamePI.Dump(); } // Whoa ... // Add a new rule to the GUIMultiOptionList function AddRule(PlayInfo.PlayInfoData NewRule, int Index) { local bool bTemp; local string Width, Op; local array Range; local moComboBox co; local moFloatEdit fl; local moEditBox ed; local moCheckbox ch; local moNumericEdit nu; local moButton bu; local int i, pos; bTemp = Controller.bCurMenuInitialized; Controller.bCurMenuInitialized = False; switch (NewRule.RenderType) { case PIT_Check: ch = moCheckbox(li_Rules.AddItem("XInterface.moCheckbox",,NewRule.DisplayName, True)); if (ch == None) break; ch.Tag = Index; ch.bAutoSizeCaption = True; break; case PIT_Select: co = moCombobox(li_Rules.AddItem("XInterface.moComboBox",,NewRule.DisplayName, True)); if (co == None) break; co.ReadOnly(True); co.bAutoSizeCaption = True; co.Tag = Index; co.CaptionWidth=0.5; GamePI.SplitStringToArray(Range, NewRule.Data, ";"); for (i = 0; i+1 < Range.Length; i += 2) co.AddItem(Range[i+1],,Range[i]); break; case PIT_Text: if ( !Divide(NewRule.Data, ";", Width, Op) ) Width = NewRule.Data; pos = InStr(Width, ","); if (pos != -1) Width = Left(Width, pos); if (Width != "") i = int(Width); else i = -1; GamePI.SplitStringToArray(Range, Op, ":"); if (Range.Length > 1) { // Ranged data if (InStr(Range[0], ".") != -1) { // float edit fl = moFloatEdit(li_Rules.AddItem("XInterface.moFloatEdit",,NewRule.DisplayName, True)); if (fl == None) break; fl.Tag = Index; fl.bAutoSizeCaption = True; fl.ComponentWidth = 0.25; if (i != -1) fl.Setup( float(Range[0]), float(Range[1]), fl.MyNumericEdit.Step); } else { nu = moNumericEdit(li_Rules.AddItem("XInterface.moNumericEdit",,NewRule.DisplayName, True)); if (nu == None) break; nu.Tag = Index; nu.bAutoSizeCaption = True; nu.ComponentWidth = 0.25; if (i != -1) nu.Setup( int(Range[0]), int(Range[1]), nu.MyNumericEdit.Step); } } else if (NewRule.ArrayDim != -1) { bu = moButton(li_Rules.AddItem("XInterface.moButton",,NewRule.DisplayName, True)); if (bu == None) break; bu.Tag = Index; bu.bAutoSizeCaption = True; bu.ComponentWidth = 0.25; bu.OnChange = ArrayPropClicked; } else { ed = moEditbox(li_Rules.AddItem("XInterface.moEditBox",,NewRule.DisplayName, True)); if (ed == None) break; ed.Tag = Index; ed.bAutoSizeCaption = True; if (i != -1) ed.MyEditBox.MaxWidth = i; } break; default: bu = moButton(li_Rules.AddItem("XInterface.moButton",,NewRule.DisplayName, True)); if (bu == None) break; bu.Tag = Index; bu.bAutoSizeCaption = True; bu.StandardHeight = 0.03; bu.ComponentWidth = 0.25; bu.OnChange = CustomClicked; } Controller.bCurMenuInitialized = bTemp; } function AddGroupHeader(int PlayInfoIndex, bool InitialRow) { local int ModResult, i; local GUIMenuOption mo; // If the GUIMultiOptionList has more than one column, add a spacer component // for each column until we are back to the first column if ( !li_Rules.bVerticalLayout ) { ModResult = li_Rules.Elements.Length % lb_Rules.NumColumns; while (ModResult-- > 0) li_Rules.AddItem( "XInterface.GUIListSpacer" ); if (!InitialRow) for (i = 0; i < lb_Rules.NumColumns; i++) li_Rules.AddItem( "XInterface.GUIListSpacer" ); } // We are now at the first column - safe to add a header row mo = li_Rules.AddItem( "XInterface.GUIListHeader",, InfoRules[PlayInfoIndex].Grouping ); if ( mo != None ) mo.bAutoSizeCaption = True; if ( !li_Rules.bVerticalLayout ) { i = 0; while (++i < lb_Rules.NumColumns) { mo = li_Rules.AddItem( "XInterface.GUIListHeader" ); if ( mo != None ) mo.bAutoSizeCaption = True; } } } function ClearRules() { li_Rules.Clear(); } function InternalOnActivate() { if (bRefresh) Refresh(); else if (bUpdate) UpdateRules(); } function ListBoxCreateComponent(GUIComponent NewComp, GUIComponent Sender) { if (GUIMultiOptionList(NewComp) != None) { GUIMultiOptionList(NewComp).bVerticalLayout = bVerticalLayout; GUIMultiOptionList(NewComp).bDrawSelectionBorder = False; GUIMultiOptionList(NewComp).ItemPadding = 0.15; } if (Sender == lb_Rules) lb_Rules.InternalOnCreateComponent(NewComp, Sender); } function InternalOnCreateComponent(GUIMenuOption NewComp, GUIMultiOptionList Sender) { if (Sender == li_Rules) { NewComp.ComponentJustification = TXTA_Right; NewComp.LabelJustification = TXTA_Left; NewComp.CaptionWidth = 0.65; if (moButton(NewComp) != None) { moButton(NewComp).ButtonStyleName = "SquareButton"; moButton(NewComp).ButtonCaption = EditText; } } } function InternalOnChange(GUIComponent Sender) { if (GUIMultiOptionList(Sender) != None) { if (Controller.bCurMenuInitialized) UpdateSetting(GUIMultiOptionList(Sender).Get()); } else if ( GUIMenuOption(Sender) != None && Controller.bCurMenuInitialized ) UpdateSetting( GUIMenuOption(Sender) ); } function UpdateSetting(GUIMenuOption Sender) { local int i; local int Index; if (Sender == None) return; i = Sender.Tag; if (i < 0) return; if (InfoRules[i].DisplayName != Sender.Caption) { if ( Controller.bModAuthor ) { log("Corrupt list index detected in component"@Sender.Name,'ModAuthor'); DumpListElements( FindComponentIndex(Sender), i ); } return; } Index = GamePI.FindIndex(InfoRules[i].SettingName); if (InfoRules[i].DisplayName != Sender.Caption || Index == -1) { if ( Controller.bModAuthor ) { log("Invalid setting requested from PlayInfo!",'ModAuthor'); DumpListElements(FindComponentIndex(Sender), i); } return; } StoreSetting(Index, Sender.GetComponentValue()); } protected function StoreSetting( int Index, string NewValue ) { GamePI.StoreSetting(Index, NewValue); } function ArrayPropClicked(GUIComponent Sender) { local int i, Index; local GUIArrayPropPage ArrayPage; local string ArrayMenu; i = Sender.Tag; if (i < 0) return; Index = GamePI.FindIndex(InfoRules[i].SettingName); if ( GamePI.Settings[Index].ArrayDim > 1 ) ArrayMenu = Controller.ArrayPropertyMenu; else ArrayMenu = Controller.DynArrayPropertyMenu; if (Controller.OpenMenu(ArrayMenu, GamePI.Settings[Index].DisplayName, GamePI.Settings[Index].Value)) { ArrayPage = GUIArrayPropPage(Controller.ActivePage); ArrayPage.Item = GamePI.Settings[Index]; ArrayPage.OnClose = CustomPageClosed; ArrayPage.SetOwner(Sender); } } function CustomClicked(GUIComponent Sender) { local int i, Index; local GUICustomPropertyPage Page; local string CustomMenu; local array Parts; i = Sender.Tag; if ( i < 0 ) return; Index = GamePI.FindIndex( InfoRules[i].SettingName ); Split(GamePI.Settings[Index].Data, ";", Parts); if ( Parts.Length > 2 ) { CustomMenu = Parts[2]; if ( Controller.OpenMenu(CustomMenu) ) { Page = GUICustomPropertyPage(Controller.ActivePage); Page.Item = GamePI.Settings[Index]; Page.OnClose = CustomPageClosed; Page.SetOwner(Sender); } } } function CustomPageClosed( optional bool bCancelled ) { local GUICustomPropertyPage Page; local GUIComponent CompOwner; Page = GUICustomPropertyPage(Controller.ActivePage); if ( Page != None && !bCancelled ) { CompOwner = Page.GetOwner(); if ( CompOwner != None && moButton(CompOwner) != None ) { moButton(CompOwner).SetComponentValue( Page.GetDataString(), True ); InternalOnChange(CompOwner); } } } function int FindComponentWithTag(int FindTag) { local int i; for ( i = 0; i < li_Rules.Elements.Length; i++ ) { if ( li_Rules.Elements[i].Tag == FindTag ) return i; } return -1; } function int FindGroupIndex(string Group) { local int i; for (i = 0; i < GamePI.Groups.Length; i++) if (GamePI.Groups[i] ~= Group) return i; return -1; } function Free() { GamePI = None; Super.Free(); } DefaultProperties { EditText="Edit" NumColumns=1 OnActivate=InternalOnActivate bRefresh=True bUpdate=False FadeInTime=0.25 Begin Object Class=GUIMultiOptionListBox Name=RuleListBox OnChange=InternalOnChange OnCreateComponent=ListBoxCreateComponent bBoundToParent=True bScaleToParent=True WinWidth=1.000000 WinHeight=0.930009 WinLeft=0.000000 WinTop=0.000000 TabOrder=0 bVisibleWhenEmpty=True End Object lb_Rules=RuleListBox }