1- using System ;
2- using System . IO ;
1+ using System . IO ;
2+ using System . Linq ;
33using Microsoft . Xna . Framework . Graphics ;
44using ModReloader . UI . Elements . MainMenuElements ;
5+ using Terraria . GameContent ;
56using Terraria . GameContent . UI . Elements ;
67using Terraria . UI ;
78
89namespace ModReloader . Common . Systems . Hooks . MainMenu ;
910
1011internal sealed class MainMenuState : UIState
1112{
12- // Colors
13- private static readonly Color Normal = new ( 173 , 173 , 198 ) ;
14- private static readonly Color Hover = new ( 237 , 246 , 255 ) ;
15-
16- // Position
17- private float verticalSpacing = 23f ;
18- private float currentY = 15f ;
19-
2013 // Elements
14+ private UIList mainMenuList ;
2115 private TooltipPanel tooltipPanel ;
22- private UIText tooltipText ;
2316
24- #region constructor
2517 public MainMenuState ( )
2618 {
2719 // Null checks
2820 if ( Conf . C is null || ! Conf . C . ShowMainMenuInfo )
2921 return ;
3022
23+ // Set up UIList
24+ mainMenuList = new UIList
25+ {
26+ Width = { Pixels = 310f } ,
27+ Height = StyleDimension . Fill ,
28+ ListPadding = 0f ,
29+ Left = { Pixels = 15f } ,
30+ Top = { Pixels = 15f } ,
31+ ManualSortMethod = ( e ) => { }
32+ } ;
33+
3134 // Extra spacing if other big menu mods are loaded
3235 if ( ModLoader . HasMod ( "TerrariaOverhaul" ) || ModLoader . HasMod ( "Terramon" ) )
3336 {
34- currentY += 205f ;
35- verticalSpacing = 20f ; // tighter spacing to try to fit with terramon lol
37+ mainMenuList . Top . Pixels += 205f ;
3638 }
3739 if ( ModLoader . HasMod ( "CompatChecker" ) )
38- currentY += 30f ; // move everything down a bit to fit compat checker elements at the top
40+ mainMenuList . Top . Pixels += 30f ;
41+
42+ tooltipPanel = new TooltipPanel ( ) ;
3943
44+ // Add elements to the main menu list
45+ AddModReloaderSection ( tooltipPanel ) ;
46+ AddOptionsSection ( tooltipPanel ) ;
47+ AddSingleplayerSection ( tooltipPanel ) ;
48+ AddMultiplayerSection ( tooltipPanel ) ;
49+ AddWorldSection ( tooltipPanel ) ;
50+
51+ Append ( tooltipPanel ) ;
52+ Append ( mainMenuList ) ;
53+ }
54+
55+ private void AddModReloaderSection ( TooltipPanel tooltipPanel )
56+ {
4057 // Helpers
4158 string headerModName = $ "{ ModContent . GetInstance < ModReloader > ( ) . DisplayName } v{ ModContent . GetInstance < ModReloader > ( ) . Version } ";
4259 string reloadHoverMods = ReloadUtilities . IsModsToReloadEmpty ? "No mods selected" : string . Join ( "," , Conf . C . ModsToReload ) ;
4360
44- // Add Mod Reloader section
45- AddOption ( headerModName , tooltip : ( ) => Loc . Get ( "MainMenu.WelcomeTooltip" ) , isHeader : true ) ;
46- AddOption ( Loc . Get ( "MainMenu.OpenConfigText" ) , ( ) => Conf . C . Open ( ) , ( ) => Loc . Get ( "MainMenu.OpenConfigTooltip" ) ) ;
47- AddOption ( Loc . Get ( "MainMenu.ReloadText" ) , async ( ) => await ReloadUtilities . SinglePlayerReload ( ) , ( ) => Loc . Get ( "MainMenu.ReloadTooltip" , $ "[c/FFFF00:{ reloadHoverMods } ] ") ) ;
48- AddOption ( string . Empty ) ;
49-
50- // Add options section
51- AddOption ( Loc . Get ( "MainMenu.OptionsHeader" ) , ( ) => Loc . Get ( "MainMenu.OptionsTooltip" ) , isHeader : true ) ;
52- AddOption ( Loc . Get ( "MainMenu.StartServerText" ) , MainMenuActions . StartServer , ( ) => Loc . Get ( "MainMenu.StartServerTooltip" ) ) ;
53- AddOption ( Loc . Get ( "MainMenu.StartClientText" ) , MainMenuActions . StartClient , ( ) => Loc . Get ( "MainMenu.StartClientTooltip" ) ) ;
54- AddOption ( Loc . Get ( "MainMenu.OpenLogText" ) , Log . OpenClientLog , ( ) => Loc . Get ( "MainMenu.OpenLogTooltip" , $ "[c/FFFF00:{ Path . GetFileName ( Logging . LogPath ) } ]") ) ;
55- AddOption ( Loc . Get ( "MainMenu.ClearLogText" ) , Log . ClearClientLog , ( ) => Loc . Get ( "MainMenu.ClearLogTooltip" , $ "[c/FFFF00:{ Path . GetFileName ( Logging . LogPath ) } ]") ) ;
56- AddOption ( string . Empty ) ;
57-
58- // Add singleplayer section
61+ var headerElement = new HeaderMainMenuElement ( headerModName , ( ) => Loc . Get ( "MainMenu.WelcomeTooltip" ) , tooltipPanel ) ;
62+ var configElement = new ActionMainMenuElement (
63+ ( ) => Conf . C . Open ( ) ,
64+ Loc . Get ( "MainMenu.OpenConfigText" ) ,
65+ ( ) => Loc . Get ( "MainMenu.OpenConfigTooltip" ) ,
66+ tooltipPanel
67+ ) ;
68+ var reloadElement = new ActionMainMenuElement (
69+ async ( ) => await ReloadUtilities . SinglePlayerReload ( ) ,
70+ Loc . Get ( "MainMenu.ReloadText" ) ,
71+ ( ) => Loc . Get ( "MainMenu.ReloadTooltip" , $ "[c/FFFF00:{ reloadHoverMods } ]") ,
72+ tooltipPanel
73+ ) ;
74+ var spacer = new SpacerMainMenuElement ( ) ;
75+ mainMenuList . Add ( headerElement ) ;
76+ mainMenuList . Add ( configElement ) ;
77+ mainMenuList . Add ( reloadElement ) ;
78+ mainMenuList . Add ( spacer ) ;
79+ }
80+
81+ private void AddOptionsSection ( TooltipPanel tooltipPanel )
82+ {
83+ var optionsHeader = new HeaderMainMenuElement ( Loc . Get ( "MainMenu.OptionsHeader" ) , ( ) => Loc . Get ( "MainMenu.OptionsTooltip" ) , tooltipPanel ) ;
84+ var startServerElement = new ActionMainMenuElement (
85+ MainMenuActions . StartServer ,
86+ Loc . Get ( "MainMenu.StartServerText" ) ,
87+ ( ) => Loc . Get ( "MainMenu.StartServerTooltip" ) ,
88+ tooltipPanel
89+ ) ;
90+ var startClientElement = new ActionMainMenuElement (
91+ MainMenuActions . StartClient ,
92+ Loc . Get ( "MainMenu.StartClientText" ) ,
93+ ( ) => Loc . Get ( "MainMenu.StartClientTooltip" ) ,
94+ tooltipPanel
95+ ) ;
96+ var openLogElement = new ActionMainMenuElement (
97+ Log . OpenClientLog ,
98+ Loc . Get ( "MainMenu.OpenLogText" ) ,
99+ ( ) => Loc . Get ( "MainMenu.OpenLogTooltip" , $ "[c/FFFF00:{ Path . GetFileName ( Logging . LogPath ) } ]") ,
100+ tooltipPanel
101+ ) ;
102+ var clearLogElement = new ActionMainMenuElement (
103+ Log . ClearClientLog ,
104+ Loc . Get ( "MainMenu.ClearLogText" ) ,
105+ ( ) => Loc . Get ( "MainMenu.ClearLogTooltip" , $ "[c/FFFF00:{ Path . GetFileName ( Logging . LogPath ) } ]") ,
106+ tooltipPanel
107+ ) ;
108+ var spacer = new SpacerMainMenuElement ( ) ;
109+ mainMenuList . Add ( optionsHeader ) ;
110+ mainMenuList . Add ( startServerElement ) ;
111+ mainMenuList . Add ( startClientElement ) ;
112+ mainMenuList . Add ( openLogElement ) ;
113+ mainMenuList . Add ( clearLogElement ) ;
114+ mainMenuList . Add ( spacer ) ;
115+ }
116+
117+ private void AddSingleplayerSection ( TooltipPanel tooltipPanel )
118+ {
59119 // Load players and worlds for tooltips
60120 Main . LoadPlayers ( ) ;
61121 int playerIdx = Conf . C . Player ;
@@ -66,109 +126,119 @@ public MainMenuState()
66126 int worldIdx = Conf . C . World ;
67127 if ( worldIdx < 0 || worldIdx >= Main . WorldList . Count ) worldIdx = 0 ;
68128 string worldName = Main . WorldList . Count > 0 ? Main . WorldList [ worldIdx ] . Name : "" ;
129+ Log . Info ( "Loaded and found this many worlds in main menu: " + Main . WorldList . Count ) ;
69130
70- // Add singleplayer section
71- AddOption ( Loc . Get ( "MainMenu.SingleplayerHeader" ) , tooltip : ( ) => Loc . Get ( "MainMenu.SingleplayerTooltip" ) , isHeader : true ) ;
72- AddOption (
73- Loc . Get ( "MainMenu.JoinSingleplayerText" ) ,
131+ var singleplayerHeader = new HeaderMainMenuElement ( Loc . Get ( "MainMenu.SingleplayerHeader" ) , ( ) => Loc . Get ( "MainMenu.SingleplayerTooltip" ) , tooltipPanel ) ;
132+ var joinSingleplayer = new ActionMainMenuElement (
74133 ( ) =>
75134 {
76135 ClientDataJsonHelper . ClientMode = ClientMode . SinglePlayer ;
77136 ClientDataJsonHelper . PlayerPath = null ;
78137 ClientDataJsonHelper . WorldPath = null ;
79138 AutoloadPlayerInWorldSystem . EnterSingleplayerWorld ( ) ;
80139 } ,
140+ Loc . Get ( "MainMenu.JoinSingleplayerText" ) ,
81141 ( ) =>
82142 {
83143 if ( string . IsNullOrEmpty ( playerName ) || string . IsNullOrEmpty ( worldName ) )
84144 return Loc . Get ( "MainMenu.JoinSingleplayerTooltipNoData" ) ;
85145 return Loc . Get ( "MainMenu.JoinSingleplayerTooltip" , $ "[c/FFFF00:{ playerName } ]", $ "[c/FFFF00:{ worldName } ]") ;
86- }
146+ } ,
147+ tooltipPanel
87148 ) ;
88- AddOption ( string . Empty ) ;
149+ var spacer = new SpacerMainMenuElement ( ) ;
150+ mainMenuList . Add ( singleplayerHeader ) ;
151+ mainMenuList . Add ( joinSingleplayer ) ;
152+ mainMenuList . Add ( spacer ) ;
153+ }
89154
90- // Add multiplayer section
91- AddOption ( Loc . Get ( "MainMenu.MultiplayerHeader" ) , tooltip : ( ) => Loc . Get ( "MainMenu.MultiplayerTooltip" ) , isHeader : true ) ;
92- AddOption ( Loc . Get ( "MainMenu.HostMultiplayerText" ) , AutoloadPlayerInWorldSystem . HostMultiplayerWorld , ( ) => Loc . Get ( "MainMenu.HostMultiplayerTooltip" ) ) ;
93- AddOption ( Loc . Get ( "MainMenu.JoinMultiplayerText" ) , AutoloadPlayerInWorldSystem . EnterMultiplayerWorld , ( ) => Loc . Get ( "MainMenu.JoinMultiplayerTooltip" ) ) ;
94- AddOption ( string . Empty ) ;
155+ private void AddMultiplayerSection ( TooltipPanel tooltipPanel )
156+ {
157+ var multiplayerHeader = new HeaderMainMenuElement ( Loc . Get ( "MainMenu.MultiplayerHeader" ) , ( ) => Loc . Get ( "MainMenu.MultiplayerTooltip" ) , tooltipPanel ) ;
158+ var hostMultiplayer = new ActionMainMenuElement (
159+ AutoloadPlayerInWorldSystem . HostMultiplayerWorld ,
160+ Loc . Get ( "MainMenu.HostMultiplayerText" ) ,
161+ ( ) => Loc . Get ( "MainMenu.HostMultiplayerTooltip" ) ,
162+ tooltipPanel
163+ ) ;
164+ var joinMultiplayer = new ActionMainMenuElement (
165+ AutoloadPlayerInWorldSystem . EnterMultiplayerWorld ,
166+ Loc . Get ( "MainMenu.JoinMultiplayerText" ) ,
167+ ( ) => Loc . Get ( "MainMenu.JoinMultiplayerTooltip" ) ,
168+ tooltipPanel
169+ ) ;
170+ var spacer = new SpacerMainMenuElement ( ) ;
171+ mainMenuList . Add ( multiplayerHeader ) ;
172+ mainMenuList . Add ( hostMultiplayer ) ;
173+ mainMenuList . Add ( joinMultiplayer ) ;
174+ mainMenuList . Add ( spacer ) ;
175+ }
95176
96- // Add world section
97- AddOption ( Loc . Get ( "MainMenu.WorldHeader" ) , tooltip : ( ) => Loc . Get ( "MainMenu.WorldTooltip" ) , isHeader : true ) ;
98- AddOption (
99- Loc . Get ( "MainMenu.CreateNewWorld" ) ,
177+ private void AddWorldSection ( TooltipPanel tooltipPanel )
178+ {
179+ var worldHeader = new HeaderMainMenuElement ( Loc . Get ( "MainMenu.WorldHeader" ) , ( ) => Loc . Get ( "MainMenu.WorldTooltip" ) , tooltipPanel ) ;
180+ var createNewWorld = new ActionMainMenuElement (
100181 ( ) => MainMenuActions . CreateNewWorld ( MainMenuActions . GetNextAvailableTestWorldName ( ) ) ,
101- ( ) => Loc . Get (
102- "MainMenu.CreateNewWorldTooltip" ,
182+ Loc . Get ( "MainMenu.CreateNewWorld" ) ,
183+ ( ) => Loc . Get ( "MainMenu.CreateNewWorldTooltip" ,
103184 $ "[c/FFFF00:{ MainMenuActions . GetNextAvailableTestWorldName ( ) } ]",
104185 $ "[c/FFFF00:{ Conf . C . CreateTestWorldSize } ]",
105186 $ "[c/FFFF00:{ Conf . C . CreateTestWorldDifficulty } ]"
106- )
187+ ) ,
188+ tooltipPanel
107189 ) ;
190+ var spacer = new SpacerMainMenuElement ( ) ;
191+ mainMenuList . Add ( worldHeader ) ;
192+ mainMenuList . Add ( createNewWorld ) ;
193+ mainMenuList . Add ( spacer ) ;
194+ }
108195
109- // Add tooltip panel
110- tooltipPanel = new ( ) ;
111- tooltipPanel . BorderColor = new Color ( 33 , 43 , 79 ) * 0.8f ;
112- tooltipPanel . BackgroundColor = new Color ( 73 , 94 , 171 ) ;
113- tooltipPanel . Left . Set ( 15 - 3 , 0f ) ; // -3 panel padding on each side is 6/2 = 3
114- tooltipPanel . Top . Set ( currentY + 10 , 0f ) ;
115- tooltipPanel . Width . Set ( 310f , 0f ) ;
116- tooltipPanel . Height . Set ( 68f , 0f ) ;
117-
118- // Add tooltip text
119- tooltipText = new UIText ( string . Empty , 0.9f ) ;
120- tooltipText . Left . Set ( 0f , 0f ) ;
121- tooltipText . TextOriginX = 0 ;
122- tooltipText . TextOriginY = 0 ;
123- tooltipPanel . Append ( tooltipText ) ;
124- Append ( tooltipPanel ) ;
196+ public override void Draw ( SpriteBatch spriteBatch )
197+ {
198+ base . Draw ( spriteBatch ) ;
199+
200+ //DrawActionRowsDebug(spriteBatch);
125201 }
126- #endregion
127-
128- /// <summary>
129- /// Helper method to add a menu option.
130- /// </summary>
131- private void AddOption ( string text ,
132- Action action = null ,
133- Func < string > tooltip = null ,
134- bool isHeader = false )
202+
203+ private void PositionTooltip ( )
135204 {
136- float size = isHeader ? 1.15f : 1f ;
137- var label = new UIText ( text , size )
138- {
139- TextColor = isHeader ? Hover : Normal
140- } ;
205+ tooltipPanel . Left . Set ( 15 + 3 , 0f ) ;
206+ tooltipPanel . Top . Set ( 470f , 0f ) ; // 6 px under the list
207+ tooltipPanel . Recalculate ( ) ;
208+ }
141209
142- label . Left . Set ( 15f , 0f ) ;
143- label . Top . Set ( currentY , 0f ) ;
144- currentY += verticalSpacing ;
210+ public override void Update ( GameTime gameTime )
211+ {
212+ base . Update ( gameTime ) ;
213+ PositionTooltip ( ) ;
214+ }
215+
216+ private void DrawActionRowsDebug ( SpriteBatch spriteBatch )
217+ {
218+ Texture2D pixel = TextureAssets . MagicPixel . Value ;
219+ Color debugColor = Color . Red * 0.3f ;
145220
146- label . OnMouseOver += ( _ , _ ) =>
221+ // the first child is the inner list
222+ foreach ( var inner in mainMenuList . Children )
147223 {
148- if ( ! isHeader )
149- label . TextColor = Hover ;
150- if ( tooltip != null )
224+ if ( inner is not UIElement ) continue ;
225+
226+ foreach ( var child in inner . Children )
151227 {
152- tooltipText . SetText ( tooltip ( ) ) ;
153- tooltipPanel . Hidden = false ;
228+ if ( child is ActionMainMenuElement )
229+ {
230+ CalculatedStyle d = child . GetOuterDimensions ( ) ;
231+ Rectangle rect = new (
232+ ( int ) d . X ,
233+ ( int ) d . Y ,
234+ ( int ) d . Width ,
235+ ( int ) d . Height ) ;
236+
237+ spriteBatch . Draw ( pixel , rect , debugColor ) ;
238+ }
154239 }
155- } ;
156- label . OnMouseOut += ( _ , _ ) =>
157- {
158- if ( ! isHeader )
159- label . TextColor = Normal ;
160- tooltipText . SetText ( string . Empty ) ;
161- tooltipPanel . Hidden = true ;
162- } ;
163-
164- if ( action != null )
165- label . OnLeftClick += ( _ , _ ) => action . Invoke ( ) ;
166-
167- Append ( label ) ;
240+ }
168241 }
169242
170- public override void Draw ( SpriteBatch sb )
171- {
172- base . Draw ( sb ) ;
173- }
243+
174244}
0 commit comments