├── .gitattributes
├── .gitignore
├── README.md
├── SimpleUI.sln
├── SimpleUI
├── Properties
│ └── AssemblyInfo.cs
├── SimpleUI.cs
├── SimpleUI.csproj
└── packages.config
├── SimpleUI_Example
├── Properties
│ └── AssemblyInfo.cs
├── SimpleUIExample.cs
├── SimpleUI_Example.csproj
└── packages.config
└── media
├── Menu Image (Zoomed).png
└── Menu Image.png
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | [Xx]64/
19 | [Xx]86/
20 | [Bb]uild/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opendb
80 | *.opensdf
81 | *.sdf
82 | *.cachefile
83 | *.VC.db
84 |
85 | # Visual Studio profiler
86 | *.psess
87 | *.vsp
88 | *.vspx
89 | *.sap
90 |
91 | # TFS 2012 Local Workspace
92 | $tf/
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 | *.DotSettings.user
101 |
102 | # JustCode is a .NET coding add-in
103 | .JustCode
104 |
105 | # TeamCity is a build add-in
106 | _TeamCity*
107 |
108 | # DotCover is a Code Coverage Tool
109 | *.dotCover
110 |
111 | # NCrunch
112 | _NCrunch_*
113 | .*crunch*.local.xml
114 | nCrunchTemp_*
115 |
116 | # MightyMoose
117 | *.mm.*
118 | AutoTest.Net/
119 |
120 | # Web workbench (sass)
121 | .sass-cache/
122 |
123 | # Installshield output folder
124 | [Ee]xpress/
125 |
126 | # DocProject is a documentation generator add-in
127 | DocProject/buildhelp/
128 | DocProject/Help/*.HxT
129 | DocProject/Help/*.HxC
130 | DocProject/Help/*.hhc
131 | DocProject/Help/*.hhk
132 | DocProject/Help/*.hhp
133 | DocProject/Help/Html2
134 | DocProject/Help/html
135 |
136 | # Click-Once directory
137 | publish/
138 |
139 | # Publish Web Output
140 | *.[Pp]ublish.xml
141 | *.azurePubxml
142 |
143 | # TODO: Un-comment the next line if you do not want to checkin
144 | # your web deploy settings because they may include unencrypted
145 | # passwords
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # NuGet Packages
150 | *.nupkg
151 | # The packages folder can be ignored because of Package Restore
152 | **/packages/*
153 | # except build/, which is used as an MSBuild target.
154 | !**/packages/build/
155 | # Uncomment if necessary however generally it will be regenerated when needed
156 | #!**/packages/repositories.config
157 | # NuGet v3's project.json files produces more ignoreable files
158 | *.nuget.props
159 | *.nuget.targets
160 |
161 | # Microsoft Azure Build Output
162 | csx/
163 | *.build.csdef
164 |
165 | # Microsoft Azure Emulator
166 | ecf/
167 | rcf/
168 |
169 | # Windows Store app package directory
170 | AppPackages/
171 | BundleArtifacts/
172 |
173 | # Visual Studio cache files
174 | # files ending in .cache can be ignored
175 | *.[Cc]ache
176 | # but keep track of directories ending in .cache
177 | !*.[Cc]ache/
178 |
179 | # Others
180 | ClientBin/
181 | [Ss]tyle[Cc]op.*
182 | ~$*
183 | *~
184 | *.dbmdl
185 | *.dbproj.schemaview
186 | *.pfx
187 | *.publishsettings
188 | node_modules/
189 | orleans.codegen.cs
190 |
191 | # RIA/Silverlight projects
192 | Generated_Code/
193 |
194 | # Backup & report files from converting an old project file
195 | # to a newer Visual Studio version. Backup files are not needed,
196 | # because we have git ;-)
197 | _UpgradeReport_Files/
198 | Backup*/
199 | UpgradeLog*.XML
200 | UpgradeLog*.htm
201 |
202 | # SQL Server files
203 | *.mdf
204 | *.ldf
205 |
206 | # Business Intelligence projects
207 | *.rdl.data
208 | *.bim.layout
209 | *.bim_*.settings
210 |
211 | # Microsoft Fakes
212 | FakesAssemblies/
213 |
214 | # GhostDoc plugin setting file
215 | *.GhostDoc.xml
216 |
217 | # Node.js Tools for Visual Studio
218 | .ntvs_analysis.dat
219 |
220 | # Visual Studio 6 build log
221 | *.plg
222 |
223 | # Visual Studio 6 workspace options file
224 | *.opt
225 |
226 | # Visual Studio LightSwitch build output
227 | **/*.HTMLClient/GeneratedArtifacts
228 | **/*.DesktopClient/GeneratedArtifacts
229 | **/*.DesktopClient/ModelManifest.xml
230 | **/*.Server/GeneratedArtifacts
231 | **/*.Server/ModelManifest.xml
232 | _Pvt_Extensions
233 |
234 | # LightSwitch generated files
235 | GeneratedArtifacts/
236 | ModelManifest.xml
237 |
238 | # Paket dependency manager
239 | .paket/paket.exe
240 |
241 | # FAKE - F# Make
242 | .fake/
243 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SimpleUI
2 | A Simple UI Menu for GTA V's .NET wrapper.
3 |
4 | 
5 |
6 | Download the menu base and example from [`/SimpleUI_Example`](https://github.com/LfxB/SimpleUI/tree/master/SimpleUI_Example).
7 |
--------------------------------------------------------------------------------
/SimpleUI.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 12.00
2 | # Visual Studio 14
3 | VisualStudioVersion = 14.0.25420.1
4 | MinimumVisualStudioVersion = 10.0.40219.1
5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleUI", "SimpleUI\SimpleUI.csproj", "{753BAE41-2693-4B87-8AFC-5D7DE84797E8}"
6 | EndProject
7 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleUI_Example", "SimpleUI_Example\SimpleUI_Example.csproj", "{A527F5B9-F6FE-4EBB-95F9-87C7DC87600A}"
8 | EndProject
9 | Global
10 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
11 | Debug|Any CPU = Debug|Any CPU
12 | Release|Any CPU = Release|Any CPU
13 | EndGlobalSection
14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
15 | {753BAE41-2693-4B87-8AFC-5D7DE84797E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
16 | {753BAE41-2693-4B87-8AFC-5D7DE84797E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
17 | {753BAE41-2693-4B87-8AFC-5D7DE84797E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
18 | {753BAE41-2693-4B87-8AFC-5D7DE84797E8}.Release|Any CPU.Build.0 = Release|Any CPU
19 | {A527F5B9-F6FE-4EBB-95F9-87C7DC87600A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
20 | {A527F5B9-F6FE-4EBB-95F9-87C7DC87600A}.Debug|Any CPU.Build.0 = Debug|Any CPU
21 | {A527F5B9-F6FE-4EBB-95F9-87C7DC87600A}.Release|Any CPU.ActiveCfg = Release|Any CPU
22 | {A527F5B9-F6FE-4EBB-95F9-87C7DC87600A}.Release|Any CPU.Build.0 = Release|Any CPU
23 | EndGlobalSection
24 | GlobalSection(SolutionProperties) = preSolution
25 | HideSolutionNode = FALSE
26 | EndGlobalSection
27 | EndGlobal
28 |
--------------------------------------------------------------------------------
/SimpleUI/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("SimpleUI")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("SimpleUI")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("753bae41-2693-4b87-8afc-5d7de84797e8")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/SimpleUI/SimpleUI.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Text.RegularExpressions;
7 | using System.Windows.Forms;
8 | using System.Drawing;
9 | using GTA;
10 | using GTA.Native;
11 | using Control = GTA.Control;
12 |
13 | namespace SimpleUI
14 | {
15 |
16 | public enum Font
17 | {
18 | ChaletLondon,
19 | HouseScript,
20 | Monospace,
21 | ChaletComprimeCologne = 4,
22 | Pricedown = 7,
23 | }
24 |
25 | public class SimpleScreen
26 | {
27 | ///
28 | /// Gets the ScreenResolution.
29 | ///
30 | public static Size ScreenResolution
31 | {
32 | get
33 | {
34 | int w, h;
35 | unsafe { Function.Call(Hash.GET_SCREEN_RESOLUTION, &w, &h); }
36 | return new Size(w, h);
37 | }
38 | }
39 | }
40 |
41 | public class MenuPool
42 | {
43 | List _menuList = new List();
44 | public UIMenu LastUsedMenu { get; set; }
45 |
46 | ///
47 | /// Called when main menu is closed.
48 | ///
49 | public event MainMenuEnterEvent OnMainMenuEnter;
50 |
51 | ///
52 | /// Called when main menu is closed.
53 | ///
54 | public event MainMenuQuitEvent OnMainMenuQuit;
55 |
56 | public delegate void MainMenuEnterEvent();
57 | public delegate void MainMenuQuitEvent();
58 |
59 | protected virtual void MainMenuEnter()
60 | {
61 | OnMainMenuEnter?.Invoke();
62 | //GTA.UI.Notification.Show("MainMenuEnter", true);
63 | }
64 |
65 | protected virtual void MainMenuQuit()
66 | {
67 | OnMainMenuQuit?.Invoke();
68 | //GTA.UI.Notification.Show("MainMenuQuit", true);
69 | }
70 |
71 | public void UnsubscribeAll_OnMenuEnter()
72 | {
73 | OnMainMenuEnter = null;
74 | }
75 |
76 | public void UnsubscribeAll_OnMenuQuit()
77 | {
78 | OnMainMenuQuit = null;
79 | }
80 |
81 |
82 |
83 | ///
84 | /// Disable this before editing the menu so that the pool will stop iterating over the menus and not crash.
85 | ///
86 | private static bool AllowMenuDraw = true;
87 |
88 | ///
89 | /// Additional text displayed on the right side of a Submenu's parent item.
90 | /// Default is " ~r~>" (with two spaces in front)
91 | /// Colour codes: https://pastebin.com/nqNYWMSB
92 | ///
93 | public string SubmenuItemIndication = " ~r~>";
94 |
95 | public List UIMenuList
96 | {
97 | get { return _menuList; }
98 | set { _menuList = value; }
99 | }
100 |
101 | public void AddMenu(UIMenu menu)
102 | {
103 | _menuList.Add(menu);
104 | if (_menuList.Count == 1) { LastUsedMenu = menu; }
105 | }
106 |
107 | ///
108 | /// Adds a submenu to a parent menu and to the MenuPool. Returns UIMenuItem that links the parent menu to the submenu.
109 | /// will be added to the end of the item text.
110 | ///
111 | /// The submenu
112 | /// The parent menu.
113 | /// The text of the menu item in the parent menu that leads to the submenu when entered.
114 | public void AddSubMenu(UIMenu SubMenu, UIMenu ParentMenu, string text, bool UseSameColorsAsParent = true)
115 | {
116 | AddMenu(SubMenu);
117 | /*SubMenu.ParentMenu = ParentMenu;
118 | ParentMenu.NextMenu = SubMenu;*/
119 | var item = new UIMenuItem(text + SubmenuItemIndication); //colour codes: https://pastebin.com/nqNYWMSB
120 | //ParentMenu.BindingMenuItem = BindingItem;
121 | ParentMenu.AddMenuItem(item);
122 | //ParentMenu.BindingMenuItem = item;
123 | ParentMenu.BindItemToSubmenu(SubMenu, item);
124 |
125 | if (UseSameColorsAsParent)
126 | {
127 | ApplyColorScheme(SubMenu, ParentMenu);
128 | }
129 | }
130 |
131 | ///
132 | /// Adds a submenu to a parent menu and to the MenuPool. Returns UIMenuItem that links the parent menu to the submenu.
133 | /// will be added to the end of the item text.
134 | ///
135 | /// The submenu
136 | /// The parent menu.
137 | /// The text of the menu item in the parent menu that leads to the submenu when entered.
138 | /// The description of the menu item that leads to the submenu when entered.
139 | public void AddSubMenu(UIMenu SubMenu, UIMenu ParentMenu, string text, string description, bool UseSameColorsAsParent = true)
140 | {
141 | AddMenu(SubMenu);
142 | //SubMenu.ParentMenu = ParentMenu;
143 | //ParentMenu.NextMenu = SubMenu;
144 | var item = new UIMenuItem(text + SubmenuItemIndication, null, description);
145 | //ParentMenu.BindingMenuItem = BindingItem;
146 | ParentMenu.AddMenuItem(item);
147 | //ParentMenu.BindingMenuItem = item;
148 | ParentMenu.BindItemToSubmenu(SubMenu, item);
149 |
150 | if (UseSameColorsAsParent)
151 | {
152 | ApplyColorScheme(SubMenu, ParentMenu);
153 | }
154 | }
155 |
156 | ///
157 | /// Applies the color scheme of the baseMenu to the targetMenu.
158 | ///
159 | /// The UIMenu you would like to modify.
160 | /// The UIMenu that has the color scheme you would like to copy.
161 | public void ApplyColorScheme(UIMenu targetMenu, UIMenu baseMenu)
162 | {
163 | targetMenu.TitleColor = baseMenu.TitleColor;
164 | targetMenu.TitleUnderlineColor = baseMenu.TitleUnderlineColor;
165 | targetMenu.TitleBackgroundColor = baseMenu.TitleBackgroundColor;
166 |
167 | targetMenu.DefaultTextColor = baseMenu.DefaultTextColor;
168 | targetMenu.DefaultBoxColor = baseMenu.DefaultBoxColor;
169 | targetMenu.HighlightedItemTextColor = baseMenu.HighlightedItemTextColor;
170 | targetMenu.HighlightedBoxColor = baseMenu.HighlightedBoxColor;
171 | targetMenu.SubsectionDefaultTextColor = baseMenu.SubsectionDefaultTextColor;
172 | targetMenu.SubsectionDefaultBoxColor = baseMenu.SubsectionDefaultBoxColor;
173 |
174 | targetMenu.DescriptionTextColor = baseMenu.DescriptionTextColor;
175 | targetMenu.DescriptionBoxColor = baseMenu.DescriptionBoxColor;
176 | }
177 |
178 | ///
179 | /// Draws all visible menus.
180 | ///
181 | public void Draw()
182 | {
183 | foreach (var menu in _menuList.Where(menu => menu.IsVisible).ToList())
184 | {
185 | menu.Draw();
186 | SetLastUsedMenu(menu);
187 | }
188 | }
189 |
190 | ///
191 | /// Set the last used menu.
192 | ///
193 | public void SetLastUsedMenu(UIMenu menu)
194 | {
195 | LastUsedMenu = menu;
196 | }
197 |
198 | ///
199 | /// Process all of your menus' functions. Call this in a tick event.
200 | ///
201 | public void ProcessMenus()
202 | {
203 | if (!AllowMenuDraw) return;
204 |
205 | if (LastUsedMenu == null)
206 | {
207 | LastUsedMenu = _menuList[0];
208 | }
209 | Draw();
210 | }
211 |
212 | ///
213 | /// Checks if any menu is currently visible.
214 | ///
215 | /// true if at least one menu is visible, false if not.
216 | public bool IsAnyMenuOpen()
217 | {
218 | return _menuList.Any(menu => menu.IsVisible);
219 | }
220 |
221 | public bool IsMenuDrawAllowed()
222 | {
223 | return AllowMenuDraw;
224 | }
225 |
226 | ///
227 | /// Closes all of your menus.
228 | ///
229 | public void CloseAllMenus()
230 | {
231 | foreach (var menu in _menuList.Where(menu => menu.IsVisible).ToList())
232 | {
233 | menu.IsVisible = false;
234 | }
235 |
236 | MainMenuQuit();
237 | }
238 |
239 | public void RemoveAllMenus()
240 | {
241 | _menuList.Clear();
242 | }
243 |
244 | public void OpenCloseLastMenu()
245 | {
246 | if (this.IsAnyMenuOpen())
247 | {
248 | this.CloseAllMenus();
249 | }
250 | else
251 | {
252 | this.LastUsedMenu.IsVisible = !this.LastUsedMenu.IsVisible;
253 | }
254 |
255 | if (this.LastUsedMenu.IsVisible)
256 | this.MainMenuEnter();
257 | }
258 | }
259 |
260 | public delegate void MenuOpenEvent(UIMenu sender);
261 | public delegate void MenuExitEvent(UIMenu sender);
262 | public delegate void ItemHighlightEvent(UIMenu sender, UIMenuItem selectedItem, int index);
263 | public delegate void ItemSelectEvent(UIMenu sender, UIMenuItem selectedItem, int index);
264 | public delegate void ItemLeftRightEvent(UIMenu sender, UIMenuItem selectedItem, int index, UIMenu.Direction direction);
265 |
266 | public class UIMenu
267 | {
268 | ///
269 | /// If this UIMenu object is not a submenu, ParentMenu returns null.
270 | ///
271 | public UIMenu ParentMenu { get; set; }
272 |
273 | ///
274 | /// Returns the UIMenuItem object within the ParentMenu that is binded to this menu when selected, assuming this menu is a submenu.
275 | ///
276 | public UIMenuItem ParentItem { get; set; }
277 |
278 | public UIMenuItem SelectedItem;
279 | protected List _itemList = new List();
280 | List _bindedList = new List();
281 | List _disabledItems = new List();
282 |
283 | public int SelectedIndex = 0;
284 |
285 | private bool _visible = false;
286 | public bool IsVisible
287 | {
288 | get { return _visible; }
289 | set
290 | {
291 | if (value && !_visible)
292 | {
293 | SaveIndexPositionFromOutOfBounds();
294 | MenuOpen();
295 | }
296 |
297 | if (!value && _visible)
298 | {
299 | MenuExit();
300 | }
301 |
302 | _visible = value;
303 | }
304 | }
305 |
306 | public string Title { get; set; }
307 |
308 | public bool UseEventBasedControls = true;
309 |
310 | ///
311 | /// Called when menu is opened.
312 | ///
313 | public event MenuOpenEvent OnMenuOpen;
314 |
315 | ///
316 | /// Called when menu is closed.
317 | ///
318 | public event MenuExitEvent OnMenuExit;
319 |
320 | ///
321 | /// Called while item is highlighted/hovered over.
322 | ///
323 | public event ItemHighlightEvent WhileItemHighlight;
324 |
325 | ///
326 | /// Called when user selects a simple item.
327 | ///
328 | public event ItemSelectEvent OnItemSelect;
329 |
330 | ///
331 | /// Called when user presses left or right over a simple item.
332 | ///
333 | public event ItemLeftRightEvent OnItemLeftRight;
334 |
335 | public int menuXPos = 38; //pixels from the top
336 | public int menuYPos = 38; //pixels from the left
337 | public int boxWidth = 500; //width in pixels
338 | public int boxScrollWidth = 4; //width in pixels
339 | public int boxTitleHeight = 76; //height in pixels
340 | public int boxUnderlineHeight = 1; //height in pixels
341 | public int boxHeight = 38; //height in pixels
342 |
343 | /*Title Formatting*/
344 | public Color TitleColor = Color.FromArgb(255, 255, 255, 255);
345 | public Color TitleUnderlineColor = Color.FromArgb(140, 0, 255, 255);
346 | public Color TitleBackgroundColor = Color.FromArgb(144, 0, 0, 0);
347 |
348 | /*Title*/
349 | public float TitleFontSize;
350 | internal float yPosTitleBG;
351 | internal float yPosTitleText;
352 | internal float TitleBGHeight;
353 | internal float UnderlineHeight;
354 | internal float yPosUnderline;
355 |
356 | /*UIMenuItem Formatting*/
357 | public Color DefaultTextColor = Color.FromArgb(255, 255, 255, 255);
358 | public Color DefaultBoxColor = Color.FromArgb(144, 0, 0, 0);
359 | public Color HighlightedItemTextColor = Color.FromArgb(255, 0, 255, 255);
360 | public Color HighlightedBoxColor = Color.FromArgb(255, 0, 0, 0);
361 |
362 | public Color SubsectionDefaultTextColor = Color.FromArgb(180, 255, 255, 255);
363 | public Color SubsectionDefaultBoxColor = Color.FromArgb(144, 0, 0, 0);
364 |
365 | /*Rectangle box for UIMenuItem objects*/
366 | internal float xPosBG;
367 | internal float yPosItemBG;
368 | internal float MenuBGWidth;
369 | internal float heightItemBG;
370 | internal float posMultiplier;
371 |
372 | internal float ItemTextFontSize;
373 | internal Font ItemTextFontType;
374 | internal float xPosItemText;
375 | internal float xPosRightEndOfMenu;
376 | internal float xPosItemValue;
377 | internal float yPosItem;
378 | internal float yTextOffset;
379 |
380 | protected float ScrollBarWidth;
381 | protected float xPosScrollBar;
382 |
383 | /*Description Formatting*/
384 | public Color DescriptionTextColor = Color.FromArgb(255, 0, 0, 0);
385 | public Color DescriptionBoxColor = Color.FromArgb(150, 0, 255, 255);
386 |
387 | /*Scroll or nah?*/
388 | bool UseScroll = true;
389 | internal int YPosBasedOnScroll;
390 | internal int YPosDescBasedOnScroll;
391 | float YPosSmoothScrollBar;
392 | protected int MaxItemsOnScreen = 15;
393 | protected int minItem = 0;
394 | protected int maxItem = 14; //must always be 1 less than MaxItemsOnScreen
395 |
396 | private string AUDIO_LIBRARY = "HUD_FRONTEND_DEFAULT_SOUNDSET";
397 |
398 | private string AUDIO_UPDOWN = "NAV_UP_DOWN";
399 | private string AUDIO_LEFTRIGHT = "NAV_LEFT_RIGHT";
400 | private string AUDIO_SELECT = "SELECT";
401 | private string AUDIO_BACK = "BACK";
402 |
403 | //protected event KeyEventHandler KeyUp;
404 | //bool AcceptPressed;
405 | //bool CancelPressed;
406 |
407 | public UIMenu(string title)
408 | {
409 | Title = title;
410 |
411 | TitleFontSize = 0.9f; //TitleFont = 1.1f; for no-value fit.
412 | ItemTextFontSize = 0.452f;
413 | ItemTextFontType = Font.ChaletComprimeCologne;
414 |
415 | CalculateMenuPositioning();
416 |
417 | //KeyUp += UIMenu_KeyUp;
418 | }
419 |
420 | /*private void UIMenu_KeyUp(object sender, KeyEventArgs e)
421 | {
422 | if (IsVisible)
423 | {
424 | if (e.KeyCode == Keys.NumPad5 || e.KeyCode == Keys.Enter)
425 | {
426 | AcceptPressed = true;
427 | GTA.UI.Notification.Show("HI");
428 | }
429 |
430 | if (e.KeyCode == Keys.NumPad0 || e.KeyCode == Keys.Back)
431 | {
432 | CancelPressed = true;
433 | }
434 | }
435 | }*/
436 |
437 | public virtual void CalculateMenuPositioning()
438 | {
439 | const float height = 1080f;
440 | float ratio = (float)SimpleScreen.ScreenResolution.Width / SimpleScreen.ScreenResolution.Height;
441 | var width = height * ratio;
442 |
443 | TitleBGHeight = boxTitleHeight / height; //0.046f
444 | yPosTitleBG = ((menuYPos) / height) + TitleBGHeight * 0.5f;
445 | MenuBGWidth = boxWidth / width; //MenuBGWidth = 0.24f; for no-value fit.
446 | xPosBG = (menuXPos / width) + MenuBGWidth * 0.5f; //xPosBG = 0.13f; for no-value fit.
447 | xPosItemText = ((menuXPos + 10) / width);
448 | heightItemBG = boxHeight / height;
449 | UnderlineHeight = boxUnderlineHeight / height; //0.002f;
450 | posMultiplier = boxHeight / height;
451 | yTextOffset = 0.015f; //offset between text pos and box pos. yPosItemBG - yTextOffset
452 | ScrollBarWidth = boxScrollWidth / width;
453 |
454 | yPosTitleText = yPosTitleBG - (TitleFontSize / 35f);
455 | yPosUnderline = yPosTitleBG + (TitleBGHeight / 2) + (UnderlineHeight / 2);
456 | yPosItemBG = yPosUnderline + (UnderlineHeight / 2) + (heightItemBG / 2); //0.0655f;
457 | yPosItem = yPosItemBG - (ItemTextFontSize / 30.13f);
458 | //xPosItemText = xPosBG - (MenuBGWidth / 2) + 0.0055f;
459 | xPosRightEndOfMenu = xPosBG + MenuBGWidth / 2; //will Right Justify
460 | xPosScrollBar = xPosRightEndOfMenu - (ScrollBarWidth / 2);
461 | xPosItemValue = xPosScrollBar - (ScrollBarWidth / 2);
462 | YPosSmoothScrollBar = yPosItemBG; //sets starting scroll bar Y pos. Will be manipulated for smooth scrolling later.
463 | }
464 |
465 | public void MaxItemsInMenu(int number)
466 | {
467 | MaxItemsOnScreen = number;
468 | maxItem = number - 1;
469 | }
470 |
471 | public void ResetIndexPosition()
472 | {
473 | SelectedIndex = 0;
474 | minItem = 0;
475 | MaxItemsInMenu(MaxItemsOnScreen);
476 | }
477 |
478 | public void SaveIndexPositionFromOutOfBounds()
479 | {
480 | SetIndexPosition(SelectedIndex >= _itemList.Count ? _itemList.Count - 1 : SelectedIndex);
481 | }
482 |
483 | public void SetIndexPosition(int indexPosition)
484 | {
485 | if (indexPosition >= _itemList.Count) return;
486 |
487 | SelectedIndex = indexPosition;
488 |
489 | if (SelectedIndex < MaxItemsOnScreen)
490 | {
491 | minItem = 0;
492 | maxItem = MaxItemsOnScreen - 1;
493 | }
494 | else
495 | {
496 | maxItem = SelectedIndex;
497 | minItem = SelectedIndex - (MaxItemsOnScreen - 1);
498 | }
499 | }
500 |
501 | public void AddMenuItem(UIMenuItem item)
502 | {
503 | _itemList.Add(item);
504 | item.PersistentIndex = _itemList.IndexOf(item);
505 | }
506 |
507 | public void BindItemToSubmenu(UIMenu submenu, UIMenuItem itemToBindTo)
508 | {
509 | submenu.ParentMenu = this;
510 | submenu.ParentItem = itemToBindTo;
511 | itemToBindTo.SubmenuWithin = submenu;
512 | _bindedList.Add(new BindedItem { BindedSubmenu = submenu, BindedItemToSubmenu = itemToBindTo });
513 | }
514 |
515 | public List UIMenuItemList
516 | {
517 | get { return _itemList; }
518 | set { _itemList = value; }
519 | }
520 |
521 | public List BindedList
522 | {
523 | get { return _bindedList; }
524 | set { _bindedList = value; }
525 | }
526 |
527 | public List DisabledList
528 | {
529 | get { return _disabledItems; }
530 | set { _disabledItems = value; }
531 | }
532 |
533 | public virtual void Draw()
534 | {
535 | if (IsVisible)
536 | {
537 | /*GTA.UI.Notification.Show("selectedIndex: " + SelectedIndex
538 | + "\nminItem: " + minItem
539 | + "\nmaxItem: " + maxItem
540 | + "\nitemListCount: " + _itemList.Count
541 | , 1);*/
542 |
543 | DisplayMenu();
544 | DisableControls();
545 | DrawScrollBar();
546 | ManageCurrentIndex();
547 | /*if (SelectedItem is UIMenuListItem)
548 | {
549 | SelectedItem.ChangeListIndex();
550 | }*/
551 | //GTA.UI.Notification.Show("selectedIndex: " + SelectedIndex + ", minItem: " + minItem + ", maxItem: " + maxItem); //Debug
552 |
553 | if (/*BindingMenuItem != null && NextMenu != null*/ _bindedList.Count > 0)
554 | {
555 | if (JustPressedAccept() && /*BindingMenuItem == SelectedItem*/ _bindedList.Any(bind => bind.BindedItemToSubmenu == SelectedItem))
556 | {
557 | IsVisible = false;
558 |
559 | foreach (var bind in _bindedList.Where(bind => bind.BindedItemToSubmenu == SelectedItem))
560 | {
561 | bind.BindedSubmenu.IsVisible = true;
562 | //bind.BindedSubmenu.AcceptPressed = false;
563 | //bind.BindedSubmenu.InputTimer = DateTime.Now.AddMilliseconds(350);
564 | }
565 |
566 | if (UseEventBasedControls)
567 | {
568 | ItemSelect(SelectedItem, SelectedIndex);
569 | }
570 | UIInput.InputTimer = DateTime.Now.AddMilliseconds(350);
571 | }
572 | }
573 |
574 | if (JustPressedCancel())
575 | {
576 | GoBack(false);
577 |
578 | //CancelPressed = false;
579 | UIInput.InputTimer = DateTime.Now.AddMilliseconds(350);
580 | //return;
581 | }
582 |
583 | if (UseEventBasedControls)
584 | {
585 | if (JustPressedAccept())
586 | {
587 | ItemSelect(SelectedItem, SelectedIndex);
588 | UIInput.InputTimer = DateTime.Now.AddMilliseconds(UIInput.InputWait);
589 | //AcceptPressed = false;
590 | }
591 |
592 | if (JustPressedLeft())
593 | {
594 | ItemLeftRight(SelectedItem, SelectedIndex, Direction.Left);
595 | UIInput.InputTimer = DateTime.Now.AddMilliseconds(UIInput.InputWait);
596 | }
597 |
598 | if (JustPressedRight())
599 | {
600 | ItemLeftRight(SelectedItem, SelectedIndex, Direction.Right);
601 | UIInput.InputTimer = DateTime.Now.AddMilliseconds(UIInput.InputWait);
602 | }
603 |
604 | ItemHighlight(SelectedItem, SelectedIndex);
605 | }
606 | }
607 | }
608 |
609 |
610 | protected void DisplayMenu()
611 | {
612 | DrawCustomText(Title, TitleFontSize, Font.HouseScript, TitleColor.R, TitleColor.G, TitleColor.B, TitleColor.A, xPosBG, yPosTitleText, TextJustification.Center); //Draw title text
613 | DrawRectangle(xPosBG, yPosTitleBG, MenuBGWidth, TitleBGHeight, TitleBackgroundColor.R, TitleBackgroundColor.G, TitleBackgroundColor.B, TitleBackgroundColor.A); //Draw main rectangle
614 | DrawRectangle(xPosBG, yPosUnderline, MenuBGWidth, UnderlineHeight, TitleUnderlineColor.R, TitleUnderlineColor.G, TitleUnderlineColor.B, TitleUnderlineColor.A); //Draw rectangle as underline of title
615 |
616 | foreach (UIMenuItem item in _itemList)
617 | {
618 | bool ScrollOrNotDecision = (UseScroll && _itemList.IndexOf(item) >= minItem && _itemList.IndexOf(item) <= maxItem) || !UseScroll;
619 | if (ScrollOrNotDecision)
620 | {
621 | YPosBasedOnScroll = UseScroll && _itemList.Count > MaxItemsOnScreen ? CalculatePosition(_itemList.IndexOf(item), minItem, maxItem, 0, MaxItemsOnScreen - 1) : _itemList.IndexOf(item);
622 | YPosDescBasedOnScroll = UseScroll && _itemList.Count > MaxItemsOnScreen ? MaxItemsOnScreen : _itemList.Count;
623 |
624 | item.Draw(this);
625 | }
626 | }
627 | }
628 |
629 | protected void DrawScrollBar()
630 | {
631 | if (UseScroll && _itemList.Count > MaxItemsOnScreen)
632 | {
633 | YPosSmoothScrollBar = CalculateSmoothPosition(YPosSmoothScrollBar, CalculateScroll(SelectedIndex, 0, _itemList.Count - 1, yPosItemBG, yPosItemBG + (MaxItemsOnScreen - 1) * posMultiplier), 0.0005f, yPosItemBG, yPosItemBG + (MaxItemsOnScreen - 1) * posMultiplier);
634 | DrawRectangle(xPosScrollBar, YPosSmoothScrollBar, ScrollBarWidth, heightItemBG, TitleUnderlineColor.R, TitleUnderlineColor.G, TitleUnderlineColor.B, TitleUnderlineColor.A);
635 |
636 | //DrawRectangle(xPosScrollBar, CalculateScroll(SelectedIndex, 0, _itemList.Count - 1, yPosItemBG, yPosItemBG + (MaxItemsOnScreen - 1) * posMultiplier), ScrollBarWidth, heightItemBG, TitleUnderlineColor.R, TitleUnderlineColor.G, TitleUnderlineColor.B, TitleUnderlineColor.A);
637 | }
638 | }
639 |
640 | int CalculatePosition(int input, int inputMin, int inputMax, int outputMin, int outputMax)
641 | {
642 | //http://stackoverflow.com/questions/22083199/method-for-calculating-a-value-relative-to-min-max-values
643 | //Making sure bounderies arent broken...
644 | if (input > inputMax)
645 | {
646 | input = inputMax;
647 | }
648 | if (input < inputMin)
649 | {
650 | input = inputMin;
651 | }
652 | //Return value in relation to min og max
653 |
654 | double position = (double)(input - inputMin) / (inputMax - inputMin);
655 |
656 | int relativeValue = (int)(position * (outputMax - outputMin)) + outputMin;
657 |
658 | return relativeValue;
659 | }
660 |
661 | float CalculateScroll(float input, float inputMin, float inputMax, float outputMin, float outputMax)
662 | {
663 | //http://stackoverflow.com/questions/22083199/method-for-calculating-a-value-relative-to-min-max-values
664 | //Making sure bounderies arent broken...
665 | if (input > inputMax)
666 | {
667 | input = inputMax;
668 | }
669 | if (input < inputMin)
670 | {
671 | input = inputMin;
672 | }
673 | //Return value in relation to min og max
674 |
675 | double position = (double)(input - inputMin) / (inputMax - inputMin);
676 |
677 | float relativeValue = (float)(position * (outputMax - outputMin)) + outputMin;
678 |
679 | return relativeValue;
680 | }
681 |
682 | float CalculateSmoothPosition(float currentPosition, float desiredPosition, float step, float min, float max)
683 | {
684 | if (currentPosition == desiredPosition) return currentPosition;
685 |
686 | if (currentPosition < desiredPosition)
687 | {
688 | //currentPosition += (desiredPosition - currentPosition) * 0.1f;
689 | currentPosition += (desiredPosition - currentPosition) * 5f * Game.LastFrameTime;
690 | if (currentPosition > max)
691 | {
692 | currentPosition = max;
693 | }
694 | return currentPosition;
695 | }
696 | else if (currentPosition > desiredPosition)
697 | {
698 | //currentPosition -= (currentPosition - desiredPosition) * 0.1f;
699 | currentPosition -= (currentPosition - desiredPosition) * 5f * Game.LastFrameTime;
700 | if (currentPosition < min)
701 | {
702 | currentPosition = min;
703 | }
704 | return currentPosition;
705 | }
706 | return currentPosition;
707 | }
708 |
709 | internal enum TextJustification
710 | {
711 | Center = 0,
712 | Left,
713 | Right //requires SET_TEXT_WRAP
714 | }
715 |
716 | internal void DrawCustomText(string Message, float FontSize, Font FontType, int Red, int Green, int Blue, int Alpha, float XPos, float YPos, TextJustification justifyType = TextJustification.Left, bool ForceTextWrap = false)
717 | {
718 | Function.Call(Hash.BEGIN_TEXT_COMMAND_DISPLAY_TEXT, "jamyfafi"); //Required
719 | Function.Call(Hash.SET_TEXT_SCALE, 1.0f, FontSize);
720 | Function.Call(Hash.SET_TEXT_FONT, (int)FontType);
721 | Function.Call(Hash.SET_TEXT_COLOUR, Red, Green, Blue, Alpha);
722 | //Function.Call(Hash.SET_TEXT_DROPSHADOW, 0, 0, 0, 0, 0);
723 | Function.Call(Hash.SET_TEXT_JUSTIFICATION, (int)justifyType);
724 | if (justifyType == TextJustification.Right || ForceTextWrap)
725 | {
726 | Function.Call(Hash.SET_TEXT_WRAP, xPosItemText, xPosItemValue);
727 | }
728 |
729 | //Function.Call(Hash._ADD_TEXT_COMPONENT_STRING, Message);
730 | StringHelper.AddLongString(Message);
731 |
732 | Function.Call(Hash.END_TEXT_COMMAND_DISPLAY_TEXT, XPos, YPos);
733 | }
734 |
735 | internal void DrawRectangle(float BgXpos, float BgYpos, float BgWidth, float BgHeight, int bgR, int bgG, int bgB, int bgA)
736 | {
737 | Function.Call(Hash.DRAW_RECT, BgXpos, BgYpos, BgWidth, BgHeight, bgR, bgG, bgB, bgA);
738 | }
739 |
740 | protected virtual void ManageCurrentIndex()
741 | {
742 | if (JustPressedUp())
743 | {
744 | MoveUp();
745 | }
746 |
747 | if (JustPressedDown())
748 | {
749 | MoveDown();
750 | }
751 | }
752 |
753 | public void MoveUp()
754 | {
755 | if (SelectedIndex > 0 && SelectedIndex <= _itemList.Count - 1)
756 | {
757 | SelectedIndex--;
758 | if (SelectedIndex < minItem && minItem > 0)
759 | {
760 | minItem--;
761 | maxItem--;
762 | }
763 | }
764 | else if (SelectedIndex == 0)
765 | {
766 | SelectedIndex = _itemList.Count - 1;
767 | minItem = _itemList.Count - MaxItemsOnScreen;
768 | maxItem = _itemList.Count - 1;
769 | }
770 | else
771 | {
772 | SelectedIndex = _itemList.Count - 1;
773 | minItem = _itemList.Count - MaxItemsOnScreen;
774 | maxItem = _itemList.Count - 1;
775 | }
776 |
777 | if (IsHoldingSpeedupControl())
778 | {
779 | UIInput.InputTimer = DateTime.Now.AddMilliseconds(20);
780 | }
781 | else
782 | {
783 | UIInput.InputTimer = DateTime.Now.AddMilliseconds(UIInput.InputWait);
784 | }
785 | }
786 |
787 | public void MoveDown()
788 | {
789 | if (SelectedIndex >= 0 && SelectedIndex < _itemList.Count - 1)
790 | {
791 | SelectedIndex++;
792 | if (SelectedIndex >= maxItem + 1)
793 | {
794 | minItem++;
795 | maxItem++;
796 | }
797 | }
798 | else if (SelectedIndex == _itemList.Count - 1)
799 | {
800 | SelectedIndex = 0;
801 | minItem = 0;
802 | maxItem = MaxItemsOnScreen - 1;
803 | }
804 | else
805 | {
806 | SelectedIndex = 0;
807 | minItem = 0;
808 | maxItem = MaxItemsOnScreen - 1;
809 | }
810 |
811 | if (IsHoldingSpeedupControl())
812 | {
813 | UIInput.InputTimer = DateTime.Now.AddMilliseconds(20);
814 | }
815 | else
816 | {
817 | UIInput.InputTimer = DateTime.Now.AddMilliseconds(UIInput.InputWait);
818 | }
819 | }
820 |
821 | public void DisableItem(UIMenuItem itemToDisable)
822 | {
823 | if (_itemList.Contains(itemToDisable))
824 | {
825 | _disabledItems.Add(itemToDisable);
826 | _itemList.Remove(itemToDisable);
827 | SaveIndexPositionFromOutOfBounds();
828 | }
829 | }
830 |
831 | public void DisableAllItems()
832 | {
833 | _itemList.ForEach(i => _disabledItems.Add(i));
834 | _itemList.Clear();
835 | //SortMenuItemsByOriginalOrder();
836 | SaveIndexPositionFromOutOfBounds();
837 | }
838 |
839 | public void ReenableItem(UIMenuItem itemToEnable)
840 | {
841 | if (_disabledItems.Contains(itemToEnable))
842 | {
843 | //_itemList.Insert(itemToEnable.PersistentIndex, itemToEnable);
844 | _itemList.Add(itemToEnable);
845 | //SortMenuItemsByOriginalOrder();
846 | _disabledItems.Remove(itemToEnable);
847 | SaveIndexPositionFromOutOfBounds();
848 | }
849 | }
850 |
851 | public void ReenableAllItems()
852 | {
853 | _disabledItems.ForEach(d => _itemList.Add(d));
854 | //SortMenuItemsByOriginalOrder();
855 | _disabledItems.Clear();
856 | SaveIndexPositionFromOutOfBounds();
857 | }
858 |
859 | public void SetEnabledItem(UIMenuItem item, bool enable)
860 | {
861 | if (enable)
862 | {
863 | if (_disabledItems.Contains(item))
864 | ReenableItem(item);
865 | }
866 | else
867 | {
868 | if (_itemList.Contains(item))
869 | DisableItem(item);
870 | }
871 | }
872 |
873 | public void ResetOriginalOrder()
874 | {
875 | _itemList.ForEach(i => i.PersistentIndex = _itemList.IndexOf(i));
876 | }
877 |
878 | public void SortMenuItemsByOriginalOrder()
879 | {
880 | _itemList.Sort((x, y) => x.PersistentIndex.CompareTo(y.PersistentIndex));
881 | }
882 |
883 | List ControlsToEnable = new List
884 | {
885 | /*Control.FrontendAccept,
886 | Control.FrontendAxisX,
887 | Control.FrontendAxisY,
888 | Control.FrontendDown,
889 | Control.FrontendUp,
890 | Control.FrontendLeft,
891 | Control.FrontendRight,
892 | Control.FrontendCancel,
893 | Control.FrontendSelect,
894 | Control.CharacterWheel,
895 | Control.CursorScrollDown,
896 | Control.CursorScrollUp,
897 | Control.CursorX,
898 | Control.CursorY,*/
899 | Control.MoveUpDown,
900 | Control.MoveLeftRight,
901 | Control.Sprint,
902 | Control.Jump,
903 | Control.Enter,
904 | Control.VehicleExit,
905 | Control.VehicleAccelerate,
906 | Control.VehicleBrake,
907 | Control.VehicleMoveLeftRight,
908 | Control.VehicleFlyYawLeft,
909 | Control.FlyLeftRight,
910 | Control.FlyUpDown,
911 | Control.VehicleFlyYawRight,
912 | Control.VehicleHandbrake,
913 | /*Control.VehicleRadioWheel,
914 | Control.VehicleRoof,
915 | Control.VehicleHeadlight,
916 | Control.VehicleCinCam,
917 | Control.Phone,
918 | Control.MeleeAttack1,
919 | Control.MeleeAttack2,
920 | Control.Attack,
921 | Control.Attack2*/
922 | Control.LookUpDown,
923 | Control.LookLeftRight
924 | };
925 |
926 | protected void DisableControls()
927 | {
928 | Game.DisableAllControlsThisFrame();
929 |
930 | foreach (var con in ControlsToEnable)
931 | {
932 | Game.EnableControlThisFrame(con);
933 |
934 |
935 |
936 | }
937 | }
938 |
939 | bool IsGamepad()
940 | {
941 | return Game.LastInputMethod == InputMethod.GamePad;
942 | }
943 |
944 | internal bool IsHoldingUp()
945 | {
946 | return (IsGamepad() && Game.IsControlPressed(Control.PhoneUp)) || Game.IsKeyPressed(Keys.NumPad8) || Game.IsKeyPressed(Keys.Up);
947 | }
948 |
949 | public bool JustPressedUp()
950 | {
951 | if (IsHoldingUp())
952 | {
953 | if (UIInput.InputTimer < DateTime.Now)
954 | {
955 | Audio.ReleaseSound(Audio.PlaySoundFrontend(AUDIO_UPDOWN, AUDIO_LIBRARY));
956 | return true;
957 | }
958 | }
959 | return false;
960 | }
961 |
962 | bool IsHoldingDown()
963 | {
964 | return (IsGamepad() && Game.IsControlPressed(Control.PhoneDown)) || Game.IsKeyPressed(Keys.NumPad2) || Game.IsKeyPressed(Keys.Down);
965 | }
966 |
967 | public bool JustPressedDown()
968 | {
969 | if (IsHoldingDown())
970 | {
971 | if (UIInput.InputTimer < DateTime.Now)
972 | {
973 | Audio.ReleaseSound(Audio.PlaySoundFrontend(AUDIO_UPDOWN, AUDIO_LIBRARY));
974 | return true;
975 | }
976 | }
977 | return false;
978 | }
979 |
980 | public bool JustPressedLeft()
981 | {
982 | if ((IsGamepad() && Game.IsControlPressed(Control.PhoneLeft)) || Game.IsKeyPressed(Keys.NumPad4) || Game.IsKeyPressed(Keys.Left))
983 | {
984 | if (UIInput.InputTimer < DateTime.Now)
985 | {
986 | Audio.ReleaseSound(Audio.PlaySoundFrontend(AUDIO_UPDOWN, AUDIO_LIBRARY));
987 | return true;
988 | }
989 | }
990 | return false;
991 | }
992 |
993 | public bool JustPressedRight()
994 | {
995 | if ((IsGamepad() && Game.IsControlPressed(Control.PhoneRight)) || Game.IsKeyPressed(Keys.NumPad6) || Game.IsKeyPressed(Keys.Right))
996 | {
997 | if (UIInput.InputTimer < DateTime.Now)
998 | {
999 | Audio.ReleaseSound(Audio.PlaySoundFrontend(AUDIO_UPDOWN, AUDIO_LIBRARY));
1000 | return true;
1001 | }
1002 | }
1003 | return false;
1004 | }
1005 |
1006 | /*public bool JustPressedAccept()
1007 | {
1008 | if ((IsGamepad() && Game.IsControlJustPressed(2, Control.PhoneSelect)) || AcceptPressed)
1009 | {
1010 | Audio.ReleaseSound(Audio.PlaySoundFrontend(AUDIO_SELECT, AUDIO_LIBRARY);
1011 | //AcceptPressed = false;
1012 | return true;
1013 | }
1014 | return false;
1015 | }
1016 |
1017 | public bool JustPressedCancel()
1018 | {
1019 | if ((IsGamepad() && Game.IsControlJustPressed(2, Control.PhoneCancel)) || CancelPressed)
1020 | {
1021 | Audio.ReleaseSound(Audio.PlaySoundFrontend(AUDIO_BACK, AUDIO_LIBRARY);
1022 | //CancelPressed = false;
1023 | return true;
1024 | }
1025 | return false;
1026 | }*/
1027 |
1028 | public bool JustPressedAccept()
1029 | {
1030 | if (Game.IsControlPressed(Control.PhoneSelect) || Game.IsKeyPressed(Keys.NumPad5) || Game.IsKeyPressed(Keys.Enter))
1031 | {
1032 | if (UIInput.InputTimer < DateTime.Now)
1033 | {
1034 | Audio.ReleaseSound(Audio.PlaySoundFrontend(AUDIO_SELECT, AUDIO_LIBRARY));
1035 | //InputTimer = Game.GameTime + 350;
1036 | return true;
1037 | }
1038 | }
1039 | return false;
1040 | }
1041 |
1042 | public bool JustPressedCancel()
1043 | {
1044 | if (Game.IsControlPressed(Control.PhoneCancel) || Game.IsKeyPressed(Keys.NumPad0) || Game.IsKeyPressed(Keys.Back))
1045 | {
1046 | if (UIInput.InputTimer < DateTime.Now)
1047 | {
1048 | Audio.ReleaseSound(Audio.PlaySoundFrontend(AUDIO_BACK, AUDIO_LIBRARY));
1049 | //InputTimer = Game.GameTime + InputWait;
1050 | return true;
1051 | }
1052 | }
1053 | return false;
1054 | }
1055 |
1056 | public void GoBack(bool withSound)
1057 | {
1058 | IsVisible = false;
1059 |
1060 | if (ParentMenu != null)
1061 | {
1062 | ParentMenu.IsVisible = true;
1063 | }
1064 |
1065 | if (withSound)
1066 | Audio.ReleaseSound(Audio.PlaySoundFrontend(AUDIO_BACK, AUDIO_LIBRARY));
1067 | }
1068 |
1069 | bool IsHoldingSpeedupControl()
1070 | {
1071 | if (IsGamepad())
1072 | {
1073 | return Game.IsControlPressed(Control.VehicleHandbrake);
1074 | }
1075 | else
1076 | {
1077 | return Game.IsKeyPressed(Keys.ShiftKey);
1078 | }
1079 | }
1080 |
1081 | public void SetInputWait(int ms = 350)
1082 | {
1083 | UIInput.InputTimer = DateTime.Now.AddMilliseconds(ms);
1084 | }
1085 |
1086 | public enum Direction
1087 | {
1088 | None,
1089 | Left,
1090 | Right
1091 | }
1092 |
1093 | ///
1094 | /// Control a bool easily inside a event
1095 | ///
1096 | /// The bool to control
1097 | /// The item that controls this bool
1098 | public void ControlBoolValue(ref bool boolToControl, UIMenuItem controllingItem)
1099 | {
1100 | if (IsVisible && SelectedItem == controllingItem)
1101 | {
1102 | boolToControl = !boolToControl;
1103 | }
1104 | controllingItem.Value = boolToControl;
1105 | }
1106 |
1107 | public bool ControlBoolValue(bool boolToControl, UIMenuItem controllingItem)
1108 | {
1109 | ControlBoolValue(ref boolToControl, controllingItem);
1110 | return boolToControl;
1111 | }
1112 |
1113 | public bool ControlBoolValue_NoEvent(UIMenuItem item, bool boolToControl)
1114 | {
1115 | item.Value = boolToControl;
1116 |
1117 | if (IsVisible && SelectedItem == item)
1118 | {
1119 | if (JustPressedAccept())
1120 | {
1121 | boolToControl = !boolToControl;
1122 | item.Value = boolToControl;
1123 | UIInput.InputTimer = DateTime.Now.AddMilliseconds(UIInput.InputWait);
1124 | return boolToControl;
1125 | }
1126 | }
1127 | return boolToControl;
1128 | }
1129 |
1130 | ///
1131 | /// Control a float easily inside a event
1132 | ///
1133 | /// The float to control
1134 | /// The item that controls this float
1135 | /// The direction given by the event
1136 | /// How many units you want to add/subtract when left/right is pressed
1137 | /// Same as incrementValue, but when holding SHIFT or the R1/RB gamepad button
1138 | /// How many decimals to round to
1139 | /// Set whether you'd like to limit how high/low this float can go
1140 | ///
1141 | ///
1142 | public void ControlFloatValue(ref float numberToControl, UIMenuItem controllingItem, Direction direction, float incrementValue, float incrementValueFast, int decimals = 2, bool limit = false, float min = 0f, float max = 1f)
1143 | {
1144 | if (IsVisible && SelectedItem == controllingItem)
1145 | {
1146 | float temp = numberToControl;
1147 | if (direction == Direction.Left)
1148 | {
1149 | if (IsHoldingSpeedupControl())
1150 | {
1151 | temp -= incrementValueFast;
1152 | }
1153 | else
1154 | {
1155 | temp -= incrementValue;
1156 | }
1157 | }
1158 | else if (direction == Direction.Right)
1159 | {
1160 | if (IsHoldingSpeedupControl())
1161 | {
1162 | temp += incrementValueFast;
1163 | }
1164 | else
1165 | {
1166 | temp += incrementValue;
1167 | }
1168 | }
1169 | if (limit)
1170 | {
1171 | if (temp < min)
1172 | {
1173 | temp = min;
1174 | }
1175 | else if (temp > max)
1176 | {
1177 | temp = max;
1178 | }
1179 | }
1180 |
1181 | numberToControl = (float)Math.Round(temp, decimals);
1182 | }
1183 | controllingItem.Value = "< " + numberToControl + " >";
1184 | }
1185 |
1186 | public float ControlFloatValue(float numberToControl, UIMenuItem controllingItem, Direction direction, float incrementValue, float incrementValueFast, int decimals = 2, bool limit = false, float min = 0f, float max = 1f)
1187 | {
1188 | ControlFloatValue(ref numberToControl, controllingItem, direction, incrementValue, incrementValueFast, decimals, limit, min, max);
1189 | return numberToControl;
1190 | }
1191 |
1192 | public float ControlFloatValue_NoEvent(UIMenuItem item, float numberToControl, float incrementValue, float incrementValueFast, int decimals = 2, bool limit = false, float min = 0f, float max = 1f)
1193 | {
1194 | item.Value = "< " + numberToControl + " >";
1195 |
1196 | if (IsVisible && SelectedItem == item)
1197 | {
1198 | if (JustPressedLeft())
1199 | {
1200 | if (IsHoldingSpeedupControl())
1201 | {
1202 | numberToControl -= incrementValueFast;
1203 | }
1204 | else
1205 | {
1206 | numberToControl -= incrementValue;
1207 | }
1208 |
1209 | if (limit)
1210 | {
1211 | if (numberToControl < min)
1212 | {
1213 | numberToControl = min;
1214 | }
1215 | if (numberToControl > max)
1216 | {
1217 | numberToControl = max;
1218 | }
1219 | }
1220 |
1221 | item.Value = "< " + numberToControl + " >";
1222 |
1223 | UIInput.InputTimer = DateTime.Now.AddMilliseconds(UIInput.InputWait);
1224 |
1225 | return (float)Math.Round(numberToControl, decimals);
1226 | }
1227 | if (JustPressedRight())
1228 | {
1229 | if (IsHoldingSpeedupControl())
1230 | {
1231 | numberToControl += incrementValueFast;
1232 | }
1233 | else
1234 | {
1235 | numberToControl += incrementValue;
1236 | }
1237 |
1238 | if (limit)
1239 | {
1240 | if (numberToControl < min)
1241 | {
1242 | numberToControl = min;
1243 | }
1244 | if (numberToControl > max)
1245 | {
1246 | numberToControl = max;
1247 | }
1248 | }
1249 |
1250 | item.Value = "< " + numberToControl + " >";
1251 |
1252 | UIInput.InputTimer = DateTime.Now.AddMilliseconds(UIInput.InputWait);
1253 |
1254 | return (float)Math.Round(numberToControl, decimals);
1255 | }
1256 | }
1257 | return numberToControl;
1258 | }
1259 |
1260 | ///
1261 | /// Control an integer easily inside a event
1262 | ///
1263 | /// The int to control
1264 | /// The item that controls this int
1265 | /// The direction given by the event
1266 | /// How many units you want to add/subtract when left/right is pressed
1267 | /// Same as incrementValue, but when holding SHIFT or the R1/RB gamepad button
1268 | /// Set whether you'd like to limit how high/low this int can go
1269 | ///
1270 | ///
1271 | public void ControlIntValue(ref int numberToControl, UIMenuItem controllingItem, Direction direction, int incrementValue, int incrementValueFast, bool limit = false, int min = 0, int max = 100)
1272 | {
1273 | if (IsVisible && SelectedItem == controllingItem)
1274 | {
1275 | int temp = numberToControl;
1276 | if (direction == Direction.Left)
1277 | {
1278 | if (IsHoldingSpeedupControl())
1279 | {
1280 | temp -= incrementValueFast;
1281 | }
1282 | else
1283 | {
1284 | temp -= incrementValue;
1285 | }
1286 | }
1287 | else if (direction == Direction.Right)
1288 | {
1289 | if (IsHoldingSpeedupControl())
1290 | {
1291 | temp += incrementValueFast;
1292 | }
1293 | else
1294 | {
1295 | temp += incrementValue;
1296 | }
1297 | }
1298 | if (limit)
1299 | {
1300 | if (temp < min)
1301 | {
1302 | temp = min;
1303 | }
1304 | else if (temp > max)
1305 | {
1306 | temp = max;
1307 | }
1308 | }
1309 |
1310 | numberToControl = temp;
1311 |
1312 | }
1313 | controllingItem.Value = "< " + numberToControl + " >";
1314 | }
1315 |
1316 | public int ControlIntValue(int numberToControl, UIMenuItem controllingItem, Direction direction, int incrementValue, int incrementValueFast, bool limit = false, int min = 0, int max = 100)
1317 | {
1318 | ControlIntValue(ref numberToControl, controllingItem, direction, incrementValue, incrementValueFast, limit, min, max);
1319 | return numberToControl;
1320 | }
1321 |
1322 | public int ControlIntValue_NoEvent(UIMenuItem item, int numberToControl, int incrementValue, int incrementValueFast, bool limit = false, int min = 0, int max = 100)
1323 | {
1324 | item.Value = "< " + numberToControl + " >";
1325 |
1326 | if (IsVisible && SelectedItem == item)
1327 | {
1328 | if (JustPressedLeft())
1329 | {
1330 | if (IsHoldingSpeedupControl())
1331 | {
1332 | numberToControl -= incrementValueFast;
1333 | }
1334 | else
1335 | {
1336 | numberToControl -= incrementValue;
1337 | }
1338 |
1339 | if (limit)
1340 | {
1341 | if (numberToControl < min)
1342 | {
1343 | numberToControl = min;
1344 | }
1345 | if (numberToControl > max)
1346 | {
1347 | numberToControl = max;
1348 | }
1349 | }
1350 |
1351 | item.Value = "< " + numberToControl + " >";
1352 |
1353 | UIInput.InputTimer = DateTime.Now.AddMilliseconds(UIInput.InputWait);
1354 |
1355 | return numberToControl;
1356 | }
1357 | if (JustPressedRight())
1358 | {
1359 | if (IsHoldingSpeedupControl())
1360 | {
1361 | numberToControl += incrementValueFast;
1362 | }
1363 | else
1364 | {
1365 | numberToControl += incrementValue;
1366 | }
1367 |
1368 | if (limit)
1369 | {
1370 | if (numberToControl < min)
1371 | {
1372 | numberToControl = min;
1373 | }
1374 | if (numberToControl > max)
1375 | {
1376 | numberToControl = max;
1377 | }
1378 | }
1379 |
1380 | item.Value = "< " + numberToControl + " >";
1381 |
1382 | UIInput.InputTimer = DateTime.Now.AddMilliseconds(UIInput.InputWait);
1383 |
1384 | return numberToControl;
1385 | }
1386 | }
1387 | return numberToControl;
1388 | }
1389 |
1390 | ///
1391 | /// Control an Enum easily inside a event
1392 | ///
1393 | /// Must be an Enum
1394 | /// The Enum to control
1395 | /// The item that controls this enum
1396 | /// The direction given by the event
1397 | public void ControlEnumValue(ref T enumToControl, UIMenuItem controllingItem, Direction direction) where T : struct
1398 | {
1399 | if (IsVisible && SelectedItem == controllingItem)
1400 | {
1401 | if (direction == Direction.Left)
1402 | {
1403 | enumToControl = enumToControl.Previous();
1404 | }
1405 | else if (direction == Direction.Right)
1406 | {
1407 | enumToControl = enumToControl.Next();
1408 | }
1409 | }
1410 |
1411 | controllingItem.Value = "< " + enumToControl.ToString() + " >";
1412 | }
1413 |
1414 | protected virtual void MenuOpen()
1415 | {
1416 | OnMenuOpen?.Invoke(this);
1417 | }
1418 |
1419 | protected virtual void MenuExit()
1420 | {
1421 | OnMenuExit?.Invoke(this);
1422 | }
1423 |
1424 | protected virtual void ItemHighlight(UIMenuItem selecteditem, int index)
1425 | {
1426 | WhileItemHighlight?.Invoke(this, selecteditem, index);
1427 | }
1428 |
1429 | protected virtual void ItemSelect(UIMenuItem selecteditem, int index)
1430 | {
1431 | OnItemSelect?.Invoke(this, selecteditem, index);
1432 | }
1433 |
1434 | protected virtual void ItemLeftRight(UIMenuItem selecteditem, int index, Direction direction)
1435 | {
1436 | OnItemLeftRight?.Invoke(this, selecteditem, index, direction);
1437 | }
1438 |
1439 | public void UnsubscribeAll_OnMenuOpen()
1440 | {
1441 | OnMenuOpen = null;
1442 | }
1443 |
1444 | public void UnsubscribeAll_OnMenuExit()
1445 | {
1446 | OnMenuExit = null;
1447 | }
1448 |
1449 | public void UnsubscribeAll_OnItemSelect()
1450 | {
1451 | OnItemSelect = null;
1452 | //OnItemSelect = delegate { }; // Causes more overhead
1453 | }
1454 |
1455 | public void UnsubscribeAll_OnItemLeftRight()
1456 | {
1457 | OnItemLeftRight = null;
1458 | }
1459 |
1460 | public void UnsubscribeAll_WhileItemHighlight()
1461 | {
1462 | WhileItemHighlight = null;
1463 | }
1464 |
1465 | public void Dispose()
1466 | {
1467 | UnsubscribeAll_OnMenuOpen();
1468 | UnsubscribeAll_OnMenuExit();
1469 | UnsubscribeAll_OnItemSelect();
1470 | UnsubscribeAll_OnItemLeftRight();
1471 | UnsubscribeAll_WhileItemHighlight();
1472 |
1473 | ParentMenu = null;
1474 | ParentItem = null;
1475 |
1476 | SelectedItem = null;
1477 |
1478 | foreach (var item in _itemList.ToList())
1479 | {
1480 | item.Dispose();
1481 | }
1482 | _itemList.Clear();
1483 |
1484 | foreach (var item in _disabledItems.ToList())
1485 | {
1486 | item.Dispose();
1487 | }
1488 | _disabledItems.Clear();
1489 |
1490 | _bindedList.Clear();
1491 | }
1492 | }
1493 |
1494 | public class UIMenuDisplayOnly : UIMenu
1495 | {
1496 | public UIMenuDisplayOnly(string text) : base(text)
1497 | {
1498 | base.TitleFontSize = 0.5f;
1499 | base.boxWidth = 400;
1500 |
1501 | CalculateMenuPositioning();
1502 |
1503 | MaxItemsInMenu(8);
1504 | }
1505 |
1506 | public override void Draw()
1507 | {
1508 | if (IsVisible)
1509 | {
1510 | DisplayMenu();
1511 | DisableControls();
1512 | DrawScrollBar();
1513 | //ManageCurrentIndex();
1514 | }
1515 | }
1516 |
1517 | protected override void ManageCurrentIndex()
1518 | {
1519 | //base.ManageCurrentIndex();
1520 | }
1521 |
1522 | public void GoToNextItem()
1523 | {
1524 | SelectedIndex++;
1525 | if (SelectedIndex >= maxItem + 1)
1526 | {
1527 | minItem++;
1528 | maxItem++;
1529 | }
1530 | }
1531 |
1532 | public void GoToFirstItem()
1533 | {
1534 | SelectedIndex = 0;
1535 | minItem = 0;
1536 | maxItem = MaxItemsOnScreen - 1;
1537 | }
1538 |
1539 | public void GoToPreviousItem()
1540 | {
1541 | SelectedIndex--;
1542 | if (SelectedIndex < minItem && minItem > 0)
1543 | {
1544 | minItem--;
1545 | maxItem--;
1546 | }
1547 | }
1548 |
1549 | public void GoToLastItem()
1550 | {
1551 | SelectedIndex = _itemList.Count - 1;
1552 | minItem = _itemList.Count - MaxItemsOnScreen;
1553 | maxItem = _itemList.Count - 1;
1554 | }
1555 | }
1556 |
1557 | public class UIMenuItem
1558 | {
1559 | private string _text;
1560 | private dynamic _value;
1561 | private string _description;
1562 | //public List DescriptionTexts;
1563 | public float DescriptionWidth { get; set; }
1564 | private int _persistentIndex;
1565 | private UIMenu _submenuWithin;
1566 |
1567 | public UIMenuItem(string text)
1568 | {
1569 | _text = text;
1570 | }
1571 |
1572 | public UIMenuItem(string text, dynamic value)
1573 | {
1574 | _text = text;
1575 | _value = value;
1576 | }
1577 |
1578 | public UIMenuItem(string text, dynamic value, string description)
1579 | {
1580 | _text = text;
1581 | _value = value;
1582 | Description = description;
1583 | }
1584 |
1585 | public UIMenuItem(string text, string description)
1586 | {
1587 | _text = text;
1588 | Description = description;
1589 | }
1590 |
1591 | public string Text
1592 | {
1593 | get { return _text; }
1594 | set { _text = value; }
1595 | }
1596 |
1597 | public dynamic Value
1598 | {
1599 | get { return _value; }
1600 | set { _value = value; }
1601 | }
1602 |
1603 | public string Description
1604 | {
1605 | get { return _description; }
1606 | set
1607 | {
1608 | if (value != null)
1609 | { DescriptionWidth = StringHelper.MeasureStringWidth(value, Font.ChaletComprimeCologne, 0.452f); }
1610 |
1611 | _description = value;
1612 | }
1613 | }
1614 |
1615 | public int PersistentIndex
1616 | {
1617 | get { return _persistentIndex; }
1618 | set { _persistentIndex = value; }
1619 | }
1620 |
1621 | ///
1622 | /// The Submenu which this UIMenuItem leads to, if any.
1623 | ///
1624 | public UIMenu SubmenuWithin
1625 | {
1626 | get { return _submenuWithin; }
1627 | set { _submenuWithin = value; }
1628 | }
1629 |
1630 | public virtual void Draw(UIMenu sourceMenu)
1631 | {
1632 | if (sourceMenu.UIMenuItemList.IndexOf(this) == sourceMenu.SelectedIndex)
1633 | {
1634 | sourceMenu.DrawCustomText(this.Text, sourceMenu.ItemTextFontSize, sourceMenu.ItemTextFontType, sourceMenu.HighlightedItemTextColor.R, sourceMenu.HighlightedItemTextColor.G, sourceMenu.HighlightedItemTextColor.B, sourceMenu.HighlightedItemTextColor.A, sourceMenu.xPosItemText, sourceMenu.yPosItem + sourceMenu.YPosBasedOnScroll * sourceMenu.posMultiplier); //Draw highlighted item text
1635 |
1636 | if (this.Value != null)
1637 | { sourceMenu.DrawCustomText(Convert.ToString(this.Value), sourceMenu.ItemTextFontSize, sourceMenu.ItemTextFontType, sourceMenu.HighlightedItemTextColor.R, sourceMenu.HighlightedItemTextColor.G, sourceMenu.HighlightedItemTextColor.B, sourceMenu.HighlightedItemTextColor.A, sourceMenu.xPosItemValue, sourceMenu.yPosItem + sourceMenu.YPosBasedOnScroll * sourceMenu.posMultiplier, UIMenu.TextJustification.Right); } //Draw highlighted item value
1638 |
1639 | sourceMenu.DrawRectangle(sourceMenu.xPosBG, sourceMenu.yPosItemBG + sourceMenu.YPosBasedOnScroll * sourceMenu.posMultiplier, sourceMenu.MenuBGWidth, sourceMenu.heightItemBG, sourceMenu.HighlightedBoxColor.R, sourceMenu.HighlightedBoxColor.G, sourceMenu.HighlightedBoxColor.B, sourceMenu.HighlightedBoxColor.A); //Draw rectangle over highlighted text
1640 |
1641 | if (this.Description != null)
1642 | {
1643 | /*foreach (string desc in item.DescriptionTexts)
1644 | {
1645 | DrawCustomText(desc, ItemTextFontSize, ItemTextFontType, DescriptionTextColor.R, DescriptionTextColor.G, DescriptionTextColor.B, DescriptionTextColor.A, xPosItemText, yPosItem + (item.DescriptionTexts.IndexOf(desc) + YPosDescBasedOnScroll) * posMultiplier, TextJustification.Left, false); // Draw description text at bottom of menu
1646 | DrawRectangle(xPosBG, yPosItemBG + (item.DescriptionTexts.IndexOf(desc) + YPosDescBasedOnScroll) * posMultiplier, MenuBGWidth, heightItemBG, DescriptionBoxColor.R, DescriptionBoxColor.G, DescriptionBoxColor.B, DescriptionBoxColor.A); //Draw rectangle over description text at bottom of the list.
1647 | }*/
1648 |
1649 | sourceMenu.DrawCustomText(this.Description, sourceMenu.ItemTextFontSize, sourceMenu.ItemTextFontType, sourceMenu.DescriptionTextColor.R, sourceMenu.DescriptionTextColor.G, sourceMenu.DescriptionTextColor.B, sourceMenu.DescriptionTextColor.A, sourceMenu.xPosItemText, sourceMenu.yPosItem + sourceMenu.YPosDescBasedOnScroll * sourceMenu.posMultiplier, UIMenu.TextJustification.Left, true); // Draw description text at bottom of menu
1650 | float numLines = this.DescriptionWidth / (sourceMenu.boxWidth - 10);
1651 | for (int l = 0; l < (int)Math.Ceiling(numLines); l++)
1652 | {
1653 | sourceMenu.DrawRectangle(sourceMenu.xPosBG, sourceMenu.yPosItemBG + (l + sourceMenu.YPosDescBasedOnScroll) * sourceMenu.posMultiplier, sourceMenu.MenuBGWidth, sourceMenu.heightItemBG, sourceMenu.DescriptionBoxColor.R, sourceMenu.DescriptionBoxColor.G, sourceMenu.DescriptionBoxColor.B, sourceMenu.DescriptionBoxColor.A); //Draw rectangle over description text at bottom of the list.
1654 | }
1655 | //GTA.UI.Notification.Show(numLines.ToString());
1656 | }
1657 |
1658 | sourceMenu.SelectedItem = this;
1659 | }
1660 | else
1661 | {
1662 | sourceMenu.DrawCustomText(this.Text, sourceMenu.ItemTextFontSize, sourceMenu.ItemTextFontType,
1663 | sourceMenu.DefaultTextColor.R, sourceMenu.DefaultTextColor.G, sourceMenu.DefaultTextColor.B, sourceMenu.DefaultTextColor.A,
1664 | sourceMenu.xPosItemText, sourceMenu.yPosItem + sourceMenu.YPosBasedOnScroll * sourceMenu.posMultiplier, UIMenu.TextJustification.Left); //Draw item text
1665 |
1666 | if (this.Value != null)
1667 | { sourceMenu.DrawCustomText(Convert.ToString(this.Value), sourceMenu.ItemTextFontSize, sourceMenu.ItemTextFontType, sourceMenu.DefaultTextColor.R, sourceMenu.DefaultTextColor.G, sourceMenu.DefaultTextColor.B, sourceMenu.DefaultTextColor.A, sourceMenu.xPosItemValue, sourceMenu.yPosItem + sourceMenu.YPosBasedOnScroll * sourceMenu.posMultiplier, UIMenu.TextJustification.Right); } //Draw item value
1668 |
1669 | sourceMenu.DrawRectangle(sourceMenu.xPosBG, sourceMenu.yPosItemBG + sourceMenu.YPosBasedOnScroll * sourceMenu.posMultiplier, sourceMenu.MenuBGWidth, sourceMenu.heightItemBG, sourceMenu.DefaultBoxColor.R, sourceMenu.DefaultBoxColor.G, sourceMenu.DefaultBoxColor.B, sourceMenu.DefaultBoxColor.A); //Draw background rectangle around item.
1670 | }
1671 | }
1672 | public virtual void Dispose()
1673 | {
1674 | _submenuWithin = null;
1675 | }
1676 | }
1677 |
1678 | public class UIMenuNumberValueItem : UIMenuItem
1679 | {
1680 | public UIMenuNumberValueItem(string text, dynamic value) : base(text, (object)value)
1681 | {
1682 | this.Text = text;
1683 | SetValue(value);
1684 | }
1685 |
1686 | public UIMenuNumberValueItem(string text, dynamic value, string description) : base(text, (object)value, description)
1687 | {
1688 | this.Text = text;
1689 | SetValue(value);
1690 | this.Description = description;
1691 | }
1692 |
1693 | public void SetValue(dynamic value)
1694 | {
1695 | this.Value = "< " + value + " >";
1696 | }
1697 | }
1698 |
1699 | public class UIMenuListItem : UIMenuItem
1700 | {
1701 | private List