├── .vs └── NativeUI │ └── v15 │ └── Server │ └── sqlite3 │ ├── db.lock │ └── storage.ide ├── NativeUI ├── stream │ └── NativeUI.ytd ├── Items │ ├── IListItem.cs │ ├── UIMenuSeparatorItem.cs │ ├── UIMenuSliderHeritageItem.cs │ ├── UIMenuDynamicListItem.cs │ ├── UIMenuColoredItem.cs │ ├── UIMenuCheckboxItem.cs │ ├── UIMenuProgressItem.cs │ ├── UIMenuSliderItem.cs │ ├── UIMenuSliderProgressItem.cs │ ├── UIMenuListItem.cs │ └── UIMenuItem.cs ├── packages.config ├── Windows │ ├── UIMenuWindow.cs │ └── UIMenuHeritageWindow.cs ├── StringMeasurer.cs ├── TimerBars │ ├── TimerBarPool.cs │ └── Bars │ │ ├── TextTimerBar.cs │ │ ├── TimerBarBase.cs │ │ └── ProgressTimerBar.cs ├── Panels │ ├── UIMenuPanel.cs │ ├── UIMenuStatisticsPanel.cs │ ├── UIMenuPercentagePanel.cs │ ├── UIMenuVerticalOneLineGridPanel.cs │ ├── UIMenuHorizontalOneLineGridPanel.cs │ ├── UIMenuGridPanel.cs │ └── UIMenuColorPanel.cs ├── PauseMenu │ ├── TabTextItem.cs │ ├── TabItemSimpleList.cs │ ├── TabItem.cs │ ├── TabSubmenuItem.cs │ └── TabMissionSelectItem.cs ├── Hud │ ├── Markers │ │ ├── MarkersHandler.cs │ │ └── Marker.cs │ └── Notifications │ │ └── NotificationChars.cs ├── Properties │ └── AssemblyInfo.cs ├── Elements │ ├── UIResRectangle.cs │ ├── UIResText.cs │ └── Sprite.cs ├── Controls.cs ├── Scaleforms │ ├── MediumMessage │ │ └── MediumMessage.cs │ ├── PopupWarning │ │ └── PopupWarning.cs │ └── BigMessage │ │ └── BigMessage.cs ├── PointExtensions.cs ├── NativeUI.csproj ├── ScreenTools.cs └── MenuPool.cs ├── packages.config ├── MenuExample ├── packages.config └── MenuExample.csproj ├── LICENSE.md ├── NativeUI.sln ├── README.md ├── .gitattributes └── .gitignore /.vs/NativeUI/v15/Server/sqlite3/db.lock: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /NativeUI/stream/NativeUI.ytd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/citizenfx/NativeUI/HEAD/NativeUI/stream/NativeUI.ytd -------------------------------------------------------------------------------- /.vs/NativeUI/v15/Server/sqlite3/storage.ide: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/citizenfx/NativeUI/HEAD/.vs/NativeUI/v15/Server/sqlite3/storage.ide -------------------------------------------------------------------------------- /NativeUI/Items/IListItem.cs: -------------------------------------------------------------------------------- 1 | namespace NativeUI 2 | { 3 | public interface IListItem 4 | { 5 | string CurrentItem(); 6 | } 7 | } -------------------------------------------------------------------------------- /packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /NativeUI/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /MenuExample/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /NativeUI/Items/UIMenuSeparatorItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NativeUI 8 | { 9 | public class UIMenuSeparatorItem : UIMenuItem 10 | { 11 | /// 12 | /// Use it to create an Empty item to separate menu Items 13 | /// 14 | public UIMenuSeparatorItem() : base("", "") 15 | { 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /NativeUI/Windows/UIMenuWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NativeUI 8 | { 9 | public class UIMenuWindow 10 | { 11 | public UIMenu ParentMenu { get; set; } 12 | internal Sprite Background; 13 | 14 | public virtual bool Enabled { get; set; } 15 | internal virtual void Position(float y) 16 | { 17 | } 18 | internal virtual void UpdateParent() 19 | { 20 | } 21 | internal virtual void Draw() 22 | { 23 | } 24 | 25 | public void SetParentMenu(UIMenu Menu) 26 | { 27 | ParentMenu = Menu; 28 | } 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /NativeUI/StringMeasurer.cs: -------------------------------------------------------------------------------- 1 | using CitizenFX.Core.UI; 2 | using System; 3 | 4 | namespace NativeUI 5 | { 6 | public class StringMeasurer 7 | { 8 | /// 9 | /// Measures width of a 0.35 scale string. 10 | /// 11 | /// 12 | /// 13 | [Obsolete("Use Screen.GetTextWidth instead.", true)] 14 | public static int MeasureString(string input) => (int)ScreenTools.GetTextWidth(input, Font.ChaletLondon, 1f); 15 | 16 | [Obsolete("Use Screen.GetTextWidth instead.", true)] 17 | public static float MeasureString(string input, Font font, float scale) => ScreenTools.GetTextWidth(input, font, scale); 18 | } 19 | } -------------------------------------------------------------------------------- /NativeUI/TimerBars/TimerBarPool.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace NativeUI 4 | { 5 | public class TimerBarPool 6 | { 7 | private static List _bars = new List(); 8 | 9 | public TimerBarPool() 10 | { 11 | _bars = new List(); 12 | } 13 | 14 | public List ToList() 15 | { 16 | return _bars; 17 | } 18 | 19 | public void Add(TimerBarBase timer) 20 | { 21 | _bars.Add(timer); 22 | } 23 | 24 | public void Remove(TimerBarBase timer) 25 | { 26 | _bars.Remove(timer); 27 | } 28 | 29 | public void Draw() 30 | { 31 | for (int i = 0; i < _bars.Count; i++) 32 | { 33 | _bars[i].Draw(i * 10); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /NativeUI/Panels/UIMenuPanel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace NativeUI 9 | { 10 | public class UIMenuPanel 11 | { 12 | internal dynamic Background; 13 | protected SizeF Resolution = ScreenTools.ResolutionMaintainRatio; 14 | public UIMenuPanel() 15 | { 16 | } 17 | public virtual bool Selected { get; set; } 18 | public virtual bool Enabled { get; set; } 19 | internal virtual void Position(float y) 20 | { 21 | } 22 | public virtual void UpdateParent() 23 | { 24 | ParentItem.Parent.ListChange(ParentItem, ParentItem.Index); 25 | ParentItem.ListChangedTrigger(ParentItem.Index); 26 | } 27 | internal async virtual Task Draw() 28 | { 29 | } 30 | 31 | public void SetParentItem(UIMenuListItem item) 32 | { 33 | ParentItem = item; 34 | } 35 | 36 | public UIMenuListItem ParentItem { get; set; } 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /NativeUI/TimerBars/Bars/TextTimerBar.cs: -------------------------------------------------------------------------------- 1 | using CitizenFX.Core.UI; 2 | using System.Drawing; 3 | using Font = CitizenFX.Core.UI.Font; 4 | 5 | namespace NativeUI 6 | { 7 | public class TextTimerBar : TimerBarBase 8 | { 9 | public string Caption { get; set; } 10 | public Color CaptionColor { get; set; } = Colors.White; 11 | 12 | public TextTimerBar(string label, string text) : base(label) 13 | { 14 | Caption = text; 15 | } 16 | public TextTimerBar(string label, string text, Color captionColor) : base(label) 17 | { 18 | Caption = text; 19 | CaptionColor = captionColor; 20 | } 21 | 22 | public override void Draw(int interval) 23 | { 24 | SizeF res = ScreenTools.ResolutionMaintainRatio; 25 | PointF safe = ScreenTools.SafezoneBounds; 26 | 27 | base.Draw(interval); 28 | new UIResText(Caption, new PointF((int)res.Width - safe.X - 10, (int)res.Height - safe.Y - (42 + (4 * interval))), 0.5f, CaptionColor, Font.ChaletLondon, Alignment.Right).Draw(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Guad 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NativeUI/TimerBars/Bars/TimerBarBase.cs: -------------------------------------------------------------------------------- 1 | using CitizenFX.Core.UI; 2 | using System.Drawing; 3 | using Font = CitizenFX.Core.UI.Font; 4 | 5 | namespace NativeUI 6 | { 7 | public abstract class TimerBarBase 8 | { 9 | public string Label { get; set; } 10 | 11 | public TimerBarBase(string label) 12 | { 13 | Label = label; 14 | } 15 | 16 | public virtual void Draw(int interval) 17 | { 18 | SizeF res = ScreenTools.ResolutionMaintainRatio; 19 | PointF safe = ScreenTools.SafezoneBounds; 20 | new UIResText(Label, new PointF((int)res.Width - safe.X - 180, (int)res.Height - safe.Y - (30 + (4 * interval))), 0.3f, Colors.White, Font.ChaletLondon, Alignment.Right).Draw(); 21 | 22 | new Sprite("timerbars", "all_black_bg", new PointF((int)res.Width - safe.X - 298, (int)res.Height - safe.Y - (40 + (4 * interval))), new SizeF(300, 37), 0f, Color.FromArgb(180, 255, 255, 255)).Draw(); 23 | 24 | Screen.Hud.HideComponentThisFrame(HudComponent.AreaName); 25 | Screen.Hud.HideComponentThisFrame(HudComponent.StreetName); 26 | Screen.Hud.HideComponentThisFrame(HudComponent.VehicleName); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /NativeUI/PauseMenu/TabTextItem.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace NativeUI.PauseMenu 4 | { 5 | public class TabTextItem : TabItem 6 | { 7 | public string TextTitle { get; set; } 8 | public string Text { get; set; } 9 | public int WordWrap { get; set; } 10 | 11 | public TabTextItem(string name, string title) : base(name) 12 | { 13 | TextTitle = title; 14 | } 15 | 16 | public TabTextItem(string name, string title, string text) : base(name) 17 | { 18 | TextTitle = title; 19 | Text = text; 20 | } 21 | 22 | public override void Draw() 23 | { 24 | base.Draw(); 25 | 26 | var alpha = (Focused || !CanBeFocused) ? 255 : 200; 27 | 28 | if (!string.IsNullOrEmpty(TextTitle)) 29 | new UIResText(TextTitle, SafeSize.AddPoints(new PointF(40, 20)), 1.5f, Color.FromArgb(alpha, Colors.White)).Draw(); 30 | 31 | if (!string.IsNullOrEmpty(Text)) 32 | { 33 | var ww = WordWrap == 0 ? BottomRight.X - TopLeft.X - 40 : WordWrap; 34 | new UIResText(Text, SafeSize.AddPoints(new PointF(40, 150)), 0.4f, Color.FromArgb(alpha, Colors.White)) { Wrap = ww }.Draw(); 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /NativeUI/Hud/Markers/MarkersHandler.cs: -------------------------------------------------------------------------------- 1 | using CitizenFX.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using static CitizenFX.Core.Native.API; 8 | 9 | namespace NativeUI 10 | { 11 | public class MarkersHandler : BaseScript 12 | { 13 | 14 | private static List _markerList = new List(); 15 | 16 | public MarkersHandler() 17 | { 18 | Tick += MainHandler; 19 | } 20 | 21 | public async Task MainHandler() 22 | { 23 | if (_markerList.Count == 0) return; 24 | 25 | for(int i=0; i FilterMarkers() => _markerList.Where(x => MenuPool.PlayerPed.IsInRangeOf(x.Position, x.Distance)).ToList(); 31 | 32 | /// 33 | /// Adds a marker to the list 34 | /// 35 | /// 36 | public static void AddMarker(Marker marker) 37 | { 38 | if (!_markerList.Contains(marker)) 39 | _markerList.Add(marker); 40 | } 41 | 42 | /// 43 | /// Removes the marker from the list 44 | /// 45 | /// 46 | public static void RemoveMarker(Marker marker) 47 | { 48 | if (_markerList.Contains(marker)) 49 | _markerList.Remove(marker); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /NativeUI.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.22823.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NativeUI", "NativeUI\NativeUI.csproj", "{F3E16ED9-DBF7-4E7B-B04B-9B24B11891D3}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MenuExample", "MenuExample\MenuExample.csproj", "{79D9A09F-1999-4148-9BA0-20AEBA9B3C8B}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {F3E16ED9-DBF7-4E7B-B04B-9B24B11891D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {F3E16ED9-DBF7-4E7B-B04B-9B24B11891D3}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {F3E16ED9-DBF7-4E7B-B04B-9B24B11891D3}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {F3E16ED9-DBF7-4E7B-B04B-9B24B11891D3}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {79D9A09F-1999-4148-9BA0-20AEBA9B3C8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {79D9A09F-1999-4148-9BA0-20AEBA9B3C8B}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {79D9A09F-1999-4148-9BA0-20AEBA9B3C8B}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {79D9A09F-1999-4148-9BA0-20AEBA9B3C8B}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /NativeUI/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("NativeUI")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("NativeUI")] 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("f3e16ed9-dbf7-4e7b-b04b-9b24b11891d3")] 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.7.0.0")] 36 | [assembly: AssemblyFileVersion("1.7.0.0")] 37 | -------------------------------------------------------------------------------- /NativeUI/PauseMenu/TabItemSimpleList.cs: -------------------------------------------------------------------------------- 1 | using CitizenFX.Core.UI; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Linq; 5 | using Font = CitizenFX.Core.UI.Font; 6 | 7 | namespace NativeUI.PauseMenu 8 | { 9 | public class TabItemSimpleList : TabItem 10 | { 11 | public TabItemSimpleList(string title, Dictionary dict) : base(title) 12 | { 13 | Dictionary = dict; 14 | DrawBg = false; 15 | } 16 | 17 | public Dictionary Dictionary { get; set; } 18 | 19 | public override void Draw() 20 | { 21 | base.Draw(); 22 | 23 | var alpha = (Focused || !CanBeFocused) ? 180 : 60; 24 | var blackAlpha = (Focused || !CanBeFocused) ? 200 : 90; 25 | var fullAlpha = (Focused || !CanBeFocused) ? 255 : 150; 26 | 27 | var rectSize = (int)(BottomRight.X - TopLeft.X); 28 | 29 | for (int i = 0; i < Dictionary.Count; i++) 30 | { 31 | new UIResRectangle(new PointF(TopLeft.X, TopLeft.Y + (40 * i)), 32 | new SizeF(rectSize, 40), i % 2 == 0 ? Color.FromArgb(alpha, 0, 0, 0) : Color.FromArgb(blackAlpha, 0, 0, 0)).Draw(); 33 | 34 | var item = Dictionary.ElementAt(i); 35 | 36 | new UIResText(item.Key, new PointF(TopLeft.X + 6, TopLeft.Y + 5 + (40 * i)), 0.35f, Color.FromArgb(fullAlpha, Colors.White)).Draw(); 37 | new UIResText(item.Value, new PointF(BottomRight.X - 6, TopLeft.Y + 5 + (40 * i)), 0.35f, Color.FromArgb(fullAlpha, Colors.White), Font.ChaletLondon, Alignment.Right).Draw(); 38 | } 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /NativeUI/Items/UIMenuSliderHeritageItem.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Threading.Tasks; 3 | 4 | namespace NativeUI 5 | { 6 | public class UIMenuSliderHeritageItem : UIMenuSliderItem 7 | { 8 | public UIMenuSliderHeritageItem(string text, string description, bool divider):base(text, description, divider) 9 | { 10 | const int y = 0; 11 | _arrowLeft = new Sprite("mpleaderboard", "leaderboard_female_icon", new PointF(0, 105 + y), new Size(40, 40), 0, Color.FromArgb(255,255,255)); 12 | _arrowRight = new Sprite("mpleaderboard", "leaderboard_male_icon", new PointF(0, 105 + y), new Size(40, 40), 0, Color.FromArgb(255, 255, 255)); 13 | } 14 | 15 | public override void Position(int y) 16 | { 17 | base.Position(y); 18 | _rectangleBackground.Position = new PointF(250f + base.Offset.X + Parent.WidthOffset, y + 158.5f + base.Offset.Y); 19 | _rectangleSlider.Position = new PointF(250f + base.Offset.X + Parent.WidthOffset, y + 158.5f + base.Offset.Y); 20 | _rectangleDivider.Position = new PointF(323.5f + base.Offset.X + Parent.WidthOffset, y + 153 + base.Offset.Y); 21 | _arrowLeft.Position = new PointF(217f + base.Offset.X + Parent.WidthOffset, y + 143.5f + base.Offset.Y); 22 | _arrowRight.Position = new PointF(395f + base.Offset.X + Parent.WidthOffset, y + 143.5f + base.Offset.Y); 23 | } 24 | 25 | public async override Task Draw() 26 | { 27 | await base.Draw(); 28 | _arrowLeft.Color = Enabled ? Selected ? Color.FromArgb(255, 102, 178) : Colors.WhiteSmoke : Color.FromArgb(163, 159, 148); 29 | _arrowRight.Color = Enabled ? Selected ? Color.FromArgb(51,51,255) : Colors.WhiteSmoke : Color.FromArgb(163, 159, 148); 30 | _arrowLeft.Draw(); 31 | _arrowRight.Draw(); 32 | await Task.FromResult(0); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /NativeUI/Windows/UIMenuHeritageWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using CitizenFX.Core; 5 | using CitizenFX.Core.Native; 6 | using CitizenFX.Core.UI; 7 | 8 | namespace NativeUI 9 | { 10 | public class UIMenuHeritageWindow : UIMenuWindow 11 | { 12 | private Sprite MomSprite; 13 | private Sprite DadSprite; 14 | private int Mom; 15 | private int Dad; 16 | public PointF Offset; 17 | 18 | public UIMenuHeritageWindow(int mom, int dad) 19 | { 20 | Background = new Sprite("pause_menu_pages_char_mom_dad", "mumdadbg", new Point(0, 0), new Size(431, 228)); 21 | Mom = mom; 22 | Dad = dad; 23 | MomSprite = new Sprite("char_creator_portraits", (Mom < 21)? "female_" + (Mom) : "special_female_" + (Mom - 21), new Point(0, 0), new Size(228, 228)); 24 | DadSprite = new Sprite("char_creator_portraits", (Dad < 21)? "Male_" + (Dad) : "special_male_" + (Dad-21), new Point(0, 0), new Size(228, 228)); 25 | Offset = new PointF(0, 0); 26 | } 27 | 28 | internal override void Position(float y) 29 | { 30 | Background.Position = new PointF(Offset.X, 70 + y + ParentMenu.Offset.Y); 31 | MomSprite.Position = new PointF(Offset.X + (ParentMenu.WidthOffset / 2) + 25, 70 + y + ParentMenu.Offset.Y); 32 | DadSprite.Position = new PointF(Offset.X + (ParentMenu.WidthOffset / 2) + 195, 70 + y + ParentMenu.Offset.Y); 33 | } 34 | 35 | public void Index(int mom, int dad) 36 | { 37 | Mom = mom; 38 | Dad = dad; 39 | MomSprite.TextureName = (Mom < 21) ? "female_" + Mom : "special_female_" + (Mom - 21); 40 | DadSprite.TextureName = (Dad < 21) ? "male_" + Dad : "special_male_" + (Dad - 21); 41 | } 42 | 43 | internal override void Draw() 44 | { 45 | Background.Size = new Size(431 + ParentMenu.WidthOffset, 228); 46 | Background.Draw(); 47 | DadSprite.Draw(); 48 | MomSprite.Draw(); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /NativeUI/Elements/UIResRectangle.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using CitizenFX.Core.Native; 3 | using CitizenFX.Core.UI; 4 | 5 | namespace NativeUI 6 | { 7 | /// 8 | /// A rectangle in 1080 pixels height system. 9 | /// 10 | public class UIResRectangle : CitizenFX.Core.UI.Rectangle 11 | { 12 | public UIResRectangle() 13 | { } 14 | 15 | public UIResRectangle(PointF pos, SizeF size) : base(pos, size) 16 | { } 17 | 18 | public UIResRectangle(PointF pos, SizeF size, Color color) : base(pos, size, color) 19 | { } 20 | 21 | public override void Draw(SizeF offset) 22 | { 23 | if (!Enabled) return; 24 | int screenw = Screen.Resolution.Width; 25 | int screenh = Screen.Resolution.Height; 26 | const float height = 1080f; 27 | float ratio = (float)screenw / screenh; 28 | var width = height * ratio; 29 | 30 | float w = Size.Width / width; 31 | float h = Size.Height / height; 32 | float x = ((Position.X + offset.Width) / width) + w * 0.5f; 33 | float y = ((Position.Y + offset.Height) / height) + h * 0.5f; 34 | 35 | API.DrawRect(x, y, w, h, Color.R, Color.G, Color.B, Color.A); 36 | } 37 | 38 | public static void Draw(float xPos, float yPos, int boxWidth, int boxHeight, Color color) 39 | { 40 | int screenw = Screen.Resolution.Width; 41 | int screenh = Screen.Resolution.Height; 42 | const float height = 1080f; 43 | float ratio = (float)screenw / screenh; 44 | var width = height * ratio; 45 | 46 | float w = boxWidth / width; 47 | float h = boxHeight / height; 48 | float x = ((xPos) / width) + w * 0.5f; 49 | float y = ((yPos) / height) + h * 0.5f; 50 | 51 | API.DrawRect(x, y, w, h, color.R, color.G, color.B, color.A); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NativeUI 2 | ![NativeUI Example](https://forum.cfx.re/uploads/default/original/4X/7/b/a/7ba89f317f1087e512632b7ea30edc11c85d71a7.jpeg) 3 | 4 | ![PauseMenu Example!](https://forum.cfx.re/uploads/default/original/4X/8/3/5/8354aceac39143276d05108371286a30a013cd90.jpeg) 5 | 6 | NativeUI is a library that helps you quickly and easily build Rockstar-like menus and Pause Menus. 7 | 8 | ### Documentation 9 | Take a look at our [wiki page](https://github.com/Guad/NativeUI/wiki/Home). 10 | 11 | ### Features 12 | * Support for simple buttons, checkboxes and lists. 13 | * Support for custom banners from game sprites and your own textures. 14 | * Support for panels from grid panels to color panels. 15 | * Easy nested menus for fast and painless nested menu system. 16 | * Controller support. 17 | * Mouse controls. 18 | * Custom instructional buttons. 19 | * Support for all screen resolutions. 20 | * Item descriptions. 21 | * Rebindable keys and controls. 22 | * Badges to decorate your items. 23 | * Event-based callbacks. 24 | 25 | ### Distribution 26 | Please, do not distribute the .dll with your mod. This causes many old versions floating around on the internet. Instead, point your users to [this post](http://gtaforums.com/topic/809284-net-nativeui/). 27 | 28 | ### License 29 | Copyright (c) 2016 Phillipp 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | 33 | ### Port to CitizenFX 34 | This is a ported version to CitizenFX. 35 | Developers looking to create C# Resources for [FiveM](https://fivem.net/) can use this port to create custom menus. 36 | Note, not all features are documented yet. 37 | This ported version may contain small changes and some features from the original NativeUI by GUAD have been disabled because they are not available through CitizenFX. -------------------------------------------------------------------------------- /NativeUI/TimerBars/Bars/ProgressTimerBar.cs: -------------------------------------------------------------------------------- 1 | 2 | using System.Drawing; 3 | 4 | namespace NativeUI 5 | { 6 | public class ProgressTimerBar : TimerBarBase 7 | { 8 | /// 9 | /// Bar percentage. Goes from 0 to 1. 10 | /// 11 | public float Percentage { get; set; } 12 | 13 | public Color BackgroundColor { get; set; } 14 | public Color ForegroundColor { get; set; } 15 | 16 | private UIResRectangle _background; 17 | private UIResRectangle _foreground; 18 | 19 | public ProgressTimerBar(string label) : base(label) 20 | { 21 | BackgroundColor = Colors.DarkRed; 22 | ForegroundColor = Colors.Red; 23 | _background = new UIResRectangle(new PointF(0, 0), new SizeF(150, 15), BackgroundColor); 24 | _foreground = new UIResRectangle(new PointF(0,0), new SizeF(0, 15), ForegroundColor); 25 | } 26 | 27 | public ProgressTimerBar(string label, Color background, Color foreground) : base(label) 28 | { 29 | BackgroundColor = background; 30 | ForegroundColor = foreground; 31 | _background = new UIResRectangle(new PointF(0, 0), new SizeF(150, 15), BackgroundColor); 32 | _foreground = new UIResRectangle(new PointF(0, 0), new SizeF(0, 15), ForegroundColor); 33 | } 34 | 35 | public override void Draw(int interval) 36 | { 37 | SizeF res = ScreenTools.ResolutionMaintainRatio; 38 | PointF safe = ScreenTools.SafezoneBounds; 39 | 40 | base.Draw(interval); 41 | 42 | var start = new PointF((int)res.Width - safe.X - 160, (int)res.Height - safe.Y - (28 + (4 * interval))); 43 | 44 | _background.Position = start; 45 | _foreground.Position = start; 46 | 47 | _foreground.Size = new SizeF(150 * Percentage, 15); 48 | 49 | // In case someone decides to change colors while drawing.. 50 | _background.Color = BackgroundColor; 51 | _foreground.Color = ForegroundColor; 52 | 53 | _background.Draw(); 54 | _foreground.Draw(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /NativeUI/Controls.cs: -------------------------------------------------------------------------------- 1 | using CitizenFX.Core; 2 | using static CitizenFX.Core.Native.API; 3 | using System.Linq; 4 | 5 | namespace NativeUI 6 | { 7 | /// 8 | /// Class that provides tools to handle the game controls. 9 | /// 10 | public static class Controls 11 | { 12 | /// 13 | /// All of the controls required for using a keyboard. 14 | /// 15 | private static readonly Control[] NecessaryControlsKeyboard = new Control[] 16 | { 17 | Control.FrontendAccept, 18 | Control.FrontendAxisX, 19 | Control.FrontendAxisY, 20 | Control.FrontendDown, 21 | Control.FrontendUp, 22 | Control.FrontendLeft, 23 | Control.FrontendRight, 24 | Control.FrontendCancel, 25 | Control.FrontendSelect, 26 | Control.CursorScrollDown, 27 | Control.CursorScrollUp, 28 | Control.CursorX, 29 | Control.CursorY, 30 | Control.MoveUpDown, 31 | Control.MoveLeftRight, 32 | Control.Sprint, 33 | Control.Jump, 34 | Control.Enter, 35 | Control.VehicleExit, 36 | Control.VehicleAccelerate, 37 | Control.VehicleBrake, 38 | Control.VehicleMoveLeftRight, 39 | Control.VehicleFlyYawLeft, 40 | Control.FlyLeftRight, 41 | Control.FlyUpDown, 42 | Control.VehicleFlyYawRight, 43 | Control.VehicleHandbrake, 44 | }; 45 | /// 46 | /// All of the controls required for using a keyboard. 47 | /// 48 | private static readonly Control[] NecessaryControlsGamePad = NecessaryControlsKeyboard.Concat(new Control[] 49 | { 50 | Control.LookUpDown, 51 | Control.LookLeftRight, 52 | Control.Aim, 53 | Control.Attack, 54 | }) 55 | .ToArray(); 56 | 57 | /// 58 | /// Toggles the availability of the controls. 59 | /// It does not disable the basic movement and frontend controls. 60 | /// 61 | /// If we want to enable or disable the controls. 62 | public static void Toggle(bool toggle) 63 | { 64 | // If we want to enable the controls 65 | if (toggle) 66 | { 67 | // Enable all of them 68 | Game.EnableAllControlsThisFrame(0); 69 | Game.EnableAllControlsThisFrame(1); 70 | Game.EnableAllControlsThisFrame(2); 71 | } 72 | // If we don't need them 73 | else 74 | { 75 | // Disable all of the controls 76 | Game.DisableAllControlsThisFrame(2); 77 | 78 | // Now, re-enable the controls that are required for the game 79 | // First, pick the right controls for gamepad or keyboard and mouse 80 | Control[] list = Game.CurrentInputMode == InputMode.GamePad ? NecessaryControlsGamePad : NecessaryControlsKeyboard; 81 | // Then, enable all of the controls for that input mode 82 | foreach (Control control in list) 83 | EnableControlAction(0, (int)control, true); 84 | } 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /NativeUI/Scaleforms/MediumMessage/MediumMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using CitizenFX.Core; 7 | using static CitizenFX.Core.Native.API; 8 | 9 | namespace NativeUI 10 | { 11 | public class MediumMessageBase : BaseScript 12 | { 13 | public static MediumMessageHandler MessageInstance { get; set; } 14 | 15 | public MediumMessageBase() 16 | { 17 | MessageInstance = new MediumMessageHandler(); 18 | Tick += MediumMessageTick; 19 | } 20 | 21 | private async Task MediumMessageTick() 22 | { 23 | await MessageInstance.Update(); 24 | } 25 | } 26 | 27 | public class MediumMessageHandler 28 | { 29 | private Scaleform _sc; 30 | private int _start; 31 | private int _timer; 32 | private bool _hasAnimatedOut; 33 | 34 | public MediumMessageHandler() { } 35 | 36 | public async Task Load() 37 | { 38 | if (_sc != null) return; 39 | _sc = new Scaleform("MIDSIZED_MESSAGE"); 40 | 41 | var timeout = 1000; 42 | var start = DateTime.Now; 43 | while (!_sc.IsLoaded && DateTime.Now.Subtract(start).TotalMilliseconds < timeout) await BaseScript.Delay(0); 44 | } 45 | 46 | public void Dispose() 47 | { 48 | _sc.Dispose(); 49 | _sc = null; 50 | } 51 | 52 | public async void ShowColoredShard(string msg, string desc, HudColor bgColor, bool useDarkerShard = false, bool useCondensedShard = false, int time = 5000) 53 | { 54 | await Load(); 55 | _start = Game.GameTime; 56 | _sc.CallFunction("SHOW_SHARD_MIDSIZED_MESSAGE", msg, desc, (int)bgColor, useDarkerShard, useCondensedShard); 57 | _timer = time; 58 | _hasAnimatedOut = false; 59 | } 60 | 61 | internal Task Update() 62 | { 63 | if (_sc == null) return Task.FromResult(0); 64 | _sc.Render2D(); 65 | 66 | if (_start != 0 && Game.GameTime - _start > _timer) 67 | { 68 | if (!_hasAnimatedOut) 69 | { 70 | _sc.CallFunction("SHARD_ANIM_OUT", (int)HudColor.HUD_COLOUR_PURPLE, 750); 71 | _hasAnimatedOut = true; 72 | _timer += 750; 73 | } 74 | else 75 | { 76 | Audio.PlaySoundFrontend("Shard_Disappear", "GTAO_FM_Events_Soundset"); 77 | _start = 0; 78 | Dispose(); 79 | _sc = null; 80 | } 81 | } 82 | 83 | return Task.FromResult(0); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /NativeUI/PointExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using CitizenFX.Core; 4 | using System.Drawing; 5 | 6 | namespace NativeUI 7 | { 8 | public static class MiscExtensions 9 | { 10 | public static Random SharedRandom = new Random(); 11 | 12 | public static Point AddPoints(this Point left, Point right) 13 | { 14 | return new Point(left.X + right.X, left.Y + right.Y); 15 | } 16 | 17 | public static Point SubtractPoints(this Point left, Point right) 18 | { 19 | return new Point(left.X - right.X, left.Y - right.Y); 20 | } 21 | 22 | public static PointF AddPoints(this PointF left, PointF right) 23 | { 24 | return new PointF(left.X + right.X, left.Y + right.Y); 25 | } 26 | 27 | public static PointF SubtractPoints(this PointF left, PointF right) 28 | { 29 | return new PointF(left.X - right.X, left.Y - right.Y); 30 | } 31 | 32 | public static float Clamp(this float val, float min, float max) 33 | { 34 | if (val > max) 35 | return max; 36 | if (val < min) 37 | return min; 38 | return val; 39 | } 40 | 41 | public static Vector3 LinearVectorLerp(Vector3 start, Vector3 end, int currentTime, int duration) 42 | { 43 | return new Vector3() 44 | { 45 | X = LinearFloatLerp(start.X, end.X, currentTime, duration), 46 | Y = LinearFloatLerp(start.Y, end.Y, currentTime, duration), 47 | Z = LinearFloatLerp(start.Z, end.Z, currentTime, duration), 48 | }; 49 | } 50 | 51 | public static Vector3 VectorLerp(Vector3 start, Vector3 end, int currentTime, int duration, Func easingFunc) 52 | { 53 | return new Vector3() 54 | { 55 | X = easingFunc(start.X, end.X, currentTime, duration), 56 | Y = easingFunc(start.Y, end.Y, currentTime, duration), 57 | Z = easingFunc(start.Z, end.Z, currentTime, duration), 58 | }; 59 | } 60 | 61 | public static float LinearFloatLerp(float start, float end, int currentTime, int duration) 62 | { 63 | float change = end - start; 64 | return change * currentTime / duration + start; 65 | } 66 | 67 | public static float QuadraticEasingLerp(float start, float end, int currentTime, int duration) 68 | { 69 | var time = (float)currentTime; 70 | var dur = (float)duration; 71 | 72 | float change = end - start; 73 | 74 | time /= dur / 2; 75 | if (time < 1) return change / 2 * time * time + start; 76 | time--; 77 | return -change / 2 * (time * (time - 2) - 1) + start; 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /NativeUI/PauseMenu/TabItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | namespace NativeUI.PauseMenu 5 | { 6 | public class TabItem 7 | { 8 | public TabItem(string name) 9 | { 10 | RockstarTile = new Sprite("pause_menu_sp_content", "rockstartilebmp", new PointF(), new SizeF(64, 64), 0f, Color.FromArgb(40, 255, 255, 255)); 11 | Title = name; 12 | DrawBg = true; 13 | UseDynamicPositionment = true; 14 | } 15 | 16 | public virtual bool Visible { get; set; } 17 | public virtual bool Focused { get; set; } 18 | public string Title { get; set; } 19 | public bool Active { get; set; } 20 | public bool JustOpened { get; set; } 21 | public bool CanBeFocused { get; set; } 22 | public PointF TopLeft { get; set; } 23 | public PointF BottomRight { get; set; } 24 | public PointF SafeSize { get; set; } 25 | public bool UseDynamicPositionment { get; set; } 26 | public TabView Parent { get; set; } 27 | protected SizeF Resolution = ScreenTools.ResolutionMaintainRatio; 28 | 29 | public event EventHandler Activated; 30 | public event EventHandler DrawInstructionalButtons; 31 | public bool DrawBg; 32 | public bool FadeInWhenFocused { get; set; } 33 | 34 | protected Sprite RockstarTile; 35 | 36 | public void OnActivated() 37 | { 38 | Activated?.Invoke(this, EventArgs.Empty); 39 | } 40 | 41 | 42 | public virtual void ProcessControls() 43 | { 44 | 45 | } 46 | 47 | public virtual void Draw() 48 | { 49 | if (!Visible) return; 50 | 51 | 52 | if (UseDynamicPositionment) 53 | { 54 | SafeSize = new PointF(300, Parent.SubTitle != null && Parent.SubTitle != "" ? 255 : 245); 55 | 56 | TopLeft = new PointF(SafeSize.X, SafeSize.Y); 57 | BottomRight = new PointF((int)Resolution.Width - SafeSize.X, (int)Resolution.Height - SafeSize.Y); 58 | } 59 | 60 | var rectSize = new SizeF(BottomRight.SubtractPoints(TopLeft)); 61 | 62 | DrawInstructionalButtons?.Invoke(this, EventArgs.Empty); 63 | 64 | if (DrawBg) 65 | { 66 | new UIResRectangle(TopLeft, rectSize, 67 | Color.FromArgb((Focused || !FadeInWhenFocused) ? 200 : 120, 0, 0, 0)).Draw(); 68 | 69 | var titleSize = 100; 70 | RockstarTile.Size = new SizeF(titleSize, titleSize); 71 | 72 | var cols = rectSize.Width / titleSize; 73 | var fils = 4; 74 | 75 | for (int i = 0; i < cols * fils; i++) 76 | { 77 | RockstarTile.Position = TopLeft.AddPoints(new PointF(titleSize * (i % (int)cols), titleSize * i / (int)cols)); 78 | RockstarTile.Color = Color.FromArgb((int)MiscExtensions.LinearFloatLerp(20, 0, i / (int)cols, fils), 255, 255, 255); 79 | RockstarTile.Draw(); 80 | } 81 | } 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /MenuExample/MenuExample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {79D9A09F-1999-4148-9BA0-20AEBA9B3C8B} 8 | Library 9 | Properties 10 | MenuExample 11 | MenuExample.net 12 | v4.5.2 13 | 512 14 | 15 | 16 | true 17 | embedded 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\packages\CitizenFX.Core.Client.1.0.4207\lib\net45\CitizenFX.Core.Client.dll 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | {f3e16ed9-dbf7-4e7b-b04b-9b24b11891d3} 53 | NativeUI 54 | 55 | 56 | 57 | 58 | 59 | 60 | 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | *.dll 5 | .vs/ 6 | 7 | # User-specific files 8 | *.suo 9 | *.user 10 | *.sln.docstates 11 | 12 | # Build results 13 | [Dd]ebug/ 14 | [Dd]ebugPublic/ 15 | [Rr]elease/ 16 | x64/ 17 | build/ 18 | bld/ 19 | [Bb]in/ 20 | [Oo]bj/ 21 | 22 | # Roslyn cache directories 23 | *.ide/ 24 | 25 | # MSTest test Results 26 | [Tt]est[Rr]esult*/ 27 | [Bb]uild[Ll]og.* 28 | 29 | #NUNIT 30 | *.VisualState.xml 31 | TestResult.xml 32 | 33 | # Build Results of an ATL Project 34 | [Dd]ebugPS/ 35 | [Rr]eleasePS/ 36 | dlldata.c 37 | 38 | *_i.c 39 | *_p.c 40 | *_i.h 41 | *.ilk 42 | *.meta 43 | *.obj 44 | *.pch 45 | *.pdb 46 | *.pgc 47 | *.pgd 48 | *.rsp 49 | *.sbr 50 | *.tlb 51 | *.tli 52 | *.tlh 53 | *.tmp 54 | *.tmp_proj 55 | *.log 56 | *.vspscc 57 | *.vssscc 58 | .builds 59 | *.pidb 60 | *.svclog 61 | *.scc 62 | 63 | # Chutzpah Test files 64 | _Chutzpah* 65 | 66 | # Visual C++ cache files 67 | ipch/ 68 | *.aps 69 | *.ncb 70 | *.opensdf 71 | *.sdf 72 | *.cachefile 73 | 74 | # Visual Studio profiler 75 | *.psess 76 | *.vsp 77 | *.vspx 78 | 79 | # TFS 2012 Local Workspace 80 | $tf/ 81 | 82 | # Guidance Automation Toolkit 83 | *.gpState 84 | 85 | # ReSharper is a .NET coding add-in 86 | _ReSharper*/ 87 | *.[Rr]e[Ss]harper 88 | *.DotSettings.user 89 | 90 | # JustCode is a .NET coding addin-in 91 | .JustCode 92 | 93 | # TeamCity is a build add-in 94 | _TeamCity* 95 | 96 | # DotCover is a Code Coverage Tool 97 | *.dotCover 98 | 99 | # NCrunch 100 | _NCrunch_* 101 | .*crunch*.local.xml 102 | 103 | # MightyMoose 104 | *.mm.* 105 | AutoTest.Net/ 106 | 107 | # Web workbench (sass) 108 | .sass-cache/ 109 | 110 | # Installshield output folder 111 | [Ee]xpress/ 112 | 113 | # DocProject is a documentation generator add-in 114 | DocProject/buildhelp/ 115 | DocProject/Help/*.HxT 116 | DocProject/Help/*.HxC 117 | DocProject/Help/*.hhc 118 | DocProject/Help/*.hhk 119 | DocProject/Help/*.hhp 120 | DocProject/Help/Html2 121 | DocProject/Help/html 122 | 123 | # Click-Once directory 124 | publish/ 125 | 126 | # Publish Web Output 127 | *.[Pp]ublish.xml 128 | *.azurePubxml 129 | ## TODO: Comment the next line if you want to checkin your 130 | ## web deploy settings but do note that will include unencrypted 131 | ## passwords 132 | #*.pubxml 133 | 134 | # NuGet Packages Directory 135 | packages/* 136 | ## TODO: If the tool you use requires repositories.config 137 | ## uncomment the next line 138 | #!packages/repositories.config 139 | 140 | # Enable "build/" folder in the NuGet Packages folder since 141 | # NuGet packages use it for MSBuild targets. 142 | # This line needs to be after the ignore of the build folder 143 | # (and the packages folder if the line above has been uncommented) 144 | !packages/build/ 145 | 146 | # Windows Azure Build Output 147 | csx/ 148 | *.build.csdef 149 | 150 | # Windows Store app package directory 151 | AppPackages/ 152 | 153 | # Others 154 | sql/ 155 | *.Cache 156 | ClientBin/ 157 | [Ss]tyle[Cc]op.* 158 | ~$* 159 | *~ 160 | *.dbmdl 161 | *.dbproj.schemaview 162 | *.pfx 163 | *.publishsettings 164 | node_modules/ 165 | bower_components/ 166 | 167 | # RIA/Silverlight projects 168 | Generated_Code/ 169 | 170 | # Backup & report files from converting an old project file 171 | # to a newer Visual Studio version. Backup files are not needed, 172 | # because we have git ;-) 173 | _UpgradeReport_Files/ 174 | Backup*/ 175 | UpgradeLog*.XML 176 | UpgradeLog*.htm 177 | 178 | # SQL Server files 179 | *.mdf 180 | *.ldf 181 | 182 | # Business Intelligence projects 183 | *.rdl.data 184 | *.bim.layout 185 | *.bim_*.settings 186 | 187 | # Microsoft Fakes 188 | FakesAssemblies/ 189 | 190 | # LightSwitch generated files 191 | GeneratedArtifacts/ 192 | _Pvt_Extensions/ 193 | ModelManifest.xml -------------------------------------------------------------------------------- /NativeUI/Panels/UIMenuStatisticsPanel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | using System.Threading.Tasks; 4 | using CitizenFX.Core.UI; 5 | 6 | namespace NativeUI 7 | { 8 | public class UIMenuStatisticsPanel : UIMenuPanel 9 | { 10 | private List Items = new List(); 11 | private bool Divider; 12 | 13 | public UIMenuStatisticsPanel() 14 | { 15 | Background = new UIResRectangle(new Point(0, 0), new Size(431, 47), Color.FromArgb(170, 0, 0, 0)); 16 | Divider = true; 17 | } 18 | 19 | public void AddStatistics (string Name) 20 | { 21 | StatisticsForPanel items = new StatisticsForPanel 22 | { 23 | Text = new UIResText(Name ?? "", new Point(0, 0), .35f, Color.FromArgb(255, 255, 255), CitizenFX.Core.UI.Font.ChaletLondon, Alignment.Left), 24 | BackgroundProgressBar = new UIResRectangle(new Point(0, 0), new Size(200, 10), Color.FromArgb(100, 255, 255, 255)), 25 | ProgressBar = new UIResRectangle(new Point(0, 0), new Size(100, 10), Color.FromArgb(255, 255, 255, 255)), 26 | Divider = new UIResRectangle[5] 27 | { 28 | new UIResRectangle(new Point(0,0), new Size(2,10), Color.FromArgb(255, 0,0,0)), 29 | new UIResRectangle(new Point(0,0), new Size(2,10), Color.FromArgb(255, 0,0,0)), 30 | new UIResRectangle(new Point(0,0), new Size(2,10), Color.FromArgb(255, 0,0,0)), 31 | new UIResRectangle(new Point(0,0), new Size(2,10), Color.FromArgb(255, 0,0,0)), 32 | new UIResRectangle(new Point(0,0), new Size(2,10), Color.FromArgb(255, 0,0,0)) 33 | } 34 | }; 35 | Items.Add(items); 36 | } 37 | 38 | public float GetPercentage(int ItemId) 39 | { 40 | return Items[ItemId].ProgressBar.Size.Width * 2f; 41 | } 42 | 43 | public void SetPercentage(int ItemId, float number) 44 | { 45 | if (number <= 0) 46 | Items[ItemId].ProgressBar.Size = new SizeF(0, Items[ItemId].ProgressBar.Size.Height); 47 | else 48 | { 49 | if (number <= 100) 50 | Items[ItemId].ProgressBar.Size = new SizeF(number * 2f, Items[ItemId].ProgressBar.Size.Height); 51 | else 52 | Items[ItemId].ProgressBar.Size = new SizeF(100f * 2f, Items[ItemId].ProgressBar.Size.Height); 53 | 54 | } 55 | } 56 | 57 | internal override void Position(float y) 58 | { 59 | float Y = y + 35; 60 | float ParentOffsetX = ParentItem.Offset.X; 61 | int ParentOffsetWidth = ParentItem.Parent.WidthOffset; 62 | Background.Position = new PointF(ParentOffsetX, Y); 63 | for (int i = 0; i < Items.Count; i++) 64 | { 65 | int OffsetItemCount = 40 * (i + 1); 66 | Items[i].Text.Position = new PointF(ParentOffsetX + (ParentOffsetWidth / 2) + 13, Y - 34 + OffsetItemCount); 67 | Items[i].BackgroundProgressBar.Position = new PointF(ParentOffsetX + (ParentOffsetWidth / 2) + 200, Y - 22 + OffsetItemCount); 68 | Items[i].ProgressBar.Position = new PointF(ParentOffsetX + (ParentOffsetWidth / 2) + 200, Y - 22 + OffsetItemCount); 69 | if (Divider) 70 | { 71 | for (int _ = 0; _ < Items[i].Divider.Length; _++) 72 | { 73 | int DividerOffsetWidth = _ * 40; 74 | Items[i].Divider[_].Position = new PointF(ParentOffsetX + (ParentOffsetWidth / 2) + 200 + DividerOffsetWidth, Y - 22 + OffsetItemCount); 75 | Background.Size = new SizeF(431 + ParentItem.Parent.WidthOffset, 47 + OffsetItemCount - 39); 76 | } 77 | } 78 | } 79 | } 80 | 81 | internal async override Task Draw() 82 | { 83 | Background.Draw(); 84 | for (int i=0; i 27 | /// List item with items generated at runtime 28 | /// 29 | /// Label text 30 | public UIMenuDynamicListItem(string text, string startingItem, DynamicListItemChangeCallback changeCallback) : this(text, null, startingItem, changeCallback) 31 | { 32 | } 33 | 34 | /// 35 | /// List item with items generated at runtime 36 | /// 37 | /// Label text 38 | /// Item description 39 | public UIMenuDynamicListItem(string text, string description, string startingItem, DynamicListItemChangeCallback changeCallback) : base(text, description) 40 | { 41 | const int y = 0; 42 | _arrowLeft = new Sprite("commonmenu", "arrowleft", new PointF(110, 105 + y), new SizeF(30, 30)); 43 | _arrowRight = new Sprite("commonmenu", "arrowright", new PointF(280, 105 + y), new SizeF(30, 30)); 44 | _itemText = new UIResText("", new PointF(290, y + 104), 0.35f, Colors.White, Font.ChaletLondon, 45 | Alignment.Right); 46 | 47 | CurrentListItem = startingItem; 48 | Callback = changeCallback; 49 | } 50 | 51 | 52 | /// 53 | /// Change item's position. 54 | /// 55 | /// New Y position. 56 | public override void Position(int y) 57 | { 58 | _arrowLeft.Position = new PointF(300 + Offset.X + Parent.WidthOffset, 147 + y + Offset.Y); 59 | _arrowRight.Position = new PointF(400 + Offset.X + Parent.WidthOffset, 147 + y + Offset.Y); 60 | _itemText.Position = new PointF(300 + Offset.X + Parent.WidthOffset, y + 147 + Offset.Y); 61 | base.Position(y); 62 | } 63 | 64 | /// 65 | /// Draw item. 66 | /// 67 | public override async Task Draw() 68 | { 69 | base.Draw(); 70 | 71 | string caption = CurrentListItem; 72 | float offset = ScreenTools.GetTextWidth(caption, _itemText.Font, _itemText.Scale); 73 | 74 | _itemText.Color = Enabled ? Selected ? Colors.Black : Colors.WhiteSmoke : Color.FromArgb(163, 159, 148); 75 | 76 | _itemText.Caption = caption; 77 | 78 | _arrowLeft.Color = Enabled ? Selected ? Colors.Black : Colors.WhiteSmoke : Color.FromArgb(163, 159, 148); 79 | _arrowRight.Color = Enabled ? Selected ? Colors.Black : Colors.WhiteSmoke : Color.FromArgb(163, 159, 148); 80 | 81 | _arrowLeft.Position = new PointF(375 - (int)offset + Offset.X + Parent.WidthOffset, _arrowLeft.Position.Y); 82 | if (Selected) 83 | { 84 | _arrowLeft.Draw(); 85 | _arrowRight.Draw(); 86 | _itemText.Position = new PointF(403 + Offset.X + Parent.WidthOffset, _itemText.Position.Y); 87 | } 88 | else 89 | { 90 | _itemText.Position = new PointF(418 + Offset.X + Parent.WidthOffset, _itemText.Position.Y); 91 | } 92 | _itemText.Draw(); 93 | } 94 | 95 | public override void SetRightBadge(BadgeStyle badge) 96 | { 97 | throw new Exception("UIMenuListItem cannot have a right badge."); 98 | } 99 | 100 | public override void SetRightLabel(string text) 101 | { 102 | throw new Exception("UIMenuListItem cannot have a right label."); 103 | } 104 | 105 | public string CurrentItem() 106 | { 107 | return CurrentListItem; 108 | } 109 | } 110 | } -------------------------------------------------------------------------------- /NativeUI/Items/UIMenuColoredItem.cs: -------------------------------------------------------------------------------- 1 | using CitizenFX.Core.UI; 2 | using System; 3 | using System.Drawing; 4 | using System.Threading.Tasks; 5 | 6 | namespace NativeUI 7 | { 8 | [Obsolete("UIMenuColoredItem is deprecated: use UIMenuItem(text, description, mainColor, hilightColor) instead", true)] 9 | public class UIMenuColoredItem : UIMenuItem 10 | { 11 | public Color MainColor { get; set; } 12 | public Color HighlightColor { get; set; } 13 | 14 | public Color TextColor { get; set; } 15 | public Color HighlightedTextColor { get; set; } 16 | 17 | public UIMenuColoredItem(string label, Color color, Color highlightColor) : base(label, "") 18 | { 19 | MainColor = color; 20 | HighlightColor = highlightColor; 21 | 22 | TextColor = Colors.White; 23 | HighlightedTextColor = Colors.Black; 24 | 25 | Init(); 26 | } 27 | 28 | public UIMenuColoredItem(string label, string description, Color color, Color highlightColor) : base(label, description) 29 | { 30 | MainColor = color; 31 | HighlightColor = highlightColor; 32 | 33 | TextColor = Colors.White; 34 | HighlightedTextColor = Colors.Black; 35 | 36 | Init(); 37 | } 38 | 39 | protected void Init() 40 | { 41 | _selectedSprite = new Sprite("commonmenu", "gradient_nav", new PointF(0, 0), new SizeF(431, 38), 0, HighlightColor); 42 | _rectangle = new UIResRectangle(new PointF(0, 0), new SizeF(431, 38), Color.FromArgb(150, 0, 0, 0)); 43 | _text = new UIResText(Text, new PointF(8, 0), 0.33f, Colors.WhiteSmoke, CitizenFX.Core.UI.Font.ChaletLondon, Alignment.Left); 44 | Description = Description; 45 | 46 | _badgeLeft = new Sprite("commonmenu", "", new PointF(0, 0), new SizeF(40, 40)); 47 | _badgeRight = new Sprite("commonmenu", "", new PointF(0, 0), new SizeF(40, 40)); 48 | 49 | _labelText = new UIResText("", new PointF(0, 0), 0.35f) { TextAlignment = Alignment.Right }; 50 | } 51 | 52 | 53 | public override async Task Draw() 54 | { 55 | _rectangle.Size = new SizeF(431 + Parent.WidthOffset, 38); 56 | _selectedSprite.Size = new SizeF(431 + Parent.WidthOffset, 38); 57 | 58 | if (Hovered && !Selected) 59 | { 60 | _rectangle.Color = Color.FromArgb(20, 255, 255, 255); 61 | _rectangle.Draw(); 62 | } 63 | if (Selected) 64 | { 65 | _selectedSprite.Color = HighlightColor; 66 | _selectedSprite.Draw(); 67 | } 68 | else 69 | { 70 | _selectedSprite.Color = MainColor; 71 | _selectedSprite.Draw(); 72 | } 73 | 74 | _text.Color = Enabled ? Selected ? HighlightedTextColor : TextColor : Color.FromArgb(163, 159, 148); 75 | 76 | if (LeftBadge != BadgeStyle.None) 77 | { 78 | _text.Position = new PointF(35 + Offset.X, _text.Position.Y); 79 | _badgeLeft.TextureDict = BadgeToSpriteLib(LeftBadge); 80 | _badgeLeft.TextureName = BadgeToSpriteName(LeftBadge, Selected); 81 | _badgeLeft.Color = BadgeToColor(LeftBadge, Selected); 82 | _badgeLeft.Draw(); 83 | } 84 | else 85 | { 86 | _text.Position = new PointF(8 + Offset.X, _text.Position.Y); 87 | } 88 | 89 | if (RightBadge != BadgeStyle.None) 90 | { 91 | _badgeRight.Position = new PointF(385 + Offset.X + Parent.WidthOffset, _badgeRight.Position.Y); 92 | _badgeRight.TextureDict = BadgeToSpriteLib(RightBadge); 93 | _badgeRight.TextureName = BadgeToSpriteName(RightBadge, Selected); 94 | _badgeRight.Color = BadgeToColor(RightBadge, Selected); 95 | _badgeRight.Draw(); 96 | } 97 | 98 | if (!string.IsNullOrWhiteSpace(RightLabel)) 99 | { 100 | _labelText.Position = new PointF(420 + Offset.X + Parent.WidthOffset, _labelText.Position.Y); 101 | _labelText.Caption = RightLabel; 102 | _labelText.Color = _text.Color = Enabled ? Selected ? HighlightedTextColor : TextColor : Color.FromArgb(163, 159, 148); 103 | _labelText.Draw(); 104 | } 105 | _text.Draw(); 106 | } 107 | } 108 | } -------------------------------------------------------------------------------- /NativeUI/Items/UIMenuCheckboxItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Threading.Tasks; 4 | 5 | namespace NativeUI 6 | { 7 | public enum UIMenuCheckboxStyle 8 | { 9 | Cross, 10 | Tick 11 | } 12 | 13 | public class UIMenuCheckboxItem : UIMenuItem 14 | { 15 | protected internal Sprite _checkedSprite; 16 | 17 | /// 18 | /// Triggered when the checkbox state is changed. 19 | /// 20 | public event ItemCheckboxEvent CheckboxEvent; 21 | 22 | public UIMenuCheckboxStyle Style { get; set; } 23 | 24 | /// 25 | /// Checkbox item with a toggleable checkbox. 26 | /// 27 | /// Item label. 28 | /// Boolean value whether the checkbox is checked. 29 | public UIMenuCheckboxItem(string text, bool check) : this(text, check, "") 30 | { 31 | } 32 | 33 | /// 34 | /// Checkbox item with a toggleable checkbox. 35 | /// 36 | /// Item label. 37 | /// Boolean value whether the checkbox is checked. 38 | /// Description for this item. 39 | public UIMenuCheckboxItem(string text, bool check, string description) : this(text, UIMenuCheckboxStyle.Tick, check, description, Color.Transparent, Color.FromArgb(255, 255, 255, 255)) 40 | { 41 | } 42 | 43 | /// 44 | /// Checkbox item with a toggleable checkbox. 45 | /// 46 | /// Item label. 47 | /// CheckBox style (Tick or Cross). 48 | /// Boolean value whether the checkbox is checked. 49 | /// Description for this item. 50 | public UIMenuCheckboxItem(string text, UIMenuCheckboxStyle style, bool check, string description) : this(text, style, check, description, Color.Transparent, Color.FromArgb(255, 255, 255, 255)) 51 | { 52 | } 53 | 54 | /// 55 | /// Checkbox item with a toggleable checkbox. 56 | /// 57 | /// Item label. 58 | /// CheckBox style (Tick or Cross). 59 | /// Boolean value whether the checkbox is checked. 60 | /// Description for this item. 61 | /// Main item color. 62 | /// Highlight item color. 63 | public UIMenuCheckboxItem(string text, UIMenuCheckboxStyle style, bool check, string description, Color mainColor, Color highlightColor) : base(text, description, mainColor, highlightColor) 64 | { 65 | const int y = 0; 66 | Style = style; 67 | _checkedSprite = new Sprite("commonmenu", "shop_box_blank", new PointF(410, y + 95), new SizeF(50, 50)); 68 | Checked = check; 69 | } 70 | 71 | 72 | /// 73 | /// Change or get whether the checkbox is checked. 74 | /// 75 | public bool Checked { get; set; } 76 | 77 | /// 78 | /// Change item's position. 79 | /// 80 | /// New Y value. 81 | public override void Position(int y) 82 | { 83 | base.Position(y); 84 | _checkedSprite.Position = new PointF(380 + Offset.X + Parent.WidthOffset, y + 138 + Offset.Y); 85 | } 86 | 87 | 88 | /// 89 | /// Draw item. 90 | /// 91 | public override async Task Draw() 92 | { 93 | base.Draw(); 94 | _checkedSprite.Position = new PointF(380 + Offset.X + Parent.WidthOffset, _checkedSprite.Position.Y); 95 | _checkedSprite.TextureName = Selected ? (Checked ? (Style == UIMenuCheckboxStyle.Tick ? "shop_box_tickb" : "shop_box_crossb") : "shop_box_blankb") : Checked ? (Style == UIMenuCheckboxStyle.Tick ? "shop_box_tick" : "shop_box_cross") : "shop_box_blank"; 96 | _checkedSprite.Draw(); 97 | } 98 | 99 | public void CheckboxEventTrigger() 100 | { 101 | CheckboxEvent?.Invoke(this, Checked); 102 | } 103 | 104 | public override void SetRightBadge(BadgeStyle badge) 105 | { 106 | throw new Exception("UIMenuCheckboxItem cannot have a right badge."); 107 | } 108 | 109 | public override void SetRightLabel(string text) 110 | { 111 | throw new Exception("UIMenuListItem cannot have a right label."); 112 | } 113 | } 114 | } -------------------------------------------------------------------------------- /NativeUI/Items/UIMenuProgressItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Threading.Tasks; 5 | using CitizenFX.Core; 6 | using CitizenFX.Core.Native; 7 | 8 | namespace NativeUI 9 | { 10 | public class UIMenuProgressItem : UIMenuItem 11 | { 12 | protected UIResRectangle _background; 13 | protected int Items; 14 | protected bool Pressed; 15 | protected bool Counter; 16 | protected float _max = 407.5f; 17 | protected UIMenuGridAudio Audio; 18 | protected UIResRectangle _bar; 19 | protected int _index; 20 | public int Index 21 | { 22 | get { return _index; } 23 | set 24 | { 25 | if (value > Items) 26 | _index = Items; 27 | else if (value < 0) 28 | _index = 0; 29 | else 30 | _index = value; 31 | if (Counter) 32 | SetRightLabel(_index + "/" + Items); 33 | else 34 | SetRightLabel("" + _index); 35 | 36 | UpdateBar(); 37 | } 38 | } 39 | 40 | protected void UpdateBar() 41 | { 42 | _bar.Size = new SizeF(Index *(_max / Items), _bar.Size.Height); 43 | } 44 | 45 | public event OnProgressChanged OnProgressChanged; 46 | public event OnProgressSelected OnProgressSelected; 47 | 48 | public UIMenuProgressItem(string text, string description, int maxItems, int index, bool counter) : base(text, description) 49 | { 50 | Items = maxItems; 51 | _index = index; 52 | Counter = counter; 53 | _max = 407.5f; 54 | Audio = new UIMenuGridAudio("CONTINUOUS_SLIDER", "HUD_FRONTEND_DEFAULT_SOUNDSET", 0); 55 | _background = new UIResRectangle(new PointF(0, 0), new SizeF(415, 14), Color.FromArgb(255, 0, 0, 0)); 56 | _bar = new UIResRectangle(new PointF(0, 0), new SizeF(407.5f, 7.5f)); 57 | if (Counter) 58 | SetRightLabel(_index + "/" + Items); 59 | else 60 | SetRightLabel(""+_index); 61 | 62 | UpdateBar(); 63 | } 64 | 65 | public void ProgressChanged(UIMenu Menu, UIMenuProgressItem Item, int index) 66 | { 67 | OnProgressChanged?.Invoke(Menu, Item, index); 68 | } 69 | 70 | public void ProgressSelected(UIMenu Menu, UIMenuProgressItem Item, int index) 71 | { 72 | OnProgressSelected?.Invoke(Menu, Item, index); 73 | } 74 | 75 | public override void SetRightBadge(BadgeStyle badge) 76 | { 77 | throw new Exception("UIMenuProgressItem cannot have a right badge."); 78 | } 79 | 80 | public override void Position(int y) 81 | { 82 | _rectangle.Position = new PointF(Offset.X, y + 144 + Offset.Y); 83 | _selectedSprite.Position = new PointF(0 + Offset.X, y + 144 + Offset.Y); 84 | _text.Position = new PointF(8 + Offset.X, y + 141.5f + Offset.Y); 85 | 86 | _labelText.Position = new PointF(420 + Offset.X, y + 141.5f + Offset.Y); 87 | 88 | _max = 407.5f + Parent.WidthOffset; 89 | _background.Size = new SizeF(415f + Parent.WidthOffset, 14f); 90 | _background.Position = new PointF(8f + Offset.X, 170f + y + Offset.Y); 91 | _bar.Position = new PointF(11.75f + Offset.X, 172.5f + y + Offset.Y); 92 | } 93 | 94 | public void CalculateProgress(float CursorX) 95 | { 96 | var Progress = CursorX - _bar.Position.X; 97 | Index = (int)Math.Round(Items * ((Progress >= 0f && Progress <= _max ) ? Progress : (Progress < 0) ? 0 : _max) / _max); 98 | } 99 | 100 | public async void Functions() 101 | { 102 | if (ScreenTools.IsMouseInBounds(new PointF(_bar.Position.X, _bar.Position.Y - 7.5f), new SizeF(_max, _bar.Size.Height + 19))) 103 | { 104 | if (API.IsDisabledControlPressed(0, 24)) 105 | { 106 | if (!Pressed) 107 | { 108 | Pressed = true; 109 | Audio.Id = API.GetSoundId(); 110 | API.PlaySoundFrontend(Audio.Id, Audio.Slider, Audio.Library, true); 111 | while (API.IsDisabledControlPressed(0, 24) && ScreenTools.IsMouseInBounds(new PointF(_bar.Position.X, _bar.Position.Y - 7.5f), new SizeF(_max, _bar.Size.Height + 19))) 112 | { 113 | await BaseScript.Delay(0); 114 | float CursorX = API.GetDisabledControlNormal(0, 239) * Resolution.Width; 115 | CalculateProgress(CursorX); 116 | Parent.ProgressChange(this, _index); 117 | ProgressChanged(Parent, this, _index); 118 | 119 | } 120 | API.StopSound(Audio.Id); 121 | API.ReleaseSoundId(Audio.Id); 122 | Pressed = false; 123 | } 124 | } 125 | } 126 | } 127 | 128 | public async override Task Draw() 129 | { 130 | base.Draw(); 131 | if (Selected) 132 | { 133 | _background.Color = Colors.Black; 134 | _bar.Color = Colors.White; 135 | } 136 | else 137 | { 138 | _background.Color = Colors.White; 139 | _bar.Color = Colors.Black; 140 | } 141 | Functions(); 142 | _background.Draw(); 143 | _bar.Draw(); 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /NativeUI/Panels/UIMenuPercentagePanel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Threading.Tasks; 5 | using CitizenFX.Core; 6 | using CitizenFX.Core.Native; 7 | using CitizenFX.Core.UI; 8 | 9 | namespace NativeUI 10 | { 11 | public class UIMenuPercentagePanel : UIMenuPanel 12 | { 13 | 14 | private UIResRectangle ActiveBar; 15 | private UIResRectangle BackgroundBar; 16 | private UIMenuGridAudio Audio; 17 | private UIResText Min; 18 | private UIResText Max; 19 | private UIResText Title; 20 | private readonly PointF safezoneOffset = ScreenTools.SafezoneBounds; 21 | private bool Pressed; 22 | public float Percentage 23 | { 24 | get 25 | { 26 | float progress = (float)Math.Round(API.GetDisabledControlNormal(0, 239) * Resolution.Width) - ActiveBar.Position.X; 27 | return (float)Math.Round(((progress >= 0 && progress <= 413) ? progress : ((progress < 0) ? 0 : 413)) / Background.Size.Width, 2); 28 | } 29 | set 30 | { 31 | float percent = (value < 0.0f) ? 0.0f : (value > 1f) ? 1.0f : value; 32 | ActiveBar.Size = new SizeF(BackgroundBar.Size.Width * percent, ActiveBar.Size.Height); 33 | } 34 | } 35 | 36 | 37 | public UIMenuPercentagePanel(string title, string MinText, string MaxText) 38 | { 39 | Enabled = true; 40 | Background = new Sprite("commonmenu", "gradient_bgd", new Point(0, 0), new Size(431, 275)); 41 | ActiveBar = new UIResRectangle(new Point(0, 0), new Size(413, 10), Color.FromArgb(245, 245, 245)); 42 | BackgroundBar = new UIResRectangle(new Point(0, 0), new Size(413, 10), Color.FromArgb(80, 80, 80)); 43 | Min = new UIResText(MinText != "" || MinText != null ? MinText : "0%", new Point(0, 0), .35f, Color.FromArgb(255, 255, 255), CitizenFX.Core.UI.Font.ChaletLondon, Alignment.Center); 44 | Max = new UIResText(MaxText != "" || MaxText != null ? MaxText : "100%", new Point(0, 0), .35f, Color.FromArgb(255, 255, 255), CitizenFX.Core.UI.Font.ChaletLondon, Alignment.Center); 45 | Title = new UIResText(title != "" || title != null ? title : "Opacity", new Point(0, 0), .35f, Color.FromArgb(255, 255, 255), CitizenFX.Core.UI.Font.ChaletLondon, Alignment.Center); 46 | Audio = new UIMenuGridAudio("CONTINUOUS_SLIDER", "HUD_FRONTEND_DEFAULT_SOUNDSET", 0); 47 | } 48 | 49 | internal override void Position(float y) 50 | { 51 | float ParentOffsetX = ParentItem.Offset.X; 52 | int ParentOffsetWidth = ParentItem.Parent.WidthOffset; 53 | Background.Position = new PointF(ParentOffsetX, 35f + y); 54 | ActiveBar.Position = new PointF(ParentOffsetX + (ParentOffsetWidth / 2) + 9, 50 + 35f + y); 55 | BackgroundBar.Position = ActiveBar.Position; 56 | Min.Position = new PointF(ParentOffsetX + (ParentOffsetWidth / 2) + 25, 15 + 35f + y); 57 | Max.Position = new PointF(ParentOffsetX + (ParentOffsetWidth / 2) + 398, 15 + 35f + y); 58 | Title.Position = new PointF(ParentOffsetX + (ParentOffsetWidth / 2) + 215.5f, 15 + 35f + y); 59 | } 60 | 61 | public void UpdateParent(float Percentage) 62 | { 63 | ParentItem.Parent.ListChange(ParentItem, ParentItem.Index); 64 | ParentItem.ListChangedTrigger(ParentItem.Index); 65 | } 66 | 67 | private async void Functions() 68 | { 69 | if (ScreenTools.IsMouseInBounds(new PointF(BackgroundBar.Position.X + safezoneOffset.X, BackgroundBar.Position.Y - 4f + safezoneOffset.Y), new SizeF(BackgroundBar.Size.Width, BackgroundBar.Size.Height + 8f))) 70 | { 71 | if (API.IsDisabledControlPressed(0, 24)) 72 | { 73 | if (!Pressed) 74 | { 75 | Pressed = true; 76 | Audio.Id = API.GetSoundId(); 77 | API.PlaySoundFrontend(Audio.Id, Audio.Slider, Audio.Library, true); 78 | } 79 | await BaseScript.Delay(0); 80 | float Progress = API.GetDisabledControlNormal(0, 239) * Resolution.Width; 81 | Progress -= ActiveBar.Position.X + safezoneOffset.X; 82 | ActiveBar.Size = new SizeF(Progress >= 0 && Progress <= 413 ? Progress : (Progress < 0 ? 0 : 413), ActiveBar.Size.Height); 83 | UpdateParent((float)Math.Round(Progress >= 0 && Progress <= 413 ? Progress : (Progress < 0 ? 0 : 413) / BackgroundBar.Size.Width, 2)); 84 | } 85 | else 86 | { 87 | API.StopSound(Audio.Id); 88 | API.ReleaseSoundId(Audio.Id); 89 | Pressed = false; 90 | 91 | } 92 | } 93 | else 94 | { 95 | API.StopSound(Audio.Id); 96 | API.ReleaseSoundId(Audio.Id); 97 | Pressed = false; 98 | } 99 | } 100 | 101 | internal async override Task Draw() 102 | { 103 | if (Enabled) 104 | { 105 | Background.Size = new Size(431 + ParentItem.Parent.WidthOffset, 76); 106 | Background.Draw(); 107 | BackgroundBar.Draw(); 108 | ActiveBar.Draw(); 109 | Min.Draw(); 110 | Max.Draw(); 111 | Title.Draw(); 112 | Functions(); 113 | } 114 | await Task.FromResult(0); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /NativeUI/Hud/Markers/Marker.cs: -------------------------------------------------------------------------------- 1 | using CitizenFX.Core; 2 | using System; 3 | using System.Drawing; 4 | using System.Threading.Tasks; 5 | using static CitizenFX.Core.Native.API; 6 | 7 | namespace NativeUI 8 | { 9 | public class Marker 10 | { 11 | internal float _height = 0; 12 | private float distance; 13 | 14 | public MarkerType MarkerType { get; set; } 15 | /// 16 | /// Hardcoded to be not more than 250units away. 17 | /// 18 | public float Distance { get => distance; set => distance = value > 250f ? 250f : value; } 19 | public Vector3 Position { get; set; } 20 | 21 | // this is optional and default to 0 22 | public Vector3 Direction { get; set; } = Vector3.Zero; 23 | // this is optional and default to 0 24 | public Vector3 Rotation { get; set; } = Vector3.Zero; 25 | 26 | public Vector3 Scale { get; set; } = new Vector3(1.5f); 27 | public Color Color { get; set; } 28 | public bool BobUpDown { get; set; } 29 | public bool Rotate { get; set; } 30 | public bool FaceCamera { get; set; } 31 | public bool IsInMarker { get; private set; } 32 | public bool IsInRange { get => MenuPool.PlayerPed.IsInRangeOf(Position, Distance); } 33 | public bool CheckZ { get; set; } 34 | /// 35 | /// It doesn't work on water and under the map! 36 | /// 37 | public bool PlaceOnGround { get; set; } 38 | 39 | /// 40 | /// Creates a Marker in a world position 41 | /// 42 | /// The type of marker 43 | /// Position in world coords of the marker 44 | /// Drawing distance, if you're more distant than this value the marker won't be drawn 45 | /// Color of the marker 46 | /// The marker will bounce up and down 47 | /// The marker will rotate on its Z axiz 48 | /// The marker will face camera 49 | public Marker(MarkerType type, Vector3 position, float distance, Color color, bool placeOnGround = false, bool bobUpDown = false, bool rotate = false, bool faceCamera = false) 50 | { 51 | MarkerType = type; 52 | Position = position; 53 | Distance = distance; 54 | Color = color; 55 | BobUpDown = bobUpDown; 56 | Rotate = rotate; 57 | FaceCamera = faceCamera; 58 | PlaceOnGround = placeOnGround; 59 | if (Rotate && FaceCamera) 60 | Rotate = false; 61 | } 62 | 63 | /// 64 | /// Creates a Marker in a world position 65 | /// 66 | /// The type of marker 67 | /// Position in world coords of the marker 68 | /// Dimensions of the marker 69 | /// Drawing distance, if you're more distant than this value the marker won't be drawn 70 | /// Color of the marker 71 | /// The marker will bounce up and down 72 | /// The marker will rotate on its Z axiz 73 | /// The marker will face camera 74 | public Marker(MarkerType type, Vector3 position, Vector3 scale, float distance, Color color, bool placeOnGround = false, bool bobUpDown = false, bool rotate = false, bool faceCamera = false) 75 | { 76 | MarkerType = type; 77 | Position = position; 78 | Scale = scale; 79 | Distance = distance; 80 | Color = color; 81 | BobUpDown = bobUpDown; 82 | Rotate = rotate; 83 | PlaceOnGround = placeOnGround; 84 | FaceCamera = faceCamera; 85 | if (Rotate && FaceCamera) 86 | Rotate = false; 87 | } 88 | 89 | public void Draw() 90 | { 91 | // [Position.Z != _height] means that we make the check only if we change position 92 | // but if we change position and the Z is still the same then we don't need to check again 93 | // We draw it with _height + 0.1 to ensure marker drawing (like horizontal circles) 94 | if (IsInRange && PlaceOnGround && (Position.Z != _height + 0.1f)) 95 | { 96 | if (GetGroundZFor_3dCoord(Position.X, Position.Y, Position.Z, ref _height, false)) 97 | Position = new Vector3(Position.X, Position.Y, _height + 0.03f); 98 | } 99 | World.DrawMarker(MarkerType, Position, Direction, Rotation, Scale, Color, BobUpDown, FaceCamera, Rotate); 100 | if (CheckZ) 101 | { 102 | float distanceSquared = Position.DistanceToSquared(MenuPool.PlayerPed.Position); 103 | IsInMarker = (distanceSquared < Math.Pow(Scale.X / 2, 2) || distanceSquared < Math.Pow(Scale.Y / 2, 2)) || distanceSquared < Math.Pow(Scale.Z / 2, 2); 104 | } 105 | else 106 | { 107 | var distanceSquared = Position.DistanceToSquared2D(MenuPool.PlayerPed.Position); 108 | IsInMarker = distanceSquared <= Math.Pow(Scale.X / 2, 2) || distanceSquared <= Math.Pow(Scale.Y / 2, 2); 109 | } 110 | } 111 | } 112 | } -------------------------------------------------------------------------------- /NativeUI/Panels/UIMenuVerticalOneLineGridPanel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Threading.Tasks; 5 | using CitizenFX.Core; 6 | using CitizenFX.Core.Native; 7 | using CitizenFX.Core.UI; 8 | 9 | namespace NativeUI 10 | { 11 | public class UIMenuVerticalOneLineGridPanel : UIMenuPanel 12 | { 13 | private UIResText Top; 14 | private UIResText Bottom; 15 | private Sprite Grid; 16 | private Sprite Circle; 17 | private UIMenuGridAudio Audio; 18 | private PointF SetCirclePosition; 19 | protected bool CircleLocked; 20 | protected bool Pressed; 21 | private readonly PointF safezoneOffset = ScreenTools.SafezoneBounds; 22 | public PointF CirclePosition 23 | { 24 | get 25 | { 26 | return new PointF((float)Math.Round((Circle.Position.X - (Grid.Position.X + 20) + (Circle.Size.Width / 2)) / (Grid.Size.Width - 40), 2), (float)Math.Round((Circle.Position.Y - (Grid.Position.Y + 20) + (Circle.Size.Height / 2)) / (Grid.Size.Height - 40), 2)); 27 | } 28 | set 29 | { 30 | Circle.Position.X = (Grid.Position.X + 20) + ((Grid.Size.Width - 40) * (value.X >= 0f && value.X <= 1.0f ? value.X : 0.0f)) - (Circle.Size.Width / 2); 31 | Circle.Position.Y = (Grid.Position.Y + 20) + ((Grid.Size.Height - 40) * (value.Y >= 0f && value.Y <= 1.0f ? value.Y : 0.0f)) - (Circle.Size.Height / 2); 32 | } 33 | } 34 | 35 | public UIMenuVerticalOneLineGridPanel(string TopText, string BottomText, float circlePositionY = .5f) 36 | { 37 | Enabled = true; 38 | Background = new Sprite("commonmenu", "gradient_bgd", new Point(0, 0), new Size(431, 275)); 39 | Grid = new Sprite("NativeUI", "vertical_grid", new Point(0, 0), new Size(200, 200), 0f, Color.FromArgb(255, 255, 255)); 40 | Circle = new Sprite("mpinventory", "in_world_circle", new Point(0, 0), new Size(20, 20), 0f, Color.FromArgb(255, 255, 255)); 41 | Audio = new UIMenuGridAudio("CONTINUOUS_SLIDER", "HUD_FRONTEND_DEFAULT_SOUNDSET", 0); 42 | Top = new UIResText(TopText ?? "Up", new Point(0, 0), .35f, Color.FromArgb(255, 255, 255), CitizenFX.Core.UI.Font.ChaletLondon, Alignment.Center); 43 | Bottom = new UIResText(BottomText ?? "Down", new Point(0, 0), .35f, Color.FromArgb(255, 255, 255), CitizenFX.Core.UI.Font.ChaletLondon, Alignment.Center); 44 | SetCirclePosition = new PointF(.5f, circlePositionY != 0 ? circlePositionY : .5f); 45 | } 46 | 47 | internal override void Position(float y) 48 | { 49 | float ParentOffsetX = ParentItem.Offset.X; 50 | int ParentOffsetWidth = ParentItem.Parent.WidthOffset; 51 | Background.Position = new PointF(ParentOffsetX, 35 + y); 52 | Grid.Position = new PointF(ParentOffsetX + 115.5f + (ParentOffsetWidth / 2), 72.5f + y); 53 | Top.Position = new PointF(ParentOffsetX + 215.5f + (ParentOffsetWidth / 2), 40f + y); 54 | Bottom.Position = new PointF(ParentOffsetX + 215.5f + (ParentOffsetWidth / 2), 275f + y); 55 | if (!CircleLocked) 56 | { 57 | CircleLocked = true; 58 | CirclePosition = SetCirclePosition; 59 | } 60 | } 61 | 62 | private void UpdateParent(float Y) 63 | { 64 | ParentItem.Parent.ListChange(ParentItem, ParentItem.Index); 65 | ParentItem.ListChangedTrigger(ParentItem.Index); 66 | } 67 | 68 | private async void Functions() 69 | { 70 | if (ScreenTools.IsMouseInBounds(new PointF(Grid.Position.X + 20f + safezoneOffset.X, Grid.Position.Y + 20f + safezoneOffset.Y), new SizeF(Grid.Size.Width - 40f, Grid.Size.Height - 40f))) 71 | { 72 | if (API.IsDisabledControlPressed(0, 24)) 73 | { 74 | if (!Pressed) 75 | { 76 | Pressed = true; 77 | Audio.Id = API.GetSoundId(); 78 | API.PlaySoundFrontend(Audio.Id, Audio.Slider, Audio.Library, true); 79 | } 80 | await BaseScript.Delay(0); 81 | float mouseY = API.GetDisabledControlNormal(0, 240) * Resolution.Height; 82 | mouseY -= (Circle.Size.Height / 2) + safezoneOffset.Y; 83 | Circle.Position = new PointF(Circle.Position.X, mouseY > (Grid.Position.Y + 10 + Grid.Size.Height - 40) ? (Grid.Position.Y + 10 + Grid.Size.Height - 40) : ((mouseY < (Grid.Position.Y + 20 - (Circle.Size.Height / 2))) ? (Grid.Position.Y + 20 - (Circle.Size.Height / 2)) : mouseY)); 84 | var resultY = (float)Math.Round((Circle.Position.Y - (Grid.Position.Y + 20) + (Circle.Size.Height + 20)) / (Grid.Size.Height - 40), 2); 85 | UpdateParent(((resultY >= 0.0f && resultY <= 1.0f) ? resultY : ((resultY <= 0f) ? 0.0f : 1.0f) * 2f) - 1f); 86 | } 87 | else 88 | { 89 | API.StopSound(Audio.Id); 90 | API.ReleaseSoundId(Audio.Id); 91 | Pressed = false; 92 | } 93 | } 94 | else 95 | { 96 | API.StopSound(Audio.Id); 97 | API.ReleaseSoundId(Audio.Id); 98 | Pressed = false; 99 | } 100 | } 101 | 102 | internal async override Task Draw() 103 | { 104 | if (!Enabled) return; 105 | Background.Size = new Size(431 + ParentItem.Parent.WidthOffset, 275); 106 | Background.Draw(); 107 | Grid.Draw(); 108 | Circle.Draw(); 109 | Top.Draw(); 110 | Bottom.Draw(); 111 | Functions(); 112 | await Task.FromResult(0); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /NativeUI/Panels/UIMenuHorizontalOneLineGridPanel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Threading.Tasks; 5 | using CitizenFX.Core; 6 | using CitizenFX.Core.Native; 7 | using CitizenFX.Core.UI; 8 | 9 | namespace NativeUI 10 | { 11 | public class UIMenuHorizontalOneLineGridPanel : UIMenuPanel 12 | { 13 | private UIResText Left; 14 | private UIResText Right; 15 | private Sprite Grid; 16 | private Sprite Circle; 17 | private UIMenuGridAudio Audio; 18 | private PointF SetCirclePosition; 19 | protected bool CircleLocked; 20 | protected bool Pressed; 21 | private readonly PointF safezoneOffset = ScreenTools.SafezoneBounds; 22 | public PointF CirclePosition 23 | { 24 | get 25 | { 26 | return new PointF((float)Math.Round((Circle.Position.X - (Grid.Position.X + 20) + (Circle.Size.Width / 2)) / (Grid.Size.Width - 40), 2), (float)Math.Round((Circle.Position.Y - (Grid.Position.Y + 20) + (Circle.Size.Height / 2)) / (Grid.Size.Height - 40), 2)); 27 | } 28 | set 29 | { 30 | Circle.Position.X = (Grid.Position.X + 20) + ((Grid.Size.Width - 40) * (value.X >= 0f && value.X <= 1.0f ? value.X : 0.0f)) - (Circle.Size.Width / 2); 31 | Circle.Position.Y = (Grid.Position.Y + 20) + ((Grid.Size.Height - 40) * (value.Y >= 0f && value.Y <= 1.0f ? value.Y : 0.0f)) - (Circle.Size.Height / 2); 32 | } 33 | } 34 | 35 | public UIMenuHorizontalOneLineGridPanel(string LeftText, string RightText, float CirclePositionX = 0.5f) 36 | { 37 | Enabled = true; 38 | Background = new Sprite("commonmenu", "gradient_bgd", new Point(0, 0), new Size(431, 275)); 39 | Grid = new Sprite("NativeUI", "horizontal_grid", new Point(0, 0), new Size(200, 200), 0f, Color.FromArgb(255, 255, 255)); 40 | Circle = new Sprite("mpinventory", "in_world_circle", new Point(0, 0), new Size(20, 20), 0f, Color.FromArgb(255, 255, 255)); 41 | Audio = new UIMenuGridAudio("CONTINUOUS_SLIDER", "HUD_FRONTEND_DEFAULT_SOUNDSET", 0); 42 | Left = new UIResText(LeftText ?? "Left", new Point(0, 0), .35f, Color.FromArgb(255, 255, 255), CitizenFX.Core.UI.Font.ChaletLondon, Alignment.Center); 43 | Right = new UIResText(RightText ?? "Right", new Point(0, 0), .35f, Color.FromArgb(255, 255, 255), CitizenFX.Core.UI.Font.ChaletLondon, Alignment.Center); 44 | SetCirclePosition = new PointF(CirclePositionX, 0.5f); 45 | } 46 | 47 | internal override void Position(float y) 48 | { 49 | var Y = y + 35f; 50 | float ParentOffsetX = ParentItem.Offset.X; 51 | int ParentOffsetWidth = ParentItem.Parent.WidthOffset; 52 | Background.Position = new PointF(ParentOffsetX, Y); 53 | Grid.Position = new PointF(ParentOffsetX + 115.5f + (ParentOffsetWidth / 2), 72.5f + y); 54 | Left.Position = new PointF(ParentOffsetX + 57.75f + (ParentOffsetWidth / 2), 155f + y); 55 | Right.Position = new PointF(ParentOffsetX + 373.25f + (ParentOffsetWidth / 2), 155f + y); 56 | if (!CircleLocked) 57 | { 58 | CircleLocked = true; 59 | CirclePosition = SetCirclePosition; 60 | } 61 | } 62 | 63 | private void UpdateParent(float X) 64 | { 65 | ParentItem.Parent.ListChange(ParentItem, ParentItem.Index); 66 | ParentItem.ListChangedTrigger(ParentItem.Index); 67 | } 68 | 69 | private async void Functions() 70 | { 71 | if (ScreenTools.IsMouseInBounds(new PointF(Grid.Position.X + 20f + safezoneOffset.X, Grid.Position.Y + 20f + safezoneOffset.Y), new SizeF(Grid.Size.Width - 40f, Grid.Size.Height - 40f))) 72 | { 73 | if (API.IsDisabledControlPressed(0, 24)) 74 | { 75 | if (!Pressed) 76 | { 77 | Pressed = true; 78 | Audio.Id = API.GetSoundId(); 79 | API.PlaySoundFrontend(Audio.Id, Audio.Slider, Audio.Library, true); 80 | } 81 | float mouseX = API.GetDisabledControlNormal(0, 239) * Resolution.Width; 82 | mouseX -= (Circle.Size.Width / 2) + safezoneOffset.X; 83 | Circle.Position = new PointF(mouseX > (Grid.Position.X + 10 + Grid.Size.Width - 40) ? (Grid.Position.X + 10 + Grid.Size.Width - 40) : ((mouseX < (Grid.Position.X + 20 - (Circle.Size.Width / 2))) ? (Grid.Position.X + 20 - (Circle.Size.Width / 2)) : mouseX), Circle.Position.Y); 84 | var resultX = (float)Math.Round((Circle.Position.X - (Grid.Position.X + 20) + (Circle.Size.Width + 20)) / (Grid.Size.Width - 40), 2) + safezoneOffset.X; 85 | UpdateParent(((resultX >= 0.0f && resultX <= 1.0f) ? resultX : ((resultX <= 0f) ? 0.0f : 1.0f) * 2f) - 1f); 86 | } 87 | if (API.IsDisabledControlJustReleased(0, 24)) 88 | { 89 | API.StopSound(Audio.Id); 90 | API.ReleaseSoundId(Audio.Id); 91 | Pressed = false; 92 | } 93 | } 94 | else 95 | { 96 | API.StopSound(Audio.Id); 97 | API.ReleaseSoundId(Audio.Id); 98 | Pressed = false; 99 | } 100 | } 101 | 102 | internal async override Task Draw() 103 | { 104 | if (!Enabled) return; 105 | Background.Size = new Size(431 + ParentItem.Parent.WidthOffset, 275); 106 | Background.Draw(); 107 | Grid.Draw(); 108 | Circle.Draw(); 109 | Left.Draw(); 110 | Right.Draw(); 111 | Functions(); 112 | await Task.FromResult(0); 113 | } 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /NativeUI/Items/UIMenuSliderItem.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | using System.Threading.Tasks; 4 | 5 | namespace NativeUI 6 | { 7 | public class UIMenuSliderItem : UIMenuItem 8 | { 9 | protected internal Sprite _arrowLeft; 10 | protected internal Sprite _arrowRight; 11 | 12 | protected internal UIResRectangle _rectangleBackground; 13 | protected internal UIResRectangle _rectangleSlider; 14 | protected internal UIResRectangle _rectangleDivider; 15 | 16 | protected internal int _value = 0; 17 | protected internal int _max = 100; 18 | protected internal int _multiplier = 5; 19 | 20 | 21 | /// 22 | /// Triggered when the slider is changed. 23 | /// 24 | public event ItemSliderEvent OnSliderChanged; 25 | public bool Divider; 26 | 27 | /// 28 | /// The maximum value of the slider. 29 | /// 30 | public int Maximum 31 | { 32 | get 33 | { 34 | return _max; 35 | } 36 | set 37 | { 38 | _max = value; 39 | if (_value > value) 40 | { 41 | _value = value; 42 | } 43 | } 44 | } 45 | /// 46 | /// Curent value of the slider. 47 | /// 48 | public int Value 49 | { 50 | get 51 | { 52 | return _value; 53 | } 54 | set 55 | { 56 | if (value > _max) 57 | _value = _max; 58 | else if (value < 0) 59 | _value = 0; 60 | else 61 | _value = value; 62 | SliderChanged(_value); 63 | } 64 | } 65 | /// 66 | /// The multiplier of the left and right navigation movements. 67 | /// 68 | public int Multiplier 69 | { 70 | get 71 | { 72 | return _multiplier; 73 | } 74 | set 75 | { 76 | _multiplier = value; 77 | } 78 | } 79 | 80 | 81 | /// 82 | /// List item, with slider. 83 | /// 84 | /// Item label. 85 | /// List that contains your items. 86 | /// Index in the list. If unsure user 0. 87 | public UIMenuSliderItem(string text) : this(text, "", false) 88 | { 89 | } 90 | 91 | /// 92 | /// List item, with slider. 93 | /// 94 | /// Item label. 95 | /// List that contains your items. 96 | /// Index in the list. If unsure user 0. 97 | /// Description for this item. 98 | public UIMenuSliderItem(string text, string description) : this(text, description, false) 99 | { 100 | } 101 | 102 | /// 103 | /// List item, with slider. 104 | /// 105 | /// Item label. 106 | /// List that contains your items. 107 | /// Index in the list. If unsure user 0. 108 | /// Description for this item. 109 | /// /// Put a divider in the center of the slider 110 | public UIMenuSliderItem(string text, string description, bool divider) : base(text, description) 111 | { 112 | const int y = 0; 113 | _arrowLeft = new Sprite("commonmenutu", "arrowleft", new Point(0, 105 + y), new Size(15, 15)); 114 | _arrowRight = new Sprite("commonmenutu", "arrowright", new Point(0, 105 + y), new Size(15, 15)); 115 | _rectangleBackground = new UIResRectangle(new Point(0, 0), new Size(150, 9), Color.FromArgb(255, 4, 32, 57)); 116 | _rectangleSlider = new UIResRectangle(new Point(0, 0), new Size(75, 9), Color.FromArgb(255, 57, 116, 200)); 117 | Divider = divider; 118 | if (Divider) 119 | _rectangleDivider = new UIResRectangle(new Point(0, 0), new Size(2, 20), Colors.WhiteSmoke); 120 | else 121 | _rectangleDivider = new UIResRectangle(new Point(0, 0), new Size(2, 20), Color.Transparent); 122 | } 123 | 124 | /// 125 | /// Change item's position. 126 | /// 127 | /// New Y position. 128 | public override void Position(int y) 129 | { 130 | _rectangleBackground.Position = new PointF(250 + Offset.X, y + 158 + Offset.Y); 131 | _rectangleSlider.Position = new PointF(250 + Offset.X, y + 158 + Offset.Y); 132 | _rectangleDivider.Position = new PointF(323 + Offset.X, y + 153 + Offset.Y); 133 | _arrowLeft.Position = new PointF(235 + Offset.X + Parent.WidthOffset, 155 + y + Offset.Y); 134 | _arrowRight.Position = new PointF(400 + Offset.X + Parent.WidthOffset, 155 + y + Offset.Y); 135 | base.Position(y); 136 | } 137 | 138 | /// 139 | /// Draw item. 140 | /// 141 | public override async Task Draw() 142 | { 143 | base.Draw(); 144 | 145 | _arrowLeft.Color = Enabled ? Selected ? Colors.Black : Colors.WhiteSmoke : Color.FromArgb(163, 159, 148); 146 | _arrowRight.Color = Enabled ? Selected ? Colors.Black : Colors.WhiteSmoke : Color.FromArgb(163, 159, 148); 147 | float offset = 176 + Offset.X + _rectangleBackground.Size.Width - _rectangleSlider.Size.Width; 148 | _rectangleSlider.Position = new PointF((int)(offset + (_value / (float)_max * 73)), _rectangleSlider.Position.Y); 149 | if (Selected) 150 | { 151 | _arrowLeft.Draw(); 152 | _arrowRight.Draw(); 153 | } 154 | _rectangleBackground.Draw(); 155 | _rectangleSlider.Draw(); 156 | _rectangleDivider.Draw(); 157 | } 158 | 159 | internal virtual void SliderChanged(int value) 160 | { 161 | OnSliderChanged?.Invoke(this, value); 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /NativeUI/Hud/Notifications/NotificationChars.cs: -------------------------------------------------------------------------------- 1 | namespace NativeUI 2 | { 3 | public static class NotificationChar 4 | { 5 | public static string Abigail = "CHAR_ABIGAIL"; 6 | public static string Amanda = "CHAR_AMANDA"; 7 | public static string Ammunation = "CHAR_AMMUNATION"; 8 | public static string Andreas = "CHAR_ANDREAS"; 9 | public static string Antonia = "CHAR_ANTONIA"; 10 | public static string Ashley = "CHAR_ASHLEY"; 11 | public static string BankOfLiberty = "CHAR_BANK_BOL"; 12 | public static string BankFleeca = "CHAR_BANK_FLEECA"; 13 | public static string BankMaze = "CHAR_BANK_MAZE"; 14 | public static string Barry = "CHAR_BARRY"; 15 | public static string Beverly = "CHAR_BEVERLY"; 16 | public static string BikeSite = "CHAR_BIKESITE"; 17 | public static string BlankEntry = "CHAR_BLANK_ENTRY"; 18 | public static string Blimp = "CHAR_BLIMP"; 19 | public static string Blocked = "CHAR_BLOCKED"; 20 | public static string BoatSite = "CHAR_BOATSITE"; 21 | public static string BrokenDownGirl = "CHAR_BROKEN_DOWN_GIRL"; 22 | public static string BugStars = "CHAR_BUGSTARS"; 23 | public static string Call911 = "CHAR_CALL911"; 24 | public static string LegendaryMotorsport = "CHAR_CARSITE"; 25 | public static string SSASuperAutos = "CHAR_CARSITE2"; 26 | public static string Castro = "CHAR_CASTRO"; 27 | public static string ChatCall = "CHAR_CHAT_CALL"; 28 | public static string Chef = "CHAR_CHEF"; 29 | public static string Cheng = "CHAR_CHENG"; 30 | public static string ChengSenior = "CHAR_CHENGSR"; 31 | public static string Chop = "CHAR_CHOP"; 32 | public static string Cris = "CHAR_CRIS"; 33 | public static string Dave = "CHAR_DAVE"; 34 | public static string Default = "CHAR_DEFAULT"; 35 | public static string Denise = "CHAR_DENISE"; 36 | public static string DetonateBomb = "CHAR_DETONATEBOMB"; 37 | public static string DetonatePhone = "CHAR_DETONATEPHONE"; 38 | public static string Devin = "CHAR_DEVIN"; 39 | public static string SubMarine = "CHAR_DIAL_A_SUB"; 40 | public static string Dom = "CHAR_DOM"; 41 | public static string DomesticGirl = "CHAR_DOMESTIC_GIRL"; 42 | public static string Dreyfuss = "CHAR_DREYFUSS"; 43 | public static string DrFriedlander = "CHAR_DR_FRIEDLANDER"; 44 | public static string Epsilon = "CHAR_EPSILON"; 45 | public static string EstateAgent = "CHAR_ESTATE_AGENT"; 46 | public static string Facebook = "CHAR_FACEBOOK"; 47 | public static string FilmNoire = "CHAR_FILMNOIR"; 48 | public static string Floyd = "CHAR_FLOYD"; 49 | public static string Franklin = "CHAR_FRANKLIN"; 50 | public static string FranklinTrevor = "CHAR_FRANK_TREV_CONF"; 51 | public static string GayMilitary = "CHAR_GAYMILITARY"; 52 | public static string Hao = "CHAR_HAO"; 53 | public static string HitcherGirl = "CHAR_HITCHER_GIRL"; 54 | public static string Hunter = "CHAR_HUNTER"; 55 | public static string Jimmy = "CHAR_JIMMY"; 56 | public static string JimmyBoston = "CHAR_JIMMY_BOSTON"; 57 | public static string Joe = "CHAR_JOE"; 58 | public static string Josef = "CHAR_JOSEF"; 59 | public static string Josh = "CHAR_JOSH"; 60 | public static string LamarDog = "CHAR_LAMAR"; 61 | public static string Lester = "CHAR_LESTER"; 62 | public static string Skull = "CHAR_LESTER_DEATHWISH"; 63 | public static string LesterFranklin = "CHAR_LEST_FRANK_CONF"; 64 | public static string LesterMichael = "CHAR_LEST_MIKE_CONF"; 65 | public static string LifeInvader = "CHAR_LIFEINVADER"; 66 | public static string LsCustoms = "CHAR_LS_CUSTOMS"; 67 | public static string LSTI = "CHAR_LS_TOURIST_BOARD"; 68 | public static string Manuel = "CHAR_MANUEL"; 69 | public static string Marnie = "CHAR_MARNIE"; 70 | public static string Martin = "CHAR_MARTIN"; 71 | public static string MaryAnn = "CHAR_MARY_ANN"; 72 | public static string Maude = "CHAR_MAUDE"; 73 | public static string Mechanic = "CHAR_MECHANIC"; 74 | public static string Michael = "CHAR_MICHAEL"; 75 | public static string MichaelFranklin = "CHAR_MIKE_FRANK_CONF"; 76 | public static string MichaelTrevor = "CHAR_MIKE_TREV_CONF"; 77 | public static string WarStock = "CHAR_MILSITE"; 78 | public static string Minotaur = "CHAR_MINOTAUR"; 79 | public static string Molly = "CHAR_MOLLY"; 80 | public static string MorsMutual = "CHAR_MP_MORS_MUTUAL"; 81 | public static string ArmyContact = "CHAR_MP_ARMY_CONTACT"; 82 | public static string Brucie = "CHAR_MP_BRUCIE"; 83 | public static string FibContact = "CHAR_MP_FIB_CONTACT"; 84 | public static string RockStarLogo = "CHAR_MP_FM_CONTACT"; 85 | public static string Gerald = "CHAR_MP_GERALD"; 86 | public static string Julio = "CHAR_MP_JULIO"; 87 | public static string MechanicChinese = "CHAR_MP_MECHANIC"; 88 | public static string MerryWeather = "CHAR_MP_MERRYWEATHER"; 89 | public static string Unicorn = "CHAR_MP_STRIPCLUB_PR"; 90 | public static string Mom = "CHAR_MRS_THORNHILL"; 91 | public static string MrsThornhill = "CHAR_MRS_THORNHILL"; 92 | public static string PatriciaTrevor = "CHAR_PATRICIA"; 93 | public static string PegasusDelivery = "CHAR_PEGASUS_DELIVERY"; 94 | public static string ElitasTravel = "CHAR_PLANESITE"; 95 | public static string Sasquatch = "CHAR_SASQUATCH"; 96 | public static string Simeon = "CHAR_SIMEON"; 97 | public static string SocialClub = "CHAR_SOCIAL_CLUB"; 98 | public static string Solomon = "CHAR_SOLOMON"; 99 | public static string Taxi = "CHAR_TAXI"; 100 | public static string Trevor = "CHAR_TREVOR"; 101 | public static string YouTube = "CHAR_YOUTUBE"; 102 | public static string Wade = "CHAR_WADE"; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /NativeUI/Scaleforms/PopupWarning/PopupWarning.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using CitizenFX.Core; 5 | 6 | namespace NativeUI 7 | { 8 | 9 | public enum WarningPopupType 10 | { 11 | Classic, 12 | Serious 13 | } 14 | public delegate void PopupWarningEvent(InstructionalButton button); 15 | 16 | public class PopupWarning 17 | { 18 | private Scaleform _warning; 19 | private bool _disableControls; 20 | private List _buttonList; 21 | 22 | /// 23 | /// Returns if the PopupWarning scaleform is drawing currently 24 | /// 25 | public bool IsShowing 26 | { 27 | get => _warning != null; 28 | } 29 | 30 | public event PopupWarningEvent OnButtonPressed; 31 | 32 | private async Task Load() 33 | { 34 | if (_warning != null) return; 35 | _warning = new Scaleform("POPUP_WARNING"); 36 | int timeout = 1000; 37 | DateTime start = DateTime.Now; 38 | while (!_warning.IsLoaded && DateTime.Now.Subtract(start).TotalMilliseconds < timeout) await BaseScript.Delay(0); 39 | } 40 | 41 | /// 42 | /// Disposes the Warning scaleform. 43 | /// 44 | public void Dispose() 45 | { 46 | _warning.CallFunction("HIDE_POPUP_WARNING", 1000); 47 | _warning.Dispose(); 48 | _warning = null; 49 | _disableControls = false; 50 | } 51 | 52 | /// 53 | /// Show the Warning scaleform to the user. 54 | /// 55 | /// Title of the Warning (if empty defaults to "Warning") 56 | /// Subtitle of the Warning 57 | /// Prompt usually is used for asking to confirm or cancel (can be anything) 58 | /// This string will be shown in the Left-Bottom of the screen as error code or error message 59 | /// Type of the Warning 60 | public async void ShowWarning(string title, string subtitle, string prompt = "", string errorMsg = "", WarningPopupType type = WarningPopupType.Classic) 61 | { 62 | await Load(); 63 | _warning.CallFunction("SHOW_POPUP_WARNING", 1000, title, subtitle, prompt, true, (int)type, errorMsg); 64 | } 65 | 66 | /// 67 | /// Updates the current Warning, this is used to change any text in the current warning screen. 68 | /// 69 | /// Title of the Warning (if empty defaults to "Warning") 70 | /// Subtitle of the Warning 71 | /// Prompt usually is used for asking to confirm or cancel (can be anything) 72 | /// This string will be shown in the Left-Bottom of the screen as error code or error message 73 | /// Type of the Warning 74 | public void UpdateWarning(string title, string subtitle, string prompt = "", string errorMsg = "", WarningPopupType type = WarningPopupType.Classic) 75 | { 76 | _warning.CallFunction("SHOW_POPUP_WARNING", 1000, title, subtitle, prompt, true, (int)type, errorMsg); 77 | } 78 | 79 | /// 80 | /// Show the Warning scaleform to the user and awaits for user input 81 | /// 82 | /// Title of the Warning (if empty defaults to "Warning") 83 | /// Subtitle of the Warning 84 | /// Prompt usually is used for asking to confirm or cancel (can be anything) 85 | /// This string will be shown in the Left-Bottom of the screen as error code or error message 86 | /// List of to show to the user (the user can select with GamePad, Keyboard or Mouse) 87 | /// 88 | public async void ShowWarningWithButtons(string title, string subtitle, string prompt, List buttons, string errorMsg = "", WarningPopupType type = WarningPopupType.Classic) 89 | { 90 | await Load(); 91 | _disableControls = true; 92 | _buttonList = buttons; 93 | if (buttons == null || buttons.Count == 0) return; 94 | InstructionalButtonsHandler.InstructionalButtons.SetInstructionalButtons(_buttonList); 95 | InstructionalButtonsHandler.InstructionalButtons.UseMouseButtons = true; 96 | _warning.CallFunction("SHOW_POPUP_WARNING", 1000, title, subtitle, prompt, true, (int)type, errorMsg); 97 | InstructionalButtonsHandler.InstructionalButtons.Enabled = true; 98 | } 99 | 100 | internal async Task Update() 101 | { 102 | if (_warning == null) return; 103 | _warning.Render2D(); 104 | if (_disableControls) 105 | { 106 | InstructionalButtonsHandler.InstructionalButtons.Draw(); 107 | foreach (var b in _buttonList) 108 | { 109 | if (Game.IsControlJustPressed(1, b.GamepadButton) || Game.IsControlJustPressed(1, b.KeyboardButton)) 110 | { 111 | OnButtonPressed?.Invoke(b); 112 | Dispose(); 113 | InstructionalButtonsHandler.InstructionalButtons.Enabled = false; 114 | InstructionalButtonsHandler.InstructionalButtons.UseMouseButtons = false; 115 | return; 116 | } 117 | } 118 | } 119 | await Task.FromResult(0); 120 | } 121 | } 122 | 123 | public class PopupWarningThread : BaseScript 124 | { 125 | public static PopupWarning Warning { get; set; } 126 | 127 | public PopupWarningThread() 128 | { 129 | Warning = new PopupWarning(); 130 | Tick += PopupWarningThread_Tick; 131 | } 132 | 133 | private async Task PopupWarningThread_Tick() 134 | { 135 | await Warning.Update(); 136 | await Task.FromResult(0); 137 | } 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /NativeUI/NativeUI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F3E16ED9-DBF7-4E7B-B04B-9B24B11891D3} 8 | Library 9 | Properties 10 | NativeUI 11 | NativeUI 12 | v4.5.2 13 | 512 14 | 15 | latest 16 | 17 | 18 | true 19 | embedded 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 1 25 | AnyCPU 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | x64 35 | 36 | 37 | 38 | ..\packages\CitizenFX.Core.Client.1.0.4207\lib\net45\CitizenFX.Core.Client.dll 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 114 | -------------------------------------------------------------------------------- /NativeUI/Items/UIMenuSliderProgressItem.cs: -------------------------------------------------------------------------------- 1 | using CitizenFX.Core; 2 | using CitizenFX.Core.Native; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace NativeUI 11 | { 12 | public class UIMenuSliderProgressItem : UIMenuItem 13 | { 14 | protected internal Sprite _arrowLeft; 15 | protected internal Sprite _arrowRight; 16 | protected internal bool Pressed; 17 | protected internal UIMenuGridAudio Audio; 18 | protected internal UIResRectangle _rectangleBackground; 19 | protected internal UIResRectangle _rectangleSlider; 20 | protected internal UIResRectangle _rectangleDivider; 21 | 22 | protected internal int _value = 0; 23 | protected internal int _max; 24 | protected internal int _multiplier = 5; 25 | protected internal bool Divider; 26 | protected internal Color SliderColor; 27 | protected internal Color BackgroundSliderColor; 28 | 29 | public UIMenuSliderProgressItem(string text, int maxCount, int startIndex, bool divider = false) : this(text, maxCount, startIndex, "", divider) 30 | { 31 | _max = maxCount; 32 | _value = startIndex; 33 | } 34 | 35 | public UIMenuSliderProgressItem(string text, int maxCount, int startIndex, string description, bool divider = false) : this(text, maxCount, startIndex, description, Color.FromArgb(255, 57, 119, 200), Color.FromArgb(255, 4, 32, 57), divider) 36 | { 37 | _max = maxCount; 38 | _value = startIndex; 39 | } 40 | 41 | public UIMenuSliderProgressItem(string text, int maxCount, int startIndex, string description, Color sliderColor, Color backgroundSliderColor, bool divider = false) : base(text, description) 42 | { 43 | _max = maxCount; 44 | _value = startIndex; 45 | _arrowLeft = new Sprite("commonmenu", "arrowleft", new PointF(0, 105), new SizeF(25, 25)); 46 | _arrowRight = new Sprite("commonmenu", "arrowright", new PointF(0, 105), new SizeF(25, 25)); 47 | SliderColor = sliderColor; 48 | BackgroundSliderColor = backgroundSliderColor; 49 | _rectangleBackground = new UIResRectangle(new PointF(0, 0), new SizeF(150, 10), BackgroundSliderColor); 50 | _rectangleSlider = new UIResRectangle(new PointF(0, 0), new SizeF(75, 10), SliderColor); 51 | if (divider) 52 | _rectangleDivider = new UIResRectangle(new Point(0, 0), new Size(2, 20), Colors.WhiteSmoke); 53 | else 54 | _rectangleDivider = new UIResRectangle(new Point(0, 0), new Size(2, 20), Color.Transparent); 55 | float offset = _rectangleBackground.Size.Width / _max * _value; 56 | _rectangleSlider.Size = new SizeF(offset, _rectangleSlider.Size.Height); 57 | Audio = new UIMenuGridAudio("CONTINUOUS_SLIDER", "HUD_FRONTEND_DEFAULT_SOUNDSET", 0); 58 | } 59 | 60 | public override void Position(int y) 61 | { 62 | base.Position(y); 63 | _rectangleBackground.Position = new PointF(250f + base.Offset.X + Parent.WidthOffset, y + 158.5f + base.Offset.Y); 64 | _rectangleSlider.Position = new PointF(250f + base.Offset.X + Parent.WidthOffset, y + 158.5f + base.Offset.Y); 65 | _rectangleDivider.Position = new PointF(323.5f + base.Offset.X + Parent.WidthOffset, y + 153 + base.Offset.Y); 66 | _arrowLeft.Position = new PointF(225 + base.Offset.X + Parent.WidthOffset, y + 150.5f + base.Offset.Y); 67 | _arrowRight.Position = new PointF(400 + base.Offset.X + Parent.WidthOffset, y + 150.5f + base.Offset.Y); 68 | } 69 | 70 | public int Value 71 | { 72 | get 73 | { 74 | float offset = _rectangleBackground.Size.Width / _max * _value; 75 | _rectangleSlider.Size = new SizeF(offset, _rectangleSlider.Size.Height); 76 | return _value; 77 | } 78 | set 79 | { 80 | if (value > _max) 81 | _value = _max; 82 | else if (value < 0) 83 | _value = 0; 84 | else 85 | _value = value; 86 | SliderProgressChanged(Value); 87 | } 88 | } 89 | 90 | public int Multiplier 91 | { 92 | get => _multiplier; 93 | set =>_multiplier = value; 94 | } 95 | 96 | /// 97 | /// Triggered when the slider is changed. 98 | /// 99 | public event ItemSliderProgressEvent OnSliderChanged; 100 | 101 | internal virtual void SliderProgressChanged(int value) 102 | { 103 | OnSliderChanged?.Invoke(this, value); 104 | } 105 | 106 | public async void Functions() 107 | { 108 | if (ScreenTools.IsMouseInBounds(new PointF(_rectangleBackground.Position.X, _rectangleBackground.Position.Y), new SizeF(150f, _rectangleBackground.Size.Height))) 109 | { 110 | if (API.IsDisabledControlPressed(0, 24)) 111 | { 112 | if (!Pressed) 113 | { 114 | Pressed = true; 115 | Audio.Id = API.GetSoundId(); 116 | API.PlaySoundFrontend(Audio.Id, Audio.Slider, Audio.Library, true); 117 | } 118 | await BaseScript.Delay(0); 119 | float CursorX = API.GetDisabledControlNormal(0, 239) * Resolution.Width; 120 | var Progress = CursorX - _rectangleSlider.Position.X; 121 | Value = (int)Math.Round(_max * ((Progress >= 0f && Progress <= 150f) ? Progress : (Progress < 0) ? 0 : 150f) / 150f); 122 | SliderProgressChanged(Value); 123 | } 124 | else 125 | { 126 | API.StopSound(Audio.Id); 127 | API.ReleaseSoundId(Audio.Id); 128 | Pressed = false; 129 | } 130 | } 131 | else if (ScreenTools.IsMouseInBounds(_arrowLeft.Position, _arrowLeft.Size)) 132 | { 133 | if (API.IsDisabledControlPressed(0, 24)) 134 | { 135 | Value -= Multiplier; 136 | SliderProgressChanged(Value); 137 | } 138 | } 139 | else if (ScreenTools.IsMouseInBounds(_arrowRight.Position, _arrowRight.Size)) 140 | { 141 | if (API.IsDisabledControlPressed(0, 24)) 142 | { 143 | Value += Multiplier; 144 | SliderProgressChanged(Value); 145 | } 146 | } 147 | else 148 | { 149 | API.StopSound(Audio.Id); 150 | API.ReleaseSoundId(Audio.Id); 151 | Pressed = false; 152 | } 153 | } 154 | 155 | /// 156 | /// Draw item. 157 | /// 158 | public override async Task Draw() 159 | { 160 | base.Draw(); 161 | _arrowLeft.Color = Enabled ? Selected ? Colors.Black : Colors.WhiteSmoke : Color.FromArgb(163, 159, 148); 162 | _arrowRight.Color = Enabled ? Selected ? Colors.Black : Colors.WhiteSmoke : Color.FromArgb(163, 159, 148); 163 | _arrowLeft.Draw(); 164 | _arrowRight.Draw(); 165 | _rectangleBackground.Draw(); 166 | _rectangleSlider.Draw(); 167 | _rectangleDivider.Draw(); 168 | Functions(); 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /NativeUI/Panels/UIMenuGridPanel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Threading.Tasks; 5 | using CitizenFX.Core; 6 | using CitizenFX.Core.Native; 7 | using CitizenFX.Core.UI; 8 | 9 | namespace NativeUI 10 | { 11 | public class UIMenuGridPanel : UIMenuPanel 12 | { 13 | private UIResText Top; 14 | private UIResText Left; 15 | private UIResText Right; 16 | private UIResText Bottom; 17 | private Sprite Grid; 18 | private Sprite Circle; 19 | private UIMenuGridAudio Audio; 20 | private PointF SetCirclePosition; 21 | protected bool CircleLocked = false; 22 | protected bool Pressed; 23 | private readonly PointF safezoneOffset = ScreenTools.SafezoneBounds; 24 | public PointF CirclePosition 25 | { 26 | get 27 | { 28 | return new PointF((float)Math.Round((Circle.Position.X - (Grid.Position.X + 20) + (Circle.Size.Width / 2)) / (Grid.Size.Width - 40), 2), (float)Math.Round((Circle.Position.Y - (Grid.Position.Y + 20) + (Circle.Size.Height / 2)) / (Grid.Size.Height - 40 ), 2)); 29 | } 30 | set 31 | { 32 | Circle.Position.X = (Grid.Position.X + 20) + ((Grid.Size.Width - 40) * (value.X >= 0f && value.X <= 1.0f ? value.X : 0.0f)) - (Circle.Size.Width / 2); 33 | Circle.Position.Y = (Grid.Position.Y + 20) + ((Grid.Size.Height - 40) * (value.Y >= 0f && value.Y <= 1.0f ? value.Y : 0.0f)) - (Circle.Size.Height / 2); 34 | } 35 | } 36 | 37 | public UIMenuGridPanel(string TopText, string LeftText, string RightText, string BottomText, PointF circlePosition) 38 | { 39 | Enabled = true; 40 | Background = new Sprite("commonmenu", "gradient_bgd", new Point(0, 0), new Size(431, 275)); 41 | Grid = new Sprite("pause_menu_pages_char_mom_dad", "nose_grid", new Point(0, 0), new Size(200, 200), 0f, Color.FromArgb(255, 255, 255)); 42 | Circle = new Sprite("mpinventory", "in_world_circle", new PointF(0, 0), new SizeF(20, 20), 0f, Color.FromArgb(255, 255, 255)); 43 | Audio = new UIMenuGridAudio("CONTINUOUS_SLIDER", "HUD_FRONTEND_DEFAULT_SOUNDSET", 0); 44 | Top = new UIResText(TopText ?? "Up", new Point(0, 0), .35f, Color.FromArgb(255, 255, 255), CitizenFX.Core.UI.Font.ChaletLondon, Alignment.Center); 45 | Left = new UIResText(LeftText ?? "Left", new Point(0, 0), .35f, Color.FromArgb(255, 255, 255), CitizenFX.Core.UI.Font.ChaletLondon, Alignment.Center); 46 | Right = new UIResText(RightText ?? "Right", new Point(0, 0), .35f, Color.FromArgb(255, 255, 255), CitizenFX.Core.UI.Font.ChaletLondon, Alignment.Center); 47 | Bottom = new UIResText(BottomText ?? "Down", new Point(0, 0), .35f, Color.FromArgb(255, 255, 255), CitizenFX.Core.UI.Font.ChaletLondon, Alignment.Center); 48 | SetCirclePosition = new PointF(circlePosition.X != 0 ? circlePosition.X : .5f, circlePosition.Y != 0 ? circlePosition.Y : .5f); 49 | } 50 | 51 | internal override void Position(float y) 52 | { 53 | var Y = y + 35f; 54 | float ParentOffsetX = ParentItem.Offset.X; 55 | int ParentOffsetWidth = ParentItem.Parent.WidthOffset; 56 | Background.Position = new PointF(ParentOffsetX, Y); 57 | Grid.Position = new PointF(ParentOffsetX + 115.5f + (ParentOffsetWidth / 2), 72.5f + y); 58 | Top.Position = new PointF(ParentOffsetX + 215.5f + (ParentOffsetWidth / 2), 40f + y); 59 | Left.Position = new PointF(ParentOffsetX + 57.75f + (ParentOffsetWidth / 2), 155f + y); 60 | Right.Position = new PointF(ParentOffsetX + 373.25f + (ParentOffsetWidth / 2), 155f + y); 61 | Bottom.Position = new PointF(ParentOffsetX + 215.5f + (ParentOffsetWidth / 2), 275f + y); 62 | if (!CircleLocked) 63 | { 64 | CircleLocked = true; 65 | CirclePosition = SetCirclePosition; 66 | } 67 | } 68 | 69 | internal void UpdateParent( float X, float Y) 70 | { 71 | ParentItem.Parent.ListChange(ParentItem, ParentItem.Index); 72 | ParentItem.ListChangedTrigger(ParentItem.Index); 73 | } 74 | 75 | internal async void Functions() 76 | { 77 | if (ScreenTools.IsMouseInBounds(new PointF(Grid.Position.X + 20f + safezoneOffset.X, Grid.Position.Y + 20f + safezoneOffset.Y), new SizeF(Grid.Size.Width - 40f, Grid.Size.Height - 40f))) 78 | { 79 | if (API.IsDisabledControlPressed(0, 24)) 80 | { 81 | if (!Pressed) 82 | { 83 | Audio.Id = API.GetSoundId(); 84 | API.PlaySoundFrontend(Audio.Id, Audio.Slider, Audio.Library, true); 85 | Pressed = true; 86 | } 87 | float mouseX = API.GetDisabledControlNormal(0, 239) * Resolution.Width; 88 | float mouseY = API.GetDisabledControlNormal(0, 240) * Resolution.Height; 89 | mouseX -= (Circle.Size.Width / 2) + safezoneOffset.X; 90 | mouseY -= (Circle.Size.Height / 2) + safezoneOffset.Y; 91 | PointF Position = new PointF(mouseX > (Grid.Position.X + 10 + Grid.Size.Width - 40) ? (Grid.Position.X + 10 + Grid.Size.Width - 40) : ((mouseX < (Grid.Position.X + 20 - (Circle.Size.Width / 2))) ? (Grid.Position.X + 20 - (Circle.Size.Width / 2)) : mouseX), mouseY > (Grid.Position.Y + 10 + Grid.Size.Height - 40) ? (Grid.Position.Y + 10 + Grid.Size.Height - 40) : ((mouseY < (Grid.Position.Y + 20 - (Circle.Size.Height / 2))) ? (Grid.Position.Y + 20 - (Circle.Size.Height / 2)) : mouseY)); 92 | Circle.Position = Position; 93 | var resultX = ((Circle.Position.X - (Grid.Position.X + 20) + (Circle.Size.Width + 20)) / (Grid.Size.Width - 40)) + safezoneOffset.X; 94 | var resultY = ((Circle.Position.Y - (Grid.Position.Y + 20) + (Circle.Size.Height + 20)) / (Grid.Size.Height - 40)) + safezoneOffset.Y; 95 | UpdateParent(((resultX >= 0.0f && resultX <= 2.0f) ? resultX : ((resultX <= 0f) ? 0.0f : 1.2f) * 2f) - 1f, ((resultY >= 0.0f && resultY <= 1.0f) ? resultY : ((resultY <= 0f) ? 0.0f : 1.0f) * 2f) - 1f); 96 | } 97 | if (API.IsDisabledControlJustReleased(0, 24)) 98 | { 99 | API.StopSound(Audio.Id); 100 | API.ReleaseSoundId(Audio.Id); 101 | Pressed = false; 102 | } 103 | } 104 | else 105 | { 106 | API.StopSound(Audio.Id); 107 | API.ReleaseSoundId(Audio.Id); 108 | Pressed = false; 109 | } 110 | } 111 | 112 | internal async override Task Draw() 113 | { 114 | if (!Enabled) return; 115 | Background.Size = new Size(431 + ParentItem.Parent.WidthOffset, 275); 116 | Background.Draw(); 117 | Grid.Draw(); 118 | Circle.Draw(); 119 | Top.Draw(); 120 | Left.Draw(); 121 | Right.Draw(); 122 | Bottom.Draw(); 123 | Functions(); 124 | await Task.FromResult(0); 125 | } 126 | } 127 | 128 | 129 | public class UIMenuGridAudio 130 | { 131 | public string Slider; 132 | public string Library; 133 | public int Id; 134 | public UIMenuGridAudio(string slider, string library, int id) 135 | { 136 | Slider = slider; 137 | Library = library; 138 | Id = id; 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /NativeUI/PauseMenu/TabSubmenuItem.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | using CitizenFX.Core.Native; 4 | using CitizenFX.Core; 5 | 6 | namespace NativeUI.PauseMenu 7 | { 8 | public class TabSubmenuItem : TabItem 9 | { 10 | private bool _focused; 11 | 12 | public TabSubmenuItem(string name, IEnumerable items) : base(name) 13 | { 14 | DrawBg = false; 15 | CanBeFocused = true; 16 | Items = new List(items); 17 | IsInList = true; 18 | } 19 | 20 | public void RefreshIndex() 21 | { 22 | foreach (var item in Items) 23 | { 24 | item.Focused = false; 25 | item.Active = false; 26 | item.Visible = false; 27 | } 28 | Index = (1000 - (1000 % Items.Count)) % Items.Count; 29 | } 30 | 31 | public List Items { get; set; } 32 | public int Index { get; set; } 33 | public bool IsInList { get; set; } 34 | 35 | public override bool Focused 36 | { 37 | get { return _focused; } 38 | set 39 | { 40 | _focused = value; 41 | if (!value) Items[Index].Focused = false; 42 | } 43 | } 44 | 45 | public override void ProcessControls() 46 | { 47 | if (JustOpened) 48 | { 49 | JustOpened = false; 50 | return; 51 | } 52 | 53 | if (!Focused) return; 54 | 55 | if (Game.IsControlJustPressed(0, Control.PhoneSelect) && Focused && Parent.FocusLevel == 1) 56 | { 57 | Game.PlaySound("SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET"); 58 | if (Items[Index].CanBeFocused && !Items[Index].Focused) 59 | { 60 | Parent.FocusLevel++; 61 | Items[Index].JustOpened = true; 62 | Items[Index].Focused = true; 63 | } 64 | else 65 | { 66 | Items[Index].OnActivated(); 67 | } 68 | } 69 | 70 | if (Game.IsControlJustPressed(0, Control.PhoneCancel) && Focused && Parent.FocusLevel > 1) 71 | { 72 | Game.PlaySound("CANCEL", "HUD_FRONTEND_DEFAULT_SOUNDSET"); 73 | if (Items[Index].CanBeFocused && Items[Index].Focused) 74 | { 75 | Parent.FocusLevel--; 76 | Items[Index].Focused = false; 77 | } 78 | } 79 | 80 | if ((Game.IsControlJustPressed(0, Control.FrontendUp) || Game.IsControlJustPressed(0, Control.MoveUpOnly) || Game.IsControlJustPressed(0, Control.CursorScrollUp)) && Parent.FocusLevel == 1) 81 | { 82 | Index = (1000 - (1000 % Items.Count) + Index - 1) % Items.Count; 83 | Game.PlaySound("NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET"); 84 | } 85 | else if ((Game.IsControlJustPressed(0, Control.FrontendDown) || Game.IsControlJustPressed(0, Control.MoveDownOnly) || Game.IsControlJustPressed(0, Control.CursorScrollDown)) && Parent.FocusLevel == 1) 86 | { 87 | Index = (1000 - (1000 % Items.Count) + Index + 1) % Items.Count; 88 | Game.PlaySound("NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET"); 89 | } 90 | 91 | if (Items.Count > 0) Items[Index].ProcessControls(); 92 | } 93 | 94 | public override void Draw() 95 | { 96 | if (!Visible) return; 97 | base.Draw(); 98 | 99 | var alpha = Focused ? 120 : 30; 100 | var blackAlpha = Focused ? 200 : 100; 101 | var fullAlpha = Focused ? 255 : 150; 102 | 103 | var activeWidth = Resolution.Width - SafeSize.X * 2; 104 | var submenuWidth = (int)(activeWidth * 0.6818f); 105 | var itemSize = new SizeF((int)activeWidth - (submenuWidth + 3), 40); 106 | 107 | for (int i = 0; i < Items.Count; i++) 108 | { 109 | var hovering = ScreenTools.IsMouseInBounds(SafeSize.AddPoints(new PointF(0, (itemSize.Height + 3) * i)), 110 | itemSize); 111 | 112 | new UIResRectangle(SafeSize.AddPoints(new PointF(0, (itemSize.Height + 3) * i)), itemSize, (Index == i && Focused) ? Color.FromArgb(fullAlpha, Colors.White) : hovering && Focused ? Color.FromArgb(100, 50, 50, 50) : Color.FromArgb(blackAlpha, Colors.Black)).Draw(); 113 | new UIResText(Items[i].Title, SafeSize.AddPoints(new PointF(6, 5 + (itemSize.Height + 3) * i)), 0.35f, Color.FromArgb(fullAlpha, (Index == i && Focused) ? Colors.Black : Colors.White)).Draw(); 114 | 115 | if (Focused && hovering && Game.IsControlJustPressed(0, Control.CursorAccept)) 116 | { 117 | Items[Index].Focused = false; 118 | Game.PlaySound("NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET"); 119 | bool open = Index == i; 120 | Index = (1000 - (1000 % Items.Count) + i) % Items.Count; 121 | if (open) 122 | { 123 | if (Items[Index].CanBeFocused && !Items[Index].Focused) 124 | { 125 | Parent.FocusLevel = 2; 126 | Items[Index].JustOpened = true; 127 | Items[Index].Focused = true; 128 | } 129 | else 130 | { 131 | Items[Index].OnActivated(); 132 | } 133 | } 134 | else 135 | { 136 | Parent.FocusLevel = 1; 137 | } 138 | } 139 | } 140 | 141 | Items[Index].Visible = true; 142 | Items[Index].FadeInWhenFocused = true; 143 | //Items[Index].CanBeFocused = true; 144 | if (!Items[Index].CanBeFocused) 145 | Items[Index].Focused = Focused; 146 | Items[Index].UseDynamicPositionment = false; 147 | Items[Index].SafeSize = SafeSize.AddPoints(new PointF((int)activeWidth - submenuWidth, 0)); 148 | Items[Index].TopLeft = SafeSize.AddPoints(new PointF((int)activeWidth - submenuWidth, 0)); 149 | Items[Index].BottomRight = new PointF((int)Resolution.Width - SafeSize.X, (int)Resolution.Height - SafeSize.Y); 150 | if (Items[Index] is TabMissionSelectItem it) 151 | { 152 | it._add = -420; 153 | } 154 | Items[Index].Draw(); 155 | } 156 | } 157 | } -------------------------------------------------------------------------------- /NativeUI/Elements/UIResText.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using CitizenFX.Core.Native; 4 | using CitizenFX.Core.UI; 5 | using Font = CitizenFX.Core.UI.Font; 6 | 7 | namespace NativeUI 8 | { 9 | /// 10 | /// A Text object in the 1080 pixels height base system. 11 | /// 12 | public class UIResText : Text 13 | { 14 | public UIResText(string caption, PointF position, float scale) : base(caption, position, scale) 15 | { 16 | TextAlignment = Alignment.Left; 17 | } 18 | 19 | public UIResText(string caption, PointF position, float scale, Color color) 20 | : base(caption, position, scale, color) 21 | { 22 | TextAlignment = Alignment.Left; 23 | } 24 | 25 | public UIResText(string caption, PointF position, float scale, Color color, Font font, Alignment justify) 26 | : base(caption, position, scale, color, font, CitizenFX.Core.UI.Alignment.Left) 27 | { 28 | TextAlignment = justify; 29 | } 30 | 31 | 32 | public Alignment TextAlignment { get; set; } 33 | 34 | /// 35 | /// Push a long string into the stack. 36 | /// 37 | /// 38 | public static void AddLongString(string str) 39 | { 40 | var utf8ByteCount = System.Text.Encoding.UTF8.GetByteCount(str); 41 | 42 | if (utf8ByteCount == str.Length) 43 | { 44 | AddLongStringForAscii(str); 45 | } 46 | else 47 | { 48 | AddLongStringForUtf8(str); 49 | } 50 | } 51 | 52 | private static void AddLongStringForAscii(string input) 53 | { 54 | const int maxByteLengthPerString = 99; 55 | 56 | for (int i = 0; i < input.Length; i += maxByteLengthPerString) 57 | { 58 | string substr = (input.Substring(i, Math.Min(maxByteLengthPerString, input.Length - i))); 59 | API.AddTextComponentString(substr); 60 | } 61 | } 62 | 63 | internal static void AddLongStringForUtf8(string input) 64 | { 65 | const int maxByteLengthPerString = 99; 66 | 67 | if (maxByteLengthPerString < 0) 68 | { 69 | throw new ArgumentOutOfRangeException("maxLengthPerString"); 70 | } 71 | if (string.IsNullOrEmpty(input) || maxByteLengthPerString == 0) 72 | { 73 | return; 74 | } 75 | 76 | var enc = System.Text.Encoding.UTF8; 77 | 78 | var utf8ByteCount = enc.GetByteCount(input); 79 | if (utf8ByteCount < maxByteLengthPerString) 80 | { 81 | API.AddTextComponentString(input); 82 | return; 83 | } 84 | 85 | var startIndex = 0; 86 | 87 | for (int i = 0; i < input.Length; i++) 88 | { 89 | var length = i - startIndex; 90 | if (enc.GetByteCount(input.Substring(startIndex, length)) > maxByteLengthPerString) 91 | { 92 | string substr = (input.Substring(startIndex, length - 1)); 93 | API.AddTextComponentString(substr); 94 | 95 | i -= 1; 96 | startIndex = (startIndex + length - 1); 97 | } 98 | } 99 | API.AddTextComponentString(input.Substring(startIndex, input.Length - startIndex)); 100 | } 101 | 102 | [Obsolete("Use ScreenTools.GetTextWidth instead.", true)] 103 | public static float MeasureStringWidth(string str, Font font, float scale) => ScreenTools.GetTextWidth(str, font, scale); 104 | 105 | [Obsolete("Use ScreenTools.GetTextWidth instead.", true)] 106 | public static float MeasureStringWidthNoConvert(string str, Font font, float scale) => ScreenTools.GetTextWidth(str, font, scale); 107 | 108 | /// 109 | /// Width of the text wrap box. Set to zero to disable. 110 | /// 111 | public float Wrap { get; set; } = 0; 112 | /// 113 | /// Size of the text wrap box. 114 | /// 115 | [Obsolete("Use UIResText.Wrap instead.", true)] 116 | public SizeF WordWrap 117 | { 118 | get => new SizeF(Wrap, 0); 119 | set => Wrap = value.Width; 120 | } 121 | 122 | public override void Draw(SizeF offset) 123 | { 124 | int screenw = Screen.Resolution.Width; 125 | int screenh = Screen.Resolution.Height; 126 | const float height = 1080f; 127 | float ratio = (float)screenw / screenh; 128 | var width = height * ratio; 129 | 130 | float x = (Position.X) / width; 131 | float y = (Position.Y) / height; 132 | 133 | API.SetTextFont((int)Font); 134 | API.SetTextScale(1.0f, Scale); 135 | API.SetTextColour(Color.R, Color.G, Color.B, Color.A); 136 | if (Shadow) 137 | API.SetTextDropShadow(); 138 | if (Outline) 139 | API.SetTextOutline(); 140 | switch (TextAlignment) 141 | { 142 | case Alignment.Center: 143 | API.SetTextCentre(true); 144 | break; 145 | case Alignment.Right: 146 | API.SetTextRightJustify(true); 147 | API.SetTextWrap(0, x); 148 | break; 149 | } 150 | 151 | if (Wrap != 0) 152 | { 153 | float xsize = (Position.X + Wrap) / width; 154 | API.SetTextWrap(x, xsize); 155 | } 156 | 157 | API.SetTextEntry("jamyfafi"); 158 | AddLongString(Caption); 159 | 160 | API.DrawText(x, y); 161 | } 162 | 163 | //public static void Draw(string caption, int xPos, int yPos, Font font, float scale, UnknownColors color, Alignment alignment, bool Shadow, bool outline, int wordWrap) 164 | //{ 165 | // int screenw = Screen.Resolution.Width; 166 | // int screenh = Screen.Resolution.Height; 167 | // const float height = 1080f; 168 | // float ratio = (float)screenw / screenh; 169 | // var width = height * ratio; 170 | 171 | // float x = (xPos) / width; 172 | // float y = (yPos) / height; 173 | 174 | // Function.Call(Hash.SET_TEXT_FONT, (int)font); 175 | // Function.Call(Hash.SET_TEXT_SCALE, 1.0f, scale); 176 | // Function.Call(Hash.SET_TEXT_COLOUR, color.R, color.G, color.B, color.A); 177 | // if (Shadow) 178 | // Function.Call(Hash.SET_TEXT_DROP_SHADOW); 179 | // if (outline) 180 | // Function.Call(Hash.SET_TEXT_OUTLINE); 181 | // switch (alignment) 182 | // { 183 | // case Alignment.Center: 184 | // Function.Call(Hash.SET_TEXT_CENTRE, true); 185 | // break; 186 | // case Alignment.Right: 187 | // Function.Call(Hash.SET_TEXT_RIGHT_JUSTIFY, true); 188 | // Function.Call(Hash.SET_TEXT_WRAP, 0, x); 189 | // break; 190 | // } 191 | 192 | // if (wordWrap != 0) 193 | // { 194 | // float xsize = (xPos + wordWrap) / width; 195 | // Function.Call(Hash.SET_TEXT_WRAP, x, xsize); 196 | // } 197 | 198 | // Function.Call(Hash._SET_TEXT_ENTRY, "jamyfafi"); 199 | // AddLongString(caption); 200 | 201 | // Function.Call(Hash._DRAW_TEXT, x, y); 202 | //} 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /NativeUI/Items/UIMenuListItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Threading.Tasks; 5 | using CitizenFX.Core.UI; 6 | 7 | namespace NativeUI 8 | { 9 | public class UIMenuListItem : UIMenuItem, IListItem 10 | { 11 | protected internal UIResText _itemText; 12 | protected internal Sprite _arrowLeft; 13 | protected internal Sprite _arrowRight; 14 | 15 | protected internal int _index; 16 | protected internal List _items; 17 | 18 | 19 | /// 20 | /// Triggered when the list is changed. 21 | /// 22 | public event ItemListEvent OnListChanged; 23 | 24 | /// 25 | /// Triggered when a list item is selected. 26 | /// 27 | public event ItemListEvent OnListSelected; 28 | 29 | /// 30 | /// Returns the current selected index. 31 | /// 32 | public int Index 33 | { 34 | get { return _index % Items.Count; } 35 | set { _index = 100000000 - (100000000 % Items.Count) + value; } 36 | } 37 | 38 | /// 39 | /// Returns the current selected index. 40 | /// 41 | public List Items 42 | { 43 | get => _items; 44 | set 45 | { 46 | Index = 0; 47 | _items = value; 48 | } 49 | } 50 | 51 | public List Panels = new List(); 52 | 53 | 54 | /// 55 | /// List item, with left/right arrows. 56 | /// 57 | /// Item label. 58 | /// List that contains your items. 59 | /// Index in the list. If unsure user 0. 60 | public UIMenuListItem(string text, List items, int index) : this(text, items, index, "") 61 | { 62 | } 63 | 64 | /// 65 | /// List item, with left/right arrows. 66 | /// 67 | /// Item label. 68 | /// List that contains your items. 69 | /// Index in the list. If unsure user 0. 70 | /// Description for this item. 71 | public UIMenuListItem(string text, List items, int index, string description) : this(text, items, index, description, Color.Transparent, Color.FromArgb(255, 255, 255, 255)) 72 | { 73 | } 74 | 75 | public UIMenuListItem(string text, List items, int index, string description, Color mainColor, Color higlightColor) : base(text, description, mainColor, higlightColor) 76 | { 77 | const int y = 0; 78 | _items = items; 79 | _arrowLeft = new Sprite("commonmenu", "arrowleft", new PointF(110, 105 + y), new SizeF(30, 30)); 80 | _arrowRight = new Sprite("commonmenu", "arrowright", new PointF(280, 105 + y), new SizeF(30, 30)); 81 | _itemText = new UIResText("", new PointF(290, y + 104), 0.35f, Colors.White, CitizenFX.Core.UI.Font.ChaletLondon, 82 | Alignment.Left) 83 | { TextAlignment = Alignment.Right }; 84 | Index = index; 85 | } 86 | 87 | 88 | /// 89 | /// Change item's position. 90 | /// 91 | /// New Y position. 92 | public override void Position(int y) 93 | { 94 | _arrowLeft.Position = new PointF(300 + Offset.X + Parent.WidthOffset, 147 + y + Offset.Y); 95 | _arrowRight.Position = new PointF(400 + Offset.X + Parent.WidthOffset, 147 + y + Offset.Y); 96 | _itemText.Position = new PointF(300 + Offset.X + Parent.WidthOffset, y + 147 + Offset.Y); 97 | base.Position(y); 98 | } 99 | 100 | 101 | /// 102 | /// Find an item in the list and return it's index. 103 | /// 104 | /// Item to search for. 105 | /// Item index. 106 | [Obsolete("Use UIMenuListItem.Items.FindIndex(p => ReferenceEquals(p, item)) instead.")] 107 | public virtual int ItemToIndex(dynamic item) 108 | { 109 | return _items.FindIndex(p => ReferenceEquals(p, item)); 110 | } 111 | 112 | 113 | /// 114 | /// Find an item by it's index and return the item. 115 | /// 116 | /// Item's index. 117 | /// Item 118 | [Obsolete("Use UIMenuListItem.Items[Index] instead.")] 119 | public virtual dynamic IndexToItem(int index) 120 | { 121 | return _items[index]; 122 | } 123 | 124 | 125 | /// 126 | /// Draw item. 127 | /// 128 | public override async Task Draw() 129 | { 130 | base.Draw(); 131 | 132 | string caption = _items[Index].ToString(); 133 | float offset = ScreenTools.GetTextWidth(caption, _itemText.Font, _itemText.Scale); 134 | 135 | _itemText.Color = Enabled ? Selected ? Colors.Black : Colors.WhiteSmoke : Color.FromArgb(163, 159, 148); 136 | 137 | _itemText.Caption = caption; 138 | 139 | _arrowLeft.Color = Enabled ? Selected ? Colors.Black : Colors.WhiteSmoke : Color.FromArgb(163, 159, 148); 140 | _arrowRight.Color = Enabled ? Selected ? Colors.Black : Colors.WhiteSmoke : Color.FromArgb(163, 159, 148); 141 | 142 | _arrowLeft.Position = new PointF(375 - (int)offset + Offset.X + Parent.WidthOffset, _arrowLeft.Position.Y); 143 | if (Selected) 144 | { 145 | _arrowLeft.Draw(); 146 | _arrowRight.Draw(); 147 | _itemText.Position = new PointF(403 + Offset.X + Parent.WidthOffset, _itemText.Position.Y); 148 | } 149 | else 150 | { 151 | _itemText.Position = new PointF(418 + Offset.X + Parent.WidthOffset, _itemText.Position.Y); 152 | } 153 | _itemText.Draw(); 154 | } 155 | 156 | internal virtual void ListChangedTrigger(int newindex) 157 | { 158 | OnListChanged?.Invoke(this, newindex); 159 | } 160 | 161 | internal virtual void ListSelectedTrigger(int newindex) 162 | { 163 | OnListSelected?.Invoke(this, newindex); 164 | } 165 | 166 | public override void SetRightBadge(BadgeStyle badge) 167 | { 168 | throw new Exception("UIMenuListItem cannot have a right badge."); 169 | } 170 | 171 | public override void SetRightLabel(string text) 172 | { 173 | throw new Exception("UIMenuListItem cannot have a right label."); 174 | } 175 | 176 | /// 177 | /// Add a Panel to the UIMenuListItem 178 | /// 179 | /// 180 | public virtual void AddPanel(UIMenuPanel panel) 181 | { 182 | Panels.Add(panel); 183 | panel.SetParentItem(this); 184 | } 185 | 186 | /// 187 | /// Removes a panel at a defined Index 188 | /// 189 | /// 190 | public virtual void RemovePanelAt(int Index) 191 | { 192 | Panels.RemoveAt(Index); 193 | } 194 | 195 | 196 | [Obsolete("Use UIMenuListItem.Items[Index].ToString() instead.")] 197 | public string CurrentItem() 198 | { 199 | return _items[Index].ToString(); 200 | } 201 | } 202 | } -------------------------------------------------------------------------------- /NativeUI/Panels/UIMenuColorPanel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | using CitizenFX.Core.Native; 4 | using CitizenFX.Core.UI; 5 | using CitizenFX.Core; 6 | using System.Threading.Tasks; 7 | 8 | namespace NativeUI 9 | { 10 | public class UIMenuColorPanel : UIMenuPanel 11 | { 12 | private ColorPanelData Data = new ColorPanelData(); 13 | private List Bar = new List(); 14 | private bool EnableArrow; 15 | private Sprite LeftArrow; 16 | private Sprite RightArrow; 17 | private UIResRectangle SelectedRectangle; 18 | private UIResText Text; 19 | private List Colors = new List(); 20 | int r = 0; 21 | int g = 0; 22 | int b = 0; 23 | public enum ColorPanelType { Hair, Makeup } 24 | public ColorPanelType ColorPanelColorType; 25 | public int CurrentSelection 26 | { 27 | get 28 | { 29 | if (Data.Items.Count == 0) 30 | return 0; 31 | else if (Data.Index % Data.Items.Count == 0) 32 | return 0; 33 | else 34 | return Data.Index % Data.Items.Count; 35 | } 36 | set 37 | { 38 | if (Data.Items.Count == 0) 39 | Data.Index = 0; 40 | Data.Index = 1000000 - (1000000 % Data.Items.Count) + value; 41 | if (CurrentSelection > Data.Pagination.Max) 42 | { 43 | Data.Pagination.Min = CurrentSelection - (Data.Pagination.Total + 1); 44 | Data.Pagination.Max = CurrentSelection; 45 | } 46 | else if (CurrentSelection < Data.Pagination.Min) 47 | { 48 | Data.Pagination.Min = CurrentSelection - 1; 49 | Data.Pagination.Max = CurrentSelection + Data.Pagination.Total + 1; 50 | } 51 | UpdateSelection(false); 52 | } 53 | } 54 | 55 | public UIMenuColorPanel(string Title, ColorPanelType ColorType) 56 | { 57 | if (ColorType == ColorPanelType.Hair) 58 | { 59 | Colors.Clear(); 60 | for (int i = 0; i < 64; i++) 61 | { 62 | API.GetHairRgbColor(i, ref r, ref g, ref b); 63 | Colors.Add(Color.FromArgb(r, g, b)); 64 | } 65 | 66 | } 67 | else if (ColorType == ColorPanelType.Makeup) 68 | { 69 | Colors.Clear(); 70 | for (int i = 0; i < 64; i++) 71 | { 72 | API.GetMakeupRgbColor(i, ref r, ref g, ref b); 73 | Colors.Add(Color.FromArgb(r, g, b)); 74 | } 75 | } 76 | Data.Pagination.Min = 0; 77 | Data.Pagination.Max = 7; 78 | Data.Pagination.Total = 7; 79 | Data.Index = 1000; 80 | Data.Items = Colors; 81 | Data.Title = Title ?? "Title"; 82 | Enabled = true; 83 | Data.Value = 1; 84 | Background = new Sprite("commonmenu", "gradient_bgd", new Point(0, 0), new Size(431, 122)); 85 | EnableArrow = true; 86 | LeftArrow = new Sprite("commonmenu", "arrowleft", new Point(0, 0), new Size(30, 30)); 87 | RightArrow = new Sprite("commonmenu", "arrowright", new Point(0, 0), new Size(30, 30)); 88 | SelectedRectangle = new UIResRectangle(new Point(0, 0), new Size(44, 8), Color.FromArgb(255, 255, 255)); 89 | Text = new UIResText(Title + " [1 / " + Colors.Count + "]", new Point(0, 0), 0.35f, Color.FromArgb(255, 255, 255, 255), CitizenFX.Core.UI.Font.ChaletLondon, Alignment.Center); 90 | ParentItem = null; 91 | 92 | for (int Index = 0; Index < Colors.Count; Index++) 93 | { 94 | if (Index < 9) 95 | Bar.Add(new UIResRectangle(new PointF(0, 0), new SizeF(44.5f, 44.5f), Colors[Index])); 96 | else 97 | break; 98 | } 99 | if (Data.Items.Count != 0) 100 | { 101 | Data.Index = 1000 - (1000 % Data.Items.Count); 102 | Data.Pagination.Max = Data.Pagination.Total + 1; 103 | Data.Pagination.Min = 0; 104 | } 105 | } 106 | 107 | internal override void Position(float y) 108 | { 109 | float ParentOffsetX = ParentItem.Offset.X; float ParentOffsetWidth = ParentItem.Parent.WidthOffset; 110 | Background.Position = new PointF(ParentOffsetX, 35 + y); 111 | for (int Index = 0; Index < Bar.Count; Index++) 112 | Bar[Index].Position = new PointF(15f + (44.5f * Index) + ParentOffsetX + (ParentOffsetWidth / 2), 90f + y); 113 | SelectedRectangle.Position = new PointF(15f + (44.5f * (CurrentSelection - Data.Pagination.Min)) + ParentOffsetX + (ParentOffsetWidth / 2), 77f + y); 114 | if (EnableArrow) 115 | { 116 | LeftArrow.Position = new PointF(7.5f + ParentOffsetX + (ParentOffsetWidth / 2), 50f + y); 117 | RightArrow.Position = new PointF(393.5f + ParentOffsetX + (ParentOffsetWidth / 2), 50f + y); 118 | } 119 | Text.Position = new PointF(215.5f + ParentOffsetX + (ParentOffsetWidth / 2), 50f + y); 120 | } 121 | 122 | private void UpdateSelection(bool update) 123 | { 124 | if (update) 125 | { 126 | ParentItem.Parent.ListChange(ParentItem, ParentItem.Index); 127 | ParentItem.ListChangedTrigger(ParentItem.Index); 128 | } 129 | SelectedRectangle.Position = new PointF(15f + (44.5f * ((CurrentSelection - Data.Pagination.Min))) + ParentItem.Offset.X, SelectedRectangle.Position.Y); 130 | for (int index = 0; index < 9; index++) 131 | Bar[index].Color = Data.Items[Data.Pagination.Min + index]; 132 | Text.Caption = Data.Title + " [" + (CurrentSelection + 1) + " / " + (Data.Items.Count) + "]"; 133 | } 134 | 135 | private void Functions() 136 | { 137 | Point safezoneOffset = ScreenTools.SafezoneBounds; 138 | if (ScreenTools.IsMouseInBounds(new PointF(LeftArrow.Position.X + safezoneOffset.X, LeftArrow.Position.Y + safezoneOffset.Y), LeftArrow.Size)) 139 | if (API.IsDisabledControlJustPressed(0, 24) || API.IsControlJustPressed(0, 24)) 140 | GoLeft(); 141 | if (ScreenTools.IsMouseInBounds(new PointF(RightArrow.Position.X + safezoneOffset.X, RightArrow.Position.Y + safezoneOffset.Y), RightArrow.Size)) 142 | if (API.IsDisabledControlJustPressed(0, 24) || API.IsControlJustPressed(0, 24)) 143 | GoRight(); 144 | for (int Index = 0; Index < Bar.Count; Index++) 145 | { 146 | if (ScreenTools.IsMouseInBounds(new PointF(Bar[Index].Position.X + safezoneOffset.X, Bar[Index].Position.Y + safezoneOffset.Y), Bar[Index].Size)) 147 | if (API.IsDisabledControlJustPressed(0, 24) || API.IsControlJustPressed(0, 24)) 148 | { 149 | CurrentSelection = Data.Pagination.Min + Index; 150 | UpdateSelection(true); 151 | } 152 | } 153 | } 154 | 155 | private void GoLeft() 156 | { 157 | if (Data.Items.Count > Data.Pagination.Total + 1) 158 | { 159 | if (CurrentSelection <= Data.Pagination.Min) 160 | { 161 | if (CurrentSelection == 0) 162 | { 163 | Data.Pagination.Min = Data.Items.Count - (Data.Pagination.Total + 1) - 1; 164 | Data.Pagination.Max = Data.Items.Count - 1; 165 | Data.Index = 1000 - (1000 % Data.Items.Count); 166 | Data.Index += (Data.Items.Count - 1); 167 | UpdateSelection(true); 168 | } 169 | else 170 | { 171 | Data.Pagination.Min -= 1; 172 | Data.Pagination.Max -= 1; 173 | Data.Index -= 1; 174 | UpdateSelection(true); 175 | } 176 | } 177 | else 178 | { 179 | Data.Index -= 1; 180 | UpdateSelection(true); 181 | } 182 | } 183 | else 184 | { 185 | Data.Index -= 1; 186 | UpdateSelection(true); 187 | } 188 | } 189 | 190 | private void GoRight() 191 | { 192 | if (Data.Items.Count > Data.Pagination.Total + 1) 193 | { 194 | if (CurrentSelection >= Data.Pagination.Max) 195 | { 196 | if (CurrentSelection == Data.Items.Count -1) 197 | { 198 | Data.Pagination.Min = 0; 199 | Data.Pagination.Max = Data.Pagination.Total + 1; 200 | Data.Index = 1000 - (1000 % Data.Items.Count); 201 | UpdateSelection(true); 202 | } 203 | else 204 | { 205 | Data.Pagination.Max += 1; 206 | Data.Pagination.Min = Data.Pagination.Max - (Data.Pagination.Total + 1); 207 | Data.Index += 1; 208 | UpdateSelection(true); 209 | } 210 | } 211 | else 212 | { 213 | Data.Index += 1; 214 | UpdateSelection(true); 215 | } 216 | } 217 | else 218 | { 219 | Data.Index += 1; 220 | UpdateSelection(true); 221 | } 222 | } 223 | 224 | internal async override Task Draw() 225 | { 226 | if (Enabled) 227 | { 228 | Background.Size = new Size(431 + ParentItem.Parent.WidthOffset, 112); 229 | Background.Draw(); 230 | if (EnableArrow) 231 | { 232 | LeftArrow.Draw(); 233 | RightArrow.Draw(); 234 | } 235 | Text.Draw(); 236 | for (int Index = 0; Index < Bar.Count; Index++) 237 | Bar[Index].Draw(); 238 | SelectedRectangle.Draw(); 239 | Functions(); 240 | } 241 | await Task.FromResult(0); 242 | } 243 | } 244 | 245 | public class ColorPanelData 246 | { 247 | public Pagination Pagination = new Pagination(); 248 | public int Index; 249 | public List Items; 250 | public string Title; 251 | public bool Enabled; 252 | public int Value; 253 | } 254 | 255 | public class Pagination 256 | { 257 | public int Min; 258 | public int Max; 259 | public int Total; 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /NativeUI/ScreenTools.cs: -------------------------------------------------------------------------------- 1 | using CitizenFX.Core; 2 | using CitizenFX.Core.Native; 3 | using static CitizenFX.Core.Native.API; 4 | using System.Drawing; 5 | using System; 6 | using CitizenFX.Core.UI; 7 | 8 | namespace NativeUI 9 | { 10 | /// 11 | /// Tools to deal with the game screen. 12 | /// 13 | public static class ScreenTools 14 | { 15 | /// 16 | /// The 1080pixels-based screen resolution while mantaining current aspect ratio. 17 | /// 18 | public static SizeF ResolutionMaintainRatio 19 | { 20 | get 21 | { 22 | // Get the game width and height 23 | int screenw = Screen.Resolution.Width; 24 | int screenh = Screen.Resolution.Height; 25 | // Calculate the ratio 26 | float ratio = (float)screenw / screenh; 27 | // And the width with that ratio 28 | float width = 1080f * ratio; 29 | // Finally, return a SizeF 30 | return new SizeF(width, 1080f); 31 | } 32 | } 33 | 34 | /// 35 | /// Chech whether the mouse is inside the specified rectangle. 36 | /// 37 | /// Start point of the rectangle at the top left. 38 | /// size of your rectangle. 39 | /// true if the mouse is inside of the specified bounds, false otherwise. 40 | public static bool IsMouseInBounds(Point topLeft, Size boxSize) 41 | { 42 | Game.EnableControlThisFrame(0, Control.CursorX); 43 | Game.EnableControlThisFrame(0, Control.CursorY); 44 | // Get the resolution while maintaining the ratio. 45 | SizeF res = ResolutionMaintainRatio; 46 | // Then, get the position of mouse on the screen while relative to the current resolution 47 | int mouseX = (int)Math.Round(API.GetDisabledControlNormal(0, 239) * res.Width); 48 | int mouseY = (int)Math.Round(API.GetDisabledControlNormal(0, 240) * res.Height); 49 | // And check if the mouse is on the rectangle bounds 50 | bool isX = mouseX >= topLeft.X && mouseX <= topLeft.X + boxSize.Width; 51 | bool isY = mouseY > topLeft.Y && mouseY < topLeft.Y + boxSize.Height; 52 | // Finally, return the result of the checks 53 | return isX && isY; 54 | } 55 | 56 | public static bool IsMouseInBounds(PointF topLeft, SizeF boxSize) 57 | { 58 | Game.EnableControlThisFrame(0, Control.CursorX); 59 | Game.EnableControlThisFrame(0, Control.CursorY); 60 | // Get the resolution while maintaining the ratio. 61 | SizeF res = ResolutionMaintainRatio; 62 | // Then, get the position of mouse on the screen while relative to the current resolution 63 | float mouseX = GetDisabledControlNormal(0, 239) * res.Width; 64 | float mouseY = GetDisabledControlNormal(0, 240) * res.Height; 65 | // And check if the mouse is on the rectangle bounds 66 | bool isX = mouseX >= topLeft.X && mouseX <= topLeft.X + boxSize.Width; 67 | bool isY = mouseY > topLeft.Y && mouseY < topLeft.Y + boxSize.Height; 68 | // Finally, return the result of the checks 69 | return isX && isY; 70 | } 71 | 72 | public static bool IsMouseInBounds(Point topLeft, Size boxSize, Point DrawOffset) 73 | { 74 | Game.EnableControlThisFrame(0, Control.CursorX); 75 | Game.EnableControlThisFrame(0, Control.CursorY); 76 | SizeF res = ResolutionMaintainRatio; 77 | 78 | int mouseX = (int)Math.Round(API.GetDisabledControlNormal(0, 239) * res.Width); 79 | int mouseY = (int)Math.Round(API.GetDisabledControlNormal(0, 240) * res.Height); 80 | 81 | mouseX += DrawOffset.X; 82 | mouseY += DrawOffset.Y; 83 | 84 | return (mouseX >= topLeft.X && mouseX <= topLeft.X + boxSize.Width) 85 | && (mouseY > topLeft.Y && mouseY < topLeft.Y + boxSize.Height); 86 | } 87 | 88 | public static bool IsMouseInBounds(PointF topLeft, SizeF boxSize, PointF DrawOffset) 89 | { 90 | Game.EnableControlThisFrame(0, Control.CursorX); 91 | Game.EnableControlThisFrame(0, Control.CursorY); 92 | SizeF res = ResolutionMaintainRatio; 93 | 94 | float mouseX = GetDisabledControlNormal(0, 239) * res.Width; 95 | float mouseY = GetDisabledControlNormal(0, 240) * res.Height; 96 | 97 | mouseX += DrawOffset.X; 98 | mouseY += DrawOffset.Y; 99 | 100 | return (mouseX >= topLeft.X && mouseX <= topLeft.X + boxSize.Width) 101 | && (mouseY > topLeft.Y && mouseY < topLeft.Y + boxSize.Height); 102 | } 103 | 104 | /// 105 | /// Returns the safezone bounds in pixel, relative to the 1080pixel based system. 106 | /// 107 | /// 108 | /// 109 | /// Safezone bounds relative to the 1080pixel based resolution. 110 | /// 111 | public static Point SafezoneBounds 112 | { 113 | get 114 | { 115 | // Get the size of the safezone as a float 116 | float t = GetSafeZoneSize(); 117 | // Round the value with a max of 2 decimal places and do some calculations 118 | double g = Math.Round(Convert.ToDouble(t), 2); 119 | g = (g * 100) - 90; 120 | g = 10 - g; 121 | 122 | // Then, get the screen resolution 123 | int screenw = Screen.Resolution.Width; 124 | int screenh = Screen.Resolution.Height; 125 | // Calculate the ratio 126 | float ratio = (float)screenw / screenh; 127 | // And this thing (that I don't know what it does) 128 | float wmp = ratio * 5.4f; 129 | 130 | // Finally, return a new point with the correct resolution 131 | return new Point((int)Math.Round(g * wmp), (int)Math.Round(g * 5.4f)); 132 | } 133 | } 134 | 135 | /// 136 | /// Calculates the width of a string. 137 | /// 138 | /// The text to measure. 139 | /// Game font used for measurements. 140 | /// The scale of the characters. 141 | /// The width of the string based on the font and scale. 142 | public static float GetTextWidth(string text, CitizenFX.Core.UI.Font font, float scale) 143 | { 144 | // Start by requesting the game to start processing a width measurement 145 | SetTextEntryForWidth("CELL_EMAIL_BCON"); // _BEGIN_TEXT_COMMAND_WIDTH 146 | // Add the text string 147 | UIResText.AddLongString(text); 148 | // Set the properties for the text 149 | SetTextFont((int)font); 150 | SetTextScale(1f, scale); 151 | 152 | // Ask the game for the relative string width 153 | float width = GetTextScreenWidth(true); 154 | // And return the literal result 155 | return ResolutionMaintainRatio.Width * width; 156 | } 157 | 158 | /// 159 | /// Gets the line count for the text. 160 | /// 161 | /// The text to measure. 162 | /// The position of the text. 163 | /// The font to use. 164 | /// The number of lines used. 165 | public static int GetLineCount(string text, Point position, CitizenFX.Core.UI.Font font, float scale, int wrap) 166 | { 167 | // Tell the game that we are going to request the number of lines 168 | BeginTextCommandLineCount("CELL_EMAIL_BCON"); // _BEGIN_TEXT_COMMAND_LINE_COUNT 169 | 170 | UIResText.AddLongString(text);// Add the text that has been sent to us 171 | 172 | // Get the resolution with the correct aspect ratio 173 | SizeF res = ResolutionMaintainRatio; 174 | // Calculate the x and y positions 175 | float x = position.X / res.Width; 176 | float y = position.Y / res.Height; 177 | 178 | // Set the properties for the text 179 | SetTextFont((int)font); 180 | SetTextScale(1f, scale); 181 | 182 | // If there is some text wrap to add 183 | if (wrap > 0) 184 | { 185 | // Calculate the wrap size 186 | float start = position.X / res.Width; 187 | float end = start + (wrap / res.Width); 188 | // And apply it 189 | SetTextWrap(x, end); 190 | } 191 | // Finally, return the number of lines being made by the string 192 | return GetTextScreenLineCount(x, y); // _GET_TEXT_SCREEN_LINE_COUNT 193 | } 194 | 195 | public static int GetLineCount(string text, PointF position, CitizenFX.Core.UI.Font font, float scale, float wrap) 196 | { 197 | // Tell the game that we are going to request the number of lines 198 | BeginTextCommandLineCount("CELL_EMAIL_BCON"); // _BEGIN_TEXT_COMMAND_LINE_COUNT 199 | 200 | // Add the text that has been sent to us 201 | UIResText.AddLongString(text);// Add the text that has been sent to us 202 | // Get the resolution with the correct aspect ratio 203 | SizeF res = ResolutionMaintainRatio; 204 | // Calculate the x and y positions 205 | float x = position.X / res.Width; 206 | float y = position.Y / res.Height; 207 | 208 | // Set the properties for the text 209 | SetTextFont((int)font); 210 | SetTextScale(1f, scale); 211 | 212 | // If there is some text wrap to add 213 | if (wrap > 0) 214 | { 215 | // Calculate the wrap size 216 | float start = position.X / res.Width; 217 | float end = start + (wrap / res.Width); 218 | // And apply it 219 | SetTextWrap(x, end); 220 | } 221 | // Finally, return the number of lines being made by the string 222 | return GetTextScreenLineCount(x, y); // _GET_TEXT_SCREEN_LINE_COUNT 223 | } 224 | } 225 | } 226 | 227 | -------------------------------------------------------------------------------- /NativeUI/Elements/Sprite.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using System.IO; 4 | using System.Reflection; 5 | using CitizenFX.Core.Native; 6 | using CitizenFX.Core; 7 | using CitizenFX.Core.UI; 8 | using System.Drawing; 9 | 10 | namespace NativeUI 11 | { 12 | public class Sprite 13 | { 14 | public PointF Position; 15 | public SizeF Size; 16 | public Color Color; 17 | public bool Visible; 18 | public float Heading; 19 | 20 | public string TextureDict 21 | { 22 | get { return _textureDict; } 23 | set 24 | { 25 | _textureDict = value; 26 | //if(_autoload && !Function.Call(Hash.HAS_STREAMED_TEXTURE_DICT_LOADED, value)) 27 | //Function.Call(Hash.REQUEST_STREAMED_TEXTURE_DICT, value, true); 28 | } 29 | } 30 | 31 | public string TextureName; 32 | private string _textureDict; 33 | 34 | /// 35 | /// Creates a game sprite object from a texture dictionary and texture name. 36 | /// 37 | /// 38 | /// 39 | /// 40 | /// 41 | /// 42 | /// 43 | public Sprite(string textureDict, string textureName, PointF position, SizeF size, float heading, Color color) //BASE 44 | { 45 | //if (!Function.Call(Hash.HAS_STREAMED_TEXTURE_DICT_LOADED, textureDict)) 46 | //Function.Call(Hash.REQUEST_STREAMED_TEXTURE_DICT, textureDict, true); 47 | TextureDict = textureDict; 48 | TextureName = textureName; 49 | 50 | Position = position; 51 | Size = size; 52 | Heading = heading; 53 | Color = color; 54 | Visible = true; 55 | } 56 | 57 | /// 58 | /// Creates a game sprite object from a texture dictionary and texture name. 59 | /// 60 | /// 61 | /// 62 | /// 63 | /// 64 | public Sprite(string textureDict, string textureName, PointF position, SizeF size) : this(textureDict, textureName, position, size, 0f, Color.FromArgb(255, 255, 255, 255)) 65 | { 66 | } 67 | 68 | 69 | /// 70 | /// Draws the sprite on a 1080-pixels height base. 71 | /// 72 | public void Draw() 73 | { 74 | if (!Visible) return; 75 | if (!API.HasStreamedTextureDictLoaded(TextureDict)) 76 | API.RequestStreamedTextureDict(TextureDict, true); 77 | 78 | int screenw = Screen.Resolution.Width; 79 | int screenh = Screen.Resolution.Height; 80 | const float height = 1080f; 81 | float ratio = (float)screenw / screenh; 82 | var width = height * ratio; 83 | 84 | 85 | float w = (Size.Width / width); 86 | float h = (Size.Height / height); 87 | float x = (Position.X / width) + w * 0.5f; 88 | float y = (Position.Y / height) + h * 0.5f; 89 | 90 | API.DrawSprite(TextureDict, TextureName, x, y, w, h, Heading, Color.R, Color.G, Color.B, Color.A); 91 | } 92 | 93 | public static void Draw(string dict, string name, int xpos, int ypos, int boxWidth, int boxHeight, float rotation, Color color) 94 | { 95 | if (!API.HasStreamedTextureDictLoaded(dict)) 96 | API.RequestStreamedTextureDict(dict, true); 97 | 98 | int screenw = Screen.Resolution.Width; 99 | int screenh = Screen.Resolution.Height; 100 | const float height = 1080f; 101 | float ratio = (float)screenw / screenh; 102 | var width = height * ratio; 103 | 104 | 105 | float w = (boxWidth / width); 106 | float h = (boxHeight / height); 107 | float x = (xpos / width) + w * 0.5f; 108 | float y = (ypos / height) + h * 0.5f; 109 | 110 | API.DrawSprite(dict, name, x, y, w, h, rotation, color.R, color.G, color.B, color.A); 111 | } 112 | 113 | /* 114 | /// 115 | /// Draw a custom texture from a file on a 1080-pixels height base. 116 | /// 117 | /// Path to texture file. 118 | /// 119 | /// 120 | public static void DrawTexture(string path, PointF position, SizeF size, float rotation, Color color) 121 | { 122 | int screenw = Screen.Resolution.Width; 123 | int screenh = Screen.Resolution.Height; 124 | 125 | const float height = 1080f; 126 | float ratio = (float)screenw / screenh; 127 | float width = height * ratio; 128 | 129 | float reduceX = Screen.Width / width; 130 | float reduceY = Screen.Height / height; 131 | 132 | 133 | PointF extra = new PointF(0,0); 134 | if (screenw == 1914 && screenh == 1052) //TODO: Fix this when ScriptHookVDotNet 1.2 comes out. 135 | extra = new PointF(15, 0); 136 | 137 | DrawTexture(path, 1, 1, 60, 138 | new PointF(Convert.ToInt32(position.X*reduceX) + extra.X, Convert.ToInt32(position.Y*reduceY) + extra.Y), 139 | new PointF(0f, 0f), 140 | new SizeF(Convert.ToInt32(size.Width * reduceX), Convert.ToInt32(size.Height * reduceY)), 141 | rotation, color); 142 | } 143 | 144 | /// 145 | /// Draw a custom texture from a file on a 1080-pixels height base. 146 | /// 147 | /// Path to texture file. 148 | /// 149 | /// 150 | public static void DrawTexture(string path, PointF position, SizeF size) 151 | { 152 | int screenw = Game.ScreenResolution.Width; 153 | int screenh = Game.ScreenResolution.Height; 154 | 155 | const float height = 1080f; 156 | float ratio = (float)screenw / screenh; 157 | float width = height * ratio; 158 | 159 | float reduceX = UI.WIDTH / width; 160 | float reduceY = UI.HEIGHT / height; 161 | 162 | 163 | PointF extra = new PointF(0, 0); 164 | if (screenw == 1914 && screenh == 1052) //TODO: Fix this when ScriptHookVDotNet 1.2 comes out. 165 | extra = new PointF(15, 0); 166 | 167 | UI.DrawTexture(path, 1, 1, 60, 168 | new PointF(Convert.ToInt32(position.X * reduceX) + extra.X, Convert.ToInt32(position.Y * reduceY) + extra.Y), 169 | new PointFF(0f, 0f), 170 | new SizeF(Convert.ToInt32(size.Width * reduceX), Convert.ToInt32(size.Height * reduceY)), 171 | 0f, Color.White); 172 | } 173 | */ 174 | 175 | /// 176 | /// Save an embedded resource to a temporary file. 177 | /// 178 | /// Your executing assembly. 179 | /// Resource name including your solution name. E.G MyMenuMod.banner.png 180 | /// Absolute path to the written file. 181 | public static string WriteFileFromResources(Assembly yourAssembly, string fullResourceName) 182 | { 183 | string tmpPath = Path.GetTempFileName(); 184 | return WriteFileFromResources(yourAssembly, fullResourceName, tmpPath); 185 | } 186 | 187 | 188 | /// 189 | /// Save an embedded resource to a concrete path. 190 | /// 191 | /// Your executing assembly. 192 | /// Resource name including your solution name. E.G MyMenuMod.banner.png 193 | /// Path to where save the file, including the filename. 194 | /// Absolute path to the written file. 195 | public static string WriteFileFromResources(Assembly yourAssembly, string fullResourceName, string savePath) 196 | { 197 | using (Stream stream = yourAssembly.GetManifestResourceStream(fullResourceName)) 198 | { 199 | if (stream != null) 200 | { 201 | byte[] buffer = new byte[stream.Length]; 202 | stream.Read(buffer, 0, Convert.ToInt32(stream.Length)); 203 | 204 | using (FileStream fileStream = File.Create(savePath)) 205 | { 206 | fileStream.Write(buffer, 0, Convert.ToInt32(stream.Length)); 207 | fileStream.Close(); 208 | } 209 | } 210 | } 211 | return Path.GetFullPath(savePath); 212 | } 213 | } 214 | } -------------------------------------------------------------------------------- /NativeUI/PauseMenu/TabMissionSelectItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using Font = CitizenFX.Core.UI.Font; 5 | using CitizenFX.Core; 6 | using CitizenFX.Core.Native; 7 | using CitizenFX.Core.UI; 8 | 9 | namespace NativeUI.PauseMenu 10 | { 11 | public delegate void OnItemSelect(MissionInformation selectedItem); 12 | 13 | public class MissionInformation 14 | { 15 | public MissionInformation(string name, IEnumerable> info) 16 | { 17 | Name = name; 18 | ValueList = new List>(info); 19 | } 20 | 21 | public MissionInformation(string name, string description, IEnumerable> info) 22 | { 23 | Name = name; 24 | Description = description; 25 | ValueList = new List>(info); 26 | } 27 | 28 | public string Name { get; set; } 29 | public string Description { get; set; } 30 | public MissionLogo Logo { get; set; } 31 | public List> ValueList { get; set; } 32 | } 33 | 34 | public class MissionLogo 35 | { 36 | /// 37 | /// Create a logo from an external picture. 38 | /// 39 | /// Path to the picture 40 | public MissionLogo(string filepath) 41 | { 42 | FileName = filepath; 43 | IsGameTexture = false; 44 | } 45 | 46 | /// 47 | /// Create a mission logo from a game texture. 48 | /// 49 | /// Name of the texture dictionary 50 | /// Name of the texture. 51 | public MissionLogo(string textureDict, string textureName) 52 | { 53 | FileName = textureName; 54 | DictionaryName = textureDict; 55 | IsGameTexture = true; 56 | } 57 | 58 | internal bool IsGameTexture; 59 | internal string FileName { get; set; } 60 | internal string DictionaryName { get; set; } 61 | } 62 | 63 | public class TabMissionSelectItem : TabItem 64 | { 65 | protected internal float _add = 0; 66 | public TabMissionSelectItem(string name, IEnumerable list) : base(name) 67 | { 68 | base.FadeInWhenFocused = true; 69 | base.DrawBg = false; 70 | 71 | _noLogo = new Sprite("gtav_online", "rockstarlogo256", new PointF(), new SizeF(512, 256)); 72 | _maxItem = MaxItemsPerView; 73 | _minItem = 0; 74 | 75 | CanBeFocused = true; 76 | 77 | Heists = new List(list); 78 | } 79 | 80 | public event OnItemSelect OnItemSelect; 81 | 82 | public List Heists { get; set; } 83 | public int Index { get; set; } 84 | 85 | protected const int MaxItemsPerView = 15; 86 | protected int _minItem; 87 | protected int _maxItem; 88 | protected Sprite _noLogo { get; set; } 89 | 90 | public override void ProcessControls() 91 | { 92 | if (!Focused) return; 93 | if (Heists.Count == 0) return; 94 | if (JustOpened) 95 | { 96 | JustOpened = false; 97 | return; 98 | } 99 | 100 | if (Game.IsControlJustPressed(0, Control.PhoneSelect)) 101 | { 102 | Game.PlaySound("SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET"); 103 | OnItemSelect?.Invoke(Heists[Index]); 104 | } 105 | 106 | if (Game.IsControlJustPressed(0, Control.FrontendUp) || Game.IsControlJustPressed(0, Control.MoveUpOnly)) 107 | { 108 | Index = (1000 - (1000 % Heists.Count) + Index - 1) % Heists.Count; 109 | Game.PlaySound("NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET"); 110 | 111 | if (Heists.Count <= MaxItemsPerView) return; 112 | 113 | if (Index < _minItem) 114 | { 115 | _minItem--; 116 | _maxItem--; 117 | } 118 | 119 | if (Index == Heists.Count - 1) 120 | { 121 | _minItem = Heists.Count - MaxItemsPerView; 122 | _maxItem = Heists.Count; 123 | } 124 | } 125 | 126 | else if (Game.IsControlJustPressed(0, Control.FrontendDown) || Game.IsControlJustPressed(0, Control.MoveDownOnly)) 127 | { 128 | Index = (1000 - (1000 % Heists.Count) + Index + 1) % Heists.Count; 129 | Game.PlaySound("NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET"); 130 | 131 | if (Heists.Count <= MaxItemsPerView) return; 132 | 133 | if (Index >= _maxItem) 134 | { 135 | _maxItem++; 136 | _minItem++; 137 | } 138 | 139 | if (Index == 0) 140 | { 141 | _minItem = 0; 142 | _maxItem = MaxItemsPerView; 143 | } 144 | } 145 | } 146 | 147 | public override void Draw() 148 | { 149 | base.Draw(); 150 | if (Heists.Count == 0) return; 151 | 152 | 153 | var alpha = Focused ? 120 : 30; 154 | var blackAlpha = Focused ? 200 : 100; 155 | var fullAlpha = Focused ? 255 : 150; 156 | var activeWidth = Resolution.Width - SafeSize.X * 2; 157 | var itemSize = new SizeF((int)activeWidth - (_add + 515), 40); 158 | var counter = 0; 159 | for (int i = _minItem; i < Math.Min(Heists.Count, _maxItem); i++) 160 | { 161 | new UIResRectangle(SafeSize.AddPoints(new PointF(0, 43 * counter)), itemSize, (Index == i && Focused) ? Color.FromArgb(fullAlpha, Colors.White) : Color.FromArgb(blackAlpha, Colors.Black)).Draw(); 162 | new UIResText(Heists[i].Name, SafeSize.AddPoints(new PointF(6, 5 + 43 * counter)), 0.35f, Color.FromArgb(fullAlpha, (Index == i && Focused) ? Colors.Black : Colors.White)).Draw(); 163 | counter++; 164 | } 165 | 166 | if (Heists[Index].Logo == null || string.IsNullOrEmpty(Heists[Index].Logo.FileName)) 167 | { 168 | _noLogo.Position = new PointF((int)Resolution.Width - SafeSize.X - (512 + _add), SafeSize.Y); 169 | _noLogo.Color = Color.FromArgb(blackAlpha, 0, 0, 0); 170 | _noLogo.Draw(); 171 | } 172 | else if (Heists[Index].Logo != null && Heists[Index].Logo.FileName != null && !Heists[Index].Logo.IsGameTexture) 173 | { 174 | //var target = Heists[Index].Logo.FileName; 175 | //Sprite.DrawTexture(target, new PointF((int)Resolution.Width - SafeSize.X - 512, SafeSize.Y), new SizeF(512, 256)); 176 | } 177 | else if (Heists[Index].Logo != null && Heists[Index].Logo.FileName != null && 178 | Heists[Index].Logo.IsGameTexture) 179 | { 180 | var newLogo = new Sprite(Heists[Index].Logo.DictionaryName, Heists[Index].Logo.FileName, new PointF((int)Resolution.Width - SafeSize.X - (512 + _add), SafeSize.Y), new SizeF(512, 256)) 181 | { 182 | Color = Color.FromArgb(blackAlpha, 0, 0, 0) 183 | }; 184 | newLogo.Draw(); 185 | } 186 | 187 | new UIResRectangle(new PointF((int)Resolution.Width - SafeSize.X - (512 + _add), SafeSize.Y + 256), new SizeF(512, 40), Color.FromArgb(fullAlpha, Colors.Black)).Draw(); 188 | new UIResText(Heists[Index].Name, new PointF((int)Resolution.Width - SafeSize.X - (4 + _add), SafeSize.Y + 260), 0.5f, Color.FromArgb(fullAlpha, Colors.White), 189 | Font.HouseScript, Alignment.Right).Draw(); 190 | 191 | for (int i = 0; i < Heists[Index].ValueList.Count; i++) 192 | { 193 | new UIResRectangle(new PointF((int)Resolution.Width - SafeSize.X - (512 + _add), SafeSize.Y + 256 + 40 + (40 * i)), 194 | new SizeF(512, 40), i % 2 == 0 ? Color.FromArgb(alpha, 0, 0, 0) : Color.FromArgb(blackAlpha, 0, 0, 0)).Draw(); 195 | var text = Heists[Index].ValueList[i].Item1; 196 | var label = Heists[Index].ValueList[i].Item2; 197 | 198 | 199 | new UIResText(text, new PointF((int)Resolution.Width - SafeSize.X - (506 + _add), SafeSize.Y + 260 + 42 + (40 * i)), 0.35f, Color.FromArgb(fullAlpha, Colors.White)).Draw(); 200 | new UIResText(label, new PointF((int)Resolution.Width - SafeSize.X - (6 + _add), SafeSize.Y + 260 + 42 + (40 * i)), 0.35f, Color.FromArgb(fullAlpha, Colors.White), Font.ChaletLondon, Alignment.Right).Draw(); 201 | } 202 | 203 | if (!string.IsNullOrEmpty(Heists[Index].Description)) 204 | { 205 | var propLen = Heists[Index].ValueList.Count; 206 | new UIResRectangle(new PointF((int)Resolution.Width - SafeSize.X - (512 + _add), SafeSize.Y + 256 + 42 + 40 * propLen), 207 | new SizeF(512, 2), Color.FromArgb(fullAlpha, Colors.White)).Draw(); 208 | new UIResText(Heists[Index].Description, 209 | new PointF((int)Resolution.Width - SafeSize.X - (508 + _add), SafeSize.Y + 256 + 45 + 40 * propLen + 4), 0.35f, 210 | Color.FromArgb(fullAlpha, Colors.White)) { Wrap = (508 + _add) }.Draw(); 211 | new UIResRectangle(new PointF((int)Resolution.Width - SafeSize.X - (512 + _add), SafeSize.Y + 256 + 44 + 40 * propLen), 212 | new SizeF(512, 45 * (int)(ScreenTools.GetTextWidth(Heists[Index].Description, Font.ChaletLondon, 0.35f) / 500)), 213 | Color.FromArgb(blackAlpha, 0, 0, 0)).Draw(); 214 | } 215 | } 216 | } 217 | } -------------------------------------------------------------------------------- /NativeUI/Scaleforms/BigMessage/BigMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Remoting.Messaging; 3 | using CitizenFX.Core; 4 | using CitizenFX.Core.Native; 5 | using System.Threading.Tasks; 6 | 7 | namespace NativeUI 8 | { 9 | public class BigMessageHandler 10 | { 11 | private Scaleform _sc; 12 | private int _start; 13 | private int _timer; 14 | 15 | public BigMessageHandler() 16 | { 17 | 18 | } 19 | 20 | public async Task Load() 21 | { 22 | if (_sc != null) return; 23 | _sc = new Scaleform("MP_BIG_MESSAGE_FREEMODE"); 24 | var timeout = 1000; 25 | var start = DateTime.Now; 26 | while (!_sc.IsLoaded && DateTime.Now.Subtract(start).TotalMilliseconds < timeout) await BaseScript.Delay(0); 27 | } 28 | 29 | public void Dispose() 30 | { 31 | _sc.Dispose(); 32 | _sc = null; 33 | } 34 | 35 | public async void ShowMissionPassedMessage(string msg, int time = 5000) 36 | { 37 | await Load(); 38 | _start = Game.GameTime; 39 | _sc.CallFunction("SHOW_MISSION_PASSED_MESSAGE", msg, "", 100, true, 0, true); 40 | _timer = time; 41 | } 42 | 43 | public async void ShowColoredShard(string msg, string desc, HudColor textColor, HudColor bgColor, int time = 5000) 44 | { 45 | await Load(); 46 | _start = Game.GameTime; 47 | _sc.CallFunction("SHOW_SHARD_CENTERED_MP_MESSAGE", msg, desc, (int)bgColor, (int)textColor); 48 | _timer = time; 49 | } 50 | 51 | public async void ShowOldMessage(string msg, int time = 5000) 52 | { 53 | await Load(); 54 | _start = Game.GameTime; 55 | _sc.CallFunction("SHOW_MISSION_PASSED_MESSAGE", msg); 56 | _timer = time; 57 | } 58 | 59 | public async void ShowSimpleShard(string title, string subtitle, int time = 5000) 60 | { 61 | await Load(); 62 | _start = Game.GameTime; 63 | _sc.CallFunction("SHOW_SHARD_CREW_RANKUP_MP_MESSAGE", title, subtitle); 64 | _timer = time; 65 | } 66 | 67 | public async void ShowRankupMessage(string msg, string subtitle, int rank, int time = 5000) 68 | { 69 | await Load(); 70 | _start = Game.GameTime; 71 | _sc.CallFunction("SHOW_BIG_MP_MESSAGE", msg, subtitle, rank, "", ""); 72 | _timer = time; 73 | } 74 | 75 | public async void ShowWeaponPurchasedMessage(string bigMessage, string weaponName, WeaponHash weapon, int time = 5000) 76 | { 77 | await Load(); 78 | _start = Game.GameTime; 79 | _sc.CallFunction("SHOW_WEAPON_PURCHASED", bigMessage, weaponName, unchecked((int)weapon), "", 100); 80 | _timer = time; 81 | } 82 | 83 | public async void ShowMpMessageLarge(string msg, int time = 5000) 84 | { 85 | await Load(); 86 | _start = Game.GameTime; 87 | _sc.CallFunction("SHOW_CENTERED_MP_MESSAGE_LARGE", msg, "test", 100, true, 100); 88 | _sc.CallFunction("TRANSITION_IN"); 89 | _timer = time; 90 | } 91 | 92 | public async void ShowCustomShard(string funcName, params object[] paremeters) 93 | { 94 | await Load(); 95 | _sc.CallFunction(funcName, paremeters); 96 | } 97 | 98 | internal void Update() 99 | { 100 | if (_sc == null) return; 101 | _sc.Render2D(); 102 | if (_start != 0 && Game.GameTime - _start > _timer) 103 | { 104 | _sc.CallFunction("TRANSITION_OUT"); 105 | _start = 0; 106 | Dispose(); 107 | } 108 | 109 | } 110 | } 111 | 112 | public class BigMessageThread : BaseScript 113 | { 114 | public static BigMessageHandler MessageInstance { get; set; } 115 | 116 | public BigMessageThread() 117 | { 118 | MessageInstance = new BigMessageHandler(); 119 | Tick += BigMessageThread_Tick; 120 | } 121 | 122 | private async Task BigMessageThread_Tick() 123 | { 124 | MessageInstance.Update(); 125 | await Task.FromResult(0); 126 | } 127 | } 128 | 129 | public enum HudColor 130 | { 131 | NONE = -1, 132 | HUD_COLOUR_PURE_WHITE = 0, 133 | HUD_COLOUR_WHITE = 1, 134 | HUD_COLOUR_BLACK = 2, 135 | HUD_COLOUR_GREY = 3, 136 | HUD_COLOUR_GREYLIGHT = 4, 137 | HUD_COLOUR_GREYDARK = 5, 138 | HUD_COLOUR_RED = 6, 139 | HUD_COLOUR_REDLIGHT = 7, 140 | HUD_COLOUR_REDDARK = 8, 141 | HUD_COLOUR_BLUE = 9, 142 | HUD_COLOUR_BLUELIGHT = 10, 143 | HUD_COLOUR_BLUEDARK = 11, 144 | HUD_COLOUR_YELLOW = 12, 145 | HUD_COLOUR_YELLOWLIGHT = 13, 146 | HUD_COLOUR_YELLOWDARK = 14, 147 | HUD_COLOUR_ORANGE = 15, 148 | HUD_COLOUR_ORANGELIGHT = 16, 149 | HUD_COLOUR_ORANGEDARK = 17, 150 | HUD_COLOUR_GREEN = 18, 151 | HUD_COLOUR_GREENLIGHT = 19, 152 | HUD_COLOUR_GREENDARK = 20, 153 | HUD_COLOUR_PURPLE = 21, 154 | HUD_COLOUR_PURPLELIGHT = 22, 155 | HUD_COLOUR_PURPLEDARK = 23, 156 | HUD_COLOUR_PINK = 24, 157 | HUD_COLOUR_RADAR_HEALTH = 25, 158 | HUD_COLOUR_RADAR_ARMOUR = 26, 159 | HUD_COLOUR_RADAR_DAMAGE = 27, 160 | HUD_COLOUR_NET_PLAYER1 = 28, 161 | HUD_COLOUR_NET_PLAYER2 = 29, 162 | HUD_COLOUR_NET_PLAYER3 = 30, 163 | HUD_COLOUR_NET_PLAYER4 = 31, 164 | HUD_COLOUR_NET_PLAYER5 = 32, 165 | HUD_COLOUR_NET_PLAYER6 = 33, 166 | HUD_COLOUR_NET_PLAYER7 = 34, 167 | HUD_COLOUR_NET_PLAYER8 = 35, 168 | HUD_COLOUR_NET_PLAYER9 = 36, 169 | HUD_COLOUR_NET_PLAYER10 = 37, 170 | HUD_COLOUR_NET_PLAYER11 = 38, 171 | HUD_COLOUR_NET_PLAYER12 = 39, 172 | HUD_COLOUR_NET_PLAYER13 = 40, 173 | HUD_COLOUR_NET_PLAYER14 = 41, 174 | HUD_COLOUR_NET_PLAYER15 = 42, 175 | HUD_COLOUR_NET_PLAYER16 = 43, 176 | HUD_COLOUR_NET_PLAYER17 = 44, 177 | HUD_COLOUR_NET_PLAYER18 = 45, 178 | HUD_COLOUR_NET_PLAYER19 = 46, 179 | HUD_COLOUR_NET_PLAYER20 = 47, 180 | HUD_COLOUR_NET_PLAYER21 = 48, 181 | HUD_COLOUR_NET_PLAYER22 = 49, 182 | HUD_COLOUR_NET_PLAYER23 = 50, 183 | HUD_COLOUR_NET_PLAYER24 = 51, 184 | HUD_COLOUR_NET_PLAYER25 = 52, 185 | HUD_COLOUR_NET_PLAYER26 = 53, 186 | HUD_COLOUR_NET_PLAYER27 = 54, 187 | HUD_COLOUR_NET_PLAYER28 = 55, 188 | HUD_COLOUR_NET_PLAYER29 = 56, 189 | HUD_COLOUR_NET_PLAYER30 = 57, 190 | HUD_COLOUR_NET_PLAYER31 = 58, 191 | HUD_COLOUR_NET_PLAYER32 = 59, 192 | HUD_COLOUR_SIMPLEBLIP_DEFAULT = 60, 193 | HUD_COLOUR_MENU_BLUE = 61, 194 | HUD_COLOUR_MENU_GREY_LIGHT = 62, 195 | HUD_COLOUR_MENU_BLUE_EXTRA_DARK = 63, 196 | HUD_COLOUR_MENU_YELLOW = 64, 197 | HUD_COLOUR_MENU_YELLOW_DARK = 65, 198 | HUD_COLOUR_MENU_GREEN = 66, 199 | HUD_COLOUR_MENU_GREY = 67, 200 | HUD_COLOUR_MENU_GREY_DARK = 68, 201 | HUD_COLOUR_MENU_HIGHLIGHT = 69, 202 | HUD_COLOUR_MENU_STANDARD = 70, 203 | HUD_COLOUR_MENU_DIMMED = 71, 204 | HUD_COLOUR_MENU_EXTRA_DIMMED = 72, 205 | HUD_COLOUR_BRIEF_TITLE = 73, 206 | HUD_COLOUR_MID_GREY_MP = 74, 207 | HUD_COLOUR_NET_PLAYER1_DARK = 75, 208 | HUD_COLOUR_NET_PLAYER2_DARK = 76, 209 | HUD_COLOUR_NET_PLAYER3_DARK = 77, 210 | HUD_COLOUR_NET_PLAYER4_DARK = 78, 211 | HUD_COLOUR_NET_PLAYER5_DARK = 79, 212 | HUD_COLOUR_NET_PLAYER6_DARK = 80, 213 | HUD_COLOUR_NET_PLAYER7_DARK = 81, 214 | HUD_COLOUR_NET_PLAYER8_DARK = 82, 215 | HUD_COLOUR_NET_PLAYER9_DARK = 83, 216 | HUD_COLOUR_NET_PLAYER10_DARK = 84, 217 | HUD_COLOUR_NET_PLAYER11_DARK = 85, 218 | HUD_COLOUR_NET_PLAYER12_DARK = 86, 219 | HUD_COLOUR_NET_PLAYER13_DARK = 87, 220 | HUD_COLOUR_NET_PLAYER14_DARK = 88, 221 | HUD_COLOUR_NET_PLAYER15_DARK = 89, 222 | HUD_COLOUR_NET_PLAYER16_DARK = 90, 223 | HUD_COLOUR_NET_PLAYER17_DARK = 91, 224 | HUD_COLOUR_NET_PLAYER18_DARK = 92, 225 | HUD_COLOUR_NET_PLAYER19_DARK = 93, 226 | HUD_COLOUR_NET_PLAYER20_DARK = 94, 227 | HUD_COLOUR_NET_PLAYER21_DARK = 95, 228 | HUD_COLOUR_NET_PLAYER22_DARK = 96, 229 | HUD_COLOUR_NET_PLAYER23_DARK = 97, 230 | HUD_COLOUR_NET_PLAYER24_DARK = 98, 231 | HUD_COLOUR_NET_PLAYER25_DARK = 99, 232 | HUD_COLOUR_NET_PLAYER26_DARK = 100, 233 | HUD_COLOUR_NET_PLAYER27_DARK = 101, 234 | HUD_COLOUR_NET_PLAYER28_DARK = 102, 235 | HUD_COLOUR_NET_PLAYER29_DARK = 103, 236 | HUD_COLOUR_NET_PLAYER30_DARK = 104, 237 | HUD_COLOUR_NET_PLAYER31_DARK = 105, 238 | HUD_COLOUR_NET_PLAYER32_DARK = 106, 239 | HUD_COLOUR_BRONZE = 107, 240 | HUD_COLOUR_SILVER = 108, 241 | HUD_COLOUR_GOLD = 109, 242 | HUD_COLOUR_PLATINUM = 110, 243 | HUD_COLOUR_GANG1 = 111, 244 | HUD_COLOUR_GANG2 = 112, 245 | HUD_COLOUR_GANG3 = 113, 246 | HUD_COLOUR_GANG4 = 114, 247 | HUD_COLOUR_SAME_CREW = 115, 248 | HUD_COLOUR_FREEMODE = 116, 249 | HUD_COLOUR_PAUSE_BG = 117, 250 | HUD_COLOUR_FRIENDLY = 118, 251 | HUD_COLOUR_ENEMY = 119, 252 | HUD_COLOUR_LOCATION = 120, 253 | HUD_COLOUR_PICKUP = 121, 254 | HUD_COLOUR_PAUSE_SINGLEPLAYER = 122, 255 | HUD_COLOUR_FREEMODE_DARK = 123, 256 | HUD_COLOUR_INACTIVE_MISSION = 124, 257 | HUD_COLOUR_DAMAGE = 125, 258 | HUD_COLOUR_PINKLIGHT = 126, 259 | HUD_COLOUR_PM_MITEM_HIGHLIGHT = 127, 260 | HUD_COLOUR_SCRIPT_VARIABLE = 128, 261 | HUD_COLOUR_YOGA = 129, 262 | HUD_COLOUR_TENNIS = 130, 263 | HUD_COLOUR_GOLF = 131, 264 | HUD_COLOUR_SHOOTING_RANGE = 132, 265 | HUD_COLOUR_FLIGHT_SCHOOL = 133, 266 | HUD_COLOUR_NORTH_BLUE = 134, 267 | HUD_COLOUR_SOCIAL_CLUB = 135, 268 | HUD_COLOUR_PLATFORM_BLUE = 136, 269 | HUD_COLOUR_PLATFORM_GREEN = 137, 270 | HUD_COLOUR_PLATFORM_GREY = 138, 271 | HUD_COLOUR_FACEBOOK_BLUE = 139, 272 | HUD_COLOUR_INGAME_BG = 140, 273 | HUD_COLOUR_DARTS = 141, 274 | HUD_COLOUR_WAYPOINT = 142, 275 | HUD_COLOUR_MICHAEL = 143, 276 | HUD_COLOUR_FRANKLIN = 144, 277 | HUD_COLOUR_TREVOR = 145, 278 | HUD_COLOUR_GOLF_P1 = 146, 279 | HUD_COLOUR_GOLF_P2 = 147, 280 | HUD_COLOUR_GOLF_P3 = 148, 281 | HUD_COLOUR_GOLF_P4 = 149, 282 | HUD_COLOUR_WAYPOINTLIGHT = 150, 283 | HUD_COLOUR_WAYPOINTDARK = 151, 284 | HUD_COLOUR_PANEL_LIGHT = 152, 285 | HUD_COLOUR_MICHAEL_DARK = 153, 286 | HUD_COLOUR_FRANKLIN_DARK = 154, 287 | HUD_COLOUR_TREVOR_DARK = 155, 288 | HUD_COLOUR_OBJECTIVE_ROUTE = 156, 289 | HUD_COLOUR_PAUSEMAP_TINT = 157, 290 | HUD_COLOUR_PAUSE_DESELECT = 158, 291 | HUD_COLOUR_PM_WEAPONS_PURCHASABLE = 159, 292 | HUD_COLOUR_PM_WEAPONS_LOCKED = 160, 293 | HUD_COLOUR_END_SCREEN_BG = 161, 294 | HUD_COLOUR_CHOP = 162, 295 | HUD_COLOUR_PAUSEMAP_TINT_HALF = 163, 296 | HUD_COLOUR_NORTH_BLUE_OFFICIAL = 164, 297 | HUD_COLOUR_SCRIPT_VARIABLE_2 = 165, 298 | HUD_COLOUR_H = 166, 299 | HUD_COLOUR_HDARK = 167, 300 | HUD_COLOUR_T = 168, 301 | HUD_COLOUR_TDARK = 169, 302 | HUD_COLOUR_HSHARD = 170, 303 | HUD_COLOUR_CONTROLLER_MICHAEL = 171, 304 | HUD_COLOUR_CONTROLLER_FRANKLIN = 172, 305 | HUD_COLOUR_CONTROLLER_TREVOR = 173, 306 | HUD_COLOUR_CONTROLLER_CHOP = 174, 307 | HUD_COLOUR_VIDEO_EDITOR_VIDEO = 175, 308 | HUD_COLOUR_VIDEO_EDITOR_AUDIO = 176, 309 | HUD_COLOUR_VIDEO_EDITOR_TEXT = 177, 310 | HUD_COLOUR_HB_BLUE = 178, 311 | HUD_COLOUR_HB_YELLOW = 179, 312 | } 313 | } -------------------------------------------------------------------------------- /NativeUI/MenuPool.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | using System.Linq; 4 | using CitizenFX.Core; 5 | using CitizenFX.Core.Native; 6 | using NativeUI.PauseMenu; 7 | using Control = CitizenFX.Core.Control; 8 | 9 | namespace NativeUI 10 | { 11 | 12 | public delegate void MenuStateChangeEvent(UIMenu oldMenu, UIMenu newMenu, MenuState state); 13 | 14 | /// 15 | /// Helper class that handles all of your Menus. After instatiating it, you will have to add your menu by using the Add method. 16 | /// 17 | public class MenuPool 18 | { 19 | private static Ped _ped; 20 | internal static Ped PlayerPed { get 21 | { 22 | int handle = API.PlayerPedId(); 23 | 24 | if (_ped is null || handle != _ped.Handle) 25 | { 26 | _ped = new Ped(handle); 27 | } 28 | 29 | return _ped; 30 | } 31 | } 32 | 33 | public bool MouseEdgeEnabled { set { _menuList.ForEach(m => m.MouseEdgeEnabled = value); } } 34 | 35 | public bool ControlDisablingEnabled { set { _menuList.ForEach(m => m.ControlDisablingEnabled = value); } } 36 | 37 | public bool ResetCursorOnOpen { set { _menuList.ForEach(m => m.ResetCursorOnOpen = value); } } 38 | 39 | public bool FormatDescriptions { set { _menuList.ForEach(m => m.FormatDescriptions = value); } } 40 | 41 | public string AUDIO_LIBRARY { set { _menuList.ForEach(m => m.AUDIO_LIBRARY = value); } } 42 | 43 | public string AUDIO_UPDOWN { set { _menuList.ForEach(m => m.AUDIO_UPDOWN = value); } } 44 | 45 | public string AUDIO_SELECT { set { _menuList.ForEach(m => m.AUDIO_SELECT = value); } } 46 | 47 | public string AUDIO_BACK { set { _menuList.ForEach(m => m.AUDIO_BACK = value); } } 48 | 49 | public string AUDIO_ERROR { set { _menuList.ForEach(m => m.AUDIO_ERROR = value); } } 50 | 51 | public int WidthOffset { set { _menuList.ForEach(m => m.SetMenuWidthOffset(value)); } } 52 | 53 | public string CounterPretext { set { _menuList.ForEach(m => m.CounterPretext = value); } } 54 | 55 | public bool DisableInstructionalButtons { set { _menuList.ForEach(m => m.DisableInstructionalButtons(value)); } } 56 | 57 | public bool BannerInheritance = true; 58 | 59 | public bool OffsetInheritance = true; 60 | 61 | /// 62 | /// Called when user either opens or closes the main menu, clicks on a binded button, goes back to a parent menu. 63 | /// 64 | public event MenuStateChangeEvent OnMenuStateChanged; 65 | 66 | private readonly List _menuList = new List(); 67 | private readonly List _pauseMenus = new List(); 68 | 69 | /// 70 | /// Add your menu to the menu pool. 71 | /// 72 | /// 73 | public void Add(UIMenu menu) 74 | { 75 | _menuList.Add(menu); 76 | menu._poolcontainer = this; 77 | } 78 | 79 | /// 80 | /// Add your pause menu to the menu pool. 81 | /// 82 | /// 83 | public void AddPauseMenu(TabView menu) 84 | { 85 | _pauseMenus.Add(menu); 86 | } 87 | 88 | /// 89 | /// Create and add a submenu to the menu pool. 90 | /// Adds an item with the given text to the menu, creates a corresponding submenu, and binds the submenu to the item. 91 | /// The submenu inherits its title from the menu, and its subtitle from the item text. 92 | /// 93 | /// The parent menu to which the submenu must be added. 94 | /// The name of the submenu. 95 | /// The newly created submenu. 96 | public UIMenu AddSubMenu(UIMenu menu, string text) 97 | { 98 | PointF Offset = PointF.Empty; 99 | if (OffsetInheritance) 100 | Offset = menu.Offset; 101 | return AddSubMenu(menu, text, "", Offset); 102 | } 103 | 104 | /// 105 | /// Create and add a submenu to the menu pool with a custom offset. 106 | /// Adds an item with the given text to the menu, creates a corresponding submenu, and binds the submenu to the item. 107 | /// The submenu inherits its title from the menu, and its subtitle from the item text. 108 | /// 109 | /// The parent menu to which the submenu must be added. 110 | /// The name of the submenu 111 | /// The offset of the menu 112 | /// The newly created submenu. 113 | public UIMenu AddSubMenu(UIMenu menu, string text, PointF offset) 114 | { 115 | return AddSubMenu(menu, text, "", Point.Empty); 116 | } 117 | 118 | /// 119 | /// Create and add a submenu to the menu pool. 120 | /// Adds an item with the given text and description to the menu, creates a corresponding submenu, and binds the submenu to the item. 121 | /// The submenu inherits its title from the menu, and its subtitle from the item text. 122 | /// 123 | /// The parent menu to which the submenu must be added. 124 | /// The name of the submenu. 125 | /// The name of the submenu. 126 | /// The newly created submenu. 127 | public UIMenu AddSubMenu(UIMenu menu, string text, string description) 128 | { 129 | PointF Offset = PointF.Empty; 130 | if (OffsetInheritance) 131 | Offset = menu.Offset; 132 | return AddSubMenu(menu, text, description, Offset); 133 | } 134 | 135 | /// 136 | /// Create and add a submenu to the menu pool. 137 | /// Adds an item with the given text and description to the menu, creates a corresponding submenu, and binds the submenu to the item. 138 | /// The submenu inherits its title from the menu, and its subtitle from the item text. 139 | /// 140 | /// The parent menu to which the submenu must be added. 141 | /// The name of the submenu. 142 | /// The name of the submenu. 143 | /// The newly created submenu. 144 | public UIMenu AddSubMenu(UIMenu menu, string text, string description, PointF offset) 145 | { 146 | UIMenuItem item = new UIMenuItem(text, description); 147 | menu.AddItem(item); 148 | UIMenu submenu = new UIMenu(menu.Title.Caption, text, offset); 149 | if (BannerInheritance && menu.BannerTexture != null) 150 | submenu.SetBannerType(menu.BannerTexture); 151 | else if (BannerInheritance && menu.BannerRectangle != null) 152 | submenu.SetBannerType(menu.BannerRectangle); 153 | else if (BannerInheritance && menu.BannerSprite != null) 154 | submenu.SetBannerType(menu.BannerSprite); 155 | submenu.MouseControlsEnabled = menu.MouseControlsEnabled; 156 | submenu.MouseEdgeEnabled = menu.MouseEdgeEnabled; 157 | Add(submenu); 158 | menu.BindMenuToItem(submenu, item); 159 | menu._poolcontainer = this; 160 | return submenu; 161 | 162 | } 163 | 164 | /// 165 | /// Refresh index of every menu in the pool. 166 | /// Use this after you have finished constructing the entire menu pool. 167 | /// 168 | public void RefreshIndex() 169 | { 170 | foreach (UIMenu menu in _menuList) menu.RefreshIndex(); 171 | } 172 | 173 | /// 174 | /// Returns all of your menus. 175 | /// 176 | /// 177 | public List ToList() 178 | { 179 | return _menuList; 180 | } 181 | 182 | /// 183 | /// Processes all of your visible menus' controls. 184 | /// 185 | public void ProcessControl() 186 | { 187 | /*foreach (var menu in _menuList.Where(menu => menu.Visible)) // foreach works slower with List. Also why make a new enumerable every tick 188 | { 189 | menu.ProcessControl(); 190 | }*/ 191 | 192 | int count = _menuList.Count; // Cache count 193 | for (int i = 0; i < count; i++) 194 | { 195 | if (_menuList[i].Visible) 196 | _menuList[i].ProcessControl(); 197 | } 198 | } 199 | 200 | 201 | /// 202 | /// Processes all of your visible menus' keys. 203 | /// 204 | /// 205 | public void ProcessKey(Keys key) 206 | { 207 | /*foreach (var menu in _menuList.Where(menu => menu.Visible)) 208 | { 209 | menu.ProcessKey(key); 210 | }*/ 211 | 212 | int count = _menuList.Count; 213 | for (int i = 0; i < count; i++) 214 | { 215 | if (_menuList[i].Visible) 216 | _menuList[i].ProcessKey(key); 217 | } 218 | } 219 | 220 | 221 | /// 222 | /// Processes all of your visible menus' mouses. 223 | /// 224 | public void ProcessMouse() 225 | { 226 | /*foreach (var menu in _menuList.Where(menu => menu.Visible)) 227 | { 228 | menu.ProcessMouse(); 229 | }*/ 230 | 231 | int count = _menuList.Count; 232 | for (int i = 0; i < count; i++) 233 | { 234 | if (_menuList[i].Visible) 235 | _menuList[i].ProcessMouse(); 236 | } 237 | } 238 | 239 | 240 | /// 241 | /// Draws all visible menus. 242 | /// 243 | public void Draw() 244 | { 245 | /*foreach (var menu in _menuList.Where(menu => menu.Visible)) 246 | { 247 | menu.Draw(); 248 | }*/ 249 | 250 | int count = _menuList.Count; 251 | for (int i = 0; i < count; i++) 252 | { 253 | if (_menuList[i].Visible) 254 | _menuList[i].Draw(); 255 | } 256 | } 257 | 258 | 259 | /// 260 | /// Checks if any menu is currently visible. 261 | /// 262 | /// true if at least one menu is visible, false if not. 263 | public bool IsAnyMenuOpen() 264 | { 265 | return _menuList.Any(menu => menu.Visible) || _pauseMenus.Any(x => x.Visible); 266 | } 267 | 268 | 269 | /// 270 | /// Process all of your menus' functions. Call this in a tick event. 271 | /// 272 | public void ProcessMenus() 273 | { 274 | ProcessControl(); 275 | if (_pauseMenus.Count > 0) 276 | _pauseMenus.ForEach(x => { x.ProcessControls(); x.Draw(); }); 277 | ProcessMouse(); 278 | Draw(); 279 | } 280 | 281 | 282 | /// 283 | /// Closes all of your menus. 284 | /// 285 | public void CloseAllMenus() 286 | { 287 | foreach (var menu in _menuList.Where(menu => menu.Visible)) 288 | { 289 | menu.Visible = false; 290 | } 291 | } 292 | 293 | public void SetBannerType(Sprite bannerType) 294 | { 295 | _menuList.ForEach(m => m.SetBannerType(bannerType)); 296 | } 297 | 298 | public void SetBannerType(UIResRectangle bannerType) 299 | { 300 | _menuList.ForEach(m => m.SetBannerType(bannerType)); 301 | } 302 | 303 | public void SetBannerType(string bannerPath) 304 | { 305 | _menuList.ForEach(m => m.SetBannerType(bannerPath)); 306 | } 307 | 308 | public void SetKey(UIMenu.MenuControls menuControl, Control control) 309 | { 310 | _menuList.ForEach(m => m.SetKey(menuControl, control)); 311 | } 312 | 313 | public void SetKey(UIMenu.MenuControls menuControl, Control control, int controllerIndex) 314 | { 315 | _menuList.ForEach(m => m.SetKey(menuControl, control, controllerIndex)); 316 | } 317 | 318 | public void SetKey(UIMenu.MenuControls menuControl, Keys control) 319 | { 320 | _menuList.ForEach(m => m.SetKey(menuControl, control)); 321 | } 322 | 323 | public void ResetKey(UIMenu.MenuControls menuControl) 324 | { 325 | _menuList.ForEach(m => m.ResetKey(menuControl)); 326 | } 327 | 328 | public void MenuChangeEv(UIMenu oldmenu, UIMenu newmenu, MenuState state) 329 | { 330 | OnMenuStateChanged?.Invoke(oldmenu, newmenu, state); 331 | } 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /NativeUI/Items/UIMenuItem.cs: -------------------------------------------------------------------------------- 1 | using CitizenFX.Core.UI; 2 | using System; 3 | using System.Drawing; 4 | using System.Threading.Tasks; 5 | 6 | namespace NativeUI 7 | { 8 | /// 9 | /// Simple item with a label. 10 | /// 11 | public class UIMenuItem 12 | { 13 | internal UIResRectangle _rectangle; 14 | protected UIResText _text; 15 | protected Sprite _selectedSprite; 16 | 17 | protected Sprite _badgeLeft; 18 | protected Sprite _badgeRight; 19 | 20 | protected UIResText _labelText; 21 | protected SizeF Resolution = ScreenTools.ResolutionMaintainRatio; 22 | public Color MainColor { get; set; } 23 | public Color HighlightColor { get; set; } 24 | 25 | public Color TextColor { get; set; } 26 | public Color HighlightedTextColor { get; set; } 27 | 28 | // Allows you to attach data to a menu item if you want to identify the menu item without having to put identification info in the visible text or description. 29 | // Taken from MenuAPI (Thanks Tom). 30 | public dynamic ItemData { get; set; } 31 | 32 | private readonly Color _defaultColor = Color.FromArgb(20, 255, 255, 255); 33 | private readonly Color _disabledColor = Color.FromArgb(163, 159, 148); // Why allocating memory for same color every time? 34 | 35 | /// 36 | /// Called when user selects the current item. 37 | /// 38 | public event ItemActivatedEvent Activated; 39 | 40 | 41 | /// 42 | /// Basic menu button. 43 | /// 44 | /// Button label. 45 | public UIMenuItem(string text) : this(text, "", Color.Transparent, Color.FromArgb(255, 255, 255, 255)){} 46 | 47 | /// 48 | /// Basic menu button with description. 49 | /// 50 | /// Button label. 51 | /// Description. 52 | public UIMenuItem(string text, string description) : this(text, description, Color.Transparent, Color.FromArgb(255, 255, 255, 255)){} 53 | 54 | /// 55 | /// Basic menu button with description and colors. 56 | /// 57 | /// Button label. 58 | /// Button label. 59 | /// Button label. 60 | /// Button label. 61 | public UIMenuItem(string text, string description, Color color, Color highlightColor) 62 | { 63 | Enabled = true; 64 | 65 | MainColor = color; 66 | HighlightColor = highlightColor; 67 | 68 | TextColor = Colors.White; 69 | HighlightedTextColor = Colors.Black; 70 | 71 | _rectangle = new UIResRectangle(new Point(0, 0), new Size(431, 38), _defaultColor); // Color.FromArgb(150, 0, 0, 0) 72 | _text = new UIResText(text, new Point(8, 0), 0.33f, Colors.WhiteSmoke, CitizenFX.Core.UI.Font.ChaletLondon, Alignment.Left); 73 | Description = description; 74 | _selectedSprite = new Sprite("commonmenu", "gradient_nav", new Point(0, 0), new Size(431, 38)); 75 | 76 | _badgeLeft = new Sprite("commonmenu", "", new Point(0, 0), new Size(40, 40)); 77 | _badgeRight = new Sprite("commonmenu", "", new Point(0, 0), new Size(40, 40)); 78 | 79 | _labelText = new UIResText("", new Point(0, 0), 0.35f) { TextAlignment = Alignment.Right }; 80 | } 81 | 82 | 83 | /// 84 | /// Whether this item is currently selected. 85 | /// 86 | public virtual bool Selected { get; set; } 87 | 88 | 89 | /// 90 | /// Whether this item is currently being hovered on with a mouse. 91 | /// 92 | public virtual bool Hovered { get; set; } 93 | 94 | 95 | /// 96 | /// This item's description. 97 | /// 98 | public virtual string Description { get; set; } 99 | 100 | 101 | /// 102 | /// Whether this item is enabled or disabled (text is greyed out and you cannot select it). 103 | /// 104 | public virtual bool Enabled { get; set; } 105 | 106 | internal virtual void ItemActivate(UIMenu sender) 107 | { 108 | Activated?.Invoke(sender, this); 109 | } 110 | 111 | 112 | /// 113 | /// Set item's position. 114 | /// 115 | /// 116 | public virtual void Position(int y) 117 | { 118 | _rectangle.Position = new PointF(Offset.X, y + 144 + Offset.Y); 119 | _selectedSprite.Position = new PointF(0 + Offset.X, y + 144 + Offset.Y); 120 | _text.Position = new PointF(8 + Offset.X, y + 147 + Offset.Y); 121 | 122 | _badgeLeft.Position = new PointF(0 + Offset.X, y + 142 + Offset.Y); 123 | _badgeRight.Position = new PointF(385 + Offset.X, y + 142 + Offset.Y); 124 | 125 | _labelText.Position = new PointF(420 + Offset.X, y + 148 + Offset.Y); 126 | } 127 | 128 | /// 129 | /// Draw this item. 130 | /// 131 | public virtual async Task Draw() 132 | { 133 | // Removed because of Progress Item height calculations 134 | //_rectangle.Size = new SizeF(431 + Parent.WidthOffset, 38); 135 | //_selectedSprite.Size = new SizeF(431 + Parent.WidthOffset, 38); 136 | 137 | if (Hovered && !Selected) 138 | _rectangle.Draw(); 139 | if (Selected) 140 | { 141 | _selectedSprite.Color = HighlightColor; 142 | _selectedSprite.Draw(); 143 | } 144 | else 145 | { 146 | 147 | _selectedSprite.Color = MainColor; 148 | _selectedSprite.Draw(); 149 | } 150 | 151 | _text.Color = Enabled ? (Selected ? HighlightedTextColor : TextColor) : _disabledColor; // No alloc anymore there 152 | 153 | if (LeftBadge == BadgeStyle.None) 154 | { 155 | _text.Position = new PointF(8 + Offset.X, _text.Position.Y); 156 | } 157 | else 158 | { 159 | _text.Position = new PointF(35 + Offset.X, _text.Position.Y); 160 | _badgeLeft.TextureDict = BadgeToSpriteLib(LeftBadge); 161 | _badgeLeft.TextureName = BadgeToSpriteName(LeftBadge, Selected); 162 | _badgeLeft.Color = BadgeToColor(LeftBadge, Selected); 163 | _badgeLeft.Draw(); 164 | } 165 | 166 | if (RightBadge != BadgeStyle.None) 167 | { 168 | _badgeRight.Position = new PointF(385 + Offset.X + Parent.WidthOffset, _badgeRight.Position.Y); 169 | _badgeRight.TextureDict = BadgeToSpriteLib(RightBadge); 170 | _badgeRight.TextureName = BadgeToSpriteName(RightBadge, Selected); 171 | _badgeRight.Color = BadgeToColor(RightBadge, Selected); 172 | _badgeRight.Draw(); 173 | } 174 | 175 | if (!String.IsNullOrWhiteSpace(RightLabel)) 176 | { 177 | if (RightBadge == BadgeStyle.None) 178 | _labelText.Position = new PointF(420 + Offset.X + Parent.WidthOffset, _labelText.Position.Y); 179 | else 180 | _labelText.Position = new PointF(390 + Offset.X + Parent.WidthOffset, _labelText.Position.Y); 181 | _labelText.Caption = RightLabel; 182 | _labelText.Color = _text.Color = Enabled ? (Selected ? Colors.Black : Colors.WhiteSmoke) : _disabledColor; // No alloc anymore there 183 | _labelText.Draw(); 184 | } 185 | _text.Draw(); 186 | } 187 | 188 | 189 | /// 190 | /// This item's offset. 191 | /// 192 | public PointF Offset { get; set; } 193 | 194 | 195 | /// 196 | /// Returns this item's label. 197 | /// 198 | public string Text 199 | { 200 | get { return _text.Caption; } 201 | set { _text.Caption = value; } 202 | } 203 | 204 | 205 | /// 206 | /// Set the left badge. Set it to None to remove the badge. 207 | /// 208 | /// 209 | public virtual void SetLeftBadge(BadgeStyle badge) 210 | { 211 | LeftBadge = badge; 212 | } 213 | 214 | 215 | /// 216 | /// Set the right badge. Set it to None to remove the badge. 217 | /// 218 | /// 219 | public virtual void SetRightBadge(BadgeStyle badge) 220 | { 221 | RightBadge = badge; 222 | } 223 | 224 | 225 | /// 226 | /// Set the right label. 227 | /// 228 | /// Text as label. Set it to "" to remove the label. 229 | public virtual void SetRightLabel(string text) 230 | { 231 | RightLabel = text; 232 | } 233 | 234 | /// 235 | /// Returns the current right label. 236 | /// 237 | public virtual string RightLabel { get; private set; } 238 | 239 | 240 | /// 241 | /// Returns the current left badge. 242 | /// 243 | public virtual BadgeStyle LeftBadge { get; private set; } 244 | 245 | 246 | /// 247 | /// Returns the current right badge. 248 | /// 249 | public virtual BadgeStyle RightBadge { get; private set; } 250 | 251 | public enum BadgeStyle 252 | { 253 | None, 254 | BronzeMedal, 255 | GoldMedal, 256 | SilverMedal, 257 | Alert, 258 | Crown, 259 | Ammo, 260 | Armour, 261 | Barber, 262 | Clothes, 263 | Franklin, 264 | Bike, 265 | Car, 266 | Gun, 267 | Heart, 268 | Makeup, 269 | Mask, 270 | Michael, 271 | Star, 272 | Tatoo, 273 | Trevor, 274 | Lock, 275 | Tick, 276 | Sale, 277 | ArrowLeft, 278 | ArrowRight, 279 | Audio1, 280 | Audio2, 281 | Audio3, 282 | AudioInactive, 283 | AudioMute 284 | } 285 | 286 | internal static string BadgeToSpriteLib(BadgeStyle badge) 287 | { 288 | switch (badge) 289 | { 290 | case BadgeStyle.Sale: 291 | return "mpshopsale"; 292 | case BadgeStyle.Audio1: 293 | case BadgeStyle.Audio2: 294 | case BadgeStyle.Audio3: 295 | case BadgeStyle.AudioInactive: 296 | case BadgeStyle.AudioMute: 297 | return "mpleaderboard"; 298 | default: 299 | return "commonmenu"; 300 | } 301 | } 302 | 303 | internal static string BadgeToSpriteName(BadgeStyle badge, bool selected) 304 | { 305 | switch (badge) 306 | { 307 | case BadgeStyle.None: 308 | return ""; 309 | case BadgeStyle.BronzeMedal: 310 | return "mp_medal_bronze"; 311 | case BadgeStyle.GoldMedal: 312 | return "mp_medal_gold"; 313 | case BadgeStyle.SilverMedal: 314 | return "medal_silver"; 315 | case BadgeStyle.Alert: 316 | return "mp_alerttriangle"; 317 | case BadgeStyle.Crown: 318 | return "mp_hostcrown"; 319 | case BadgeStyle.Ammo: 320 | return selected ? "shop_ammo_icon_b" : "shop_ammo_icon_a"; 321 | case BadgeStyle.Armour: 322 | return selected ? "shop_armour_icon_b" : "shop_armour_icon_a"; 323 | case BadgeStyle.Barber: 324 | return selected ? "shop_barber_icon_b" : "shop_barber_icon_a"; 325 | case BadgeStyle.Clothes: 326 | return selected ? "shop_clothing_icon_b" : "shop_clothing_icon_a"; 327 | case BadgeStyle.Franklin: 328 | return selected ? "shop_franklin_icon_b" : "shop_franklin_icon_a"; 329 | case BadgeStyle.Bike: 330 | return selected ? "shop_garage_bike_icon_b" : "shop_garage_bike_icon_a"; 331 | case BadgeStyle.Car: 332 | return selected ? "shop_garage_icon_b" : "shop_garage_icon_a"; 333 | case BadgeStyle.Gun: 334 | return selected ? "shop_gunclub_icon_b" : "shop_gunclub_icon_a"; 335 | case BadgeStyle.Heart: 336 | return selected ? "shop_health_icon_b" : "shop_health_icon_a"; 337 | case BadgeStyle.Lock: 338 | return "shop_lock"; 339 | case BadgeStyle.Makeup: 340 | return selected ? "shop_makeup_icon_b" : "shop_makeup_icon_a"; 341 | case BadgeStyle.Mask: 342 | return selected ? "shop_mask_icon_b" : "shop_mask_icon_a"; 343 | case BadgeStyle.Michael: 344 | return selected ? "shop_michael_icon_b" : "shop_michael_icon_a"; 345 | case BadgeStyle.Star: 346 | return "shop_new_star"; 347 | case BadgeStyle.Tatoo: 348 | return selected ? "shop_tattoos_icon_b" : "shop_tattoos_icon_"; 349 | case BadgeStyle.Tick: 350 | return "shop_tick_icon"; 351 | case BadgeStyle.Trevor: 352 | return selected ? "shop_trevor_icon_b" : "shop_trevor_icon_a"; 353 | case BadgeStyle.Sale: 354 | return "saleicon"; 355 | case BadgeStyle.ArrowLeft: 356 | return "arrowleft"; 357 | case BadgeStyle.ArrowRight: 358 | return "arrowright"; 359 | case BadgeStyle.Audio1: 360 | return "leaderboard_audio_1"; 361 | case BadgeStyle.Audio2: 362 | return "leaderboard_audio_2"; 363 | case BadgeStyle.Audio3: 364 | return "leaderboard_audio_3"; 365 | case BadgeStyle.AudioInactive: 366 | return "leaderboard_audio_inactive"; 367 | case BadgeStyle.AudioMute: 368 | return "leaderboard_audio_mute"; 369 | default: 370 | return ""; 371 | } 372 | } 373 | 374 | internal static Color BadgeToColor(BadgeStyle badge, bool selected) 375 | { 376 | switch (badge) 377 | { 378 | case BadgeStyle.Lock: 379 | case BadgeStyle.Tick: 380 | case BadgeStyle.Crown: 381 | return selected ? Color.FromArgb(255, 0, 0, 0) : Color.FromArgb(255, 255, 255, 255); 382 | default: 383 | return Color.FromArgb(255, 255, 255, 255); 384 | } 385 | } 386 | 387 | 388 | /// 389 | /// Returns the menu this item is in. 390 | /// 391 | public UIMenu Parent { get; set; } 392 | } 393 | } 394 | --------------------------------------------------------------------------------