From d3b3e2a6bee2c190b4d884a73c0e292f6d28a15e Mon Sep 17 00:00:00 2001 From: "Mr. Nice" Date: Wed, 1 May 2019 13:43:49 +0100 Subject: [PATCH] Squashing changes from MrNiceUK/ControllerSupport to prepare for rebase against main branch --- ModConfigMenu/ModConfigMenu.XCOM_sln | 4 +- .../Localization/ModConfigMenu.int | 1 + .../ModConfigMenu/ModConfigMenu.x2proj | 6 + .../Src/ModConfigMenu/Classes/MCM_Button.uc | 10 +- .../ModConfigMenu/Classes/MCM_ButtonFacade.uc | 6 +- .../Src/ModConfigMenu/Classes/MCM_Checkbox.uc | 6 +- .../Classes/MCM_CheckboxFacade.uc | 9 +- .../Classes/MCM_CustomPageTest.uc | 2 - .../Src/ModConfigMenu/Classes/MCM_Dropdown.uc | 108 +---- .../Classes/MCM_DropdownFacade.uc | 9 +- .../ModConfigMenu/Classes/MCM_GroupLabel.uc | 1 - .../Classes/MCM_GroupLabelSeparator.uc | 1 + .../Src/ModConfigMenu/Classes/MCM_Label.uc | 8 +- .../ModConfigMenu/Classes/MCM_LabelFacade.uc | 1 - .../Classes/MCM_OptionsMenuListener.uc | 44 +- .../Classes/MCM_OptionsMenuListenerHook.uc | 4 +- .../Classes/MCM_OptionsScreen.uc | 409 ++++++++++++------ .../ModConfigMenu/Classes/MCM_SettingBase.uc | 64 ++- .../ModConfigMenu/Classes/MCM_SettingGroup.uc | 33 +- .../Classes/MCM_SettingsPanel.uc | 213 +++++++-- .../ModConfigMenu/Classes/MCM_SettingsTab.uc | 140 ++++-- .../Src/ModConfigMenu/Classes/MCM_Slider.uc | 20 +- .../ModConfigMenu/Classes/MCM_SliderFacade.uc | 8 +- .../Src/ModConfigMenu/Classes/MCM_Spinner.uc | 56 +-- .../Classes/MCM_SpinnerFacade.uc | 9 +- .../Src/ModConfigMenu/Classes/MCM_UIButton.uc | 86 ++++ .../Classes/MCM_UIListItemSpinner.uc | 19 + .../Classes/MCM_UISettingSeparator.uc | 1 + .../Classes/MCM_XCOM2_UISlider.uc | 10 + 29 files changed, 888 insertions(+), 400 deletions(-) create mode 100644 ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_UIButton.uc create mode 100644 ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_UIListItemSpinner.uc diff --git a/ModConfigMenu/ModConfigMenu.XCOM_sln b/ModConfigMenu/ModConfigMenu.XCOM_sln index 76c76c7..1434df6 100755 --- a/ModConfigMenu/ModConfigMenu.XCOM_sln +++ b/ModConfigMenu/ModConfigMenu.XCOM_sln @@ -11,8 +11,8 @@ Global Default|XCOM 2 = Default|XCOM 2 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {3F350978-33E7-493A-993B-92C1B54BF591}.Debug|XCOM 2.ActiveCfg = Debug|XCOM 2 - {3F350978-33E7-493A-993B-92C1B54BF591}.Debug|XCOM 2.Build.0 = Debug|XCOM 2 + {3F350978-33E7-493A-993B-92C1B54BF591}.Debug|XCOM 2.ActiveCfg = Default|XCOM 2 + {3F350978-33E7-493A-993B-92C1B54BF591}.Debug|XCOM 2.Build.0 = Default|XCOM 2 {3F350978-33E7-493A-993B-92C1B54BF591}.Default|XCOM 2.ActiveCfg = Default|XCOM 2 {3F350978-33E7-493A-993B-92C1B54BF591}.Default|XCOM 2.Build.0 = Default|XCOM 2 EndGlobalSection diff --git a/ModConfigMenu/ModConfigMenu/Localization/ModConfigMenu.int b/ModConfigMenu/ModConfigMenu/Localization/ModConfigMenu.int index 2455f63..9e9ff36 100755 --- a/ModConfigMenu/ModConfigMenu/Localization/ModConfigMenu.int +++ b/ModConfigMenu/ModConfigMenu/Localization/ModConfigMenu.int @@ -6,6 +6,7 @@ m_strSaveAndExit="Save and Exit" m_strCancel="Cancel" m_strTitle="Mod Settings" m_strSubtitle="" +m_strScroll="SCROLL" [MCM_SettingsPanel] m_strResetButton="Reset" diff --git a/ModConfigMenu/ModConfigMenu/ModConfigMenu.x2proj b/ModConfigMenu/ModConfigMenu/ModConfigMenu.x2proj index 29457ed..644d445 100755 --- a/ModConfigMenu/ModConfigMenu/ModConfigMenu.x2proj +++ b/ModConfigMenu/ModConfigMenu/ModConfigMenu.x2proj @@ -151,6 +151,12 @@ For full details on using this mod, troubleshooting, or even building your own m Content + + Content + + + Content + Content diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Button.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Button.uc index aebb5c0..00322e6 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Button.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Button.uc @@ -1,10 +1,9 @@ class MCM_Button extends MCM_SettingBase implements(MCM_API_Button) config(ModConfigMenu); -var delegate ClickHandler; +var delegate ClickHandler; var MCM_API_Setting ParentFacade; -delegate VoidSettingHandler(MCM_API_Setting Setting); simulated function MCM_SettingBase InitSettingsItem(name _Name, eSettingType _Type, optional string _Label = "", optional string _Tooltip = "") { @@ -14,7 +13,7 @@ simulated function MCM_SettingBase InitSettingsItem(name _Name, eSettingType _Ty } // Fancy init process -simulated function MCM_Button InitButton(name _SettingName, MCM_API_Setting _ParentFacade, string _Label, string _Tooltip, string _ButtonLabel, delegate _OnClick) +simulated function MCM_Button InitButton(name _SettingName, MCM_API_Setting _ParentFacade, string _Label, string _Tooltip, string _ButtonLabel, delegate _OnClick) { super.InitSettingsItem(_SettingName, eSettingType_Button, _Label, _Tooltip); @@ -42,4 +41,9 @@ function SimulateClick() { ClickHandler(ParentFacade); } +} + +simulated function bool OnUnrealCommand(int cmd, int arg) +{ + return Super(UIMechaListItem).OnUnrealCommand(cmd, arg); } \ No newline at end of file diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_ButtonFacade.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_ButtonFacade.uc index cff0efe..289bee7 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_ButtonFacade.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_ButtonFacade.uc @@ -9,14 +9,13 @@ var MCM_SettingGroup ParentGroup; var string ButtonLabel; -var delegate ClickHandler; +var delegate ClickHandler; var MCM_Button uiInstance; -delegate VoidSettingHandler(MCM_API_Setting _Setting); simulated function MCM_ButtonFacade InitButtonFacade(name _Name, string _Label, string _Tooltip, string _ButtonLabel, - delegate _OnClick, MCM_SettingGroup _ParentGroup) + delegate _OnClick, MCM_SettingGroup _ParentGroup) { SettingName = _Name; Label = _Label; @@ -40,7 +39,6 @@ simulated function UIMechaListItem InstantiateUI(UIList parent) { uiInstance = Spawn(class'MCM_Button', parent.itemContainer).InitButton(SettingName, self, Label, Tooltip, ButtonLabel, ClickHandler); uiInstance.Show(); - uiInstance.EnableNavigation(); uiInstance.SetEditable(Editable); return uiInstance; diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Checkbox.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Checkbox.uc index 96f7c9b..74edf70 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Checkbox.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Checkbox.uc @@ -1,9 +1,7 @@ class MCM_Checkbox extends MCM_SettingBase implements(MCM_API_Checkbox) config(ModConfigMenu); var MCM_API_Setting ParentFacade; -var delegate ChangeHandler; - -delegate BoolSettingHandler(MCM_API_Setting _Setting, bool _SettingValue); +var delegate ChangeHandler; simulated function MCM_SettingBase InitSettingsItem(name _Name, eSettingType _Type, optional string _Label = "", optional string _Tooltip = "") { @@ -13,7 +11,7 @@ simulated function MCM_SettingBase InitSettingsItem(name _Name, eSettingType _Ty } // Fancy init process -simulated function MCM_Checkbox InitCheckbox(name _SettingName, MCM_API_Setting _ParentFacade, string _Label, string _Tooltip, bool initiallyChecked, delegate _OnChange) +simulated function MCM_Checkbox InitCheckbox(name _SettingName, MCM_API_Setting _ParentFacade, string _Label, string _Tooltip, bool initiallyChecked, delegate _OnChange) { super.InitSettingsItem(_SettingName, eSettingType_Checkbox, _Label, _Tooltip); diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_CheckboxFacade.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_CheckboxFacade.uc index 906533a..c886306 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_CheckboxFacade.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_CheckboxFacade.uc @@ -9,15 +9,13 @@ var MCM_SettingGroup ParentGroup; var bool Checked; -var delegate ChangeHandler; -var delegate SaveHandler; +var delegate ChangeHandler; +var delegate SaveHandler; var MCM_Checkbox uiInstance; -delegate BoolSettingHandler(MCM_API_Setting _Setting, bool _SettingValue); - simulated function MCM_CheckboxFacade InitCheckboxFacade(name _Name, string _Label, string _Tooltip, bool _Checked, - delegate _OnChange, delegate _OnSave, + delegate _OnChange, delegate _OnSave, MCM_SettingGroup _ParentGroup) { SettingName = _Name; @@ -43,7 +41,6 @@ simulated function UIMechaListItem InstantiateUI(UIList parent) { uiInstance = Spawn(class'MCM_Checkbox', parent.itemContainer).InitCheckbox(SettingName, self, Label, Tooltip, Checked, ChangeHandler); uiInstance.Show(); - uiInstance.EnableNavigation(); uiInstance.SetEditable(Editable); return uiInstance; diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_CustomPageTest.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_CustomPageTest.uc index 93874cd..a96ff5d 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_CustomPageTest.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_CustomPageTest.uc @@ -3,8 +3,6 @@ class MCM_CustomPageTest extends Object config(ModConfigMenuTestHarness); `include(ModConfigMenu/Src/ModConfigMenuAPI/MCM_API_Includes.uci) -delegate CustomSettingsPageCallback(UIScreen ParentScreen, int PageID); - //event OnInit(UIScreen Screen) function OnInit(UIScreen Screen) { diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Dropdown.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Dropdown.uc index df03dab..547b149 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Dropdown.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Dropdown.uc @@ -1,14 +1,11 @@ class MCM_Dropdown extends MCM_SettingBase implements(MCM_API_Dropdown) config(ModConfigMenu); -var delegate ChangeHandler; +var delegate ChangeHandler; var MCM_API_Setting ParentFacade; var array DropdownOptions; -var int DropdownSelection; var bool TmpSuppressEvent; -delegate StringSettingHandler(MCM_API_Setting Setting, string _SettingValue); - simulated function MCM_SettingBase InitSettingsItem(name _Name, eSettingType _Type, optional string _Label = "", optional string _Tooltip = "") { `log("Don't call InitSettingsItem directly in subclass of MCM_SettingBase."); @@ -18,18 +15,20 @@ simulated function MCM_SettingBase InitSettingsItem(name _Name, eSettingType _Ty // Fancy init process simulated function MCM_Dropdown InitDropdown(name _SettingName, MCM_API_Setting _ParentFacade, string _Label, string _Tooltip, array _Options, string _Selection, - delegate _OnChange) + delegate _OnChange) { super.InitSettingsItem(_SettingName, eSettingType_Checkbox, _Label, _Tooltip); ChangeHandler = _OnChange; ParentFacade = _ParentFacade; - CloneOptionsList(_Options); - DropdownSelection = GetSelectionIndex(_Options, _Selection); + DropdownOptions = _Options; TmpSuppressEvent = true; - UpdateDataDropdown(_Label, _Options, DropdownSelection, DropdownChangedCallback); + UpdateDataDropdown(_Label, _Options, _Options.find(_Selection), DropdownChangedCallback); + Dropdown.OnMouseEventDelegate = MouseSoundCheck; + // Need to tweak text boundary limits + Desc.SetWidth(width - 340); TmpSuppressEvent = false; SetHoverTooltip(_Tooltip); @@ -39,100 +38,29 @@ simulated function MCM_Dropdown InitDropdown(name _SettingName, MCM_API_Setting // Helpers -function CloneOptionsList(array OptionsList) -{ - local int iter; - DropdownOptions.Length = 0; - for (iter = 0; iter < OptionsList.Length; iter++) - { - DropdownOptions.AddItem(OptionsList[iter]); - } -} - -function int GetSelectionIndex(array OptionsList, string SelectedOption) -{ - local int iter; - for (iter = 0; iter < OptionsList.Length; iter++) - { - if (SelectedOption == OptionsList[iter]) - return iter; - } - - return -1; -} - function DropdownChangedCallback(UIDropdown DropdownControl) { - DropdownSelection = DropdownControl.SelectedItem; - if (ChangeHandler != none && !TmpSuppressEvent) { ChangeHandler(ParentFacade, DropdownControl.GetSelectedItemText()); } } -// Need to tweak text boundary limits - -simulated function UIMechaListItem UpdateDataDropdown(string _Desc, - array Data, - int SelectedIndex, - delegate _OnSelectionChange, - optional delegate _OnClickDelegate = none) -{ - local int i; - - SetWidgetType(EUILineItemType_Dropdown); - if(Dropdown != none) - { - Dropdown.Remove(); - Dropdown = none; - } - - if( Dropdown == none ) - { - Dropdown = Spawn(class'UIDropdown', self); - Dropdown.bIsNavigable = false; - Dropdown.InitDropdown('DropdownMC'); - Dropdown.SetPosition(width - 308, 24); - } - - Dropdown.Clear(); - - for(i = 0; i < Data.Length; ++i) - { - Dropdown.AddItem(Data[i]); - } - - Dropdown.SetLabel(""); - Dropdown.SetSelected(SelectedIndex); - Dropdown.Show(); - - //Desc.SetWidth(width - 308); - Desc.SetWidth(width - 340); - Desc.SetHTMLText(_Desc); - Desc.Show(); - - OnClickDelegate = _OnClickDelegate; - Dropdown.OnItemSelectedDelegate = _OnSelectionChange; - return self; -} - // MCM_API_Dropdown implementation =========================================================================== function string GetValue() { - return DropdownOptions[DropdownSelection]; + return Dropdown.GetSelectedItemText(); } function SetValue(string Selection, bool SuppressEvent) { local int index; - index = GetSelectionIndex(DropdownOptions, Selection); + index = DropdownOptions.find(Selection); // If found. if (index >= 0) { - DropdownSelection = index; TmpSuppressEvent = SuppressEvent; Dropdown.SetSelected(index); TmpSuppressEvent = false; @@ -141,11 +69,10 @@ function SetValue(string Selection, bool SuppressEvent) function SetOptions(array NewOptions, string InitialSelection, bool SuppressEvent) { - CloneOptionsList(NewOptions); - DropdownSelection = GetSelectionIndex(NewOptions, InitialSelection); + DropdownOptions = NewOptions; TmpSuppressEvent = SuppressEvent; - UpdateDataDropdown(GetLabel(), NewOptions, DropdownSelection, DropdownChangedCallback); + UpdateDataDropdown(GetLabel(), NewOptions, NewOptions.find(InitialSelection), DropdownChangedCallback); TmpSuppressEvent = false; SetHoverTooltip(DisplayTooltip); @@ -163,4 +90,17 @@ simulated function SetEditable(bool IsEditable) { Dropdown.Hide(); } +} + +simulated function MouseSoundCheck(UIPanel Panel, int Cmd) +{ + if(cmd == class'UIUtilities_Input'.const.FXS_L_MOUSE_UP) + { + Movie.Pres.PlayUISound(eSUISound_MenuSelect); + } +} + +simulated function UIPanel ProcessMouseEvents(optional delegate MouseEventDelegate = MouseSoundCheck) +{ + return Super.ProcessMouseEvents(MouseEventDelegate); } \ No newline at end of file diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_DropdownFacade.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_DropdownFacade.uc index 47a9413..e6abb5c 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_DropdownFacade.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_DropdownFacade.uc @@ -10,16 +10,14 @@ var MCM_SettingGroup ParentGroup; var array Options; var int SelectionIndex; -var delegate ChangeHandler; -var delegate SaveHandler; +var delegate ChangeHandler; +var delegate SaveHandler; var MCM_Dropdown uiInstance; -delegate StringSettingHandler(MCM_API_Setting Setting, string _SettingValue); - simulated function MCM_DropdownFacade InitDropdownFacade(name _Name, string _Label, string _Tooltip, array _Options, string _Selection, - delegate _OnChange, delegate _OnSave, + delegate _OnChange, delegate _OnSave, MCM_SettingGroup _ParentGroup) { SettingName = _Name; @@ -77,7 +75,6 @@ function UIMechaListItem InstantiateUI(UIList Parent) { uiInstance = Spawn(class'MCM_Dropdown', parent.itemContainer).InitDropdown(SettingName, self, Label, Tooltip, Options, Options[SelectionIndex], ChangeHandler); uiInstance.Show(); - uiInstance.EnableNavigation(); uiInstance.SetEditable(Editable); return uiInstance; diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_GroupLabel.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_GroupLabel.uc index 3dd31a6..39ef003 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_GroupLabel.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_GroupLabel.uc @@ -27,7 +27,6 @@ simulated function MCM_GroupLabelSeparator InstantiateUI(UIList Parent) // Smaller text too. Instance.UpdateTitle(GetFormattedLabel()); Instance.Show(); - Instance.EnableNavigation(); return Instance; } diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_GroupLabelSeparator.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_GroupLabelSeparator.uc index 6220ade..3642fe1 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_GroupLabelSeparator.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_GroupLabelSeparator.uc @@ -54,4 +54,5 @@ defaultproperties DESC_Y = 0; bProcessesMouseEvents = true; + bShouldPlayGenericUIAudioEvents = false; } \ No newline at end of file diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Label.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Label.uc index 67231f3..4ed27ec 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Label.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Label.uc @@ -18,4 +18,10 @@ simulated function MCM_Label InitLabel(name _SettingName, MCM_API_Setting _Paren return self; } -// No special methods in MCM_API_Label. \ No newline at end of file +// No special methods in MCM_API_Label. + +defaultproperties +{ + bIsNavigable = false + bShouldPlayGenericUIAudioEvents = false +} \ No newline at end of file diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_LabelFacade.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_LabelFacade.uc index 48a3fbd..e8b0929 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_LabelFacade.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_LabelFacade.uc @@ -30,7 +30,6 @@ simulated function UIMechaListItem InstantiateUI(UIList parent) { uiInstance = Spawn(class'MCM_Label', parent.itemContainer).InitLabel(SettingName, self, Label, Tooltip); uiInstance.Show(); - uiInstance.EnableNavigation(); uiInstance.SetEditable(Editable); return uiInstance; diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_OptionsMenuListener.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_OptionsMenuListener.uc index 49d3184..a4437b8 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_OptionsMenuListener.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_OptionsMenuListener.uc @@ -8,8 +8,8 @@ // itself. Since the GC graph looks like that, we can safely keep a reference to UI objects here // instead of the actual screen listener. -//class MCM_OptionsMenuListener extends UIScreenListener config(ModConfigMenu); -class MCM_OptionsMenuListener extends Object config(ModConfigMenu); +class MCM_OptionsMenuListener extends UIScreenListener config(ModConfigMenu); +//class MCM_OptionsMenuListener extends Object config(ModConfigMenu); var config bool ENABLE_MENU; var config bool USE_FLAT_DISPLAY_STYLE; @@ -19,27 +19,47 @@ var localized string m_strModMenuButton; //var UIOptionsPCScreen ParentScreen; //var UIButton ModOptionsButton; -//event OnInit(UIScreen Screen) -function OnInit(UIOptionsPCSCreen Screen) +event OnInit(UIScreen Screen) +//function OnInit(UIOptionsPCSCreen Screen) { //if(UIOptionsPCSCreen(Screen) != none) //{ //ParentScreen = Screen; - + if (ENABLE_MENU) { - InjectModOptionsButton(Screen); + InjectModOptionsButton(UIOptionsPCSCreen(Screen)); } //} } +event OnRemoved(UIScreen Screen) +{ + MCM_UIButton(Screen.GetChildByName('ModOptionsButton')).StopInputListener(); +} + +event OnReceiveFocus(UIScreen Screen) +{ + MCM_UIButton(Screen.GetChildByName('ModOptionsButton')).StartInputListener(); +} + +event OnLoseFocus(UIScreen Screen) +{ + MCM_UIButton(Screen.GetChildByName('ModOptionsButton')).StopInputListener(); +} + simulated function InjectModOptionsButton(UIOptionsPCSCreen ParentScreen) { - local UIButton ModOptionsButton; - ModOptionsButton = ParentScreen.Spawn(class'UIButton', ParentScreen); - ModOptionsButton.InitButton(, m_strModMenuButton, ShowModOptionsDialog); + local MCM_UIButton ModOptionsButton; + + ModOptionsButton = ParentScreen.Spawn(class'MCM_UIButton', ParentScreen); + ModOptionsButton.bAnimateOnInit = false; + ModOptionsButton.InitButton('ModOptionsButton', m_strModMenuButton, ShowModOptionsDialog, eUIButtonStyle_HOTLINK_BUTTON); + ModOptionsButton.StartInputListener(class'UIUtilities_Input'.const.FXS_BUTTON_Y); + ModOptionsButton.SetGamepadIcon(class'UIUtilities_Input'.const.ICON_Y_TRIANGLE); + ModOptionsButton.DisableNavigation(); ModOptionsButton.SetPosition(500, 850); //Relative to this screen panel - ModOptionsButton.AnimateIn(0); + ModOptionsButton.SetHeight(30); } simulated function ShowModOptionsDialog(UIButton kButton) @@ -50,7 +70,7 @@ simulated function ShowModOptionsDialog(UIButton kButton) `log("Mod Options Dialog Called."); ParentScreen = UIOptionsPCScreen(kButton.ParentPanel); - + if (USE_FLAT_DISPLAY_STYLE) TargetMovie = None; else @@ -63,6 +83,6 @@ defaultproperties { //ParentScreen = none; //ModOptionsButton = none; - //ScreenClass = none; + ScreenClass = class'UIOptionsPCSCreen'; } diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_OptionsMenuListenerHook.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_OptionsMenuListenerHook.uc index 6d351dc..75eb13c 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_OptionsMenuListenerHook.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_OptionsMenuListenerHook.uc @@ -1,4 +1,4 @@ -class MCM_OptionsMenuListenerHook extends UIScreenListener; +class MCM_OptionsMenuListenerHook extends Object;//UIScreenListener; event OnInit(UIScreen Screen) { @@ -18,6 +18,6 @@ event OnInit(UIScreen Screen) defaultproperties { - ScreenClass = none; + //ScreenClass = none; //ScreenClass = 'UIOptionsPCSCreen'; } \ No newline at end of file diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_OptionsScreen.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_OptionsScreen.uc index 2b199ef..9e6d34a 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_OptionsScreen.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_OptionsScreen.uc @@ -23,6 +23,7 @@ var localized string m_strTitle; var localized string m_strSubtitle; var localized string m_strSaveAndExit; var localized string m_strCancel; +var localized string m_strScroll; var MCM_OptionsMenuListener ParentListener; @@ -32,14 +33,19 @@ var UIImage VSeparator; var UIX2PanelHeader TitleHeader; var UIList TabsList; -var int SettingsPageCounter; -var int SelectedPageID; var array SettingsTabs; var array SettingsPanels; +var MCM_SettingsPanel CurrentPanel; var UIButton SaveAndExitButton; var UIButton CancelButton; +var UITextTooltip ActiveTooltip; +var float SBOffset, ScrollHeight; var int CurrentGameMode; +var UINavigationHelp NavHelp; +var ConsoleOptionAttentionType AttentionType; +var UIMechaListItem MechaListItem; +var int MechaListItemType; //enum EUILineItemType found in UIMechaListItem; // Pawn hiding code thanks to Patrick-Seymour var bool SoldierVisible; @@ -50,8 +56,6 @@ struct PawnAndComponents { var array PawnAndComps; delegate ClientModCallback(MCM_API_Instance ConfigAPI, int GameMode); -delegate OnClickedDelegate(UIButton Button); -delegate SettingsTabDelegate(MCM_SettingsTab Caller, int PageID); delegate CustomSettingsPageCallback(UIScreen ParentScreen, int PageID); simulated function InitScreen(XComPlayerController InitController, UIMovie InitMovie, optional name InitName) @@ -100,6 +104,9 @@ simulated function OnInit() `log("MCM Core: hiding soldier guy on main menu for visibility."); HideSoldierIfMainMenu(); } + + NavHelp = Spawn(class'UINavigationHelp',self).InitNavHelp(); + UpdateNavHelp(); } simulated function OnRemoved() @@ -121,11 +128,15 @@ simulated function CreateSkeleton() { local int TotalWidth; local int TotalHeight; + local bool MouseActive; TotalWidth = TABLIST_WIDTH + OPTIONS_WIDTH; TotalHeight = HEADER_HEIGHT + OPTIONS_HEIGHT + FOOTER_HEIGHT; - - Container = Spawn(class'UIPanel', self).InitPanel('').SetPosition(PANEL_X, PANEL_Y).SetSize(TotalWidth, TotalHeight); + MouseActive =!`ISCONTROLLERACTIVE; + + Container = Spawn(class'UIPanel', self); + Container.bCascadeFocus = false; + Container.InitPanel('').SetPosition(PANEL_X, PANEL_Y).SetSize(TotalWidth, TotalHeight); BG = Spawn(class'UIImage', Container).InitImage(,"img:///MCM.gfx.MainBackground"); BG.SetPosition(0,0).SetSize(TotalWidth, TotalHeight); @@ -135,30 +146,144 @@ simulated function CreateSkeleton() // Save and exit button SaveAndExitButton = Spawn(class'UIButton', Container); - SaveAndExitButton.InitButton(, m_strSaveAndExit, OnSaveAndExit); + SaveAndExitButton.bAnimateOnInit = false; + SaveAndExitButton.InitButton(, class'UIOptionsPCScreen'.default.m_strSaveAndExit, OnSaveAndExit, eUIButtonStyle_HOTLINK_BUTTON); + SaveAndExitButton.SetGamepadIcon(class'UIUtilities_Input'.const.ICON_X_SQUARE); SaveAndExitButton.SetPosition(Container.width - 190, Container.height - 40); //Relative to this screen panel - SaveAndExitButton.AnimateIn(0); + SaveAndExitButton.DisableNavigation(); - CancelButton = Spawn(class'UIButton', Container); - CancelButton.InitButton(, m_strCancel, OnCancel); - CancelButton.SetPosition(Container.width - 190 - 170, Container.height - 40); //Relative to this screen panel - CancelButton.AnimateIn(0); + if(MouseActive) + { + CancelButton = Spawn(class'UIButton', Container); + SaveAndExitButton.bAnimateOnInit = false; + CancelButton.InitButton(, class'UIUtilities_Text'.default.m_strGenericCancel, OnCancel); + CancelButton.SetPosition(Container.width - 190 - 170, Container.height - 40); //Relative to this screen panel + CancelButton.DisableNavigation(); + } TitleHeader = Spawn(class'UIX2PanelHeader', Container); TitleHeader.InitPanelHeader('', m_strTitle, m_strSubtitle); TitleHeader.SetHeaderWidth(Container.width - 20); TitleHeader.SetPosition(10, 10); - TabsList = Spawn(class'UIList', Container).InitList('ModTabSelectList', 10, HEADER_HEIGHT + TABS_LIST_TOP_PADDING, TABLIST_WIDTH - 30, OPTIONS_HEIGHT); + TabsList = Spawn(class'UIList', Container).InitList('ModTabSelectList', 10, HEADER_HEIGHT + TABS_LIST_TOP_PADDING, TABLIST_WIDTH - 30, OPTIONS_HEIGHT,, true); // Mr. Nice: addBG to stop mouse scrolling "dead spots" + TabsList.BG.SetAlpha(0); TabsList.SetSelectedNavigation(); - TabsList.Navigator.LoopSelection = true; + if (MouseActive) + { + TabsList.bSelectFirstAvailable = false; + } +} + +simulated function UpdateNavHelp( bool bWipeButtons = false ) +{ + local UIScrollbar SB; + NavHelp.ClearButtonHelp(); + NavHelp.bIsVerticalHelp = true; //bsg-hlee (05.05.17): Stacking the B button at the bottom left nav help to match the rest of the main menu screens. + NavHelp.AddBackButton(GoBack); + + if (`ISCONTROLLERACTIVE) + { + //determines if focus is on the RIGHT column + if (AttentionType == COAT_DETAILS) + { + switch(MechaListItemType) + { + case EUILineItemType_Slider: + NavHelp.AddLeftHelp(class'UIUtilities_Text'.default.m_strGenericAdjust, class'UIUtilities_Input'.const.ICON_DPAD_HORIZONTAL); + break; + case EUILineItemType_Checkbox: + NavHelp.AddLeftHelp(class'UIUtilities_Text'.default.m_strGenericToggle, class'UIUtilities_Input'.static.GetAdvanceButtonIcon()); + break; + case EUILineItemType_Spinner: + NavHelp.AddLeftHelp(class'UIUtilities_Text'.default.m_strGenericSelect, class'UIUtilities_Input'.const.ICON_DPAD_HORIZONTAL); + break; + case EUILineItemType_Dropdown: + case EUILineItemType_Button: + NavHelp.AddSelectNavHelp(); + break; + } + // + SB = CurrentPanel.SettingsList.Scrollbar; + } + else //COAT_CATEGORIES + { + SB = TabsList.ScrollBar; + NavHelp.AddSelectNavHelp(); + } + if(SB != none) + { + NavHelp.AddLeftHelp(m_strScroll, class'UIUtilities_Input'.const.ICON_RSTICK); + } + } +} + +simulated function OnSelectionChanged(UIList ContainerList, int ItemIndex) +{ + UpdateMechItemNavHelp(ContainerList, ItemIndex); //INS: - JTA 2016/3/18 + + if(`ISCONTROLLERACTIVE) + { + if (ActiveTooltip != none) + { + if (`PRES.m_eUIMode != eUIMode_Shell) + { + ActiveTooltip.HideTooltip(); + } + + XComPresentationLayerBase(Owner).m_kTooltipMgr.DeactivateTooltip(ActiveTooltip, true); + ActiveTooltip = none; + } + + if (MechaListItem != none) + { + if (MechaListItem.BG.bHasTooltip) + { + ActiveTooltip = UITextTooltip(Movie.Pres.m_kTooltipMgr.GetTooltipByID(MechaListItem.BG.CachedTooltipId)); + if (ActiveTooltip != none) + { + ActiveTooltip.SetFollowMouse(false); + ActiveTooltip.SetTooltipPosition(950.0, MechaListItem.Y - SBOffset); + ActiveTooltip.SetDelay(0); + ActiveTooltip.ShowTooltip(); + XComPresentationLayerBase(Owner).m_kTooltipMgr.ActivateTooltip(ActiveTooltip); + } + } + } + } +} - //Container.Navigator.AddControl(SaveAndExitButton); - //Container.Navigator.AddControl(CancelButton); +function OnScrollPercentChanged( float newPercent ) +{ + SBOffset = newPercent * ScrollHeight + default.SBOffset; + if (ActiveTooltip != none) + { + ActiveTooltip.SetTooltipPosition(950.0, MechaListItem.Y - SBOffset); + } +} - // Start with nothing selected. - Container.Navigator.SetSelected(none); - //TabsList.Navigator.SelectFirstAvailable(); +//Determines if a change is necessary in the Navhelp +//Mr. Nice: Also stash MechaListItem in properties, useful elsewhere! +simulated function UpdateMechItemNavHelp(UIList ContainerList, int Index) +{ + local int NewMechaListItemType; //enum EUILineItemType found in UIMechaListItem; + + // Checks to see if the selected list item is the same as the previously selected list item (to determine if we need to refresh the navhelp) + MechaListItem = UIMechaListItem(ContainerList.GetSelectedItem()); + if(MechaListItem != None) + { + NewMechaListItemType = int(MechaListItem.Type); + if(NewMechaListItemType != MechaListItemType) + { + MechaListItemType = NewMechaListItemType; + UpdateNavHelp(); + } + } + else + { + MechaListItemType = -1; + UpdateNavHelp(); + } } // Special button handlers ======================================================================== @@ -166,14 +291,17 @@ simulated function CreateSkeleton() simulated function OnSaveAndExit(UIButton kButton) { local MCM_SettingsPanel TmpPage; - + + Movie.Pres.PlayUISound(eSUISound_MenuSelect); // Save all. foreach SettingsPanels(TmpPage) { - TmpPage.TriggerSaveEvent(); + if(TmpPage != none) + { + TmpPage.TriggerSaveEvent(); + } } - - Movie.Stack.Pop(self); + CloseScreen(); } simulated function OnCancel(UIButton kButton) @@ -183,25 +311,119 @@ simulated function OnCancel(UIButton kButton) // Cancel all. foreach SettingsPanels(TmpPage) { - TmpPage.TriggerCancelEvent(); + if(TmpPage != none) + { + TmpPage.TriggerCancelEvent(); + } } + CloseScreen(); +} + +function GoBack() +{ + switch(AttentionType) + { + case COAT_CATEGORIES: + OnCancel(none); + return; + + case COAT_DETAILS: + AttentionType = COAT_CATEGORIES; + TabsList.SetSelectedNavigation(); + MechaListItem.OnLoseFocus(); + CurrentPanel.SettingsList.SetSelectedIndex(-1); + if (CurrentPanel.SettingsList.Scrollbar !=none) + { + CurrentPanel.SettingsList.Scrollbar.SetThumbAtPercent(0); + } + Movie.Pres.PlayUISound(eSUISound_MenuClose); //bsg-crobinson (5.9.17): Add close menu sound on back + } +} - Movie.Stack.Pop(self); +simulated function CloseScreen() +{ + Super.CloseScreen(); + // Mr. Nice: UIOptionsPCScreen isn't used to being revealed from the stack,needs a prompt to update NavHelp + UIOptionsPCScreen(Movie.Stack.GetCurrentScreen()).UpdateNavHelp(); } // Keyboard input ============================================================================ simulated function bool OnUnrealCommand(int cmd, int arg) { + local UIScrollBar SB; + if( !CheckInputIsReleaseOrDirectionRepeat(cmd, arg) ) return false; + + if(!`SCREENSTACK.IsTopScreen(self)) + { + // Mr. Nice Ok we're getting unhandled input from a Custom Settings Screen, + // We should therefore do nothing, *except* handle the "B" button to allow controllers + // to escape custom screens with absolutely no controller support! + if ( cmd == class'UIUtilities_Input'.const.FXS_BUTTON_B && `ISCONTROLLERACTIVE) + { + `SCREENSTACK.PopUntil(self); + Movie.Pres.PlayUISound(eSUISound_MenuClose); + return true; + } + return false; + } + + if(AttentionType == COAT_DETAILS && MechaListItem != none && MechaListItem.OnUnrealCommand(cmd, arg)) + { + return true; + } switch( cmd ) { + case class'UIUtilities_Input'.const.FXS_R_MOUSE_DOWN: // Mr. Nice: Rmouse is flipped to escape somewhere, so no point pretending we can treat it differently... case class'UIUtilities_Input'.const.FXS_BUTTON_B: case class'UIUtilities_Input'.const.FXS_KEY_ESCAPE: - OnCancel(none); - break; + GoBack(); + return true; + + case class'UIUtilities_Input'.const.FXS_ARROW_DOWN: + case class'UIUtilities_Input'.const.FXS_DPAD_DOWN: + case class'UIUtilities_Input'.const.FXS_VIRTUAL_LSTICK_DOWN: + case class'UIUtilities_Input'.const.FXS_ARROW_UP: + case class'UIUtilities_Input'.const.FXS_DPAD_UP: + case class'UIUtilities_Input'.const.FXS_VIRTUAL_LSTICK_UP: + // Mr. Nice: Stop Navigator getting confused... + if (AttentionType == COAT_DETAILS && CurrentPanel.SettingsList.Navigator.NavigableControls.Length == 1) + { + PlaySound( SoundCue'SoundUI.MenuScrollCue', true ); + CurrentPanel.SettingsList.NavigatorSelectionChanged(0); + return true; + } + break; + + case class'UIUtilities_Input'.const.FXS_VIRTUAL_RSTICK_DOWN: + case class'UIUtilities_Input'.const.FXS_KEY_PAGEDN: + SB = AttentionType == COAT_CATEGORIES ? TabsList.ScrollBar : CurrentPanel.SettingsList.Scrollbar; + if (SB != none) + { + SB.OnMouseScrollEvent(-1); + } + return true; + case class'UIUtilities_Input'.const.FXS_VIRTUAL_RSTICK_UP: + case class'UIUtilities_Input'.const.FXS_KEY_PAGEUP: + SB = AttentionType == COAT_CATEGORIES ? TabsList.ScrollBar : CurrentPanel.SettingsList.Scrollbar; + if (SB != none) + { + SB.OnMouseScrollEvent(1); + } + return true; + + case class'UIUtilities_Input'.const.FXS_BUTTON_X: + OnSaveAndExit(none); + return true; + case class'UIUtilities_Input'.const.FXS_BUTTON_SELECT: + if(CurrentPanel != none) + { + CurrentPanel.OnResetClicked(none); + } + return true; } return super.OnUnrealCommand(cmd, arg); @@ -285,85 +507,34 @@ simulated function ShowSoldierIfMainMenu() simulated function MCM_SettingsPanel GetPanelByPageID(int PageID) { - local MCM_SettingsPanel TmpPage; - - foreach SettingsPanels(TmpPage) - { - if (TmpPage.GetPageID() == PageID) - return TmpPage; - } - - return None; + return SettingsPanels[PageID]; } -simulated function ChoosePanelByPageID(int PageID) -{ - //local MCM_SettingsPanel CurrentSettingsPage; - local MCM_SettingsTab TmpButton; - local MCM_SettingsPanel TmpPage; - - // Are we changing pages? Do nothing if not changing pages. - if (PageID != SelectedPageID) - { - SelectedPageID = PageID; - - // Now choose the panel. - foreach SettingsPanels(TmpPage) - { - if (TmpPage.GetPageID() != SelectedPageID) - { - TmpPage.Hide(); - } - else - { - `log("MCM: Found correct panel, showing."); - TmpPage.Show(); - } - } - - // Refresh the button. This is important if we're cancelling a tab change. - foreach SettingsTabs(TmpButton) - { - if (TmpButton.SettingsPageID == SelectedPageID) - { - TmpButton.SetChecked(true); - } - else - { - TmpButton.SetChecked(false); - } - } - } -} - -simulated function TabClickedHandler(MCM_SettingsTab Caller, int PageID) -{ - `log("MCM Tab clicked: " $ string(PageID)); - //TabsList.SetSelectedItem(kButton, true); - ChoosePanelByPageID(PageID); -} - -simulated function AddTabsListButton(string TabLabel, int PageID) +simulated function AddTabsListButton(string TabLabel) { local MCM_SettingsTab Item; - Item = Spawn(class'MCM_SettingsTab', TabsList.ItemContainer).InitSettingsTab(PageID, TabLabel); - Item.OnClickHandler = TabClickedHandler; + Item = Spawn(class'MCM_SettingsTab', TabsList.ItemContainer).InitSettingsTab(SettingsTabs.Length, TabLabel); + if(TabsList.bSelectFirstAvailable && TabsList.ItemCount == 1) + { + Item.SetSelectedNavigation(); + } + Item.OptionsScreen = self; + Item.SettingsPanel = SettingsPanels[Item.SettingsPageID]; SettingsTabs.AddItem(Item); } -function MCM_API_SettingsPage MakeSettingsPage(string TabLabel, int PageID) +function MCM_API_SettingsPage MakeSettingsPage(string TabLabel) { local MCM_SettingsPanel SP; - SP = Spawn(class'MCM_SettingsPanel', Container); + + SP = Spawn(class'MCM_SettingsPanel', Container); + SP.OptionsScreen = self; SP.InitPanel(); - SP.SettingsPageID = PageID; + SP.SettingsPageID = SettingsPanels.Length; SP.SetPosition(TABLIST_WIDTH + OPTIONS_MARGIN, HEADER_HEIGHT); - - SP.SetPageTitle(TabLabel); - // By default do not show the panel. - SP.Hide(); + SP.SetPageTitle(TabLabel); // Register panel. SettingsPanels.AddItem(SP); @@ -371,58 +542,39 @@ function MCM_API_SettingsPage MakeSettingsPage(string TabLabel, int PageID) return SP; } -simulated function CustomTabClickedHandler(MCM_SettingsTab Caller, int PageID) -{ - `log("MCM Custom Screen Tab clicked"); - if (Caller.CustomPageCallback != none) - { - Caller.SetChecked(false); - Caller.CustomPageCallback(self, PageID); - } -} - // MCM_API_Instance implementation =============================================================== function MCM_API_SettingsPage NewSettingsPage(string TabLabel) { - local int PageID; - - PageID = SettingsPageCounter; - SettingsPageCounter++; + local MCM_API_SettingsPage NewPage; - AddTabsListButton(TabLabel, PageID); + NewPage = MakeSettingsPage(TabLabel); + AddTabsListButton(TabLabel); - return MakeSettingsPage(TabLabel, PageID); + return NewPage; } function int NewCustomSettingsPage(string TabLabel, delegate Handler) { local MCM_SettingsTab Item; - local int PageID; - PageID = SettingsPageCounter; - SettingsPageCounter++; - - Item = Spawn(class'MCM_SettingsTab', TabsList.ItemContainer).InitSettingsTab(PageID, TabLabel); + Item = Spawn(class'MCM_SettingsTab', TabsList.ItemContainer).InitSettingsTab(SettingsTabs.Length, TabLabel); + if(TabsList.bSelectFirstAvailable && TabsList.ItemCount == 1) + { + Item.SetSelectedNavigation(); + } Item.CustomPageCallback = Handler; - Item.OnClickHandler = CustomTabClickedHandler; + Item.OptionsScreen = self; + + SettingsTabs.AddItem(Item); + SettingsPanels.AddItem(none); - return PageID; + return Item.SettingsPageID; } function MCM_API_SettingsPage GetSettingsPageByID(int PageID) { - local MCM_SettingsPanel TmpPage; - - foreach SettingsPanels(TmpPage) - { - if (TmpPage.GetPageID() == PageID) - { - return TmpPage; - } - } - - return None; + return SettingsPanels[PageID]; } @@ -446,8 +598,6 @@ function bool RegisterClientMod(int major, int minor, delegate handler, UIList Parent) +function InstantiateItems(UIList Parent, out float DropAllowance, out int DropIndexOffSet, out byte bFoundDropdown) { local int iter; local MCM_SettingFacade TmpItem; + local UIPanel tmpUI; if (UiInstantiated) return; - // now items in reverse order. + for (iter = Settings.Length-1; iter >= 0; iter--) { TmpItem = Settings[iter]; - handler(TmpItem.InstantiateUI(Parent)); + tmpUI = TmpItem.InstantiateUI(Parent); + if(bFoundDropdown == 0) + { + if(MCM_Dropdown(tmpUI) != none) + { + bFoundDropdown = 1; + } + else + { + DropAllowance -= tmpUI.Height; + DropIndexOffSet++; + } + } } - // Group header last. - handler(GroupLabel.InstantiateUI(Parent)); - + TmpUI = GroupLabel.InstantiateUI(Parent); + if(bFoundDropdown == 0) + { + DropAllowance -= tmpUI.Height; + DropIndexOffSet++; + } UiInstantiated = true; } diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_SettingsPanel.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_SettingsPanel.uc index 46b8373..a110cc6 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_SettingsPanel.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_SettingsPanel.uc @@ -14,10 +14,17 @@ var localized string m_strApplyButton; var int SettingsPageID; var UIList SettingsList; - +var MCM_OptionsScreen OptionsScreen; +var bool NavSortEnabled; // Mr. Nice: When controls are made editable *after* the page has instantiated, + // then the Navigation Order must be sorted to match the list (ie visual) order. +var byte ShowStatus; // 0=Show not requested; 1 = Show requested; 2= Show complete + var MCM_UISettingSeparator TitleLine; +var UIImage bottomPadding; var UIButton ResetButton; var string Title; +var float DropAllowance; +var int DropIndexOffSet; var array SettingGroups; //var float SettingItemStartY; @@ -35,33 +42,11 @@ simulated function UIPanel InitPanel(optional name InitName, optional name InitL SetSize(PANEL_WIDTH, PANEL_HEIGHT); - SettingsList = Spawn(class'UIList', self).InitList('OptionsList', 0, 0, PANEL_WIDTH, PANEL_HEIGHT - FOOTER_HEIGHT - 40); - //SettingsList = Spawn(class'UIList', self).InitList('OptionsList', 0, 0, PANEL_WIDTH, PANEL_HEIGHT - FOOTER_HEIGHT - 20, , true); - // Necessary to make sure dropdowns don't run past the bottom. - //SettingsList.ScrollbarPadding = 500; + //SettingsList = Spawn(class'UIList', self).InitList('OptionsList', 0, 0, PANEL_WIDTH, PANEL_HEIGHT - FOOTER_HEIGHT - 40,, true); + SettingsList = Spawn(class'UIList', self).InitList('OptionsList', 0, 0, PANEL_WIDTH, PANEL_HEIGHT - FOOTER_HEIGHT + 29,, true); // Mr. Nice: addBG to stop mouse scrolling "dead spots" SettingsList.SetSelectedNavigation(); - SettingsList.Navigator.LoopSelection = true; - - // Delay spawning of title line to make sure topmost "line" is also last layer. - // See ShowSettings(); - TitleLine = none; - //TitleLine = Spawn(class'MCM_UISettingSeparator', SettingsList.itemContainer); - //TitleLine.InitSeparator(); - //TitleLine.UpdateTitle("Mod Settings"); - //TitleLine.SetY(0); - //TitleLine.Show(); - //TitleLine.EnableNavigation(); - - //SettingItemStartY = TitleLine.Height; - - ResetButton = Spawn(class'UIButton', self); - ResetButton.InitButton(, m_strResetButton, OnResetClicked); - ResetButton.SetPosition(RESET_BUTTON_X, PANEL_HEIGHT - FOOTER_HEIGHT + 3); //Relative to this screen panel - ResetButton.Hide(); - - ResetHandler = none; - SaveHandler = none; - CancelHandler = none; + SettingsList.OnSelectionChanged = OptionsScreen.OnSelectionChanged; + SettingsList.BG.SetAlpha(0); return self; } @@ -74,15 +59,27 @@ simulated function OnInit() simulated function OnResetClicked(UIButton kButton) { if (ResetHandler != none) + { + Movie.Pres.PlayUISound(eSUISound_MenuSelect); ResetHandler(self); + } } simulated function Show() { local MCM_SettingGroup iter; + // Mr. Nice: Originally all the ShowSettings() would get handled in one tick, since they ultimately + // Get called from the OnInit() in the mods UISL, all of which get called in the same tick after the panel itself is Innited. + // Now Super Lazy and only do it when about to be shown! + if (ShowStatus == 1) + { + RealShowSettings(); + } super.Show(); + OptionsScreen.CurrentPanel = self; + OPtionsScreen.ScrollHeight = SettingsList.TotalItemSize - SettingsList.Height; // Now that it's visible, need to trigger the post-visibility update. foreach SettingGroups(iter) { @@ -90,6 +87,18 @@ simulated function Show() } } +simulated function Hide() +{ + Super.Hide(); + + if (OptionsScreen.CurrentPanel == self) + { + OptionsScreen.CurrentPanel = none; + class'UIUtilities_Controls'.static.CloseAllDropdowns(self); + OPtionsScreen.SettingsTabs[SettingsPageID].ResetAppearance(); + } +} + // Helpers for MCM_OptionsScreen ================================================================ simulated function TriggerSaveEvent() @@ -147,7 +156,17 @@ function SetCancelHandler(delegate _CancelHandler) function EnableResetButton(delegate _ResetHandler) { ResetHandler = _ResetHandler; - ResetButton.Show(); + + if (ResetButton == none) + { + SettingsList.SetHeight(PANEL_HEIGHT - FOOTER_HEIGHT - 28); + RealiseSettingsList(); + ResetButton = Spawn(class'UIButton', self); + ResetButton.bIsNavigable = false; + ResetButton.InitButton(, Caps(class'UIPhotoboothBase'.default.m_CategoryReset), OnResetClicked, eUIButtonStyle_HOTLINK_BUTTON); + ResetButton.SetPosition(RESET_BUTTON_X, PANEL_HEIGHT - FOOTER_HEIGHT + 3); //Relative to this screen panel + ResetButton.SetGamepadIcon(class'UIUtilities_Input'.const.ICON_BACK_SELECT); + } } // Groups let you visually cluster settings. @@ -187,42 +206,148 @@ function int GetGroupCount() return SettingGroups.Length; } -// Assumes that groups are iterated in reverse order and items in groups are inserted in reverse order. -//function OnSettingsLineInitialized(UIMechaListItem NextItem) -function OnSettingsLineInitialized(UIPanel NextItem) +// Mr. Nice: Instantiating all the UI can be quite slow, so defer until the Panel is about to be shown +function ShowSettings() { - SettingsList.MoveItemToTop(NextItem); + ShowStatus = 1; } -function ShowSettings() +function RealShowSettings() { // This is where magic happens. - local int groupIndex; - local UIImage bottomPadding; + local int groupIndex, i; + local byte bFoundDropdown; + local UIPanel tmpItem; // Adds padding at bottom to make sure that bottom options are visisble. - bottomPadding = Spawn(class'UIImage', SettingsList.itemContainer); - bottomPadding.bProcessesMouseEvents = true; + bottomPadding = Spawn(class'UIImage', SettingsList.itemContainer); + bottomPadding.bProcessesMouseEvents = true; + bottomPadding.bShouldPlayGenericUIAudioEvents = false; + bottomPadding.Width = PANEL_WIDTH; bottomPadding.InitImage('MCMBottomPadding',"img:///MCM.gfx.Transparent"); - bottomPadding.SetWidth(548); - bottomPadding.SetHeight(150); - OnSettingsLineInitialized(bottomPadding); + DropAllowance = 160; + DropIndexOffSet = 1; for (groupIndex = SettingGroups.Length - 1; groupIndex >= 0; groupIndex--) { - SettingGroups[groupIndex].InstantiateItems(OnSettingsLineInitialized, SettingsList); + SettingGroups[groupIndex].InstantiateItems(SettingsList, DropAllowance, DropIndexOffSet, bFoundDropdown); } + if(bFoundDropdown == 0 || !`ISCONTROLLERACTIVE && DropAllowance <= 0) + { + bottomPadding.Remove(); + bottomPadding = none; + } + TitleLine = Spawn(class'MCM_UISettingSeparator', SettingsList.itemContainer); TitleLine.InitSeparator(); TitleLine.UpdateTitle(Title != "" ? Title : "Mod Settings"); TitleLine.SetY(0); - TitleLine.Show(); - TitleLine.EnableNavigation(); - SettingsList.MoveItemToTop(TitleLine); + + for(i = 0; i < SettingsList.ItemContainer.ChildPanels.Length /2; i++) + { + tmpItem = SettingsList.ItemContainer.ChildPanels[i]; + SettingsList.ItemContainer.ChildPanels[i] = SettingsList.ItemContainer.ChildPanels[SettingsList.ItemContainer.ChildPanels.Length - 1 - i]; + SettingsList.ItemContainer.ChildPanels[SettingsList.ItemContainer.ChildPanels.Length - 1 - i] = tmpItem; + } + RealiseSettingsList(true); + + if (SettingsList.Scrollbar != none) + { + SettingsList.Scrollbar.NotifyPercentChange(OptionsScreen.OnScrollPercentChanged); + } + NavSortEnabled = true; + NavSort(); + ShowStatus = 2; +} + +function RealiseSettingsList( optional bool force) +{ + local float PaddingSize; + + if(`ISCONTROLLERACTIVE || force) + { + if(force) + { + SettingsList.RealizeItems(); + } + if(bottomPadding != none) + { + if( SettingsList.ItemContainer.ChildPanels.Find(bottomPadding) != INDEX_NONE) + { + SettingsList.ItemContainer.RemoveChild(bottomPadding); + force = false; //Mr. Nice: All force obligations met now + } + if (`ISCONTROLLERACTIVE) + { + // Controllers can't directly control the scroll bar, it's position when on the last drop down + // must make allowance for this. Maths, it just werks! + if ( 0 < DropAllowance * (SettingsList.ItemCount-1) + (SettingsList.TotalItemSize - SettingsList.Height) * (DropIndexOffSet-1) ) + PaddingSize = (DropAllowance * SettingsList.ItemCount + (SettingsList.TotalItemSize - SettingsList.Height) * DropIndexOffSet) / (SettingsList.ItemCount - DropIndexOffSet); + `log(`showvar(DropAllowance)); + `log(`showvar(PaddingSize)); + `log(`showvar((SettingsList.TotalItemSize - SettingsList.Height))); + `log(`showvar(SettingsList.ItemCount)); + `log(`showvar(DropIndexOffSet)); + } + else + { + PaddingSize = DropAllowance; + } + if(PaddingSize > 0) + { + bottomPadding.SetHeight(PaddingSize); + bottomPadding.Show(); + SettingsList.ItemContainer.AddChild(bottomPadding); + } + else + { + bottomPadding.Hide(); + if(force) + { + SettingsList.RealizeItems(); + } + } + } + else + { + SettingsList.RealizeList(); + } + } +} + +function NavSort() +{ + if(NavSortEnabled) + { + SettingsList.Navigator.NavigableControls.Sort(ListIndexOrder); + } +} + +function int ListIndexOrder(UIPanel FirstItem, UIPanel SecondItem) +{ + return SettingsList.GetItemIndex(SecondItem) - SettingsList.GetItemIndex(FirstItem); +} + +simulated function OnReceiveFocus() +{ + Super.OnReceiveFocus(); + if(bIsFocused) + { + OptionsScreen.AttentionType = COAT_DETAILS; + OptionsScreen.UpdateMechItemNavHelp(SettingsList, SettingsList.SelectedIndex); + } +} + +simulated function OnLoseFocus() +{ + Super.OnLoseFocus(); + OptionsScreen.AttentionType = COAT_CATEGORIES; } defaultproperties { bProcessesMouseEvents = false; + bCascadeFocus = false; + bIsVisible = false; } \ No newline at end of file diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_SettingsTab.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_SettingsTab.uc index 02be08e..b5bd241 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_SettingsTab.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_SettingsTab.uc @@ -1,63 +1,123 @@ class MCM_SettingsTab extends UIMechaListItem; var int SettingsPageID; -var delegate OnClickHandler; -var delegate CustomPageCallback; - -delegate ClickHandler(MCM_SettingsTab Caller, int PageID); -delegate CustomSettingsPageCallback(UIScreen ParentScreen, int PageID); +var MCM_OptionsScreen OptionsScreen; +var MCM_SettingsPanel SettingsPanel; +var delegate CustomPageCallback; +var bool MouseClick; function MCM_SettingsTab InitSettingsTab(int PageID, string Label) { - super.InitListItem(); - + InitListItem(); SettingsPageID = PageID; - OnClickHandler = none; - CustomPageCallback = none; + + //UpdateDataCheckbox(Label, "", false, CheckboxChangedCallback, CheckboxClickedCallback); + UpdateDataDescription(Label, OnSelect); + return self; +} - UpdateDataCheckbox(Label, "", false, CheckboxChangedCallback, CheckboxClickedCallback); +// Mr. Nice: UIMechaListItem implementation calls RefreshButtonVisibility(), which resets the appearance... +simulated function OnMouseEvent( int cmd, array args ) +{ + super(UIPanel).OnMouseEvent(cmd, args); - return self; + if( cmd == class'UIUtilities_Input'.const.FXS_L_MOUSE_UP ) + { + MouseClick = true; + Click(); + } + else if( cmd == class'UIUtilities_Input'.const.FXS_L_MOUSE_OUT || cmd == class'UIUtilities_Input'.const.FXS_L_MOUSE_DRAG_OUT ) + OnLoseFocus(); } -function CheckboxChangedCallback(UICheckbox CheckboxControl) +function OnSelect() { - if (OnClickHandler != none) - { - OnClickHandler(self, SettingsPageID); - } + `log("MCM Tab clicked: " $ string(SettingsPageID)); + if (OptionsScreen.CurrentPanel != none && OptionsScreen.CurrentPanel != SettingsPanel) + { + OptionsScreen.CurrentPanel.Hide(); + } - if (CustomPageCallback == none) - { - // One does not uncheck by clicking. Doesn't work that way. - SetChecked(true); - } - else + if (SettingsPanel != none) + { + `log("MCM: Found correct panel, showing."); + SettingsPanel.Show(); + // Mr. Nice: Don't bother navigating into panels with nothing to navigate there! + if (SettingsPanel.SettingsList.Navigator.NavigableControls.Length != 0) + { + SettingsPanel.SetSelectedNavigation(); + // Mr. Nice: if selection from a mouse click, then focus will be lost when + // the mouse is moved off the Tab instead. + if (!MouseClick) + { + OnLoseFocus(); + SettingsPanel.SettingsList.Navigator.SelectFirstAvailable(); + SettingsPanel.SettingsList.Scrollbar.SetThumbAtPercent(0); + } + else + { + OnReceiveFocus(); // Mr. Nice: to update the appearance + MouseClick = false; + } + } + else + { + if (MouseClick) // Mr. Nice: Confirm keyb/controller nav is on the left, otherwise may get trapped in the panel just hidden! + { + OptionsScreen.TabsList.SetSelectedNavigation(); + OptionsScreen.AttentionType = COAT_CATEGORIES; + MouseClick = false; + } + else + { + OnReceiveFocus(); // Mr. Nice: to update the appearance + } + } + } + else if (CustomPageCallback != none) { - SetChecked(false); + CustomPageCallback(OptionsScreen, SettingsPageID); + if (MouseClick) // Mr. Nice: Confirm keyb/controller nav is on the left, otherwise may get trapped in the panel just hidden! + { + OptionsScreen.TabsList.SetSelectedNavigation(); + OptionsScreen.AttentionType = COAT_CATEGORIES; + MouseClick = false; + } } } -function CheckboxClickedCallback() +// Mr. Nice: Want more UIButton like behaviour, which is easier then you might think because UIMechaListItem +// has the same background, just need to poke it with some flash magic... +simulated function OnReceiveFocus() { - if (CustomPageCallback == none) - { - // One does not uncheck by clicking. Doesn't work that way. - SetChecked(true); - } - else - { - SetChecked(false); - } + Super.OnReceiveFocus(); + // Mr. Nice: should check if we actually had focus set, for example focus is refused if init stuff isn't complete yet + if (bIsFocused) + { + if(OptionsScreen.CurrentPanel != SettingsPanel || SettingsPanel == none) + { + BG.MC.FunctionString("gotoAndStop", "_SelectedOver"); + } + else + { + BG.MC.FunctionString("gotoAndPlay", "_SelectedOver"); // Make the button pulse to show it is doubly blessed! + } + } +} - if (OnClickHandler != none) - { - OnClickHandler(self, SettingsPageID); - } +// Mr. Nice: When without focus, want to indicate if we are the currently displayed settings tab or not +simulated function OnLoseFocus() +{ + Super.OnLoseFocus(); + if(OptionsScreen.CurrentPanel == SettingsPanel && SettingsPanel != none) + { + BG.MC.FunctionString("gotoAndStop", "_SelectedUp"); + Desc.MC.ChildFunctionBool("text", "highlight", true); + } } -function SetChecked(bool Checked) +function ResetAppearance() { - // Don't need to generate change event since we care about the click. - Checkbox.SetChecked(Checked, false); + BG.MC.FunctionString("gotoAndStop", "_Up"); + Desc.MC.ChildFunctionBool("text", "highlight", false); } \ No newline at end of file diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Slider.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Slider.uc index 0ba2599..18acde1 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Slider.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Slider.uc @@ -1,7 +1,7 @@ class MCM_Slider extends MCM_SettingBase implements(MCM_API_Slider) config(ModConfigMenu); var MCM_API_Setting ParentFacade; -var delegate ChangeHandler; +var delegate ChangeHandler; var float SliderMin; var float SliderMax; @@ -15,7 +15,6 @@ var bool SuppressEvent; var delegate DisplayFilter; delegate string SliderValueDisplayFilter(float _value); -delegate FloatSettingHandler(MCM_API_Setting Setting, float _SettingValue); simulated function MCM_SettingBase InitSettingsItem(name _Name, eSettingType _Type, optional string _Label = "", optional string _Tooltip = "") { @@ -26,14 +25,14 @@ simulated function MCM_SettingBase InitSettingsItem(name _Name, eSettingType _Ty // Fancy init process simulated function MCM_Slider InitSlider(name _SettingName, MCM_API_Setting _ParentFacade, string _Label, string _Tooltip, - float sMin, float sMax, float sStep, float sValue, delegate _OnChange) + float sMin, float sMax, float sStep, float sValue, delegate _OnChange) { super.InitSettingsItem(_SettingName, eSettingType_Slider, _Label, _Tooltip); SliderValueDisplay = Spawn(class'UIScrollingText', self); SliderValueDisplay.bIsNavigable = false; SliderValueDisplay.bAnimateOnInit = bAnimateOnInit; - SliderValueDisplay.InitScrollingText('SliderValueTextControl',,90,260); + SliderValueDisplay.InitScrollingText('SliderValueTextControl',,90,260, 3); SuppressEvent = false; @@ -272,3 +271,16 @@ static function string DefaultFormatValueForDisplay(float sMin, float sMax, floa return retstring; } + +// Mr. Nice: need to keep value label visible when control is selected. +simulated function OnReceiveFocus() +{ + Super.OnReceiveFocus(); + SliderValueDisplay.MC.ChildFunctionBool("text", "highlight", true); +} + +simulated function OnLoseFocus() +{ + Super.OnLoseFocus(); + SliderValueDisplay.MC.ChildFunctionBool("text", "highlight", false); +} \ No newline at end of file diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_SliderFacade.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_SliderFacade.uc index 9de168a..61b8163 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_SliderFacade.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_SliderFacade.uc @@ -12,19 +12,18 @@ var float SliderMax; var float SliderStep; var float SliderValue; -var delegate ChangeHandler; -var delegate SaveHandler; +var delegate ChangeHandler; +var delegate SaveHandler; var delegate DisplayFilter; var MCM_Slider uiInstance; -delegate FloatSettingHandler(MCM_API_Setting Setting, float _SettingValue); delegate string SliderValueDisplayFilter(float value); simulated function MCM_SliderFacade InitSliderFacade(name _Name, string _Label, string _Tooltip, float sMin, float sMax, float sStep, float sValue, - delegate _OnChange, delegate _OnSave, + delegate _OnChange, delegate _OnSave, MCM_SettingGroup _ParentGroup) { SettingName = _Name; @@ -67,7 +66,6 @@ function UIMechaListItem InstantiateUI(UIList Parent) uiInstance = Spawn(class'MCM_Slider', parent.itemContainer).InitSlider(SettingName, self, Label, Tooltip, SliderMin, SliderMax, SliderStep, SliderValue, ChangeHandler); uiInstance.Show(); - uiInstance.EnableNavigation(); uiInstance.SetEditable(Editable); // Always have one implemented. uiInstance.SetValueDisplayFilter(InnerDisplayFilter); diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Spinner.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Spinner.uc index 522e0bf..af3f751 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Spinner.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_Spinner.uc @@ -1,14 +1,12 @@ class MCM_Spinner extends MCM_SettingBase implements(MCM_API_Spinner) config(ModConfigMenu); -var delegate ChangeHandler; +var delegate ChangeHandler; var MCM_API_Setting ParentFacade; var array SpinnerOptions; var int SpinnerSelection; var bool TmpSuppressEvent; -delegate StringSettingHandler(MCM_API_Setting Setting, string _SettingValue); - simulated function MCM_SettingBase InitSettingsItem(name _Name, eSettingType _Type, optional string _Label = "", optional string _Tooltip = "") { `log("Don't call InitSettingsItem directly in subclass of MCM_SettingBase."); @@ -17,16 +15,25 @@ simulated function MCM_SettingBase InitSettingsItem(name _Name, eSettingType _Ty } // Fancy init process -simulated function MCM_Spinner InitSpinner(name _SettingName, MCM_API_Setting _ParentFacade, string _Label, string _Tooltip, array _Options, string _Selection, - delegate _OnChange) +simulated function MCM_Spinner InitSpinner(name _SettingName, MCM_API_Setting _ParentFacade, string _Label, string _Tooltip, out array _Options, string _Selection, + delegate _OnChange) { super.InitSettingsItem(_SettingName, eSettingType_Checkbox, _Label, _Tooltip); + Spinner.Remove(); + Spinner = Spawn(class'MCM_UIListItemSpinner', self); + Spinner.bAnimateOnInit = false; + Spinner.bIsNavigable = false; + Spinner.MCName = 'SpinnerMC'; + Spinner.InitSpinner(,, OnSpinnerChangeDelegate); + Spinner.Navigator.HorizontalNavigation = true; + Spinner.SetX(width - 330); + Spinner.SetValueWidth(250, true); ChangeHandler = _OnChange; ParentFacade = _ParentFacade; - CloneOptionsList(_Options); - SpinnerSelection = GetSelectionIndex(_Options, _Selection); + SpinnerOptions = _Options; + SpinnerSelection = _Options.find(_Selection); TmpSuppressEvent = true; UpdateDataSpinner(_Label, "", SpinnerChangedCallback); @@ -40,28 +47,6 @@ simulated function MCM_Spinner InitSpinner(name _SettingName, MCM_API_Setting _P // Helpers -function CloneOptionsList(array OptionsList) -{ - local int iter; - SpinnerOptions.Length = 0; - for (iter = 0; iter < OptionsList.Length; iter++) - { - SpinnerOptions.AddItem(OptionsList[iter]); - } -} - -function int GetSelectionIndex(array OptionsList, string SelectedOption) -{ - local int iter; - for (iter = 0; iter < OptionsList.Length; iter++) - { - if (SelectedOption == OptionsList[iter]) - return iter; - } - - return -1; -} - function SpinnerChangedCallback(UIListItemSpinner SpinnerControl, int Direction) { SpinnerSelection += Direction; @@ -90,7 +75,7 @@ function SetValue(string Selection, bool SuppressEvent) { local int index; - index = GetSelectionIndex(SpinnerOptions, Selection); + index = SpinnerOptions.find(Selection); // If found. if (index >= 0) { @@ -108,10 +93,10 @@ function SetValue(string Selection, bool SuppressEvent) } } -function SetOptions(array NewOptions, string InitialSelection, bool SuppressEvent) +function SetOptions(out array NewOptions, string InitialSelection, bool SuppressEvent) { - CloneOptionsList(NewOptions); - SpinnerSelection = GetSelectionIndex(NewOptions, InitialSelection); + SpinnerOptions = NewOptions; + SpinnerSelection = NewOptions.find(InitialSelection); TmpSuppressEvent = SuppressEvent; Spinner.SetValue(InitialSelection); @@ -140,4 +125,9 @@ simulated function SetEditable(bool IsEditable) { Spinner.Hide(); } +} + +defaultproperties +{ + NavSound = "Play_MenuSelect" } \ No newline at end of file diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_SpinnerFacade.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_SpinnerFacade.uc index 548e53c..0227fd4 100755 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_SpinnerFacade.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_SpinnerFacade.uc @@ -10,16 +10,14 @@ var int SelectionIndex; var MCM_SettingGroup ParentGroup; -var delegate ChangeHandler; -var delegate SaveHandler; +var delegate ChangeHandler; +var delegate SaveHandler; var MCM_Spinner uiInstance; -delegate StringSettingHandler(MCM_API_Setting Setting, string _SettingValue); - simulated function MCM_SpinnerFacade InitSpinnerFacade(name _Name, string _Label, string _Tooltip, array _Options, string _Selection, - delegate _OnChange, delegate _OnSave, + delegate _OnChange, delegate _OnSave, MCM_SettingGroup _ParentGroup) { SettingName = _Name; @@ -69,7 +67,6 @@ function UIMechaListItem InstantiateUI(UIList Parent) { uiInstance = Spawn(class'MCM_Spinner', parent.itemContainer).InitSpinner(SettingName, self, Label, Tooltip, Options, Options[SelectionIndex], ChangeHandler); uiInstance.Show(); - uiInstance.EnableNavigation(); uiInstance.SetEditable(Editable); return uiInstance; diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_UIButton.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_UIButton.uc new file mode 100644 index 0000000..178fc8b --- /dev/null +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_UIButton.uc @@ -0,0 +1,86 @@ +//----------------------------------------------------------- +// Class: MCM_UIButton +// Author: Mr. Nice +// +//----------------------------------------------------------- + + +class MCM_UIButton extends UIButton; + +var int iButton, ShowTick; +var XComInputBase PlayerInput; +var float prevfTime; +var bool bControllerActive; + +simulated function UIButton InitButton(optional name InitName, optional string InitLabel, optional delegate InitOnClicked, optional EUIButtonStyle InitStyle = -1, optional name InitLibID = '') +{ + PlayerInput = XComInputBase(`LOCALPLAYERCONTROLLER.PlayerInput); + bControllerActive = `ISCONTROLLERACTIVE; + return Super.InitButton(InitName, InitLabel, InitOnClicked, InitStyle, InitLibID); +} + +function StartInputListener(optional int kButton) +{ + if (kButton != 0) + { + iButton = kButton; + } + PlayerInput.Subscribe(iButton, 7*24*60*60, ResetPrevfTime); + prevfTime = 0; + SetTickIsDisabled(false); +} + +function StopInputListener() +{ + PlayerInput.Unsubscribe(ResetPrevfTime); + prevfTime = -1; + SetTickIsDisabled(true); +} + +function ResetPrevfTime() +{ + prevfTime = 0; // Somehow the button has been waiting 7 days?! Anyhow, guess we'll miss a a tick of monitoring then soldier on... +} + +simulated event Tick(float DeltaTime) +{ + local float newfTime; + + if(prevfTime != -1) + { + newfTime = PlayerInput.GetIdler(iButton).fTime; + if(NewfTime < prevfTime) + { + OnClickedDelegate(self); + } + prevfTime = newfTime; + } + + // Mr. Nice: "Blinks" when controller/mouse swapped to fit in with other buttons + // Not entirely sure if the tick count it takes for the other buttons to be nuked then recreated + // Is entirely determinisitic, ShowTick set by observation... + if(ShowTick !=0) + { + if(--ShowTick == 0) + { + Show(); + } + } + if (bControllerActive != `ISCONTROLLERACTIVE) + { + // Mr. Nice: Ok, the use has swapped interface type, need to refresh the button appearance + Hide(); + ShowTick = 2; + mc.SetNum("state", 0); + mc.FunctionVoid("realize"); + bControllerActive = !bControllerActive; + } + + Super.Tick(DeltaTime); +} + +defaultproperties +{ + bTickIsDisabled = true; + bAlwaysTick = true; +} \ No newline at end of file diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_UIListItemSpinner.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_UIListItemSpinner.uc new file mode 100644 index 0000000..1f6af39 --- /dev/null +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_UIListItemSpinner.uc @@ -0,0 +1,19 @@ +//----------------------------------------------------------- +// Class: MCM_UIListItemSpinner +// Author: Mr. Nice +// +//----------------------------------------------------------- + + +class MCM_UIListItemSpinner extends UIListItemSpinner; + + +simulated function OnMouseEvent(int cmd, array args) +{ + Super.OnMouseEvent(cmd, args); + + if(cmd == class'UIUtilities_Input'.const.FXS_L_MOUSE_UP) + { + Movie.Pres.PlayUISound(eSUISound_MenuSelect); + } +} \ No newline at end of file diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_UISettingSeparator.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_UISettingSeparator.uc index 0207f61..850eb2e 100644 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_UISettingSeparator.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_UISettingSeparator.uc @@ -58,4 +58,5 @@ defaultproperties DESC_Y = 10; bProcessesMouseEvents = true; + bShouldPlayGenericUIAudioEvents = false; } \ No newline at end of file diff --git a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_XCOM2_UISlider.uc b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_XCOM2_UISlider.uc index 6281fb4..693760c 100644 --- a/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_XCOM2_UISlider.uc +++ b/ModConfigMenu/ModConfigMenu/Src/ModConfigMenu/Classes/MCM_XCOM2_UISlider.uc @@ -26,4 +26,14 @@ simulated function UISlider SetStepSize(float newValue) //mc.FunctionNum("setValue", newValue); // Is there a flash function for setting step size? } return self; +} + +simulated function OnMouseEvent(int cmd, array args) +{ + Super.OnMouseEvent(cmd, args); + + if(cmd == class'UIUtilities_Input'.const.FXS_L_MOUSE_UP) + { + PlaySound( SoundCue'SoundUI.MenuScrollCue', true ); + } } \ No newline at end of file