From 525f671513eb3f80775399ba34a879b528d9a7a4 Mon Sep 17 00:00:00 2001 From: F1F7Y <64418963+F1F7Y@users.noreply.github.com> Date: Tue, 10 Sep 2024 23:43:36 +0200 Subject: Rework mode select menu (#624) Turns mode list from page based into a scrollable list that is categorised and supports filtering. --- Northstar.Client/mod.json | 4 + .../northstar_client_localisation_english.txt | 12 + .../mod/resource/ui/menus/mode_select.menu | 613 +++++++++++++++------ .../ui/menus/panels/mode_select_button.res | 31 ++ .../mod/scripts/vscripts/ui/menu_mode_select.nut | 582 ++++++++++++++++--- 5 files changed, 1003 insertions(+), 239 deletions(-) create mode 100644 Northstar.Client/mod/resource/ui/menus/panels/mode_select_button.res diff --git a/Northstar.Client/mod.json b/Northstar.Client/mod.json index 44937a2b..0d0cfc16 100644 --- a/Northstar.Client/mod.json +++ b/Northstar.Client/mod.json @@ -46,6 +46,10 @@ "Name": "modlist_reverse", "DefaultValue": "0", "Flags": "ARCHIVE_PLAYERPROFILE" + }, + { + "Name": "modemenu_mode_filter", + "DefaultValue": "-1" } ], "Scripts": [ diff --git a/Northstar.Client/mod/resource/northstar_client_localisation_english.txt b/Northstar.Client/mod/resource/northstar_client_localisation_english.txt index 29d7cddf..f7c5ee2d 100644 --- a/Northstar.Client/mod/resource/northstar_client_localisation_english.txt +++ b/Northstar.Client/mod/resource/northstar_client_localisation_english.txt @@ -324,6 +324,18 @@ Press Yes if you agree to this. This choice can be changed in the mods menu at a "JSON_PARSE_ERROR" "Error parsing json response" "UNSUPPORTED_VERSION" "The version you are using is no longer supported" + // Mode menu + "MODE_MENU_PVPVE" "PvPvE" + "MODE_MENU_PVE" "PvE" + "MODE_MENU_PVP" "PvP" + "MODE_MENU_FFA" "FFA" + "MODE_MENU_TITAN_ONLY" "Titan Only" + "MODE_MENU_OTHER" "Other" + "MODE_MENU_CUSTOM" "Custom" + "MODE_MENU_ALL" "All" + "MODE_MENU_UNKNOWN" "Unknown" + "MODE_MENU_SWITCH" "Filter" + "AUTHENTICATION_FAILED_HEADER" "Authentication Failed" "AUTHENTICATION_FAILED_BODY" "Failed to authenticate with Atlas!" "AUTHENTICATION_FAILED_ERROR_CODE" "Error code: ^DB6F2C00%s1^" diff --git a/Northstar.Client/mod/resource/ui/menus/mode_select.menu b/Northstar.Client/mod/resource/ui/menus/mode_select.menu index e0f51105..bf07164e 100644 --- a/Northstar.Client/mod/resource/ui/menus/mode_select.menu +++ b/Northstar.Client/mod/resource/ui/menus/mode_select.menu @@ -38,33 +38,53 @@ resource/ui/menus/mode_select.menu controlSettingsFile "resource/ui/menus/panels/matchmaking_status.res" } - NextModeImageFrame - { - ControlName RuiPanel - xpos 800 + MenuTitle + { + ControlName Label + InheritProperties MenuTitle + labelText "#SELECT_GAME_MODE" + } + + ButtonRowAnchor + { + ControlName Label + labelText "" + + xpos 96 + ypos 140 + } + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// NEXT MODE PANEL +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + NextModeImageFrame + { + ControlName RuiPanel + xpos 740 ypos 160 wide 860 - tall 418 - labelText "" - visible 1 - bgcolor_override "0 0 0 0" - paintbackground 1 - rui "ui/basic_border_box.rpak" - } + tall 520 + labelText "" + visible 1 + bgcolor_override "0 0 0 0" + paintbackground 1 + rui "ui/control_options_description.rpak" + } NextModeImage { ControlName RuiPanel pin_to_sibling NextModeImageFrame - pin_corner_to_sibling BOTTOM - pin_to_sibling_corner BOTTOM -// xpos -12 - ypos -12 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner TOP_LEFT + xpos 0 + ypos 14 wide 480 tall 240 visible 1 scaleImage 1 - rui "ui/basic_menu_image.rpak" + rui "ui/basic_menu_image.rpak" zpos 2 } @@ -80,23 +100,24 @@ resource/ui/menus/mode_select.menu tall 72 visible 1 scaleImage 1 - rui "ui/basic_image_add.rpak" + rui "ui/basic_image_add.rpak" zpos 2 } NextModeName { ControlName Label - pin_to_sibling NextModeImageFrame - pin_corner_to_sibling TOP - pin_to_sibling_corner TOP - ypos -20 + pin_to_sibling NextModeImage + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + ypos -10 + xpos -10 wide 840 auto_tall_tocontents 1 visible 1 labelText "Foo" - textAlignment center - centerWrap 1 + //textAlignment center + //centerWrap 1 font Default_43_DropShadow allcaps 1 fgcolor_override "255 255 255 255" @@ -106,219 +127,463 @@ resource/ui/menus/mode_select.menu { ControlName Label pin_to_sibling NextModeName - pin_corner_to_sibling TOP - pin_to_sibling_corner BOTTOM + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT xpos 0 - ypos 0 + ypos 10 wide 840 wrap 1 auto_tall_tocontents 1 visible 1 labelText "Bar" - textAlignment center - centerWrap 1 + //textAlignment center + //centerWrap 1 font Default_27 allcaps 0 fgcolor_override "255 255 255 255" } - MenuTitle +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// FILTERS PANEL +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + FiltersPanel { - ControlName Label - InheritProperties MenuTitle - labelText "#SELECT_GAME_MODE" + ControlName RuiPanel + xpos 740 + ypos 682 + wide 860 + tall 156 + zpos -1 + + rui "ui/control_options_description.rpak" } - ButtonRowAnchor + BtnModeLabel { - ControlName Label - labelText "" + ControlName RuiButton + InheritProperties RuiSmallButton + labelText "#SEARCHBAR_LABEL" + textAlignment west + classname FilterPanelChild - xpos 96 - ypos 160 + wide 500 + xpos -18 + ypos -16 + + pin_to_sibling FiltersPanel + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner TOP_LEFT + } + + BtnModeSearch + { + ControlName TextEntry + classname FilterPanelChild + zpos 100 // This works around input weirdness when the control is constructed by code instead of VGUI blackbox. + xpos -400 + ypos -5 + wide 390 + tall 30 + textHidden 0 + editable 1 + font Default_21 + allowRightClickMenu 0 + allowSpecialCharacters 0 + unicode 1 + + pin_to_sibling BtnModeLabel + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner TOP_RIGHT + } + + SwtModeLabel + { + ControlName RuiButton + InheritProperties SwitchButton + labelText "#MODE_MENU_FILTER" + ConVar "modemenu_mode_filter" + classname FilterPanelChild + wide 500 + ypos 2 + + pin_to_sibling BtnModeLabel + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT } - BtnMode1 + BtnModeFiltersClear { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModeButton - scriptID 0 - navUp BtnMode15 - navDown BtnMode2 + ControlName RuiButton + InheritProperties RuiSmallButton + labelText "#CLEAR_FILTERS" + textAlignment west + classname FilterPanelChild - pin_to_sibling ButtonRowAnchor - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner TOP_LEFT + wide 100 + ypos 2 + + pin_to_sibling SwtModeLabel + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT } - BtnMode2 + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// PANELS LIST +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + Panel1 { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModeButton + ControlName CNestedPanel + classname ModeSelectorPanel scriptID 1 - pin_to_sibling BtnMode1 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMode1 - navDown BtnMode3 + + controlSettingsFile "resource/ui/menus/panels/mode_select_button.res" + wide %100 + tall 45 + + pin_to_sibling ButtonRowAnchor + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT } - BtnMode3 + + Panel2 { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModeButton + ControlName "CNestedPanel" + classname ModeSelectorPanel scriptID 2 - pin_to_sibling BtnMode2 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMode2 - navDown BtnMode4 + + controlSettingsFile "resource/ui/menus/panels/mode_select_button.res" + wide %100 + tall 45 + + pin_to_sibling Panel1 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT } - BtnMode4 + + Panel3 { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModeButton + ControlName "CNestedPanel" + classname ModeSelectorPanel scriptID 3 - pin_to_sibling BtnMode3 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - //ypos 11 - navUp BtnMode3 - navDown BtnMode5 + + controlSettingsFile "resource/ui/menus/panels/mode_select_button.res" + wide %100 + tall 45 + + pin_to_sibling Panel2 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT } - BtnMode5 + + Panel4 { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModeButton + ControlName "CNestedPanel" + classname ModeSelectorPanel scriptID 4 - pin_to_sibling BtnMode4 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMode4 - navDown BtnMode6 + + controlSettingsFile "resource/ui/menus/panels/mode_select_button.res" + wide %100 + tall 45 + + pin_to_sibling Panel3 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT } - BtnMode6 + + Panel5 { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModeButton + ControlName "CNestedPanel" + classname ModeSelectorPanel scriptID 5 - pin_to_sibling BtnMode5 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMode5 - navDown BtnMode7 + + controlSettingsFile "resource/ui/menus/panels/mode_select_button.res" + wide %100 + tall 45 + + pin_to_sibling Panel4 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT } - BtnMode7 + + Panel6 { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModeButton + ControlName "CNestedPanel" + classname ModeSelectorPanel scriptID 6 - pin_to_sibling BtnMode6 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMode6 - navDown BtnMode8 + + controlSettingsFile "resource/ui/menus/panels/mode_select_button.res" + wide %100 + tall 45 + + pin_to_sibling Panel5 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT } - BtnMode8 + + Panel7 { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModeButton + ControlName "CNestedPanel" + classname ModeSelectorPanel scriptID 7 - pin_to_sibling BtnMode7 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMode7 - navDown BtnMode9 + + controlSettingsFile "resource/ui/menus/panels/mode_select_button.res" + wide %100 + tall 45 + + pin_to_sibling Panel6 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT } - BtnMode9 + + Panel8 { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModeButton + ControlName "CNestedPanel" + classname ModeSelectorPanel scriptID 8 - pin_to_sibling BtnMode8 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMode8 - navDown BtnMode10 + + controlSettingsFile "resource/ui/menus/panels/mode_select_button.res" + wide %100 + tall 45 + + pin_to_sibling Panel7 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT } - BtnMode10 + + Panel9 { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModeButton + ControlName "CNestedPanel" + classname ModeSelectorPanel scriptID 9 - pin_to_sibling BtnMode9 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMode9 - navDown BtnMode11 + + controlSettingsFile "resource/ui/menus/panels/mode_select_button.res" + wide %100 + tall 45 + + pin_to_sibling Panel8 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT } - BtnMode11 + + Panel10 { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModeButton + ControlName "CNestedPanel" + classname ModeSelectorPanel scriptID 10 - pin_to_sibling BtnMode10 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMode10 - navDown BtnMode12 + + controlSettingsFile "resource/ui/menus/panels/mode_select_button.res" + wide %100 + tall 45 + + pin_to_sibling Panel9 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT } - BtnMode12 + + Panel11 { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModeButton + ControlName "CNestedPanel" + classname ModeSelectorPanel scriptID 11 - pin_to_sibling BtnMode11 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMode11 - navDown BtnMode13 + + controlSettingsFile "resource/ui/menus/panels/mode_select_button.res" + wide %100 + tall 45 + + pin_to_sibling Panel10 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT } - BtnMode13 + + Panel12 { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModeButton + ControlName "CNestedPanel" + classname ModeSelectorPanel scriptID 12 - pin_to_sibling BtnMode12 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMode12 - navDown BtnMode14 + + controlSettingsFile "resource/ui/menus/panels/mode_select_button.res" + wide %100 + tall 45 + + pin_to_sibling Panel11 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT } - BtnMode14 + + Panel13 { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModeButton + ControlName "CNestedPanel" + classname ModeSelectorPanel scriptID 13 - pin_to_sibling BtnMode13 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMode13 - navDown BtnMode15 + + controlSettingsFile "resource/ui/menus/panels/mode_select_button.res" + wide %100 + tall 45 + + pin_to_sibling Panel12 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT } - BtnMode15 + + Panel14 { - ControlName RuiButton - InheritProperties RuiSmallButton - classname ModeButton + ControlName "CNestedPanel" + classname ModeSelectorPanel scriptID 14 - pin_to_sibling BtnMode14 - pin_corner_to_sibling TOP_LEFT - pin_to_sibling_corner BOTTOM_LEFT - navUp BtnMode14 - navDown BtnMode1 + + controlSettingsFile "resource/ui/menus/panels/mode_select_button.res" + wide %100 + tall 45 + + pin_to_sibling Panel13 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + + Panel15 + { + ControlName "CNestedPanel" + classname ModeSelectorPanel + scriptID 15 + + controlSettingsFile "resource/ui/menus/panels/mode_select_button.res" + wide %100 + tall 45 + + pin_to_sibling Panel14 + pin_corner_to_sibling TOP_LEFT + pin_to_sibling_corner BOTTOM_LEFT + } + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// SLIDER +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + BtnModeListUpArrow + { + ControlName RuiButton + InheritProperties RuiSmallButton + //labelText "A" + wide 40 + tall 40 + xpos 2 + ypos 2 + + image "vgui/hud/white" + drawColor "255 255 255 128" + + pin_to_sibling NextModeImageFrame + pin_corner_to_sibling TOP_RIGHT + pin_to_sibling_corner TOP_LEFT + } + + BtnModeListUpArrowPanel + { + ControlName RuiPanel + wide 40 + tall 40 + xpos 2 + ypos 2 + + rui "ui/control_options_description.rpak" + + visible 1 + zpos -1 + + pin_to_sibling NextModeImageFrame + pin_corner_to_sibling TOP_RIGHT + pin_to_sibling_corner TOP_LEFT + } + + BtnModeListDownArrow + { + ControlName RuiButton + InheritProperties RuiSmallButton + //labelText "V" + wide 40 + tall 40 + xpos 2 + ypos -639 + + image "vgui/hud/white" + drawColor "255 255 255 128" + + pin_to_sibling NextModeImageFrame + pin_corner_to_sibling TOP_RIGHT + pin_to_sibling_corner TOP_LEFT + } + + BtnModeListDownArrowPanel + { + ControlName RuiPanel + wide 40 + tall 40 + xpos 2 + ypos -639 + + rui "ui/control_options_description.rpak" + + visible 1 + zpos -1 + + pin_to_sibling NextModeImageFrame + pin_corner_to_sibling TOP_RIGHT + pin_to_sibling_corner TOP_LEFT + } + + BtnModeListSlider + { + ControlName RuiButton + InheritProperties RuiSmallButton + //labelText "V" + wide 40 + tall 599 + xpos 2 + ypos -42 + zpos 0 + + image "vgui/hud/white" + drawColor "255 255 255 128" + + pin_to_sibling NextModeImageFrame + pin_corner_to_sibling TOP_RIGHT + pin_to_sibling_corner TOP_LEFT + } + + BtnModeListSliderPanel + { + ControlName RuiPanel + wide 40 + tall 599 + xpos 2 + ypos -42 + + rui "ui/control_options_description.rpak" + + visible 1 + zpos -1 + + pin_to_sibling NextModeImageFrame + pin_corner_to_sibling TOP_RIGHT + pin_to_sibling_corner TOP_LEFT + } + + // sh_menu_models.gnut has a global function which gets called when + // left mouse button gets called while hovering and has mouse + // deltaX; deltaY which we can yoink for ourselfes + MouseMovementCapture + { + ControlName CMouseMovementCapturePanel + wide 40 + tall 562 + xpos 2 + ypos -42 + zpos 1 + + pin_to_sibling NextModeImageFrame + pin_corner_to_sibling TOP_RIGHT + pin_to_sibling_corner TOP_LEFT } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Northstar.Client/mod/resource/ui/menus/panels/mode_select_button.res b/Northstar.Client/mod/resource/ui/menus/panels/mode_select_button.res new file mode 100644 index 00000000..b361e4fa --- /dev/null +++ b/Northstar.Client/mod/resource/ui/menus/panels/mode_select_button.res @@ -0,0 +1,31 @@ +resource/ui/menus/panels/mode_select_button.res +{ + BtnMode + { + ControlName RuiButton + InheritProperties RuiSmallButton + classname ModButton + labelText "please show up" + wide 600 + tall 45 + + pin_to_sibling ControlBox + pin_corner_to_sibling LEFT + pin_to_sibling_corner RIGHT + } + + Header + { + ControlName Label + InheritProperties RuiSmallButton + wide 600 + labelText "labelText" + font Default_41 + fgcolor_override "255 255 255 255" + tall 45 + + pin_to_sibling ControlBox + pin_corner_to_sibling LEFT + pin_to_sibling_corner RIGHT + } +} diff --git a/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut b/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut index 605af383..6cddee2a 100644 --- a/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut +++ b/Northstar.Client/mod/scripts/vscripts/ui/menu_mode_select.nut @@ -1,81 +1,551 @@ +untyped global function InitModesMenu +global function NSSetModeCategory + +global enum eModeMenuModeCategory +{ + UNKNOWN = 0, + PVPVE = 1, + PVE = 2, + PVP = 3, + FFA = 4, + TITAN = 5, + OTHER = 6, + CUSTOM = 7 + + SIZE +} + +// List of blocked modes due to them being unfinished +const array blockedModes = +[ + "fd_easy", + "fd_normal", + "fd_hard", + "fd_master", + "fd_insane" +] + +struct ListEntry_t { + string mode + int category +} + +// Slider mouse delta buffer +struct { + int deltaX = 0 + int deltaY = 0 +} mouseDeltaBuffer struct { - int currentModePage + int scrollOffset + var menu + + string searchString + int searchEnum + + // Table of category overrides + table categoryOverrides + + // List of all modes we know + array modes + + // Sorted list of modes we want to show with categories included + array sortedModes } file const int MODES_PER_PAGE = 15 void function InitModesMenu() { - var menu = GetMenu( "ModesMenu" ) + file.menu = GetMenu( "ModesMenu" ) + + AddMouseMovementCaptureHandler( Hud_GetChild( file.menu, "MouseMovementCapture"), UpdateMouseDeltaBuffer ) + + AddMenuEventHandler( file.menu, eUIEvent.MENU_CLOSE, OnCloseModesMenu ) + AddMenuEventHandler( file.menu, eUIEvent.MENU_OPEN, OnOpenModesMenu ) + AddButtonEventHandler( Hud_GetChild( file.menu, "BtnModeListUpArrow"), UIE_CLICK, OnUpArrowSelected ) + AddButtonEventHandler( Hud_GetChild( file.menu, "BtnModeListDownArrow"), UIE_CLICK, OnDownArrowSelected ) - AddMenuEventHandler( menu, eUIEvent.MENU_OPEN, OnOpenModesMenu ) + AddButtonEventHandler( Hud_GetChild( file.menu, "BtnModeLabel"), UIE_CHANGE, FilterAndUpdateList ) + AddButtonEventHandler( Hud_GetChild( file.menu, "BtnModeSearch"), UIE_CHANGE, FilterAndUpdateList ) + AddButtonEventHandler( Hud_GetChild( file.menu, "SwtModeLabel"), UIE_CHANGE, FilterAndUpdateList ) - AddEventHandlerToButtonClass( menu, "ModeButton", UIE_GET_FOCUS, ModeButton_GetFocus ) - AddEventHandlerToButtonClass( menu, "ModeButton", UIE_CLICK, ModeButton_Click ) + AddButtonEventHandler( Hud_GetChild( file.menu, "BtnModeFiltersClear"), UIE_CLICK, OnBtnFiltersClear_Activate ) + + array buttons = GetElementsByClassname( file.menu, "ModeSelectorPanel" ) + foreach ( var panel in buttons ) + { + AddEventHandlerToButton( panel, "BtnMode", UIE_GET_FOCUS, ModeButton_GetFocus ) + AddEventHandlerToButton( panel, "BtnMode", UIE_CLICK, ModeButton_Click ) + } - AddMenuFooterOption( menu, BUTTON_A, "#A_BUTTON_SELECT" ) - AddMenuFooterOption( menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) - - AddMenuFooterOption( menu, BUTTON_SHOULDER_LEFT, "#PRIVATE_MATCH_PAGE_PREV", "#PRIVATE_MATCH_PAGE_PREV", CycleModesBack ) - AddMenuFooterOption( menu, BUTTON_SHOULDER_RIGHT, "#PRIVATE_MATCH_PAGE_NEXT", "#PRIVATE_MATCH_PAGE_NEXT", CycleModesForward ) + Hud_SetText( Hud_GetChild( file.menu, "SwtModeLabel" ), "#MODE_MENU_SWITCH" ) + SetButtonRuiText( Hud_GetChild( file.menu, "SwtModeLabel" ), "" ) + Hud_DialogList_AddListItem( Hud_GetChild( file.menu, "SwtModeLabel" ) , "#MODE_MENU_ALL", "-1" ) + for( int i = 0; i < eModeMenuModeCategory.SIZE; i++ ) + { + Hud_DialogList_AddListItem( Hud_GetChild( file.menu, "SwtModeLabel" ) , GetCategoryStringFromEnum(i), string(i) ) + } + + AddMenuFooterOption( file.menu, BUTTON_A, "#A_BUTTON_SELECT" ) + AddMenuFooterOption( file.menu, BUTTON_B, "#B_BUTTON_BACK", "#BACK" ) +} + +void function NSSetModeCategory( string mode, int category ) +{ + if( mode in file.categoryOverrides ) + { + file.categoryOverrides[mode] = category + printt( "Overwriting category for mode:", mode ) + return + } + + file.categoryOverrides[mode] <- category +} + +void function OnBtnFiltersClear_Activate( var b ) +{ + file.searchString = "" + file.searchEnum = -1 + + SetConVarInt( "modemenu_mode_filter", -1 ) + Hud_SetText( Hud_GetChild( file.menu, "BtnModeSearch"), "" ) + + file.scrollOffset = 0 + + BuildSortedModesArray() + UpdateListSliderHeight(float(file.sortedModes.len())) + UpdateListSliderPosition(file.sortedModes.len()) + UpdateVisibleModes() +} + +void function FilterAndUpdateList( var n ) +{ + file.searchString = Hud_GetUTF8Text( Hud_GetChild( file.menu, "BtnModeSearch" ) ) + file.searchEnum = GetConVarInt( "modemenu_mode_filter" ) + + file.scrollOffset = 0 + + BuildSortedModesArray() + UpdateListSliderHeight(float(file.sortedModes.len())) + UpdateListSliderPosition(file.sortedModes.len()) + UpdateVisibleModes() } void function OnOpenModesMenu() { + RegisterButtonPressedCallback( MOUSE_WHEEL_UP , OnScrollUp ) + RegisterButtonPressedCallback( MOUSE_WHEEL_DOWN , OnScrollDown ) + + // Reset filters + file.searchString = "" + file.searchEnum = -1 + + // We rebuild the modes array on open menu to make sure + // all modes get listed + BuildModesArray() + BuildSortedModesArray() + + UpdateListSliderHeight(float(file.sortedModes.len())) + UpdateListSliderPosition(file.sortedModes.len()) UpdateVisibleModes() - - if ( level.ui.privatematch_mode == 0 ) // set to the first mode if there's no mode focused - Hud_SetFocused( GetElementsByClassname( GetMenu( "ModesMenu" ), "ModeButton" )[ 0 ] ) + + // Set to the first mode if there's no mode focused + if ( level.ui.privatematch_mode == 0 ) + { + array panels = GetElementsByClassname( file.menu, "ModeSelectorPanel" ) + foreach( var panel in panels ) + { + if( Hud_IsEnabled( Hud_GetChild( panel, "BtnMode") ) ) + { + Hud_SetFocused( Hud_GetChild( panel, "BtnMode") ) + break + } + } + } +} + +void function OnCloseModesMenu() +{ + try + { + DeregisterButtonPressedCallback( MOUSE_WHEEL_UP , OnScrollUp ) + DeregisterButtonPressedCallback( MOUSE_WHEEL_DOWN , OnScrollDown ) + } + catch ( ex ) {} } +string function GetCategoryStringFromEnum( int category ) +{ + switch( category ) + { + case eModeMenuModeCategory.PVPVE: return "#MODE_MENU_PVPVE" + case eModeMenuModeCategory.PVE: return "#MODE_MENU_PVE" + case eModeMenuModeCategory.PVP: return "#MODE_MENU_PVP" + case eModeMenuModeCategory.FFA: return "#MODE_MENU_FFA" + case eModeMenuModeCategory.TITAN: return "#MODE_MENU_TITAN_ONLY" + case eModeMenuModeCategory.OTHER: return "#MODE_MENU_OTHER" + case eModeMenuModeCategory.CUSTOM: return "#MODE_MENU_CUSTOM" + } + + return "#MODE_MENU_UNKNOWN" +} + +void function BuildModesArray() +{ + file.modes.clear() + + foreach( string mode in GetPrivateMatchModes() ) + { + ListEntry_t entry + entry.mode = mode + entry.category = eModeMenuModeCategory.UNKNOWN + + switch( mode ) + { + case "aitdm": + case "at": + entry.category = eModeMenuModeCategory.PVPVE + break + case "fd_easy": + case "fd_normal": + case "fd_hard": + case "fd_master": + case "fd_insane": + entry.category = eModeMenuModeCategory.PVE + break + case "tdm": + case "ctf": + case "mfd": + case "ps": + case "cp": + case "speedball": + case "rocket_lf": + case "holopilot_lf": + entry.category = eModeMenuModeCategory.PVP + break + case "ffa": + case "fra": + entry.category = eModeMenuModeCategory.FFA + break + case "lts": + case "ttdm": + case "attdm": + case "turbo_ttdm": + case "alts": + case "turbo_lts": + entry.category = eModeMenuModeCategory.TITAN + break + case "coliseum": + case "sp_coop": + entry.category = eModeMenuModeCategory.OTHER + break + case "chamber": + case "hidden": + case "sns": + case "fw": + case "gg": + case "tt": + case "inf": + case "kr": + case "fastball": + case "hs": + case "ctf_comp": + case "tffa": + entry.category = eModeMenuModeCategory.CUSTOM + break + } + + file.modes.append(entry) + } +} + +int function SortModesAlphabetize( string a, string b ) +{ + a = Localize( GetGameModeDisplayName( a ) ) + b = Localize( GetGameModeDisplayName( b ) ) + + if ( a > b ) + return 1 + + if ( a < b ) + return -1 + + return 0 +} + +void function BuildSortedModesArray() +{ + file.sortedModes.clear() + + // Build sorted list of categories + array categories + for( int i = 0; i < eModeMenuModeCategory.SIZE; i++ ) + { + if( file.searchEnum != -1 && file.searchEnum != i ) + continue + + categories.append( GetCategoryStringFromEnum( i ) ) + } + + categories.sort( SortStringAlphabetize ) + + // Build final list of mixed modes and categories + foreach( string category in categories ) + { + // Build sorted list of modes in category + array modes + foreach( ListEntry_t entry in file.modes ) + { + int iCategory = entry.category + if( entry.mode in file.categoryOverrides ) + iCategory = file.categoryOverrides[entry.mode] + + if( GetCategoryStringFromEnum( iCategory ) != category ) + continue + + string mode = entry.mode + + if( file.searchString != "" && Localize(GetGameModeDisplayName(mode)).tolower().find(file.searchString.tolower()) == null ) + continue + + if( !modes.contains(mode) ) + modes.append( mode ) + } + + modes.sort( SortModesAlphabetize ) + + if( modes.len() == 0 ) + continue + + // Add to final list we then display + file.sortedModes.append( category ) + foreach( string mode in modes ) + file.sortedModes.append( mode ) + } +} + +//////////////////////////// +// Slider +//////////////////////////// +void function UpdateMouseDeltaBuffer( int x, int y ) +{ + mouseDeltaBuffer.deltaX += x + mouseDeltaBuffer.deltaY += y + + SliderBarUpdate() +} + +void function FlushMouseDeltaBuffer() +{ + mouseDeltaBuffer.deltaX = 0 + mouseDeltaBuffer.deltaY = 0 +} + + +void function SliderBarUpdate() +{ + if( file.sortedModes.len() < MODES_PER_PAGE ) + return + + var sliderButton = Hud_GetChild( file.menu , "BtnModeListSlider" ) + var sliderPanel = Hud_GetChild( file.menu , "BtnModeListSliderPanel" ) + var movementCapture = Hud_GetChild( file.menu , "MouseMovementCapture" ) + + Hud_SetFocused( sliderButton ) + + int[2] screenSize = GetScreenSize() + float minYPos = -40.0 * ( screenSize[1] / 1080.0 ) + float maxHeight = 596.0 * ( screenSize[1] / 1080.0 ) + float maxYPos = minYPos - ( maxHeight - Hud_GetHeight( sliderPanel ) ) + float useableSpace = maxHeight - Hud_GetHeight( sliderPanel ) + + float jump = minYPos - ( useableSpace / ( float( file.sortedModes.len() ) ) ) + + // got local from official respaw scripts, without untyped throws an error + local pos = Hud_GetPos( sliderButton )[1] + local newPos = pos - mouseDeltaBuffer.deltaY + FlushMouseDeltaBuffer() + + if ( newPos < maxYPos ) newPos = maxYPos + if ( newPos > minYPos ) newPos = minYPos + + Hud_SetPos( sliderButton , 2, newPos ) + Hud_SetPos( sliderPanel , 2, newPos ) + Hud_SetPos( movementCapture , 2, newPos ) + + file.scrollOffset = -int( ( ( newPos - minYPos ) / useableSpace ) * ( file.sortedModes.len() - MODES_PER_PAGE ) ) + UpdateVisibleModes() +} + +void function UpdateListSliderHeight( float modes ) +{ + var sliderButton = Hud_GetChild( file.menu , "BtnModeListSlider" ) + var sliderPanel = Hud_GetChild( file.menu , "BtnModeListSliderPanel" ) + var movementCapture = Hud_GetChild( file.menu , "MouseMovementCapture" ) + + int[2] screenSize = GetScreenSize() + float maxHeight = 596.0 * ( screenSize[1] / 1080.0 ) + float minHeight = 80.0 * ( screenSize[1] / 1080.0 ) + + float height = maxHeight * ( MODES_PER_PAGE / modes ) + + if ( height > maxHeight ) height = maxHeight + if ( height < minHeight ) height = minHeight + + Hud_SetHeight( sliderButton, height ) + Hud_SetHeight( sliderPanel, height ) + Hud_SetHeight( movementCapture, height ) +} + + +void function UpdateListSliderPosition( int modes ) +{ + if( modes < MODES_PER_PAGE ) + return + + var sliderButton = Hud_GetChild( file.menu, "BtnModeListSlider" ) + var sliderPanel = Hud_GetChild( file.menu, "BtnModeListSliderPanel" ) + var movementCapture = Hud_GetChild( file.menu, "MouseMovementCapture" ) + + float minYPos = -40.0 * ( GetScreenSize()[1] / 1080.0 ) + float useableSpace = (596.0 * ( GetScreenSize()[1] / 1080.0 ) - Hud_GetHeight( sliderPanel ) ) + + float jump = minYPos - ( useableSpace / ( float( modes ) - MODES_PER_PAGE ) * file.scrollOffset ) + + if ( jump > minYPos ) jump = minYPos + + Hud_SetPos( sliderButton, 2, jump ) + Hud_SetPos( sliderPanel, 2, jump ) + Hud_SetPos( movementCapture, 2, jump ) +} + +void function OnScrollDown( var button ) +{ + if (file.sortedModes.len() <= MODES_PER_PAGE) return + file.scrollOffset += 5 + if (file.scrollOffset + MODES_PER_PAGE > file.sortedModes.len()) { + file.scrollOffset = file.sortedModes.len() - MODES_PER_PAGE + } + UpdateVisibleModes() + UpdateListSliderPosition( file.sortedModes.len() ) +} + +void function OnScrollUp( var button ) +{ + file.scrollOffset -= 5 + if ( file.scrollOffset < 0 ) { + file.scrollOffset = 0 + } + UpdateVisibleModes() + UpdateListSliderPosition( file.sortedModes.len() ) +} + +void function OnDownArrowSelected( var button ) +{ + if ( file.sortedModes.len() <= MODES_PER_PAGE ) return + file.scrollOffset += 1 + if ( file.scrollOffset + MODES_PER_PAGE > file.sortedModes.len() ) + { + file.scrollOffset = file.sortedModes.len() - MODES_PER_PAGE + } + + UpdateVisibleModes() + UpdateListSliderPosition( file.sortedModes.len() ) +} + + +void function OnUpArrowSelected( var button ) +{ + file.scrollOffset -= 1 + if ( file.scrollOffset < 0 ) + { + file.scrollOffset = 0 + } + + UpdateVisibleModes() + UpdateListSliderPosition( file.sortedModes.len() ) +} + +bool function IsStringCategory( string str ) +{ + return GetGameModeDisplayName( str ) == "" +} + +///////////////////////////// +// LIST +///////////////////////////// + void function UpdateVisibleModes() -{ +{ // ensures that we only ever show enough buttons for the number of modes we have - array buttons = GetElementsByClassname( GetMenu( "ModesMenu" ), "ModeButton" ) - foreach ( var button in buttons ) + array buttons = GetElementsByClassname( GetMenu( "ModesMenu" ), "ModeSelectorPanel" ) + foreach ( var panel in buttons ) { - Hud_SetEnabled( button, false ) - Hud_SetVisible( button, false ) + Hud_SetEnabled( panel, false ) + Hud_SetVisible( panel, false ) + Hud_SetText( Hud_GetChild( panel, "Header" ), "" ) + Hud_SetText( Hud_GetChild( panel, "BtnMode" ), "" ) + SetButtonRuiText( Hud_GetChild( panel, "BtnMode" ), "" ) } - - array modesArray = GetPrivateMatchModes() + for ( int i = 0; i < MODES_PER_PAGE; i++ ) { - if ( i + ( file.currentModePage * MODES_PER_PAGE ) >= modesArray.len() ) + if ( i + file.scrollOffset >= file.sortedModes.len() ) break - - int modeIndex = i + ( file.currentModePage * MODES_PER_PAGE ) - SetButtonRuiText( buttons[ i ], GetGameModeDisplayName( modesArray[ modeIndex ] ) ) - - Hud_SetEnabled( buttons[ i ], true ) - Hud_SetVisible( buttons[ i ], true ) - - // This check is refactored in the new mode menu so we can just ignore this atrocity - if ( !ModeSettings_RequiresAI( modesArray[ modeIndex ] ) || modesArray[ modeIndex ] == "aitdm" || modesArray[ modeIndex ] == "at" ) - Hud_SetLocked( buttons[ i ], false ) + + // Setup locals + var panel = buttons[i] + var button = Hud_GetChild( panel, "BtnMode" ) + var header = Hud_GetChild( panel, "Header" ) + + int modeIndex = i + file.scrollOffset + string mode = file.sortedModes[ modeIndex ] + + bool bIsCategory = IsStringCategory( mode ) + mode = bIsCategory ? mode : GetGameModeDisplayName( mode ) + + // Show the panel + Hud_SetEnabled( panel, true ) + Hud_SetVisible( panel, true ) + Hud_SetLocked( button, false ) + + if( bIsCategory ) + { + Hud_SetText( header, mode ) + Hud_SetEnabled( button, false ) + } else - Hud_SetLocked( buttons[ i ], true ) + { + Hud_SetEnabled( button, true ) + SetButtonRuiText( button, mode ) + + if( blockedModes.contains( file.sortedModes[ modeIndex ] ) ) + Hud_SetLocked( button, true ) + + if ( !PrivateMatch_IsValidMapModeCombo( PrivateMatch_GetSelectedMap(), mode ) ) + { + Hud_SetLocked( button, true ) + SetButtonRuiText( button, mode ) + } + } } } void function ModeButton_GetFocus( var button ) { - int modeId = int( Hud_GetScriptID( button ) ) + ( file.currentModePage * MODES_PER_PAGE ) - - var menu = GetMenu( "ModesMenu" ) - var nextModeImage = Hud_GetChild( menu, "NextModeImage" ) - var nextModeIcon = Hud_GetChild( menu, "ModeIconImage" ) - var nextModeName = Hud_GetChild( menu, "NextModeName" ) - var nextModeDesc = Hud_GetChild( menu, "NextModeDesc" ) + int modeId = int( Hud_GetScriptID( Hud_GetParent( button ) ) ) + file.scrollOffset - 1 - array modesArray = GetPrivateMatchModes() + var nextModeImage = Hud_GetChild( file.menu, "NextModeImage" ) + var nextModeIcon = Hud_GetChild( file.menu, "ModeIconImage" ) + var nextModeName = Hud_GetChild( file.menu, "NextModeName" ) + var nextModeDesc = Hud_GetChild( file.menu, "NextModeDesc" ) - if ( modeId > modesArray.len() ) + if ( modeId > file.sortedModes.len() ) return - string modeName = modesArray[modeId] + string modeName = file.sortedModes[modeId] asset playlistImage = GetPlaylistImage( modeName ) RuiSetImage( Hud_GetRui( nextModeImage ), "basicImage", playlistImage ) @@ -99,35 +569,17 @@ void function ModeButton_Click( var button ) if ( Hud_IsLocked( button ) ) return - int modeID = int( Hud_GetScriptID( button ) ) + ( file.currentModePage * MODES_PER_PAGE ) + int modeID = int( Hud_GetScriptID( Hud_GetParent( button ) ) ) + file.scrollOffset - 1 - array modesArray = GetPrivateMatchModes() - string modeName = modesArray[ modeID ] + string modeName = file.sortedModes[ modeID ] // on modded servers set us to the first map for that mode automatically // need this for coliseum mainly which is literally impossible to select without this - if ( !PrivateMatch_IsValidMapModeCombo( PrivateMatch_GetSelectedMap(), modesArray[ modeID ] ) ) + if ( !PrivateMatch_IsValidMapModeCombo( PrivateMatch_GetSelectedMap(), modeName ) ) + { ClientCommand( "SetCustomMap " + GetPrivateMatchMapsForMode( modeName )[ 0 ] ) - + } // set it ClientCommand( "PrivateMatchSetMode " + modeName ) CloseActiveMenu() } - -void function CycleModesBack( var button ) -{ - if ( file.currentModePage == 0 ) - return - - file.currentModePage-- - UpdateVisibleModes() -} - -void function CycleModesForward( var button ) -{ - if ( ( file.currentModePage + 1 ) * MODES_PER_PAGE >= GetPrivateMatchModes().len() ) - return - - file.currentModePage++ - UpdateVisibleModes() -} \ No newline at end of file -- cgit v1.2.3