diff --git a/MenuAPI/Menu.cs b/MenuAPI/Menu.cs index c7b9b4b..af4e3a6 100644 --- a/MenuAPI/Menu.cs +++ b/MenuAPI/Menu.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; using CitizenFX.Core; using static CitizenFX.Core.Native.API; @@ -188,7 +187,7 @@ public class Menu /// The in which this event occurred. /// The that was selected. /// The of this . - protected virtual void ItemSelectedEvent(MenuItem menuItem, int itemIndex) + internal virtual void ItemSelectedEvent(MenuItem menuItem, int itemIndex) { OnItemSelect?.Invoke(this, menuItem, itemIndex); } @@ -200,7 +199,7 @@ protected virtual void ItemSelectedEvent(MenuItem menuItem, int itemIndex) /// The that was toggled. /// The of this . /// The new state of this . - protected virtual void CheckboxChangedEvent(MenuCheckboxItem menuItem, int itemIndex, bool _checked) + internal virtual void CheckboxChangedEvent(MenuCheckboxItem menuItem, int itemIndex, bool _checked) { OnCheckboxChange?.Invoke(this, menuItem, itemIndex, _checked); } @@ -212,7 +211,7 @@ protected virtual void CheckboxChangedEvent(MenuCheckboxItem menuItem, int itemI /// The that was selected. /// The of the . /// The of the in the . - protected virtual void ListItemSelectEvent(Menu menu, MenuListItem listItem, int selectedIndex, int itemIndex) + internal virtual void ListItemSelectEvent(Menu menu, MenuListItem listItem, int selectedIndex, int itemIndex) { OnListItemSelect?.Invoke(menu, listItem, selectedIndex, itemIndex); } @@ -225,7 +224,7 @@ protected virtual void ListItemSelectEvent(Menu menu, MenuListItem listItem, int /// The old of the . /// The new of the . /// The of the in the . - protected virtual void ListItemIndexChangeEvent(Menu menu, MenuListItem listItem, int oldSelectionIndex, int newSelectionIndex, int itemIndex) + internal virtual void ListItemIndexChangeEvent(Menu menu, MenuListItem listItem, int oldSelectionIndex, int newSelectionIndex, int itemIndex) { OnListIndexChange?.Invoke(menu, listItem, oldSelectionIndex, newSelectionIndex, itemIndex); } @@ -234,7 +233,7 @@ protected virtual void ListItemIndexChangeEvent(Menu menu, MenuListItem listItem /// Triggered when a is closed. /// /// The that was closed. - protected virtual void MenuCloseEvent(Menu menu) + internal virtual void MenuCloseEvent(Menu menu) { OnMenuClose?.Invoke(menu); } @@ -243,7 +242,7 @@ protected virtual void MenuCloseEvent(Menu menu) /// Triggered when a is opened. /// /// The that has been opened. - protected virtual void MenuOpenEvent(Menu menu) + internal virtual void MenuOpenEvent(Menu menu) { OnMenuOpen?.Invoke(menu); } @@ -256,7 +255,7 @@ protected virtual void MenuOpenEvent(Menu menu) /// The new that is now selected. /// The old of this item. /// The new of this item. - protected virtual void IndexChangeEvent(Menu menu, MenuItem oldItem, MenuItem newItem, int oldIndex, int newIndex) + internal virtual void IndexChangeEvent(Menu menu, MenuItem oldItem, MenuItem newItem, int oldIndex, int newIndex) { OnIndexChange?.Invoke(menu, oldItem, newItem, oldIndex, newIndex); } @@ -270,7 +269,7 @@ protected virtual void IndexChangeEvent(Menu menu, MenuItem oldItem, MenuItem ne /// The old position of the slider bar. /// The new position of the slider bar. /// The index of this . - protected virtual void SliderItemChangedEvent(Menu menu, MenuSliderItem sliderItem, int oldPosition, int newPosition, int itemIndex) + internal virtual void SliderItemChangedEvent(Menu menu, MenuSliderItem sliderItem, int oldPosition, int newPosition, int itemIndex) { OnSliderPositionChange?.Invoke(menu, sliderItem, oldPosition, newPosition, itemIndex); } @@ -282,7 +281,7 @@ protected virtual void SliderItemChangedEvent(Menu menu, MenuSliderItem sliderIt /// The that was pressed. /// The current position of the slider bar. /// The index of this . - protected virtual void SliderSelectedEvent(Menu menu, MenuSliderItem sliderItem, int sliderPosition, int itemIndex) + internal virtual void SliderSelectedEvent(Menu menu, MenuSliderItem sliderItem, int sliderPosition, int itemIndex) { OnSliderItemSelect?.Invoke(menu, sliderItem, sliderPosition, itemIndex); } @@ -295,7 +294,7 @@ protected virtual void SliderSelectedEvent(Menu menu, MenuSliderItem sliderItem, /// The that was changed. /// The old of the . /// The new of the . - protected virtual void DynamicListItemCurrentItemChanged(Menu menu, MenuDynamicListItem dynamicListItem, string oldValue, string newValue) + internal virtual void DynamicListItemCurrentItemChanged(Menu menu, MenuDynamicListItem dynamicListItem, string oldValue, string newValue) { OnDynamicListItemCurrentItemChange?.Invoke(menu, dynamicListItem, oldValue, newValue); } @@ -306,7 +305,7 @@ protected virtual void DynamicListItemCurrentItemChanged(Menu menu, MenuDynamicL /// The in which this event occurred. /// The that was selected. /// The of the in the . - protected virtual void DynamicListItemSelectEvent(Menu menu, MenuDynamicListItem dynamicListItem, string currentItem) + internal virtual void DynamicListItemSelectEvent(Menu menu, MenuDynamicListItem dynamicListItem, string currentItem) { OnDynamicListItemSelect?.Invoke(menu, dynamicListItem, currentItem); } @@ -328,6 +327,8 @@ protected virtual void DynamicListItemSelectEvent(Menu menu, MenuDynamicListItem private int index = 0; + private bool visible = false; + public int ViewIndexOffset { get; private set; } = 0; private List VisibleMenuItems @@ -345,7 +346,6 @@ private List VisibleMenuItems var items = GetMenuItems().ToList().GetRange(ViewIndexOffset, Math.Min(MaxItemsOnScreen, Size - ViewIndexOffset)); return items; } - } } @@ -371,7 +371,25 @@ private List VisibleMenuItems public int Size => filterActive ? FilterItems.Count : MenuItems.Count; - public bool Visible { get; set; } = false; + public bool Visible + { + get + { + return visible; + } + set + { + if (value) + { + MenuController.VisibleMenus.Add(this); + } + else + { + MenuController.VisibleMenus.Remove(this); + } + visible = value; + } + } #if FIVEM public bool LeftAligned => MenuController.MenuAlignment == MenuController.MenuAlignmentOption.Left; @@ -391,9 +409,28 @@ private List VisibleMenuItems public bool EnableInstructionalButtons { get; set; } = true; - public float[] WeaponStats { get; private set; } - public float[] WeaponComponentStats { get; private set; } + /// + /// Should contain 4 floats. + /// + public float[] WeaponStats { get; private set; } = new float[4] { 0f, 0f, 0f, 0f }; + /// + /// Should contain 4 floats. + /// + public float[] WeaponComponentStats { get; private set; } = new float[4] { 0f, 0f, 0f, 0f }; + /// + /// Should contain 4 floats. + /// + public float[] VehicleStats { get; private set; } = new float[4] { 0f, 0f, 0f, 0f }; + /// + /// Should contain 4 floats. + /// + public float[] VehicleUpgradeStats { get; private set; } = new float[4] { 0f, 0f, 0f, 0f }; + public bool ShowWeaponStatsPanel { get; set; } = false; + public bool ShowVehicleStatsPanel { get; set; } = false; + + private readonly string[] weaponStatNames = new string[4] { "PM_DAMAGE", "PM_FIRERATE", "PM_ACCURACY", "PM_RANGE" }; + private readonly string[] vehicleStatNames = new string[4] { "FMMC_VEHST_0", "FMMC_VEHST_1", "FMMC_VEHST_2", "FMMC_VEHST_3" }; private bool filterActive = false; @@ -401,7 +438,36 @@ private List VisibleMenuItems public Dictionary InstructionalButtons = new Dictionary() { { Control.FrontendAccept, GetLabelText("HUD_INPUT28") }, { Control.FrontendCancel, GetLabelText("HUD_INPUT53") } }; public List CustomInstructionalButtons = new List(); +#endif +#if REDM + + public List InstructionalButtons = new List() { + new InstructionalButton( + new Control[1] + { + Control.FrontendAccept + }, + GetLabelText("INPUT_FRONTEND_SELECT") + ), + new InstructionalButton( + new Control[1] + { + Control.FrontendCancel + }, + "Back" + ), + new InstructionalButton( + new Control[2] + { + Control.FrontendUp, + Control.FrontendDown + }, + "Up / Down" + ) + }; +#endif +#if FIVEM public struct InstructionalButton { public string controlString; @@ -414,6 +480,88 @@ public InstructionalButton(string controlString, string instructionText) } } #endif +#if REDM + public class InstructionalButton + { + //private long text; + private string textString; + private Control[] controls; + private int promptHandle; + + /// + /// Constructor + /// + /// + /// + public InstructionalButton(Control[] controls, string text) + { + this.controls = controls; + textString = text; + promptHandle = 0; + } + + /// + /// Prepare the instructional button before it is displayed. + /// + public void Prepare() + { + if (IsPrepared) + { + return; + } + + // 0x04F97DE45A519419 / UipromptRegisterBegin (new name, not yet in API) + promptHandle = PromptRegisterBegin(); + + // 0xFA925AC00EB830B9 / CreateVarString (Has incorrect parameter types in API) + long _text = Call((CitizenFX.Core.Native.Hash)0xFA925AC00EB830B9, 10, "LITERAL_STRING", textString); + + // 0x5DD02A8318420DD7 / UipromptSetText (Has incorrect parameter types in API) + Call((CitizenFX.Core.Native.Hash)0x5DD02A8318420DD7, promptHandle, _text); + foreach (var c in controls) + { + // 0xB5352B7494A08258 / UipromptSetControlAction (Has incorrect parameter types in API) + Call((CitizenFX.Core.Native.Hash)0xB5352B7494A08258, this.promptHandle, c); + } + PromptRegisterEnd(promptHandle); // UipromptRegisterEnd (new name, not yet in API) + SetEnabled(false, false); + } + + /// + /// Check if it is ready to be displayed. + /// + /// + public bool IsPrepared => PromptIsValid(promptHandle); + + /// + /// Enables or disables the prompt on screen. You must prepare the prompt first using . + /// + /// + /// + public void SetEnabled(bool visible, bool enabled) + { + PromptSetVisible(promptHandle, visible ? 1 : 0); + PromptSetEnabled(promptHandle, enabled ? 1 : 0); + } + + /// + /// Disposes the prompt. Requires you to call again before you can use it again. + /// + public void Dispose() + { + if (IsPrepared) + { + SetEnabled(false, false); + PromptDelete(promptHandle); + } + promptHandle = 0; + } + + //public long GetTextHandle() => text; + public string GetTextString() => textString; + public Control[] GetControls() => controls; + } +#endif public enum ControlPressCheckType { @@ -463,8 +611,10 @@ public Menu(string name, string subtitle) MenuTitle = name; MenuSubtitle = subtitle; #if FIVEM - this.SetWeaponStats(0f, 0f, 0f, 0f); - this.SetWeaponComponentStats(0f, 0f, 0f, 0f); + SetWeaponStats(0f, 0f, 0f, 0f); + SetWeaponComponentStats(0f, 0f, 0f, 0f); + SetVehicleStats(0f, 0f, 0f, 0f); + SetVehicleUpgradeStats(0f, 0f, 0f, 0f); #endif } #endregion @@ -477,10 +627,7 @@ public Menu(string name, string subtitle) /// A value between 3 and 10 (inclusive). public void SetMaxItemsOnScreen(int max) { - if (max < 11 && max > 2) - { - MaxItemsOnScreen = max; - } + MaxItemsOnScreen = MathUtil.Clamp(max, 3, 10); } /// @@ -500,30 +647,12 @@ public List GetMenuItems() } /// - /// Retuns the currently selected menu item. Or null if there are no menu items, or the current menu index is out of range. + /// Gets the currently selected (highlighted) menu item. /// - /// + /// Retuns the currently selected menu item. Or null if there are no menu items, or the current menu index is out of range. public MenuItem GetCurrentMenuItem() { - var items = GetMenuItems(); - if (items.Count > CurrentIndex) - { - try - { - return items[CurrentIndex]; - } - catch (Exception e) - { - string itemsString = ""; - foreach (var d in items) - { - itemsString += d.Text + ", "; - } - itemsString = itemsString.Trim(',', ' '); - Debug.WriteLine($"[MenuAPI ({GetCurrentResourceName()})] Error: Could not get currrent menu item, error details: {e.Message}. Current index: {CurrentIndex}. Current menu size: {Size}. Current menu name: {MenuTitle}. List of menu items: {itemsString}."); - } - } - return null; + return GetMenuItems().ElementAtOrDefault(CurrentIndex); } /// @@ -536,6 +665,7 @@ public void ClearMenuItems() MenuItems.Clear(); FilterItems.Clear(); } + /// /// Removes all menu items. /// @@ -590,21 +720,22 @@ public void RemoveMenuItem(int itemIndex) /// public void RemoveMenuItem(MenuItem item) { - if (MenuItems.Contains(item)) + if (!MenuItems.Contains(item)) + { + return; + } + if (CurrentIndex >= item.Index) { - if (CurrentIndex >= item.Index) + if (Size > CurrentIndex) { - if (Size > CurrentIndex) - { - CurrentIndex--; - } - else - { - CurrentIndex = 0; - } + CurrentIndex--; + } + else + { + CurrentIndex = 0; } - MenuItems.Remove(item); } + MenuItems.Remove(item); } /// @@ -635,57 +766,38 @@ public void SelectItem(int index) /// public void SelectItem(MenuItem item) { - if (item != null && item.Enabled) + if (item == null) + { + return; + } + if (!item.Enabled) + { +#if FIVEM + PlaySoundFrontend(-1, "ERROR", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); +#endif +#if REDM + // Has invalid parameter types in API + Call((CitizenFX.Core.Native.Hash)0xCE5D0FFE83939AF1, -1, "NAV_ERROR", "HUD_SHOP_SOUNDSET", 1); +#endif + } + else { - if (item is MenuCheckboxItem checkbox) - { - checkbox.Checked = !checkbox.Checked; - CheckboxChangedEvent(checkbox, item.Index, checkbox.Checked); - } - else if (item is MenuListItem listItem) - { - ListItemSelectEvent(this, listItem, listItem.ListIndex, listItem.Index); - } - else if (item is MenuDynamicListItem dynamicListItem) - { - DynamicListItemSelectEvent(this, dynamicListItem, dynamicListItem.CurrentItem); - } #if FIVEM - else if (item is MenuSliderItem slider) - { - SliderSelectedEvent(this, slider, slider.Position, slider.Index); - } - else - { - ItemSelectedEvent(item, item.Index); - } PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); #endif #if REDM - else - { - ItemSelectedEvent(item, item.Index); - Call((CitizenFX.Core.Native.Hash)0xCE5D0FFE83939AF1, -1, "SELECT", "HUD_SHOP_SOUNDSET", 1); - } + // Has invalid parameter types in API. + Call((CitizenFX.Core.Native.Hash)0xCE5D0FFE83939AF1, -1, "SELECT", "HUD_SHOP_SOUNDSET", 1); #endif + item.Select(); if (MenuController.MenuButtons.ContainsKey(item)) { // this updates the parent menu. MenuController.AddSubmenu(MenuController.GetCurrentMenu(), MenuController.MenuButtons[item]); - MenuController.GetCurrentMenu().CloseMenu(); MenuController.MenuButtons[item].OpenMenu(); } } - else if (item != null && !item.Enabled) - { -#if FIVEM - PlaySoundFrontend(-1, "ERROR", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); -#endif -#if REDM - Call((CitizenFX.Core.Native.Hash)0xCE5D0FFE83939AF1, -1, "NAV_ERROR", "HUD_SHOP_SOUNDSET", 1); -#endif - } } /// @@ -697,7 +809,7 @@ public void GoBack() PlaySoundFrontend(-1, "BACK", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); #endif #if REDM - + // Has invalid parameter types in API Call((CitizenFX.Core.Native.Hash)0xCE5D0FFE83939AF1, -1, "Back", "HUD_SHOP_SOUNDSET", 1); #endif CloseMenu(); @@ -714,6 +826,13 @@ public void CloseMenu() { Visible = false; MenuCloseEvent(this); +#if REDM + foreach (var v in InstructionalButtons) + { + v.SetEnabled(false, false); + //v.Dispose(); + } +#endif } /// @@ -723,6 +842,16 @@ public void OpenMenu() { Visible = true; MenuOpenEvent(this); +#if REDM + if (EnableInstructionalButtons) + { + foreach (var v in InstructionalButtons) + { + v.Prepare(); + v.SetEnabled(true, true); + } + } +#endif } /// @@ -730,47 +859,49 @@ public void OpenMenu() /// public void GoUp() { - if (Visible && Size > 1) + if (!Visible || Size < 2) { - MenuItem oldItem; + return; + } + MenuItem oldItem; - if (filterActive) - { - oldItem = FilterItems[CurrentIndex]; - } - else - { - oldItem = MenuItems[CurrentIndex]; - } + if (filterActive) + { + oldItem = FilterItems[CurrentIndex]; + } + else + { + oldItem = MenuItems[CurrentIndex]; + } - if (CurrentIndex == 0) - { - CurrentIndex = Size - 1; - } - else - { - CurrentIndex--; - } + if (CurrentIndex == 0) + { + CurrentIndex = Size - 1; + } + else + { + CurrentIndex--; + } - var currItem = GetCurrentMenuItem(); + var currItem = GetCurrentMenuItem(); - if (currItem == null || !VisibleMenuItems.Contains(currItem)) + if (currItem == null || !VisibleMenuItems.Contains(currItem)) + { + ViewIndexOffset--; + if (ViewIndexOffset < 0) { - ViewIndexOffset--; - if (ViewIndexOffset < 0) - { - ViewIndexOffset = Math.Max(Size - MaxItemsOnScreen, 0); - } + ViewIndexOffset = Math.Max(Size - MaxItemsOnScreen, 0); } + } - IndexChangeEvent(this, oldItem, currItem, oldItem.Index, CurrentIndex); + IndexChangeEvent(this, oldItem, currItem, oldItem.Index, CurrentIndex); #if FIVEM - PlaySoundFrontend(-1, "NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); + PlaySoundFrontend(-1, "NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); #endif #if REDM - Call((CitizenFX.Core.Native.Hash)0xCE5D0FFE83939AF1, -1, "NAV_UP", "HUD_SHOP_SOUNDSET", 1); + // Has invalid parameter types in API + Call((CitizenFX.Core.Native.Hash)0xCE5D0FFE83939AF1, -1, "NAV_UP", "HUD_SHOP_SOUNDSET", 1); #endif - } } /// @@ -778,45 +909,48 @@ public void GoUp() /// public void GoDown() { - if (Visible && Size > 1) + if (!Visible || Size < 2) { - MenuItem oldItem; + return; + } - if (filterActive) - { - oldItem = FilterItems[CurrentIndex]; - } - else - { - oldItem = MenuItems[CurrentIndex]; - } + MenuItem oldItem; - if (CurrentIndex > 0 && CurrentIndex >= Size - 1) - { - CurrentIndex = 0; - } - else - { - CurrentIndex++; - } + if (filterActive) + { + oldItem = FilterItems[CurrentIndex]; + } + else + { + oldItem = MenuItems[CurrentIndex]; + } + + if (CurrentIndex > 0 && CurrentIndex >= Size - 1) + { + CurrentIndex = 0; + } + else + { + CurrentIndex++; + } - var currItem = GetCurrentMenuItem(); - if (currItem == null || !VisibleMenuItems.Contains(currItem)) + var currItem = GetCurrentMenuItem(); + if (currItem == null || !VisibleMenuItems.Contains(currItem)) + { + ViewIndexOffset++; + if (CurrentIndex == 0) { - ViewIndexOffset++; - if (CurrentIndex == 0) - { - ViewIndexOffset = 0; - } + ViewIndexOffset = 0; } - IndexChangeEvent(this, oldItem, currItem, oldItem.Index, CurrentIndex); + } + IndexChangeEvent(this, oldItem, currItem, oldItem.Index, CurrentIndex); #if FIVEM - PlaySoundFrontend(-1, "NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); + PlaySoundFrontend(-1, "NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); #endif #if REDM - Call((CitizenFX.Core.Native.Hash)0xCE5D0FFE83939AF1, -1, "NAV_DOWN", "HUD_SHOP_SOUNDSET", 1); + // Has invalid parameter types in API. + Call((CitizenFX.Core.Native.Hash)0xCE5D0FFE83939AF1, -1, "NAV_DOWN", "HUD_SHOP_SOUNDSET", 1); #endif - } } /// @@ -824,74 +958,19 @@ public void GoDown() /// public void GoLeft() { - if (MenuController.AreMenuButtonsEnabled) + if (!MenuController.AreMenuButtonsEnabled) { - var item = GetCurrentMenuItem(); - if (item != null && item.Enabled && item is MenuListItem listItem) - { - if (listItem.ItemsCount > 0) - { - int oldIndex = listItem.ListIndex; - int newIndex = oldIndex; - if (listItem.ListIndex < 1) - { - newIndex = listItem.ItemsCount - 1; - } - else - { - newIndex--; - } - listItem.ListIndex = newIndex; - - ListItemIndexChangeEvent(this, listItem, oldIndex, newIndex, listItem.Index); -#if FIVEM - PlaySoundFrontend(-1, "NAV_LEFT_RIGHT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); -#endif -#if REDM - Call((CitizenFX.Core.Native.Hash)0xCE5D0FFE83939AF1, -1, "NAV_LEFT", "HUD_SHOP_SOUNDSET", 1); -#endif - } - } -#if FIVEM - else if (item.Enabled && item is MenuSliderItem slider) - { - if (slider.Position > slider.Min) - { - SliderItemChangedEvent(this, slider, slider.Position, slider.Position - 1, slider.Index); - slider.Position--; - PlaySoundFrontend(-1, "NAV_LEFT_RIGHT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); - } - else - { - PlaySoundFrontend(-1, "ERROR", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); - } - } -#endif - else if (item.Enabled && item is MenuDynamicListItem dynList) - { - string oldValue = dynList.CurrentItem; - string newSelectedItem = dynList.Callback(dynList, true); - dynList.CurrentItem = newSelectedItem; - DynamicListItemCurrentItemChanged(this, dynList, oldValue, newSelectedItem); -#if FIVEM - PlaySoundFrontend(-1, "NAV_LEFT_RIGHT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); -#endif -#if REDM - Call((CitizenFX.Core.Native.Hash)0xCE5D0FFE83939AF1, -1, "NAV_RIGHT", "HUD_SHOP_SOUNDSET", 1); -#endif - } -#if FIVEM - // If it's a checkbox, just trigger the box instead. - else if (item.Enabled && item is MenuCheckboxItem checkbox) - { - SelectItem(checkbox); - } -#endif - // If the item is enabled and it's not any of the above, just select it. - else if (item.Enabled) - { - SelectItem(item); - } + return; + } + var item = GetCurrentMenuItem(); + if (item != null) + { + item.GoLeft(); + } + // If the item is not any of the above, return to parent menu. + else if (MenuController.NavigateMenuUsingArrows && !MenuController.DisableBackButton && !(MenuController.PreventExitingMenu && ParentMenu == null)) + { + GoBack(); } } @@ -900,78 +979,19 @@ public void GoLeft() /// public void GoRight() { - if (MenuController.AreMenuButtonsEnabled) + if (!MenuController.AreMenuButtonsEnabled) { - var item = GetCurrentMenuItem(); - if (item != null && item.Enabled && item is MenuListItem listItem) - { - if (listItem.ItemsCount > 0) - { - int oldIndex = listItem.ListIndex; - int newIndex = oldIndex; - if (listItem.ListIndex >= listItem.ItemsCount - 1) - { - newIndex = 0; - } - else - { - newIndex++; - } - listItem.ListIndex = newIndex; - ListItemIndexChangeEvent(this, listItem, oldIndex, newIndex, listItem.Index); -#if FIVEM - PlaySoundFrontend(-1, "NAV_LEFT_RIGHT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); -#endif -#if REDM - Call((CitizenFX.Core.Native.Hash)0xCE5D0FFE83939AF1, -1, "NAV_RIGHT", "HUD_SHOP_SOUNDSET", 1); -#endif - } - } -#if FIVEM - else if (item.Enabled && item is MenuSliderItem slider) - { - if (slider.Position < slider.Max) - { - SliderItemChangedEvent(this, slider, slider.Position, slider.Position + 1, slider.Index); - slider.Position++; - PlaySoundFrontend(-1, "NAV_LEFT_RIGHT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); - } - else - { - PlaySoundFrontend(-1, "ERROR", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); - } - } -#endif - else if (item.Enabled && item is MenuDynamicListItem dynList) - { - string oldValue = dynList.CurrentItem; - string newSelectedItem = dynList.Callback(dynList, false); - dynList.CurrentItem = newSelectedItem; - DynamicListItemCurrentItemChanged(this, dynList, oldValue, newSelectedItem); -#if FIVEM - PlaySoundFrontend(-1, "NAV_LEFT_RIGHT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); -#endif -#if REDM - Call((CitizenFX.Core.Native.Hash)0xCE5D0FFE83939AF1, -1, "NAV_RIGHT", "HUD_SHOP_SOUNDSET", 1); -#endif - } -#if FIVEM - // If it's a checkbox, just trigger the box instead. - else if (item.Enabled && item is MenuCheckboxItem checkbox) - { - SelectItem(checkbox); - } -#endif - // If the item is enabled and it's not any of the above, just select it. - else if (item.Enabled) - { - SelectItem(item); - } + return; + } + var item = GetCurrentMenuItem(); + if (item != null) + { + item.GoRight(); } } /// - /// Allows you to sort the menu items using your own compare function. + /// Sorts the menu items using the provided compare function. /// /// public void SortMenuItems(Comparison compare) @@ -984,6 +1004,10 @@ public void SortMenuItems(Comparison compare) MenuItems.Sort(compare); } + /// + /// Filters menu items using the provided filter function. + /// + /// public void FilterMenuItems(Func predicate) { if (filterActive) @@ -996,13 +1020,24 @@ public void FilterMenuItems(Func predicate) filterActive = true; } + /// + /// Clears the current menu items filter for this menu. + /// public void ResetFilter() { RefreshIndex(0, 0); filterActive = false; FilterItems.Clear(); } + #if FIVEM + /// + /// Values should be between 0 and 1. + /// + /// + /// + /// + /// public void SetWeaponStats(float damage, float fireRate, float accuracy, float range) { WeaponStats = new float[4] @@ -1014,6 +1049,13 @@ public void SetWeaponStats(float damage, float fireRate, float accuracy, float r }; } + /// + /// Values should be between 0 and 1. + /// + /// + /// + /// + /// public void SetWeaponComponentStats(float damage, float fireRate, float accuracy, float range) { WeaponComponentStats = new float[4] @@ -1024,883 +1066,899 @@ public void SetWeaponComponentStats(float damage, float fireRate, float accuracy MathUtil.Clamp(WeaponStats[3] + range, 0f, 1f) }; } -#endif - #endregion + /// + /// Values should be between 0 and 1. + /// + /// + /// + /// + /// + public void SetVehicleStats(float topSpeed, float acceleration, float braking, float traction) + { + VehicleStats = new float[4] + { + MathUtil.Clamp(topSpeed, 0f, 1f), + MathUtil.Clamp(acceleration, 0f, 1f), + MathUtil.Clamp(braking, 0f, 1f), + MathUtil.Clamp(traction, 0f, 1f) + }; + } - #region internal task functions /// - /// Draws the menu title + subtitle, calls all Draw functions for all menu items and draws the description for the selected item. + /// Each upgrade value gets added on top of the already existing vehicle stats. + /// So if the normal topspeed value is set to 0.5, and you provide 0.2 here, the total + /// top speed value will be 0.7, where the last section (0.2) will be colored in blue. + /// The bar can only show values between 0 and 1, so the total value will be clamped between 0 and 1. /// - /// - internal async void Draw() + /// + /// + /// + /// + public void SetVehicleUpgradeStats(float topSpeed, float acceleration, float braking, float traction) { -#if FIVEM - if (!Game.IsPaused && IsScreenFadedIn() && !IsPlayerSwitchInProgress() && !Game.PlayerPed.IsDead) -#endif -#if REDM - if (!Call(IS_PAUSE_MENU_ACTIVE) && - Call(IS_SCREEN_FADED_IN) && - !Call(IS_ENTITY_DEAD, PlayerPedId())) + VehicleUpgradeStats = new float[4] + { + MathUtil.Clamp(VehicleStats[0] + topSpeed, 0f, 1f), + MathUtil.Clamp(VehicleStats[1] + acceleration, 0f, 1f), + MathUtil.Clamp(VehicleStats[2] + braking, 0f, 1f), + MathUtil.Clamp(VehicleStats[3] + traction, 0f, 1f) + }; + } #endif + #endregion + + #region internal/private task functions + /// + /// Processes any custom button press handlers for this menu. + /// + private void ProcessButtonPressHandlers() + { + if (ButtonPressHandlers.Any()) { - #region Listen for custom key presses. - if (ButtonPressHandlers.Count > 0) + if (!MenuController.DisableMenuButtons) { - if (!MenuController.DisableMenuButtons) + foreach (ButtonPressHandler handler in ButtonPressHandlers) { - foreach (ButtonPressHandler handler in ButtonPressHandlers) + if (handler.disableControl) { - if (handler.disableControl) - { #if FIVEM - Game.DisableControlThisFrame(0, handler.control); + Game.DisableControlThisFrame(0, handler.control); #endif #if REDM - Call(DISABLE_CONTROL_ACTION, 0, handler.control, true); + DisableControlAction(0, (uint)handler.control, true); #endif - } + } - switch (handler.pressType) - { + switch (handler.pressType) + { #if FIVEM - case ControlPressCheckType.JUST_PRESSED: - if (Game.IsControlJustPressed(0, handler.control) || Game.IsDisabledControlJustPressed(0, handler.control)) - handler.function.Invoke(this, handler.control); - break; - case ControlPressCheckType.JUST_RELEASED: - if (Game.IsControlJustReleased(0, handler.control) || Game.IsDisabledControlJustReleased(0, handler.control)) - handler.function.Invoke(this, handler.control); - break; - case ControlPressCheckType.PRESSED: - if (Game.IsControlPressed(0, handler.control) || Game.IsDisabledControlPressed(0, handler.control)) - handler.function.Invoke(this, handler.control); - break; - case ControlPressCheckType.RELEASED: - if (!Game.IsControlPressed(0, handler.control) && !Game.IsDisabledControlPressed(0, handler.control)) - handler.function.Invoke(this, handler.control); - break; + case ControlPressCheckType.JUST_PRESSED: + if (Game.IsControlJustPressed(0, handler.control) || Game.IsDisabledControlJustPressed(0, handler.control)) + handler.function.Invoke(this, handler.control); + break; + case ControlPressCheckType.JUST_RELEASED: + if (Game.IsControlJustReleased(0, handler.control) || Game.IsDisabledControlJustReleased(0, handler.control)) + handler.function.Invoke(this, handler.control); + break; + case ControlPressCheckType.PRESSED: + if (Game.IsControlPressed(0, handler.control) || Game.IsDisabledControlPressed(0, handler.control)) + handler.function.Invoke(this, handler.control); + break; + case ControlPressCheckType.RELEASED: + if (!Game.IsControlPressed(0, handler.control) && !Game.IsDisabledControlPressed(0, handler.control)) + handler.function.Invoke(this, handler.control); + break; #endif #if REDM - case ControlPressCheckType.JUST_PRESSED: - if (Call(IS_CONTROL_JUST_PRESSED, 0, handler.control) || Call(IS_DISABLED_CONTROL_JUST_PRESSED, 0, handler.control)) - handler.function.Invoke(this, handler.control); - break; - case ControlPressCheckType.JUST_RELEASED: - if (Call(IS_CONTROL_JUST_RELEASED, 0, handler.control) || Call(IS_DISABLED_CONTROL_JUST_RELEASED, 0, handler.control)) - handler.function.Invoke(this, handler.control); - break; - case ControlPressCheckType.PRESSED: - if (Call(IS_CONTROL_PRESSED, 0, handler.control) || Call(IS_DISABLED_CONTROL_PRESSED, 0, handler.control)) - handler.function.Invoke(this, handler.control); - break; - case ControlPressCheckType.RELEASED: - if (!Call(IS_CONTROL_PRESSED, 0, handler.control) && !Call(IS_DISABLED_CONTROL_PRESSED, 0, handler.control)) - handler.function.Invoke(this, handler.control); - break; + case ControlPressCheckType.JUST_PRESSED: + if (IsControlJustPressed(0, (uint)handler.control) || IsDisabledControlJustPressed(0, (uint)handler.control)) + handler.function.Invoke(this, handler.control); + break; + case ControlPressCheckType.JUST_RELEASED: + if (IsControlJustReleased(0, (uint)handler.control) || IsDisabledControlJustReleased(0, (uint)handler.control)) + handler.function.Invoke(this, handler.control); + break; + case ControlPressCheckType.PRESSED: + if (IsControlPressed(0, (uint)handler.control) || IsDisabledControlPressed(0, (uint)handler.control)) + handler.function.Invoke(this, handler.control); + break; + case ControlPressCheckType.RELEASED: + if (!IsControlPressed(0, (uint)handler.control) && !IsDisabledControlPressed(0, (uint)handler.control)) + handler.function.Invoke(this, handler.control); + break; #endif - default: - break; - } + default: + break; } } } - #endregion + } + } - MenuItemsYOffset = 0f; - SetScriptGfxDrawOrder(1); - #region Draw Header - if (!string.IsNullOrEmpty(MenuTitle)) - { - #region Draw Header Background + /// + /// Draws the menu header. + /// + /// + /// The new menuItemsOffset value + private async Task DrawHeader(float menuItemsOffset) + { + if (!string.IsNullOrEmpty(MenuTitle)) + { + #region Draw Header Background #if FIVEM - SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - float x = (Position.Key + (headerSize.Key / 2f)) / MenuController.ScreenWidth; - float y = (Position.Value + (headerSize.Value/ 2f)) / MenuController.ScreenHeight; - float width = headerSize.Key / MenuController.ScreenWidth; - float height = headerSize.Value / MenuController.ScreenHeight; + float x = (Position.Key + (headerSize.Key / 2f)) / MenuController.ScreenWidth; + float y = (Position.Value + (headerSize.Value / 2f)) / MenuController.ScreenHeight; + float width = headerSize.Key / MenuController.ScreenWidth; + float height = headerSize.Value / MenuController.ScreenHeight; - if (!string.IsNullOrEmpty(HeaderTexture.Key) && !string.IsNullOrEmpty(HeaderTexture.Value)) + if (!string.IsNullOrEmpty(HeaderTexture.Key) && !string.IsNullOrEmpty(HeaderTexture.Value)) + { + if (!HasStreamedTextureDictLoaded(HeaderTexture.Key)) { - if (!HasStreamedTextureDictLoaded(HeaderTexture.Key)) + RequestStreamedTextureDict(HeaderTexture.Key, false); + while (!HasStreamedTextureDictLoaded(HeaderTexture.Key)) { - RequestStreamedTextureDict(HeaderTexture.Key, false); - while (!HasStreamedTextureDictLoaded(HeaderTexture.Key)) - { - await BaseScript.Delay(0); - } + await BaseScript.Delay(0); } - DrawSprite(HeaderTexture.Key, HeaderTexture.Value, x, y, width, height, 0f, 255, 255, 255, 255); - } - else - { - DrawSprite(MenuController._texture_dict, MenuController._header_texture, x, y, width, height, 0f, 255, 255, 255, 255); } + DrawSprite(HeaderTexture.Key, HeaderTexture.Value, x, y, width, height, 0f, 255, 255, 255, 255); + } + else + { + DrawSprite(MenuController._texture_dict, MenuController._header_texture, x, y, width, height, 0f, 255, 255, 255, 255); + } - - ResetScriptGfxAlign(); + ResetScriptGfxAlign(); #endif #if REDM + if (MenuController.SetDrawOrder) SetScriptGfxDrawOrder(2); - float x = (Position.Key + (headerSize.Key / 2f)) / MenuController.ScreenWidth; - float y = (Position.Value + (headerSize.Value / 2f)) / MenuController.ScreenHeight; - float width = headerSize.Key / MenuController.ScreenWidth; - float height = headerSize.Value / MenuController.ScreenHeight; - Call(DRAW_SPRITE, MenuController._texture_dict, MenuController._header_texture, x, y, width, height, 0f, 181, 17, 18, 255); + float x = (Position.Key + (headerSize.Key / 2f)) / MenuController.ScreenWidth; + float y = (Position.Value + (headerSize.Value / 2f)) / MenuController.ScreenHeight; + float width = headerSize.Key / MenuController.ScreenWidth; + float height = headerSize.Value / MenuController.ScreenHeight; + DrawSprite(MenuController._texture_dict, MenuController._header_texture, x, y, width, height, 0f, 181, 17, 18, 255, false); + if (MenuController.SetDrawOrder) SetScriptGfxDrawOrder(1); #endif - #endregion + #endregion - #region Draw Header Menu Title + #region Draw Header Menu Title #if FIVEM - int font = 1; - float size = (45f * 27f) / MenuController.ScreenHeight; - SetScriptGfxAlign(76, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - - BeginTextCommandDisplayText("STRING"); - SetTextFont(font); - SetTextColour(255, 255, 255, 255); - SetTextScale(size, size); - SetTextJustification(0); - AddTextComponentSubstringPlayerName(MenuTitle); - if (LeftAligned) - { - EndTextCommandDisplayText(((headerSize.Key / 2f) / MenuController.ScreenWidth), y - (GetTextScaleHeight(size, font) / 2f)); - } - else - { - EndTextCommandDisplayText(GetSafeZoneSize() - ((headerSize.Key / 2f) / MenuController.ScreenWidth), y - (GetTextScaleHeight(size, font) / 2f)); - } - - ResetScriptGfxAlign(); - - MenuItemsYOffset = headerSize.Value; + int font = 1; + float size = (45f * 27f) / MenuController.ScreenHeight; + SetScriptGfxAlign(76, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + + BeginTextCommandDisplayText("STRING"); + SetTextFont(font); + SetTextColour(255, 255, 255, 255); + SetTextScale(size, size); + SetTextJustification(0); + AddTextComponentSubstringPlayerName(MenuTitle); + if (LeftAligned) + { + EndTextCommandDisplayText(((headerSize.Key / 2f) / MenuController.ScreenWidth), y - (GetTextScaleHeight(size, font) / 2f)); + } + else + { + EndTextCommandDisplayText(GetSafeZoneSize() - ((headerSize.Key / 2f) / MenuController.ScreenWidth), y - (GetTextScaleHeight(size, font) / 2f)); + } + ResetScriptGfxAlign(); + menuItemsOffset = headerSize.Value; #endif - #if REDM - Call(SET_TEXT_CENTRE, true); - float size = (45f * 27f) / MenuController.ScreenHeight; - Call(SET_TEXT_SCALE, size, size); + SetTextCentre(true); + float size = (45f * 27f) / MenuController.ScreenHeight; + SetTextScale(size, size); + if (MenuController.SetDrawOrder) SetScriptGfxDrawOrder(3); - //SetTextWrap(textMinX, textMaxX); - int font = 10; - Call((CitizenFX.Core.Native.Hash)0xADA9255D, font); - Call(_DRAW_TEXT, Call(_CREATE_VAR_STRING, 10, "LITERAL_STRING", MenuTitle ?? "N/A"), ((headerSize.Key / 2f) / MenuController.ScreenWidth), y - (45f / MenuController.ScreenHeight)); + int font = 10; + Call((CitizenFX.Core.Native.Hash)0xADA9255D, font); + long _text = Call(_CREATE_VAR_STRING, 10, "LITERAL_STRING", MenuTitle ?? "N/A"); + float textX = (headerSize.Key / 2f) / MenuController.ScreenWidth; + float textY = y - (45f / MenuController.ScreenHeight); + DisplayText(_text, textX, textY); + if (MenuController.SetDrawOrder) SetScriptGfxDrawOrder(1); - MenuItemsYOffset = headerSize.Value; + menuItemsOffset = headerSize.Value; #endif - #endregion - } - else - { + #endregion + } + else + { #if REDM - MenuItemsYOffset = 40f; + menuItemsOffset = 40f; #endif - } - #endregion + } + await Task.FromResult(0); + return menuItemsOffset; + } - #region Draw Subtitle - { + /// + /// Draws the menu subtitle. + /// + /// + /// The new menuItemsOffset value + private float DrawSubtitle(float menuItemsOffset) + { #if FIVEM - #region draw subtitle background - SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + #region draw subtitle background + SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - float bgHeight = 38f; + float bgHeight = 38f; - float x = (Position.Key + (headerSize.Key / 2f)) / MenuController.ScreenWidth; - float y = ((Position.Value + MenuItemsYOffset + (bgHeight / 2f)) / MenuController.ScreenHeight); - float width = headerSize.Key / MenuController.ScreenWidth; - float height = bgHeight / MenuController.ScreenHeight; + float x = (Position.Key + (headerSize.Key / 2f)) / MenuController.ScreenWidth; + float y = ((Position.Value + menuItemsOffset + (bgHeight / 2f)) / MenuController.ScreenHeight); + float width = headerSize.Key / MenuController.ScreenWidth; + float height = bgHeight / MenuController.ScreenHeight; - DrawRect(x, y, width, height, 0, 0, 0, 250); - ResetScriptGfxAlign(); - #endregion + DrawRect(x, y, width, height, 0, 0, 0, 250); + ResetScriptGfxAlign(); + #endregion #endif - #if REDM - float bgHeight = 38f; - float x = (Position.Key + (headerSize.Key / 2f)) / MenuController.ScreenWidth; - float y = ((Position.Value + MenuItemsYOffset + (bgHeight / 2f)) / MenuController.ScreenHeight); - float width = headerSize.Key / MenuController.ScreenWidth; - float height = bgHeight / MenuController.ScreenHeight; - + float bgHeight = 38f; + float x = (Position.Key + (headerSize.Key / 2f)) / MenuController.ScreenWidth; + float y = ((Position.Value + menuItemsOffset + (bgHeight / 2f)) / MenuController.ScreenHeight); + float width = headerSize.Key / MenuController.ScreenWidth; + float height = bgHeight / MenuController.ScreenHeight; #endif - #if FIVEM - #region draw subtitle text - if (!string.IsNullOrEmpty(MenuSubtitle)) - { - int font = 0; - float size = (14f * 27f) / MenuController.ScreenHeight; - //float size = 0.34f; - - SetScriptGfxAlign(76, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - - BeginTextCommandDisplayText("STRING"); - SetTextFont(font); - SetTextScale(size, size); - SetTextJustification(1); - // Don't make the text blue if another color is used in the string. - if (MenuSubtitle.Contains("~") || string.IsNullOrEmpty(MenuTitle)) - { - AddTextComponentSubstringPlayerName(MenuSubtitle.ToUpper()); - } - else - { - AddTextComponentSubstringPlayerName("~HUD_COLOUR_HB_BLUE~" + MenuSubtitle.ToUpper()); - } + #region draw subtitle text + if (!string.IsNullOrEmpty(MenuSubtitle)) + { + int font = 0; + float size = (14f * 27f) / MenuController.ScreenHeight; + + SetScriptGfxAlign(76, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + + BeginTextCommandDisplayText("STRING"); + SetTextFont(font); + SetTextScale(size, size); + SetTextJustification(1); + // Don't make the text blue if another color is used in the string. + if (MenuSubtitle.Contains("~") || string.IsNullOrEmpty(MenuTitle)) + { + AddTextComponentSubstringPlayerName(MenuSubtitle.ToUpper()); + } + else + { + AddTextComponentSubstringPlayerName("~HUD_COLOUR_FREEMODE~" + MenuSubtitle.ToUpper()); + } - if (LeftAligned) - { - EndTextCommandDisplayText(10f / MenuController.ScreenWidth, y - (GetTextScaleHeight(size, font) / 2f + (4f / MenuController.ScreenHeight))); - } - else - { - EndTextCommandDisplayText(GetSafeZoneSize() - ((headerSize.Key - 10f) / MenuController.ScreenWidth), y - (GetTextScaleHeight(size, font) / 2f + (4f / MenuController.ScreenHeight))); - } - ResetScriptGfxAlign(); - } - #endregion + if (LeftAligned) + { + EndTextCommandDisplayText(10f / MenuController.ScreenWidth, y - (GetTextScaleHeight(size, font) / 2f + (4f / MenuController.ScreenHeight))); + } + else + { + EndTextCommandDisplayText(GetSafeZoneSize() - ((headerSize.Key - 10f) / MenuController.ScreenWidth), y - (GetTextScaleHeight(size, font) / 2f + (4f / MenuController.ScreenHeight))); + } + ResetScriptGfxAlign(); + } + #endregion #endif - #if REDM - if (!string.IsNullOrEmpty(MenuSubtitle)) - { - SetScriptGfxDrawOrder(3); - float size = (14f * 27f) / MenuController.ScreenHeight; - Call(SET_TEXT_SCALE, size, size); - Call(SET_TEXT_CENTRE, true); - int font = 9; - Call((CitizenFX.Core.Native.Hash)0xADA9255D, font); - Call(_DRAW_TEXT, Call(_CREATE_VAR_STRING, 10, "LITERAL_STRING", MenuSubtitle ?? "N/A"), x, y - (52f / MenuController.ScreenHeight)); - SetScriptGfxDrawOrder(1); - } + if (!string.IsNullOrEmpty(MenuSubtitle)) + { + if (MenuController.SetDrawOrder) + SetScriptGfxDrawOrder(3); + float size = (14f * 27f) / MenuController.ScreenHeight; + SetTextScale(size, size); + SetTextCentre(true); + int font = 9; + Call((CitizenFX.Core.Native.Hash)0xADA9255D, font); + long _text = Call(_CREATE_VAR_STRING, 10, "LITERAL_STRING", MenuSubtitle ?? "N/A"); + DisplayText(_text, x, y - (52f / MenuController.ScreenHeight)); + if (MenuController.SetDrawOrder) + SetScriptGfxDrawOrder(1); + } #endif - - #region draw counter + pre-counter text + #region draw counter + pre-counter text #if FIVEM - string counterText = $"{CounterPreText ?? ""}{CurrentIndex + 1} / {Size}"; - if (!string.IsNullOrEmpty(CounterPreText) || MaxItemsOnScreen < Size) - { - int font = 0; - float size = (14f * 27f) / MenuController.ScreenHeight; - //float size = 0.34f; - - SetScriptGfxAlign(76, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - - BeginTextCommandDisplayText("STRING"); - SetTextFont(font); - SetTextScale(size, size); - SetTextJustification(2); - if ((MenuSubtitle ?? "").Contains("~") || (CounterPreText ?? "").Contains("~") || string.IsNullOrEmpty(MenuTitle)) - { - AddTextComponentSubstringPlayerName(counterText.ToUpper()); - } - else - { - AddTextComponentSubstringPlayerName("~HUD_COLOUR_HB_BLUE~" + counterText.ToUpper()); - } - if (LeftAligned) - { - SetTextWrap(0f, (485f / MenuController.ScreenWidth)); - EndTextCommandDisplayText(10f / MenuController.ScreenWidth, y - (GetTextScaleHeight(size, font) / 2f + (4f / MenuController.ScreenHeight))); - } - else - { - SetTextWrap(0f, GetSafeZoneSize() - (10f / MenuController.ScreenWidth)); - EndTextCommandDisplayText(0f, y - (GetTextScaleHeight(size, font) / 2f + (4f / MenuController.ScreenHeight))); - } + string counterText = $"{CounterPreText ?? ""}{CurrentIndex + 1} / {Size}"; + if (!string.IsNullOrEmpty(CounterPreText) || MaxItemsOnScreen < Size) + { + int font = 0; + float size = (14f * 27f) / MenuController.ScreenHeight; - ResetScriptGfxAlign(); - } - if (!string.IsNullOrEmpty(MenuSubtitle) || (CounterPreText != null || MaxItemsOnScreen < Size)) - { - MenuItemsYOffset += bgHeight - 1f; - } + SetScriptGfxAlign(76, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + + BeginTextCommandDisplayText("STRING"); + SetTextFont(font); + SetTextScale(size, size); + SetTextJustification(2); + if ((MenuSubtitle ?? "").Contains("~") || (CounterPreText ?? "").Contains("~") || string.IsNullOrEmpty(MenuTitle)) + { + AddTextComponentSubstringPlayerName(counterText.ToUpper()); + } + else + { + AddTextComponentSubstringPlayerName("~HUD_COLOUR_FREEMODE~" + counterText.ToUpper()); + } + if (LeftAligned) + { + SetTextWrap(0f, (485f / MenuController.ScreenWidth)); + EndTextCommandDisplayText(10f / MenuController.ScreenWidth, y - (GetTextScaleHeight(size, font) / 2f + (4f / MenuController.ScreenHeight))); + } + else + { + SetTextWrap(0f, GetSafeZoneSize() - (10f / MenuController.ScreenWidth)); + EndTextCommandDisplayText(0f, y - (GetTextScaleHeight(size, font) / 2f + (4f / MenuController.ScreenHeight))); + } + + ResetScriptGfxAlign(); + } + if (!string.IsNullOrEmpty(MenuSubtitle) || (CounterPreText != null || MaxItemsOnScreen < Size)) + { + menuItemsOffset += bgHeight - 1f; + } #endif #if REDM - if (Size > 0) - { - float textSize = (12f * 27f) / MenuController.ScreenHeight; - Call(SET_TEXT_SCALE, textSize, textSize); - Call((CitizenFX.Core.Native.Hash)0x50A41AD966910F03, 135, 135, 135, 255); // _SET_TEXT_COLOUR / 0x50A41AD966910F03 - Call(SET_TEXT_CENTRE, true); - float textMinX = (headerSize.Key / 2f) / MenuController.ScreenWidth; - float textMaxX = (Width - 10f) / MenuController.ScreenWidth; - float textY = (MenuItemsYOffset + 38f * (MathUtil.Clamp(Size, 0, MaxItemsOnScreen) + 1) - 11f) / MenuController.ScreenHeight; - int font = 23; - Call((CitizenFX.Core.Native.Hash)0xADA9255D, font); - //SetTextWrap(textMinX, textMaxX); - - Call(_DRAW_TEXT, Call(_CREATE_VAR_STRING, 10, "LITERAL_STRING", $"{CurrentIndex + 1} of {Size}"), textMinX, textY); - } + if (Size > 0) + { + float textSize = (12f * 27f) / MenuController.ScreenHeight; + SetTextScale(textSize, textSize); + SetTextColor(135, 135, 135, 255); + SetTextCentre(true); + float textMinX = (headerSize.Key / 2f) / MenuController.ScreenWidth; + float textMaxX = (Width - 10f) / MenuController.ScreenWidth; + float textY = (menuItemsOffset + 38f * (MathUtil.Clamp(Size, 0, MaxItemsOnScreen) + 1) - 11f) / MenuController.ScreenHeight; + int font = 23; + Call((CitizenFX.Core.Native.Hash)0xADA9255D, font); + long _text = Call(_CREATE_VAR_STRING, 10, "LITERAL_STRING", $"{CurrentIndex + 1} of {Size}"); + DisplayText(_text, textMinX, textY); + } #endif + #endregion + return menuItemsOffset; + } - #endregion - } - #endregion - - #region Draw menu items background gradient - if (Size > 0) - { + /// + /// Draws the background for all visible menu item's as one large rectangle. + /// + /// + /// The new menuItemsOffset value + private float DrawBackgroundGradient(float menuItemsOffset) + { + if (Size < 1) + { + return menuItemsOffset; + } #if FIVEM - SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); #endif - - //DrawSprite(MenuController._texture_dict, "gradient_bgd", x, y, width, height, 0f, 255, 255, 255, 255); #if FIVEM - float bgHeight = 38f * MathUtil.Clamp(Size, 0, MaxItemsOnScreen); - - float x = (Position.Key + (headerSize.Key / 2f)) / MenuController.ScreenWidth; - float y = ((Position.Value + MenuItemsYOffset + ((bgHeight + 1f) / 2f)) / MenuController.ScreenHeight); - float width = headerSize.Key / MenuController.ScreenWidth; - float height = (bgHeight + 1f) / MenuController.ScreenHeight; - - ResetScriptGfxAlign(); - DrawRect(x, y, width, height, 0, 0, 0, 180); - MenuItemsYOffset += bgHeight - 1f; + float bgHeight = 38f * MathUtil.Clamp(Size, 0, MaxItemsOnScreen); + float x = (Position.Key + (headerSize.Key / 2f)) / MenuController.ScreenWidth; + float y = ((Position.Value + menuItemsOffset + ((bgHeight + 1f) / 2f)) / MenuController.ScreenHeight); + float width = headerSize.Key / MenuController.ScreenWidth; + float height = (bgHeight + 1f) / MenuController.ScreenHeight; + + DrawRect(x, y, width, height, 0, 0, 0, 180); + menuItemsOffset += bgHeight - 1f; + ResetScriptGfxAlign(); #endif #if REDM - //float x = (Position.Key + ((headerSize.Key) / 2f)) / MenuController.ScreenWidth; - //float y = ((Position.Value + MenuItemsYOffset + ((bgHeight + 1f) / 2f) /) / MenuController.ScreenHeight); - //float width = (headerSize.Key + 16f) / MenuController.ScreenWidth; - //float height = (bgHeight + 17f) / MenuController.ScreenHeight; - float bgHeight = 38f * MathUtil.Clamp(Size, 0, MaxItemsOnScreen); - var currentMenuItem = GetCurrentMenuItem(); - float descriptionBoxHeight = 0f; - if (currentMenuItem != null && !string.IsNullOrEmpty(currentMenuItem.Description)) - { - int count = (currentMenuItem.Description.Count((a => { return a == '\n'; })) - 1); - if (count < 1) - { - descriptionBoxHeight = 42f; - } - else - { - descriptionBoxHeight = (38f * count) + 30f; - } - - bgHeight += descriptionBoxHeight; - } - float actualBgYLocation = ((38f + (38f / 2f) + (bgHeight / 2f)) / MenuController.ScreenHeight); - float x = (Position.Key + (headerSize.Key / 2f)) / MenuController.ScreenWidth; - float y = ((Position.Value + MenuItemsYOffset + ((bgHeight + 1f - (headerSize.Value)) / 2f) + 19f) / MenuController.ScreenHeight); - float width = headerSize.Key / MenuController.ScreenWidth; - float height = (headerSize.Value + bgHeight + 33f + 38f) / MenuController.ScreenHeight; - Call(DRAW_SPRITE, MenuController._texture_dict, MenuController._header_texture, x, y, width, height, 0f, 0, 0, 0, 240); - Call(DRAW_SPRITE, MenuController._texture_dict, MenuController._header_texture, x, y + actualBgYLocation - (descriptionBoxHeight / MenuController.ScreenHeight), width, 38f / MenuController.ScreenHeight, 0f, 55, 55, 55, 255); - MenuItemsYOffset += bgHeight - descriptionBoxHeight - 1f; -#endif + //float x = (Position.Key + ((headerSize.Key) / 2f)) / MenuController.ScreenWidth; + //float y = ((Position.Value + menuItemsOffset + ((bgHeight + 1f) / 2f) /) / MenuController.ScreenHeight); + //float width = (headerSize.Key + 16f) / MenuController.ScreenWidth; + //float height = (bgHeight + 17f) / MenuController.ScreenHeight; + float bgHeight = 38f * MathUtil.Clamp(Size, 0, MaxItemsOnScreen); + var currentMenuItem = GetCurrentMenuItem(); + float descriptionBoxHeight = 0f; + if (currentMenuItem != null && !string.IsNullOrEmpty(currentMenuItem.Description)) + { + int count = (currentMenuItem.Description.Count((a => { return a == '\n'; })) - 1); + if (count < 1) + { + descriptionBoxHeight = 42f; } - #endregion - - #region Draw menu items that are visible in the current view. - if (Size > 0) + else { - foreach (var item in VisibleMenuItems) - { - item.Draw(ViewIndexOffset); - } + descriptionBoxHeight = (38f * count) + 30f; } - #endregion - float descriptionYOffset = 0f; + + bgHeight += descriptionBoxHeight; + } + float actualBgYLocation = ((38f + (38f / 2f) + (bgHeight / 2f)) / MenuController.ScreenHeight); + float x = (Position.Key + (headerSize.Key / 2f)) / MenuController.ScreenWidth; + float y = ((Position.Value + menuItemsOffset + ((bgHeight + 1f - (headerSize.Value)) / 2f) + 19f) / MenuController.ScreenHeight); + float width = headerSize.Key / MenuController.ScreenWidth; + float height = (headerSize.Value + bgHeight + 33f + 38f) / MenuController.ScreenHeight; + DrawSprite(MenuController._texture_dict, MenuController._header_texture, x, y, width, height, 0f, 0, 0, 0, 240, false); + DrawSprite(MenuController._texture_dict, MenuController._header_texture, x, y + actualBgYLocation - (descriptionBoxHeight / MenuController.ScreenHeight), width, 38f / MenuController.ScreenHeight, 0f, 55, 55, 55, 255, false); + menuItemsOffset += bgHeight - descriptionBoxHeight - 1f; +#endif + return menuItemsOffset; + } + + /// + /// Draw menu items that are visible in the current view. + /// + private void DrawActiveMenuItems() + { + if (Size < 1) + { + return; + } + foreach (var item in VisibleMenuItems) + { + item.Draw(ViewIndexOffset); + } + } #if FIVEM - #region Up Down overflow Indicator - if (Size > 0) - { - if (Size > MaxItemsOnScreen) - { - #region background - float width = Width / MenuController.ScreenWidth; - float height = 60f / MenuController.ScreenWidth; - float x = (Position.Key + (Width / 2f)) / MenuController.ScreenWidth; - float y = MenuItemsYOffset / MenuController.ScreenHeight + (height / 2f) + (6f / MenuController.ScreenHeight); + /// + /// Draws the up/down arrow indicators whenever the menu contains more items that are not visible in the current view. + /// + /// + private float DrawUpDownOverflowIndicators() + { + float descriptionYOffset = 0f; + if (Size < 1 || Size <= MaxItemsOnScreen) + { + return descriptionYOffset; + } + #region background + float width = Width / MenuController.ScreenWidth; + float height = 60f / MenuController.ScreenWidth; + float x = (Position.Key + (Width / 2f)) / MenuController.ScreenWidth; + float y = (MenuItemsYOffset / MenuController.ScreenHeight) + (height / 2f) + (6f / MenuController.ScreenHeight); + + SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + + DrawRect(x, y, width, height, 0, 0, 0, 180); + descriptionYOffset = height; + ResetScriptGfxAlign(); + #endregion + + #region up/down icons + SetScriptGfxAlign(76, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + float xMin = 0f; + float xMax = Width / MenuController.ScreenWidth; + float xCenter = 250f / MenuController.ScreenWidth; + float yTop = y - (20f / MenuController.ScreenHeight); + float yBottom = y - (10f / MenuController.ScreenHeight); + + BeginTextCommandDisplayText("STRING"); + AddTextComponentSubstringPlayerName("↑"); + + SetTextFont(0); + SetTextScale(1f, (14f * 27f) / MenuController.ScreenHeight); + SetTextJustification(0); + if (LeftAligned) + { + SetTextWrap(xMin, xMax); + EndTextCommandDisplayText(xCenter, yTop); + } + else + { + xMin = GetSafeZoneSize() - ((Width - 10f) / MenuController.ScreenWidth); + xMax = GetSafeZoneSize() - (10f / MenuController.ScreenWidth); + xCenter = GetSafeZoneSize() - (250f / MenuController.ScreenWidth); + SetTextWrap(xMin, xMax); + EndTextCommandDisplayText(xCenter, yTop); + } - SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + BeginTextCommandDisplayText("STRING"); + AddTextComponentSubstringPlayerName("↓"); - DrawRect(x, y, width, height, 0, 0, 0, 180); - descriptionYOffset = height; - ResetScriptGfxAlign(); - #endregion + SetTextFont(0); + SetTextScale(1f, (14f * 27f) / MenuController.ScreenHeight); + SetTextJustification(0); + if (LeftAligned) + { + SetTextWrap(xMin, xMax); + EndTextCommandDisplayText(xCenter, yBottom); + } + else + { + SetTextWrap(xMin, xMax); + EndTextCommandDisplayText(xCenter, yBottom); + } - #region up/down icons - SetScriptGfxAlign(76, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - float xMin = 0f; - float xMax = Width / MenuController.ScreenWidth; - float xCenter = 250f / MenuController.ScreenWidth; - float yTop = y - (20f / MenuController.ScreenHeight); - float yBottom = y - (10f / MenuController.ScreenHeight); - - BeginTextCommandDisplayText("STRING"); - AddTextComponentSubstringPlayerName("↑"); - - SetTextFont(0); - SetTextScale(1f, (14f * 27f) / MenuController.ScreenHeight); - SetTextJustification(0); - if (LeftAligned) - { - SetTextWrap(xMin, xMax); - EndTextCommandDisplayText(xCenter, yTop); - } - else - { - xMin = GetSafeZoneSize() - ((Width - 10f) / MenuController.ScreenWidth); - xMax = GetSafeZoneSize() - (10f / MenuController.ScreenWidth); - xCenter = GetSafeZoneSize() - (250f / MenuController.ScreenWidth); - SetTextWrap(xMin, xMax); - EndTextCommandDisplayText(xCenter, yTop); - } + ResetScriptGfxAlign(); + #endregion + return descriptionYOffset; + } +#endif + /// + /// Draws the menu item description. + /// + /// + /// + /// The new descriptionYOffset value + private float DrawDescription(float menuItemsOffset, float descriptionYOffset) + { + if (Size < 1) + { + return descriptionYOffset; + } + var currentMenuItem = GetCurrentMenuItem(); + if (currentMenuItem != null && !string.IsNullOrEmpty(currentMenuItem.Description)) + { + #region description text + int font = 0; + float textSize = (14f * 27f) / MenuController.ScreenHeight; + +#if FIVEM + float textMinX = 0f + (10f / MenuController.ScreenWidth); + float textMaxX = Width / MenuController.ScreenWidth - (10f / MenuController.ScreenWidth); + float textY = menuItemsOffset / MenuController.ScreenHeight + (16f / MenuController.ScreenHeight) + descriptionYOffset; + SetScriptGfxAlign(76, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + + BeginTextCommandDisplayText("CELL_EMAIL_BCON"); + SetTextFont(font); + SetTextScale(textSize, textSize); + SetTextJustification(1); + string text = currentMenuItem.Description; + foreach (string s in CitizenFX.Core.UI.Screen.StringToArray(text)) + { + AddTextComponentSubstringPlayerName(s); + } + float textHeight = GetTextScaleHeight(textSize, font); + if (LeftAligned) + { + SetTextWrap(textMinX, textMaxX); + EndTextCommandDisplayText(textMinX, textY); + } + else + { + textMinX = GetSafeZoneSize() - ((Width - 10f) / MenuController.ScreenWidth); + textMaxX = GetSafeZoneSize() - (10f / MenuController.ScreenWidth); + SetTextWrap(textMinX, textMaxX); + EndTextCommandDisplayText(textMinX, textY); + } - BeginTextCommandDisplayText("STRING"); - AddTextComponentSubstringPlayerName("↓"); + ResetScriptGfxAlign(); - SetTextFont(0); - SetTextScale(1f, (14f * 27f) / MenuController.ScreenHeight); - SetTextJustification(0); - if (LeftAligned) - { - SetTextWrap(xMin, xMax); - EndTextCommandDisplayText(xCenter, yBottom); - } - else - { - SetTextWrap(xMin, xMax); - EndTextCommandDisplayText(xCenter, yBottom); - } + SetScriptGfxAlign(76, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - ResetScriptGfxAlign(); - #endregion - } + BeginTextCommandLineCount("CELL_EMAIL_BCON"); + SetTextScale(textSize, textSize); + SetTextJustification(1); + SetTextFont(font); + int lineCount; + foreach (string s in CitizenFX.Core.UI.Screen.StringToArray(text)) + { + AddTextComponentSubstringPlayerName(s); + } + if (LeftAligned) + { + SetTextWrap(textMinX, textMaxX); + lineCount = GetTextScreenLineCount(textMinX, textY); + } + else + { + SetTextWrap(textMinX, textMaxX); + lineCount = GetTextScreenLineCount(textMinX, textY); } - #endregion + ResetScriptGfxAlign(); #endif - #region Draw Description - if (Size > 0) - { - var currentMenuItem = GetCurrentMenuItem(); - if (currentMenuItem != null && !string.IsNullOrEmpty(currentMenuItem.Description)) - { - #region description text - int font = 0; - float textSize = (14f * 27f) / MenuController.ScreenHeight; +#if REDM + SetTextScale(textSize, textSize); + SetTextCentre(true); + float textMinX = (headerSize.Key / 2f) / MenuController.ScreenWidth; + float textMaxX = (Width - 10f) / MenuController.ScreenWidth; + float textY = menuItemsOffset / MenuController.ScreenHeight + (18f / MenuController.ScreenHeight) + (48f / MenuController.ScreenHeight); + font = 23; + Call((CitizenFX.Core.Native.Hash)0xADA9255D, font); + long _text = Call(_CREATE_VAR_STRING, 10, "LITERAL_STRING", $"{currentMenuItem.Description}"); + DisplayText(_text, textMinX, textY); +#endif + #endregion #if FIVEM - float textMinX = 0f + (10f / MenuController.ScreenWidth); - float textMaxX = Width / MenuController.ScreenWidth - (10f / MenuController.ScreenWidth); - float textY = MenuItemsYOffset / MenuController.ScreenHeight + (16f / MenuController.ScreenHeight) + descriptionYOffset; - SetScriptGfxAlign(76, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - - BeginTextCommandDisplayText("CELL_EMAIL_BCON"); - SetTextFont(font); - SetTextScale(textSize, textSize); - SetTextJustification(1); - string text = currentMenuItem.Description; - foreach (string s in CitizenFX.Core.UI.Screen.StringToArray(text)) - { - AddTextComponentSubstringPlayerName(s); - } - float textHeight = GetTextScaleHeight(textSize, font); - if (LeftAligned) - { - SetTextWrap(textMinX, textMaxX); - EndTextCommandDisplayText(textMinX, textY); - } - else - { - textMinX = GetSafeZoneSize() - ((Width - 10f) / MenuController.ScreenWidth); - textMaxX = GetSafeZoneSize() - (10f / MenuController.ScreenWidth); - SetTextWrap(textMinX, textMaxX); - EndTextCommandDisplayText(textMinX, textY); - } + #region background + float descWidth = Width / MenuController.ScreenWidth; + float descHeight = (textHeight + 0.005f) * lineCount + (8f / MenuController.ScreenHeight) + (2.5f / MenuController.ScreenHeight); + float descX = (Position.Key + (Width / 2f)) / MenuController.ScreenWidth; + float descY = textY - (6f / MenuController.ScreenHeight) + (descHeight / 2f); - ResetScriptGfxAlign(); + SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - SetScriptGfxAlign(76, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + DrawRect(descX, descY - (descHeight / 2f) + (2f / MenuController.ScreenHeight), descWidth, 4f / MenuController.ScreenHeight, 0, 0, 0, 200); + DrawRect(descX, descY, descWidth, descHeight, 0, 0, 0, 180); - BeginTextCommandLineCount("CELL_EMAIL_BCON"); - SetTextScale(textSize, textSize); - SetTextJustification(1); - SetTextFont(font); - int lineCount; - foreach (string s in CitizenFX.Core.UI.Screen.StringToArray(text)) - { - AddTextComponentSubstringPlayerName(s); - } - if (LeftAligned) - { - SetTextWrap(textMinX, textMaxX); - lineCount = GetTextScreenLineCount(textMinX, textY); - } - else - { - SetTextWrap(textMinX, textMaxX); - lineCount = GetTextScreenLineCount(textMinX, textY); - } + ResetScriptGfxAlign(); + #endregion - ResetScriptGfxAlign(); + descriptionYOffset += descY + (descHeight / 2f) - (4f / MenuController.ScreenHeight); #endif -#if REDM - - Call(SET_TEXT_SCALE, textSize, textSize); - Call(SET_TEXT_CENTRE, true); - float textMinX = (headerSize.Key / 2f) / MenuController.ScreenWidth; - float textMaxX = (Width - 10f) / MenuController.ScreenWidth; - float textY = MenuItemsYOffset / MenuController.ScreenHeight + (18f / MenuController.ScreenHeight) + (48f / MenuController.ScreenHeight); - font = 23; - Call((CitizenFX.Core.Native.Hash)0xADA9255D, font); - Call(_DRAW_TEXT, Call(_CREATE_VAR_STRING, 10, "LITERAL_STRING", $"{currentMenuItem.Description}"), textMinX, textY); + } + else + { + descriptionYOffset += menuItemsOffset / MenuController.ScreenHeight + (2f / MenuController.ScreenHeight) + descriptionYOffset; + } + return descriptionYOffset; + } -#endif +#if FIVEM + /// + /// Draws the weapon or vehicle stats panel. + /// + /// + private void DrawWeaponOrVehicleStatsPanel(float descriptionYOffset) + { + if (Size < 1) + { + return; + } + var currentItem = GetCurrentMenuItem(); + if (currentItem == null) + { + return; + } + if (currentItem is MenuListItem listItem) + { + if (listItem.ShowColorPanel || listItem.ShowOpacityPanel) + { + return; + } + } + if (!ShowWeaponStatsPanel && !ShowVehicleStatsPanel) + { + return; + } - #endregion + float textSize = (14f * 27f) / MenuController.ScreenHeight; + float width = Width / MenuController.ScreenWidth; + float height = (140f) / MenuController.ScreenHeight; + float x = ((Width / 2f) / MenuController.ScreenWidth); + float y = descriptionYOffset + (height / 2f) + (8f / MenuController.ScreenHeight); + if (Size > MaxItemsOnScreen) + { + y -= (30f / MenuController.ScreenHeight); + } + #region background + SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + DrawRect(x, y, width, height, 0, 0, 0, 180); + ResetScriptGfxAlign(); + #endregion -#if FIVEM - #region background - float descWidth = Width / MenuController.ScreenWidth; - float descHeight = (textHeight + 0.005f) * lineCount + (8f / MenuController.ScreenHeight) + (2.5f / MenuController.ScreenHeight); - float descX = (Position.Key + (Width / 2f)) / MenuController.ScreenWidth; - float descY = textY - (6f / MenuController.ScreenHeight) + (descHeight / 2f); + float bgStatBarWidth = (Width / 2f) / MenuController.ScreenWidth; + float bgStatBarX = x + (bgStatBarWidth / 2f) - (10f / MenuController.ScreenWidth); - SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + if (!LeftAligned) + { + bgStatBarX = x - (bgStatBarWidth / 2f) - (10f / MenuController.ScreenWidth); + } + float barWidth; + float componentBarWidth; + float barY = y - (height / 2f) + (25f / MenuController.ScreenHeight); + float bgStatBarHeight = 10f / MenuController.ScreenHeight; + float barX; + float componentBarX; + + for (int i = 0; i < 4; i++) + { + int[] color = new int[3] { 93, 182, 229 }; + barWidth = bgStatBarWidth * (ShowWeaponStatsPanel ? WeaponStats[i] : VehicleStats[i]); + componentBarWidth = bgStatBarWidth * (ShowWeaponStatsPanel ? WeaponComponentStats[i] : VehicleUpgradeStats[i]); + if (componentBarWidth < barWidth) + { + float diff = barWidth - componentBarWidth; + barWidth -= diff; + componentBarWidth += diff; + color = new int[3] { 224, 50, 50 }; + } + if (LeftAligned) + { + barX = bgStatBarX - (bgStatBarWidth / 2f) + (barWidth / 2f); + componentBarX = bgStatBarX - (bgStatBarWidth / 2f) + (componentBarWidth / 2f); + } + else + { + barX = (barWidth * 1.5f) - bgStatBarWidth - (10f / MenuController.ScreenWidth); + componentBarX = (componentBarWidth * 1.5f) - bgStatBarWidth - (10f / MenuController.ScreenWidth); + } + SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + // bar bg + DrawRect(bgStatBarX, barY, bgStatBarWidth, bgStatBarHeight, 100, 100, 100, 180); + // component stats + DrawRect(componentBarX, barY, componentBarWidth, bgStatBarHeight, color[0], color[1], color[2], 255); + // real bar + DrawRect(barX, barY, barWidth, bgStatBarHeight, 255, 255, 255, 255); + ResetScriptGfxAlign(); + barY += 30f / MenuController.ScreenHeight; + } - DrawRect(descX, descY - (descHeight / 2f) + (2f / MenuController.ScreenHeight), descWidth, 4f / MenuController.ScreenHeight, 0, 0, 0, 200); - DrawRect(descX, descY, descWidth, descHeight, 0, 0, 0, 180); + #region weapon stats text + float textX = LeftAligned ? x - (width / 2f) + (10f / MenuController.ScreenWidth) : GetSafeZoneSize() - ((Width - 10f) / MenuController.ScreenWidth); + float textY = y - (height / 2f) + (10f / MenuController.ScreenHeight); - ResetScriptGfxAlign(); - #endregion + for (int i = 0; i < 4; i++) + { + SetScriptGfxAlign(76, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + BeginTextCommandDisplayText(ShowWeaponStatsPanel ? weaponStatNames[i] : vehicleStatNames[i]); + SetTextJustification(1); + SetTextScale(textSize, textSize); + + EndTextCommandDisplayText(textX, textY); + ResetScriptGfxAlign(); + textY += 30f / MenuController.ScreenHeight; + } + #endregion + } - descriptionYOffset += descY + (descHeight / 2f) - (4f / MenuController.ScreenHeight); -#endif - } - else + /// + /// Draws the Opacity and Color panels on MenuListItems. + /// + /// + private void DrawColorAndOpacityPanel(float descriptionYOffset) + { + if (Size < 1) + { + return; + } + var currentItem = GetCurrentMenuItem(); + if (currentItem == null) + { + return; + } + if (currentItem is MenuListItem listItem) + { + // OPACITY PANEL + if (listItem.ShowOpacityPanel) + { + BeginScaleformMovieMethod(OpacityPanelScaleform, "SET_TITLE"); + PushScaleformMovieMethodParameterString("Opacity"); + PushScaleformMovieMethodParameterString(""); + ScaleformMovieMethodAddParamInt(listItem.ListIndex * 10); // opacity percent + EndScaleformMovieMethod(); + + float width = Width / MenuController.ScreenWidth; + float height = ((700f / 500f) * Width) / MenuController.ScreenHeight; + float x = ((Width / 2f) / MenuController.ScreenWidth); + float y = descriptionYOffset + (height / 2f) + (4f / MenuController.ScreenHeight); + if (Size > MaxItemsOnScreen) { - descriptionYOffset += MenuItemsYOffset / MenuController.ScreenHeight + (2f / MenuController.ScreenHeight) + descriptionYOffset; + y -= (30f / MenuController.ScreenHeight); } + SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + DrawScaleformMovie(OpacityPanelScaleform, x, y, width, height, 255, 255, 255, 255, 0); + ResetScriptGfxAlign(); } - #endregion -#if FIVEM - #region Draw Weapon Stats + // COLOR PALLETE + else if (listItem.ShowColorPanel) { - if (Size > 0) + BeginScaleformMovieMethod(ColorPanelScaleform, "SET_TITLE"); + PushScaleformMovieMethodParameterString("Opacity"); + BeginTextCommandScaleformString("FACE_COLOUR"); + AddTextComponentInteger(listItem.ListIndex + 1); + AddTextComponentInteger(listItem.ItemsCount); + EndTextCommandScaleformString(); + ScaleformMovieMethodAddParamInt(0); // opacity percent unused + ScaleformMovieMethodAddParamBool(true); + EndScaleformMovieMethod(); + + BeginScaleformMovieMethod(ColorPanelScaleform, "SET_DATA_SLOT_EMPTY"); + EndScaleformMovieMethod(); + + for (int i = 0; i < 64; i++) { - var currentItem = GetCurrentMenuItem(); - if (currentItem != null) + var r = 0; + var g = 0; + var b = 0; + if (listItem.ColorPanelColorType == MenuListItem.ColorPanelType.Hair) { - if (currentItem is MenuListItem listItem) - { - if (listItem.ShowColorPanel || listItem.ShowOpacityPanel) - { - goto SKIP_WEAPON_STATS; - } - } + GetHairRgbColor(i, ref r, ref g, ref b); // _GetHairRgbColor } else { - goto SKIP_WEAPON_STATS; + GetMakeupRgbColor(i, ref r, ref g, ref b); // _GetMakeupRgbColor } - } - if (ShowWeaponStatsPanel) - { - float textSize = (14f * 27f) / MenuController.ScreenHeight; - float width = Width / MenuController.ScreenWidth; - float height = (140f) / MenuController.ScreenHeight; - float x = ((Width / 2f) / MenuController.ScreenWidth); - float y = descriptionYOffset + (height / 2f) + (8f / MenuController.ScreenHeight); - if (Size > MaxItemsOnScreen) - { - y -= (30f / MenuController.ScreenHeight); - } - - - #region background - SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - DrawRect(x, y, width, height, 0, 0, 0, 180); - ResetScriptGfxAlign(); - #endregion + BeginScaleformMovieMethod(ColorPanelScaleform, "SET_DATA_SLOT"); + ScaleformMovieMethodAddParamInt(i); // index + ScaleformMovieMethodAddParamInt(r); // r + ScaleformMovieMethodAddParamInt(g); // g + ScaleformMovieMethodAddParamInt(b); // b + EndScaleformMovieMethod(); + } - float bgStatBarWidth = (Width / 2f) / MenuController.ScreenWidth; - float bgStatBarX = x + (bgStatBarWidth / 2f) - (10f / MenuController.ScreenWidth); + BeginScaleformMovieMethod(ColorPanelScaleform, "DISPLAY_VIEW"); + EndScaleformMovieMethod(); - if (!LeftAligned) - { - bgStatBarX = x - (bgStatBarWidth / 2f) - (10f / MenuController.ScreenWidth); - } - float barWidth; - float componentBarWidth; - float barY = y - (height / 2f) + (25f / MenuController.ScreenHeight); - float bgStatBarHeight = 10f / MenuController.ScreenHeight; - float barX; - float componentBarX; - #region damage bar - barWidth = bgStatBarWidth * WeaponStats[0]; - componentBarWidth = bgStatBarWidth * WeaponComponentStats[0]; - if (LeftAligned) - { - barX = bgStatBarX - (bgStatBarWidth / 2f) + (barWidth / 2f); - componentBarX = bgStatBarX - (bgStatBarWidth / 2f) + (componentBarWidth / 2f); - } - else - { - barX = (barWidth * 1.5f) - bgStatBarWidth - (10f / MenuController.ScreenWidth); - componentBarX = (componentBarWidth * 1.5f) - bgStatBarWidth - (10f / MenuController.ScreenWidth); - } - SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - // bar bg - DrawRect(bgStatBarX, barY, bgStatBarWidth, bgStatBarHeight, 100, 100, 100, 180); - // component stats - DrawRect(componentBarX, barY, componentBarWidth, bgStatBarHeight, 93, 182, 229, 255); - // real bar - DrawRect(barX, barY, barWidth, bgStatBarHeight, 255, 255, 255, 255); - ResetScriptGfxAlign(); - #endregion + BeginScaleformMovieMethod(ColorPanelScaleform, "SET_HIGHLIGHT"); + ScaleformMovieMethodAddParamInt(listItem.ListIndex); + EndScaleformMovieMethod(); - #region fire rate bar - barWidth = bgStatBarWidth * WeaponStats[1]; - componentBarWidth = bgStatBarWidth * WeaponComponentStats[1]; - barY += 30f / MenuController.ScreenHeight; - if (LeftAligned) - { - barX = bgStatBarX - (bgStatBarWidth / 2f) + (barWidth / 2f); - componentBarX = bgStatBarX - (bgStatBarWidth / 2f) + (componentBarWidth / 2f); - } - else - { - barX = (barWidth * 1.5f) - bgStatBarWidth - (10f / MenuController.ScreenWidth); - componentBarX = (componentBarWidth * 1.5f) - bgStatBarWidth - (10f / MenuController.ScreenWidth); - } - SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - // bar bg - DrawRect(bgStatBarX, barY, bgStatBarWidth, bgStatBarHeight, 100, 100, 100, 180); - // component stats - DrawRect(componentBarX, barY, componentBarWidth, bgStatBarHeight, 93, 182, 229, 255); - // real bar - DrawRect(barX, barY, barWidth, bgStatBarHeight, 255, 255, 255, 255); - ResetScriptGfxAlign(); - #endregion + BeginScaleformMovieMethod(ColorPanelScaleform, "SHOW_OPACITY"); + ScaleformMovieMethodAddParamBool(false); + ScaleformMovieMethodAddParamBool(true); + EndScaleformMovieMethod(); - #region accuracy bar - barWidth = bgStatBarWidth * WeaponStats[2]; - componentBarWidth = bgStatBarWidth * WeaponComponentStats[2]; - barY += 30f / MenuController.ScreenHeight; - if (LeftAligned) - { - barX = bgStatBarX - (bgStatBarWidth / 2f) + (barWidth / 2f); - componentBarX = bgStatBarX - (bgStatBarWidth / 2f) + (componentBarWidth / 2f); - } - else - { - barX = (barWidth * 1.5f) - bgStatBarWidth - (10f / MenuController.ScreenWidth); - componentBarX = (componentBarWidth * 1.5f) - bgStatBarWidth - (10f / MenuController.ScreenWidth); - } - SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - // bar bg - DrawRect(bgStatBarX, barY, bgStatBarWidth, bgStatBarHeight, 100, 100, 100, 180); - // component stats - DrawRect(componentBarX, barY, componentBarWidth, bgStatBarHeight, 93, 182, 229, 255); - // real bar - DrawRect(barX, barY, barWidth, bgStatBarHeight, 255, 255, 255, 255); - ResetScriptGfxAlign(); - #endregion + float width = Width / MenuController.ScreenWidth; + float height = ((700f / 500f) * Width) / MenuController.ScreenHeight; + float x = ((Width / 2f) / MenuController.ScreenWidth); + float y = descriptionYOffset + (height / 2f) + (4f / MenuController.ScreenHeight); + if (Size > MaxItemsOnScreen) + { + y -= (30f / MenuController.ScreenHeight); + } - #region range bar - barWidth = bgStatBarWidth * WeaponStats[3]; - componentBarWidth = bgStatBarWidth * WeaponComponentStats[3]; - barY += 30f / MenuController.ScreenHeight; - if (LeftAligned) - { - barX = bgStatBarX - (bgStatBarWidth / 2f) + (barWidth / 2f); - componentBarX = bgStatBarX - (bgStatBarWidth / 2f) + (componentBarWidth / 2f); - } - else - { - barX = (barWidth * 1.5f) - bgStatBarWidth - (10f / MenuController.ScreenWidth); - componentBarX = (componentBarWidth * 1.5f) - bgStatBarWidth - (10f / MenuController.ScreenWidth); - } - SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - // bar bg - DrawRect(bgStatBarX, barY, bgStatBarWidth, bgStatBarHeight, 100, 100, 100, 180); - // component stats - DrawRect(componentBarX, barY, componentBarWidth, bgStatBarHeight, 93, 182, 229, 255); - // real bar - DrawRect(barX, barY, barWidth, bgStatBarHeight, 255, 255, 255, 255); - ResetScriptGfxAlign(); - #endregion + SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + DrawScaleformMovie(ColorPanelScaleform, x, y, width, height, 255, 255, 255, 255, 0); + ResetScriptGfxAlign(); + } + } + } +#endif - #region weapon stats text - float textX = LeftAligned ? x - (width / 2f) + (10f / MenuController.ScreenWidth) : GetSafeZoneSize() - ((Width - 10f) / MenuController.ScreenWidth); - float textY = y - (height / 2f) + (10f / MenuController.ScreenHeight); - - SetScriptGfxAlign(76, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - BeginTextCommandDisplayText("PM_DAMAGE"); - SetTextJustification(1); - SetTextScale(textSize, textSize); - - EndTextCommandDisplayText(textX, textY); - ResetScriptGfxAlign(); - - SetScriptGfxAlign(76, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - BeginTextCommandDisplayText("PM_FIRERATE"); - SetTextJustification(1); - SetTextScale(textSize, textSize); - textY += 30f / MenuController.ScreenHeight; - EndTextCommandDisplayText(textX, textY); - ResetScriptGfxAlign(); - - SetScriptGfxAlign(76, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - BeginTextCommandDisplayText("PM_ACCURACY"); - SetTextJustification(1); - SetTextScale(textSize, textSize); - textY += 30f / MenuController.ScreenHeight; - EndTextCommandDisplayText(textX, textY); - ResetScriptGfxAlign(); - - SetScriptGfxAlign(76, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - BeginTextCommandDisplayText("PM_RANGE"); - SetTextJustification(1); - SetTextScale(textSize, textSize); - textY += 30f / MenuController.ScreenHeight; - EndTextCommandDisplayText(textX, textY); - ResetScriptGfxAlign(); - #endregion + /// + /// Calls all Draw functions for all visible menu components. + /// + internal async Task Draw() + { + if (!( + IsScreenFadedIn() && +#if FIVEM + !Game.IsPaused && + !Game.PlayerPed.IsDead && + !IsPlayerSwitchInProgress() +#endif +#if REDM + !IsPauseMenuActive() && + !IsEntityDead(PlayerPedId()) +#endif + )) + { + return; + } + ProcessButtonPressHandlers(); - } - } + MenuItemsYOffset = 0f; + if (MenuController.SetDrawOrder) + { + SetScriptGfxDrawOrder(1); + } + MenuItemsYOffset = await DrawHeader(MenuItemsYOffset); - SKIP_WEAPON_STATS: - #endregion + MenuItemsYOffset = DrawSubtitle(MenuItemsYOffset); - #region Draw Color and opacity palletes - if (Size > 0) - { - var currentItem = GetCurrentMenuItem(); - if (currentItem != null) - if (currentItem is MenuListItem listItem) - { - /// OPACITY PANEL - if (listItem.ShowOpacityPanel) - { - BeginScaleformMovieMethod(OpacityPanelScaleform, "SET_TITLE"); - PushScaleformMovieMethodParameterString("Opacity"); - PushScaleformMovieMethodParameterString(""); - ScaleformMovieMethodAddParamInt(listItem.ListIndex * 10); // opacity percent - EndScaleformMovieMethod(); - - float width = Width / MenuController.ScreenWidth; - float height = ((700f / 500f) * Width) / MenuController.ScreenHeight; - float x = ((Width / 2f) / MenuController.ScreenWidth); - float y = descriptionYOffset + (height / 2f) + (4f / MenuController.ScreenHeight); - if (Size > MaxItemsOnScreen) - { - y -= (30f / MenuController.ScreenHeight); - } - - SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - DrawScaleformMovie(OpacityPanelScaleform, x, y, width, height, 255, 255, 255, 255, 0); - ResetScriptGfxAlign(); - } - - /// COLOR PALLETE - else if (listItem.ShowColorPanel) - { - BeginScaleformMovieMethod(ColorPanelScaleform, "SET_TITLE"); - PushScaleformMovieMethodParameterString("Opacity"); - BeginTextCommandScaleformString("FACE_COLOUR"); - AddTextComponentInteger(listItem.ListIndex + 1); - AddTextComponentInteger(listItem.ItemsCount); - EndTextCommandScaleformString(); - ScaleformMovieMethodAddParamInt(0); // opacity percent unused - ScaleformMovieMethodAddParamBool(true); - EndScaleformMovieMethod(); - - BeginScaleformMovieMethod(ColorPanelScaleform, "SET_DATA_SLOT_EMPTY"); - EndScaleformMovieMethod(); - - for (int i = 0; i < 64; i++) - { - var r = 0; - var g = 0; - var b = 0; - if (listItem.ColorPanelColorType == MenuListItem.ColorPanelType.Hair) - { - GetHairRgbColor(i, ref r, ref g, ref b); // _GetHairRgbColor - } - else - { - GetMakeupRgbColor(i, ref r, ref g, ref b); // _GetMakeupRgbColor - } - - BeginScaleformMovieMethod(ColorPanelScaleform, "SET_DATA_SLOT"); - ScaleformMovieMethodAddParamInt(i); // index - ScaleformMovieMethodAddParamInt(r); // r - ScaleformMovieMethodAddParamInt(g); // g - ScaleformMovieMethodAddParamInt(b); // b - EndScaleformMovieMethod(); - } - - BeginScaleformMovieMethod(ColorPanelScaleform, "DISPLAY_VIEW"); - EndScaleformMovieMethod(); - - BeginScaleformMovieMethod(ColorPanelScaleform, "SET_HIGHLIGHT"); - ScaleformMovieMethodAddParamInt(listItem.ListIndex); - EndScaleformMovieMethod(); - - BeginScaleformMovieMethod(ColorPanelScaleform, "SHOW_OPACITY"); - ScaleformMovieMethodAddParamBool(false); - ScaleformMovieMethodAddParamBool(true); - EndScaleformMovieMethod(); - - float width = Width / MenuController.ScreenWidth; - float height = ((700f / 500f) * Width) / MenuController.ScreenHeight; - float x = ((Width / 2f) / MenuController.ScreenWidth); - float y = descriptionYOffset + (height / 2f) + (4f / MenuController.ScreenHeight); - if (Size > MaxItemsOnScreen) - { - y -= (30f / MenuController.ScreenHeight); - } - - SetScriptGfxAlign(LeftAligned ? 76 : 82, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - DrawScaleformMovie(ColorPanelScaleform, x, y, width, height, 255, 255, 255, 255, 0); - ResetScriptGfxAlign(); - } - } - } + MenuItemsYOffset = DrawBackgroundGradient(MenuItemsYOffset); - #endregion + DrawActiveMenuItems(); + float descriptionYOffset = 0f; +#if FIVEM + descriptionYOffset = DrawUpDownOverflowIndicators(); +#endif + descriptionYOffset = DrawDescription(MenuItemsYOffset, descriptionYOffset); +#if FIVEM + DrawWeaponOrVehicleStatsPanel(descriptionYOffset); + DrawColorAndOpacityPanel(descriptionYOffset); #endif + if (MenuController.SetDrawOrder) + { SetScriptGfxDrawOrder(0); } - await Task.FromResult(0); } #endregion } diff --git a/MenuAPI/MenuAPI.csproj b/MenuAPI/MenuAPI.csproj index f08976e..8a6981b 100644 --- a/MenuAPI/MenuAPI.csproj +++ b/MenuAPI/MenuAPI.csproj @@ -1,20 +1,41 @@ - - + net452 embedded - $(AssemblyName) + MenuAPI Release RedM;Release FiveM;Debug RedM;Debug FiveM + + MenuAPI FiveM + MenuAPI RedM + false + Tom Grobbe + An advanced Menu API for FiveM C# resources. + An advanced Menu API for RedM C# resources. + Copyright Tom Grobbe 2018-2020 + + https://github.com/tomgrobbe/menuapi/ + https://github.com/tomgrobbe/menuapi/ + FiveM MenuAPI + RedM MenuAPI + license.txt - + FIVEM + + + FIVEM;DEBUG + - + REDM + + REDM;DEBUG + + @@ -22,7 +43,7 @@ - + runtime diff --git a/MenuAPI/MenuAPI.nuspec b/MenuAPI/MenuAPI.nuspec new file mode 100644 index 0000000..c426e41 --- /dev/null +++ b/MenuAPI/MenuAPI.nuspec @@ -0,0 +1,14 @@ + + + + $id$ + $title$ + 1.0.0 + Tom Grobbe + Tom Grobbe + https://github.com/tomgrobbe/menuapi + $description$ + Copyright Tom Grobbe 2018-2020. + $title$ + + diff --git a/MenuAPI/MenuController.cs b/MenuAPI/MenuController.cs index e7ab6d7..39bb6e6 100644 --- a/MenuAPI/MenuController.cs +++ b/MenuAPI/MenuController.cs @@ -1,18 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; using CitizenFX.Core; using static CitizenFX.Core.Native.API; -using static CitizenFX.Core.Native.Function; -using static CitizenFX.Core.Native.Hash; namespace MenuAPI { public class MenuController : BaseScript { public static List Menus { get; protected set; } = new List(); + internal static HashSet VisibleMenus { get; } = new HashSet(); #if FIVEM public const string _texture_dict = "commonmenu"; public const string _header_texture = "interaction_bgd"; @@ -33,6 +31,7 @@ public class MenuController : BaseScript "mprankbadge", "mpcarhud", "mpcarhud2", + "shared" #endif #if REDM "menu_textures", @@ -51,29 +50,30 @@ public class MenuController : BaseScript public static float ScreenHeight => 1080; public static bool DisableMenuButtons { get; set; } = false; #if FIVEM - public static bool AreMenuButtonsEnabled => Menus.Any((m) => m.Visible) && !Game.IsPaused && CitizenFX.Core.UI.Screen.Fading.IsFadedIn && !IsPlayerSwitchInProgress() && !DisableMenuButtons && !Game.Player.IsDead; + public static bool AreMenuButtonsEnabled => IsAnyMenuOpen() && !Game.IsPaused && CitizenFX.Core.UI.Screen.Fading.IsFadedIn && !IsPlayerSwitchInProgress() && !DisableMenuButtons && !Game.Player.IsDead; #endif #if REDM public static bool AreMenuButtonsEnabled => - Menus.Any((m) => m.Visible) && - !Call(IS_PAUSE_MENU_ACTIVE) && - Call(IS_SCREEN_FADED_IN) && + IsAnyMenuOpen() && + IsScreenFadedIn() && + !IsPauseMenuActive() && !DisableMenuButtons && - !Call(IS_ENTITY_DEAD, PlayerPedId()); + !IsEntityDead(PlayerPedId()); #endif + public static bool NavigateMenuUsingArrows { get; set; } = true; public static bool EnableManualGCs { get; set; } = true; public static bool DontOpenAnyMenu { get; set; } = false; public static bool PreventExitingMenu { get; set; } = false; public static bool DisableBackButton { get; set; } = false; + public static bool SetDrawOrder { get; set; } = true; public static Control MenuToggleKey { get; set; } #if FIVEM - = Control.InteractionMenu + = Control.InteractionMenu; #endif #if REDM - = Control.Map + = Control.PlayerMenu; #endif - ; public static bool EnableMenuToggleKeyOnController { get; set; } = true; @@ -91,7 +91,6 @@ public class MenuController : BaseScript private static MenuAlignmentOption _alignment = MenuAlignmentOption.Left; public static MenuAlignmentOption MenuAlignment { - get { return _alignment; @@ -187,14 +186,12 @@ public static void AddSubmenu(Menu parent, Menu child) child.ParentMenu = parent; } - /// /// Loads the texture dict for the common menu sprites. /// /// private static async Task LoadAssets() { -#if FIVEM menuTextureAssets.ForEach(asset => { if (!HasStreamedTextureDictLoaded(asset)) @@ -206,20 +203,6 @@ private static async Task LoadAssets() { await Delay(0); } -#endif -#if REDM - menuTextureAssets.ForEach(asset => - { - if (!Call(HAS_STREAMED_TEXTURE_DICT_LOADED, asset)) - { - Call(REQUEST_STREAMED_TEXTURE_DICT, asset, false); - } - }); - while (menuTextureAssets.Any(asset => { return !Call(HAS_STREAMED_TEXTURE_DICT_LOADED, asset); })) - { - await Delay(0); - } -#endif } /// @@ -227,24 +210,16 @@ private static async Task LoadAssets() /// private static void UnloadAssets() { -#if FIVEM menuTextureAssets.ForEach(asset => { - if (HasStreamedTextureDictLoaded(asset)) + if (!string.IsNullOrEmpty(asset)) { - SetStreamedTextureDictAsNoLongerNeeded(asset); - } - }); -#endif -#if REDM - menuTextureAssets.ForEach(asset => - { - if (Call(HAS_STREAMED_TEXTURE_DICT_LOADED, asset)) - { - Call(SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED, asset); + if (HasStreamedTextureDictLoaded(asset)) + { + SetStreamedTextureDictAsNoLongerNeeded(asset); + } } }); -#endif } /// @@ -253,8 +228,10 @@ private static void UnloadAssets() /// public static Menu GetCurrentMenu() { - if (Menus.Any((m) => m.Visible)) - return Menus.Find((m) => m.Visible); + if (IsAnyMenuOpen()) + { + return VisibleMenus.FirstOrDefault(); + } return null; } @@ -262,7 +239,7 @@ public static Menu GetCurrentMenu() /// Returns true if any menu is currently open. /// /// - public static bool IsAnyMenuOpen() => Menus.Any((m) => m.Visible); + public static bool IsAnyMenuOpen() => VisibleMenus.Any(); #region Process Menu Buttons @@ -272,84 +249,96 @@ public static Menu GetCurrentMenu() /// private async Task ProcessMainButtons() { - if (IsAnyMenuOpen()) + if (!IsAnyMenuOpen()) { -#if REDM - if (Call(IS_PAUSE_MENU_ACTIVE)) - { - return; - } -#endif - var currentMenu = GetCurrentMenu(); - if (currentMenu != null && !DontOpenAnyMenu) - { - if (PreventExitingMenu) - { + return; + } + if (IsPauseMenuActive()) + { + return; + } + var currentMenu = GetCurrentMenu(); + if (currentMenu == null || DontOpenAnyMenu) + { + return; + } #if FIVEM - Game.DisableControlThisFrame(0, Control.FrontendPause); - Game.DisableControlThisFrame(0, Control.FrontendPauseAlternate); + Game.DisableControlThisFrame(0, Control.MultiplayerInfo); #endif -#if REDM - Call(DISABLE_CONTROL_ACTION, 0, Control.FrontendPause, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.FrontendPauseAlternate, true); -#endif - } + HandlePreventExit(); + if (!currentMenu.Visible || !AreMenuButtonsEnabled) + { + return; + } + await HandleMainNavigationButtons(currentMenu); + } - if (currentMenu.Visible && AreMenuButtonsEnabled) - { - // Select / Enter - if ( + private async Task HandleMainNavigationButtons(Menu currentMenu) + { + // Select / Enter + if ( #if FIVEM - Game.IsDisabledControlJustReleased(0, Control.FrontendAccept) || - Game.IsControlJustReleased(0, Control.FrontendAccept) || - Game.IsDisabledControlJustReleased(0, Control.VehicleMouseControlOverride) || - Game.IsControlJustReleased(0, Control.VehicleMouseControlOverride) + Game.IsDisabledControlJustReleased(0, Control.FrontendAccept) || + Game.IsControlJustReleased(0, Control.FrontendAccept) || + Game.IsDisabledControlJustReleased(0, Control.VehicleMouseControlOverride) || + Game.IsControlJustReleased(0, Control.VehicleMouseControlOverride) #endif #if REDM - Call(IS_DISABLED_CONTROL_JUST_RELEASED, 0, Control.FrontendAccept) || - Call(IS_CONTROL_JUST_RELEASED, 0, Control.FrontendAccept) + IsDisabledControlJustReleased(0, (uint)Control.FrontendAccept) || + IsControlJustReleased(0, (uint)Control.FrontendAccept) #endif - ) - { - if (currentMenu.Size > 0) - { - currentMenu.SelectItem(currentMenu.CurrentIndex); - } - } - // Cancel / Go Back - else if ( + ) + { + if (currentMenu.Size > 0) + { + currentMenu.SelectItem(currentMenu.CurrentIndex); + } + } + // Cancel / Go Back + else if ( + !DisableBackButton && #if FIVEM - Game.IsDisabledControlJustReleased(0, Control.PhoneCancel) + Game.IsDisabledControlJustReleased(0, Control.PhoneCancel) #endif #if REDM - Call(IS_DISABLED_CONTROL_JUST_RELEASED, 0, Control.FrontendCancel) + IsDisabledControlJustReleased(0, (uint)Control.FrontendCancel) #endif - && !DisableBackButton) - { - // Wait for the next frame to make sure the "cinematic camera" button doesn't get "re-enabled" before the menu gets closed. - await Delay(0); - currentMenu.GoBack(); - } - else if ( + ) + { + // Wait for the next frame to make sure the "cinematic camera" button doesn't get "re-enabled" before the menu gets closed. + await Delay(0); + currentMenu.GoBack(); + } + else if ( + PreventExitingMenu && !DisableBackButton && #if FIVEM - Game.IsDisabledControlJustReleased(0, Control.PhoneCancel) + Game.IsDisabledControlJustReleased(0, Control.PhoneCancel) #endif #if REDM - Call(IS_DISABLED_CONTROL_JUST_RELEASED, 0, Control.CellphoneCancel) + IsDisabledControlJustReleased(0, (uint)Control.CellphoneCancel) #endif - && PreventExitingMenu && !DisableBackButton) - { - // if there's a parent menu, allow going back to that, but don't allow a 'top-level' menu to be closed. - if (currentMenu.ParentMenu != null) - { - currentMenu.GoBack(); - } - await Delay(0); - } - } + ) + { + // if there's a parent menu, allow going back to that, but don't allow a 'top-level' menu to be closed. + if (currentMenu.ParentMenu != null) + { + currentMenu.GoBack(); } + await Delay(0); + } + } + + private void HandlePreventExit() + { + if (PreventExitingMenu) + { #if FIVEM - Game.DisableControlThisFrame(0, Control.MultiplayerInfo); + Game.DisableControlThisFrame(0, Control.FrontendPause); + Game.DisableControlThisFrame(0, Control.FrontendPauseAlternate); +#endif +#if REDM + DisableControlAction(0, (uint)Control.FrontendPause, true); + DisableControlAction(0, (uint)Control.FrontendPauseAlternate, true); #endif } } @@ -360,7 +349,6 @@ private async Task ProcessMainButtons() /// private bool IsUpPressed() { - // Return false if the buttons are not currently enabled. if (!AreMenuButtonsEnabled) { return false; @@ -388,16 +376,16 @@ private bool IsUpPressed() } #endif #if REDM - if (Call(IS_CONTROL_PRESSED, 0, Control.FrontendUp) || - Call(IS_DISABLED_CONTROL_PRESSED, 0, Control.FrontendUp) || - Call(IS_CONTROL_PRESSED, 0, Control.CellphoneScrollBackward) || - Call(IS_DISABLED_CONTROL_PRESSED, 0, Control.CellphoneScrollBackward) - ) + if ( + IsControlPressed(0, (uint)Control.FrontendUp) || + IsDisabledControlPressed(0, (uint)Control.FrontendUp) || + IsControlPressed(0, (uint)Control.CellphoneScrollBackward) || + IsDisabledControlPressed(0, (uint)Control.CellphoneScrollBackward) + ) { return true; } #endif - // return false if none of the conditions matched. return false; } @@ -407,7 +395,6 @@ private bool IsUpPressed() /// private bool IsDownPressed() { - // Return false if the buttons are not currently enabled. if (!AreMenuButtonsEnabled) { return false; @@ -435,17 +422,16 @@ private bool IsDownPressed() } #endif #if REDM - if (Call(IS_CONTROL_PRESSED, 0, Control.FrontendDown) || - Call(IS_DISABLED_CONTROL_PRESSED, 0, Control.FrontendDown) || - Call(IS_CONTROL_PRESSED, 0, Control.CellphoneScrollForward) || - Call(IS_DISABLED_CONTROL_PRESSED, 0, Control.CellphoneScrollForward) - ) + if ( + IsControlPressed(0, (uint)Control.FrontendDown) || + IsDisabledControlPressed(0, (uint)Control.FrontendDown) || + IsControlPressed(0, (uint)Control.CellphoneScrollForward) || + IsDisabledControlPressed(0, (uint)Control.CellphoneScrollForward) + ) { return true; } #endif - - // return false if none of the conditions matched. return false; } @@ -455,24 +441,46 @@ private bool IsDownPressed() /// private async Task ProcessToggleMenuButton() { - #if FIVEM - Game.DisableControlThisFrame(0, MenuToggleKey); + await ProcessToggleMenuButtonFiveM(); +#endif +#if REDM + ProcessToggleMenuButtonRedM(); + await Task.FromResult(0); +#endif + } +#if REDM + private void ProcessToggleMenuButtonRedM() + { + DisableControlAction(0, (uint)MenuToggleKey, true); + if ( + !IsPauseMenuActive() && + IsScreenFadedIn() && + !IsAnyMenuOpen() && + !DisableMenuButtons && + !IsEntityDead(PlayerPedId()) && + IsDisabledControlJustReleased(0, (uint)MenuToggleKey) + ) + { + if (MainMenu != null) + { + MainMenu.OpenMenu(); + } + else + { + Debug.WriteLine($"[ERROR] [{GetCurrentResourceName()}] [MenuAPI] MainMenu is null, so we can't open it! Make sure that MenuController.MainMenu is set to a valid Menu which is not null!"); + } + } + } +#endif +#if FIVEM + private async Task ProcessToggleMenuButtonFiveM() + { if (!Game.IsPaused && !IsPauseMenuRestarting() && IsScreenFadedIn() && !IsPlayerSwitchInProgress() && !Game.Player.IsDead && !DisableMenuButtons) { if (IsAnyMenuOpen()) { - if (Game.CurrentInputMode == InputMode.MouseAndKeyboard) - { - if ((Game.IsControlJustPressed(0, MenuToggleKey) || Game.IsDisabledControlJustPressed(0, MenuToggleKey)) && !PreventExitingMenu) - { - var menu = GetCurrentMenu(); - if (menu != null) - { - menu.CloseMenu(); - } - } - } + DisableMenuKeyThisFrame(); } else { @@ -481,56 +489,16 @@ private async Task ProcessToggleMenuButton() if (!EnableMenuToggleKeyOnController) return; - int tmpTimer = GetGameTimer(); - while ((Game.IsControlPressed(0, Control.InteractionMenu) || Game.IsDisabledControlPressed(0, Control.InteractionMenu)) && !Game.IsPaused && IsScreenFadedIn() && !Game.Player.IsDead && !IsPlayerSwitchInProgress() && !DontOpenAnyMenu) - { - if (GetGameTimer() - tmpTimer > 400) - { - if (MainMenu != null) - { - MainMenu.OpenMenu(); - } - else - { - if (Menus.Count > 0) - { - Menus[0].OpenMenu(); - } - } - break; - } - await Delay(0); - } + await HandleMenuToggleKeyForController(); } else { - if ((Game.IsControlJustPressed(0, MenuToggleKey) || Game.IsDisabledControlJustPressed(0, MenuToggleKey)) && !Game.IsPaused && IsScreenFadedIn() && !Game.Player.IsDead && !IsPlayerSwitchInProgress() && !DontOpenAnyMenu) - { - if (Menus.Count > 0) - { - if (MainMenu != null) - { - MainMenu.OpenMenu(); - } - else - { - Menus[0].OpenMenu(); - } - } - } + HandleMenuToggleKeyForKeyboard(); } } } -#endif -#if REDM - Call(DISABLE_CONTROL_ACTION, 0, MenuToggleKey, true); - if (!Call(IS_PAUSE_MENU_ACTIVE) && Call(IS_SCREEN_FADED_IN) && !IsAnyMenuOpen() && !DisableMenuButtons && !Call(IS_ENTITY_DEAD, PlayerPedId()) && Call(IS_DISABLED_CONTROL_JUST_RELEASED, 0, MenuToggleKey)) - { - MainMenu.OpenMenu(); - } -#endif - await Task.FromResult(0); } +#endif /// /// Process left/right/up/down buttons (also holding down buttons will speed up after 3 iterations) @@ -547,208 +515,314 @@ private async Task ProcessDirectionalButtons() // Get the currently open menu. var currentMenu = GetCurrentMenu(); // If it exists. - if (currentMenu != null && !DontOpenAnyMenu && currentMenu.Size > 0) + if (currentMenu == null || DontOpenAnyMenu || currentMenu.Size < 1 || !currentMenu.Visible) { - if (currentMenu.Visible) - { - // Check if the Go Up controls are pressed. - if (IsUpPressed()) - { - // Update the currently selected item to the new one. - currentMenu.GoUp(); - - // Get the current game time. - var time = GetGameTimer(); - var times = 0; - var delay = 200; - - // Do the following as long as the controls are being pressed. - while (IsUpPressed() && IsAnyMenuOpen() && GetCurrentMenu() != null) - { - // Update the current menu. - currentMenu = GetCurrentMenu(); - - // Check if the game time has changed by "delay" amount. - if (GetGameTimer() - time > delay) - { - // Increment the "changed indexes" counter - times++; - - // If the controls are still being held down after moving 3 indexes, reduce the delay between index changes. - if (times > 2) - { - delay = 150; - } - if (times > 5) - { - delay = 100; - } - if (times > 25) - { - delay = 50; - } - if (times > 60) - { - delay = 25; - } - - // Update the currently selected item to the new one. - currentMenu.GoUp(); - - // Reset the time to the current game timer. - time = GetGameTimer(); - } - - // Wait for the next game tick. - await Delay(0); - } - } - - // Check if the Go Down controls are pressed. - else if (IsDownPressed()) - { - currentMenu.GoDown(); - - var time = GetGameTimer(); - var times = 0; - var delay = 200; - while (IsDownPressed() && GetCurrentMenu() != null) - { - currentMenu = GetCurrentMenu(); - if (GetGameTimer() - time > delay) - { - times++; - if (times > 2) - { - delay = 150; - } - if (times > 5) - { - delay = 100; - } - if (times > 25) - { - delay = 50; - } - if (times > 60) - { - delay = 25; - } - - currentMenu.GoDown(); - - time = GetGameTimer(); - } - await Delay(0); - } - } + return; + } + if (IsUpPressed()) + { + await HandleUpNavigation(currentMenu); + } + else if (IsDownPressed()) + { + await HandleDownNavigation(currentMenu); + } - // Check if the Go Left controls are pressed. + // Check if the Go Left controls are pressed. + else if ( + AreMenuButtonsEnabled && ( #if FIVEM - else if (Game.IsDisabledControlJustPressed(0, Control.PhoneLeft) || Game.IsControlJustPressed(0, Control.PhoneLeft)) + Game.IsDisabledControlJustPressed(0, Control.PhoneLeft) || + Game.IsControlJustPressed(0, Control.PhoneLeft) #endif #if REDM - else if (Call(IS_DISABLED_CONTROL_JUST_PRESSED, 0, Control.FrontendLeft) || Call(IS_CONTROL_JUST_PRESSED, 0, Control.FrontendLeft)) + IsDisabledControlJustPressed(0, (uint)Control.FrontendLeft) || + IsControlJustPressed(0, (uint)Control.FrontendLeft) #endif - { - var item = currentMenu.GetMenuItems()[currentMenu.CurrentIndex]; - if (item.Enabled) - { - currentMenu.GoLeft(); - var time = GetGameTimer(); - var times = 0; - var delay = 200; + ) + ) + { + await HandleLeftNavigation(currentMenu); + } + + // Check if the Go Right controls are pressed. + else if ( + AreMenuButtonsEnabled && ( #if FIVEM - while ((Game.IsDisabledControlPressed(0, Control.PhoneLeft) || Game.IsControlPressed(0, Control.PhoneLeft)) && GetCurrentMenu() != null && AreMenuButtonsEnabled) + Game.IsDisabledControlJustPressed(0, Control.PhoneRight) || + Game.IsControlJustPressed(0, Control.PhoneRight) #endif #if REDM - while ((Call(IS_DISABLED_CONTROL_PRESSED, 0, Control.FrontendLeft) || Call(IS_CONTROL_PRESSED, 0, Control.FrontendLeft)) && GetCurrentMenu() != null && AreMenuButtonsEnabled) + IsDisabledControlJustPressed(0, (uint)Control.FrontendRight) || + IsControlJustPressed(0, (uint)Control.FrontendRight) #endif - { - currentMenu = GetCurrentMenu(); - if (GetGameTimer() - time > delay) - { - times++; - if (times > 2) - { - delay = 150; - } - if (times > 5) - { - delay = 100; - } - if (times > 25) - { - delay = 50; - } - if (times > 60) - { - delay = 25; - } - currentMenu.GoLeft(); - time = GetGameTimer(); - } - await Delay(0); - } - } - } + ) + ) + { + await HandleRightNavigation(currentMenu); + } + } - // Check if the Go Right controls are pressed. + private async Task HandleRightNavigation(Menu currentMenu) + { + var item = currentMenu.GetMenuItems()[currentMenu.CurrentIndex]; + if (item.Enabled) + { + currentMenu.GoRight(); + var time = GetGameTimer(); + var times = 0; + var delay = 200; #if FIVEM - else if (Game.IsDisabledControlJustPressed(0, Control.PhoneRight) || Game.IsControlJustPressed(0, Control.PhoneRight)) + while ((Game.IsDisabledControlPressed(0, Control.PhoneRight) || Game.IsControlPressed(0, Control.PhoneRight)) && GetCurrentMenu() != null && AreMenuButtonsEnabled) #endif #if REDM - else if (AreMenuButtonsEnabled && Call(IS_DISABLED_CONTROL_JUST_PRESSED, 0, Control.FrontendRight) || Call(IS_CONTROL_JUST_PRESSED, 0, Control.FrontendRight)) + while ( + GetCurrentMenu() != null && + AreMenuButtonsEnabled && ( + IsDisabledControlPressed(0, (uint)Control.FrontendRight) || + IsControlPressed(0, (uint)Control.FrontendRight) + ) + ) #endif + { + currentMenu = GetCurrentMenu(); + if (GetGameTimer() - time > delay) { - var item = currentMenu.GetMenuItems()[currentMenu.CurrentIndex]; - if (item.Enabled) + times++; + if (times > 2) + { + delay = 150; + } + if (times > 5) { - currentMenu.GoRight(); - var time = GetGameTimer(); - var times = 0; - var delay = 200; + delay = 100; + } + if (times > 25) + { + delay = 50; + } + if (times > 60) + { + delay = 25; + } + currentMenu.GoRight(); + time = GetGameTimer(); + } + await Delay(0); + } + } + } + + private async Task HandleLeftNavigation(Menu currentMenu) + { + if (currentMenu.GetCurrentMenuItem() is MenuItem item && item.Enabled) + { + currentMenu.GoLeft(); + var time = GetGameTimer(); + var times = 0; + var delay = 200; + while ( + GetCurrentMenu() != null && + AreMenuButtonsEnabled && ( #if FIVEM - while ((Game.IsDisabledControlPressed(0, Control.PhoneRight) || Game.IsControlPressed(0, Control.PhoneRight)) && GetCurrentMenu() != null && AreMenuButtonsEnabled) + Game.IsDisabledControlPressed(0, Control.PhoneLeft) || + Game.IsControlPressed(0, Control.PhoneLeft) #endif #if REDM - while ((Call(IS_DISABLED_CONTROL_PRESSED, 0, Control.FrontendRight) || Call(IS_CONTROL_PRESSED, 0, Control.FrontendRight)) && GetCurrentMenu() != null && AreMenuButtonsEnabled) + IsDisabledControlPressed(0, (uint)Control.FrontendLeft) || + IsControlPressed(0, (uint)Control.FrontendLeft) #endif - { - currentMenu = GetCurrentMenu(); - if (GetGameTimer() - time > delay) - { - times++; - if (times > 2) - { - delay = 150; - } - if (times > 5) - { - delay = 100; - } - if (times > 25) - { - delay = 50; - } - if (times > 60) - { - delay = 25; - } - currentMenu.GoRight(); - time = GetGameTimer(); - } - await Delay(0); - } + ) + ) + { + currentMenu = GetCurrentMenu(); + if (GetGameTimer() - time > delay) + { + times++; + if (times > 2) + { + delay = 150; } + if (times > 5) + { + delay = 100; + } + if (times > 25) + { + delay = 50; + } + if (times > 60) + { + delay = 25; + } + currentMenu.GoLeft(); + time = GetGameTimer(); } + await Delay(0); } } } - private async Task MenuButtonsDisableChecks() + private async Task HandleDownNavigation(Menu currentMenu) { + currentMenu.GoDown(); + var time = GetGameTimer(); + var times = 0; + var delay = 200; + while (IsDownPressed() && GetCurrentMenu() != null) + { + currentMenu = GetCurrentMenu(); + if (GetGameTimer() - time > delay) + { + times++; + if (times > 2) + { + delay = 150; + } + if (times > 5) + { + delay = 100; + } + if (times > 25) + { + delay = 50; + } + if (times > 60) + { + delay = 25; + } + + currentMenu.GoDown(); + + time = GetGameTimer(); + } + await Delay(0); + } + } + +#if FIVEM + private void HandleMenuToggleKeyForKeyboard() + { + if ( + (Game.IsControlJustPressed(0, MenuToggleKey) || Game.IsDisabledControlJustPressed(0, MenuToggleKey)) && + !Game.IsPaused && + !Game.Player.IsDead && + !IsPlayerSwitchInProgress() && + !DontOpenAnyMenu && + IsScreenFadedIn() + ) + { + if (!Menus.Any()) + { + return; + } + if (MainMenu != null) + { + MainMenu.OpenMenu(); + } + else + { + Menus.First().OpenMenu(); + } + } + } + + private async Task HandleMenuToggleKeyForController() + { + int tmpTimer = GetGameTimer(); + while ((Game.IsControlPressed(0, Control.InteractionMenu) || Game.IsDisabledControlPressed(0, Control.InteractionMenu)) && !Game.IsPaused && IsScreenFadedIn() && !Game.Player.IsDead && !IsPlayerSwitchInProgress() && !DontOpenAnyMenu) + { + if (GetGameTimer() - tmpTimer > 400) + { + if (MainMenu != null) + { + MainMenu.OpenMenu(); + } + else + { + if (Menus.Count > 0) + { + Menus[0].OpenMenu(); + } + } + break; + } + await Delay(0); + } + } + + private void DisableMenuKeyThisFrame() + { + Game.DisableControlThisFrame(0, MenuToggleKey); + if (Game.CurrentInputMode == InputMode.MouseAndKeyboard) + { + if ((Game.IsControlJustPressed(0, MenuToggleKey) || Game.IsDisabledControlJustPressed(0, MenuToggleKey)) && !PreventExitingMenu) + { + var menu = GetCurrentMenu(); + if (menu != null) + { + menu.CloseMenu(); + } + } + } + } +#endif + + private async Task HandleUpNavigation(Menu currentMenu) + { + // Update the currently selected item to the new one. + currentMenu.GoUp(); + + // Get the current game time. + var time = GetGameTimer(); + var times = 0; + var delay = 200; + + // Do the following as long as the controls are being pressed. + while (IsUpPressed() && IsAnyMenuOpen() && GetCurrentMenu() != null) + { + // Update the current menu. + currentMenu = GetCurrentMenu(); + + // Check if the game time has changed by "delay" amount. + if (GetGameTimer() - time > delay) + { + // Increment the "changed indexes" counter + times++; + + // If the controls are still being held down after moving 3 indexes, reduce the delay between index changes. + if (times > 2) + { + delay = 150; + } + if (times > 5) + { + delay = 100; + } + if (times > 25) + { + delay = 50; + } + if (times > 60) + { + delay = 25; + } + + // Update the currently selected item to the new one. + currentMenu.GoUp(); + + // Reset the time to the current game timer. + time = GetGameTimer(); + } + + // Wait for the next game tick. + await Delay(0); + } + } + + private async Task MenuButtonsDisableChecks() + { bool isInputVisible() => UpdateOnscreenKeyboard() == 0; if (isInputVisible()) { @@ -782,263 +856,300 @@ public static void CloseAllMenus() /// private static void DisableControls() { - #region Disable Inputs when any menu is open. - if (IsAnyMenuOpen()) - { - var currMenu = GetCurrentMenu(); - if (currMenu != null) - { - var currentItem = currMenu.GetCurrentMenuItem(); - if (currentItem != null) - { -#if FIVEM - if (currentItem is MenuSliderItem || currentItem is MenuListItem || currentItem is MenuDynamicListItem) - { - if (Game.CurrentInputMode == InputMode.GamePad) - Game.DisableControlThisFrame(0, Control.SelectWeapon); - } -#endif - } - - // Close all menus when the player dies. + if (!IsAnyMenuOpen()) + return; + var currMenu = GetCurrentMenu(); + if (currMenu == null) + return; + if ( #if FIVEM - if (Game.PlayerPed.IsDead) + Game.PlayerPed.IsDead #endif #if REDM - if (Call(IS_ENTITY_DEAD, PlayerPedId())) + IsEntityDead(PlayerPedId()) #endif - { - CloseAllMenus(); - } - + ) + { + // Close all menus when the player dies. + CloseAllMenus(); + } #if FIVEM - // Disable Gamepad/Controller Specific controls: - if (Game.CurrentInputMode == InputMode.GamePad) - { - Game.DisableControlThisFrame(0, Control.MultiplayerInfo); - // when in a vehicle. - if (Game.PlayerPed.IsInVehicle()) - { - Game.DisableControlThisFrame(0, Control.VehicleHeadlight); - Game.DisableControlThisFrame(0, Control.VehicleDuck); + DisableGenericControls(currMenu); + DisableRadioInputs(); + DisablePhoneAndArrowKeysInputs(); + DisableAttackControls(); - // toggles boost in some dlc vehicles, hence it's disabled for controllers only (pressing select in the menu would trigger this). - Game.DisableControlThisFrame(0, Control.VehicleFlyTransform); - } - } - else // when not using a controller. - { - Game.DisableControlThisFrame(0, Control.FrontendPauseAlternate); // disable the escape key opening the pause menu, pressing P still works. - - // Disable the scrollwheel button changing weapons while the menu is open. - // Only if you press TAB (to show the weapon wheel) then it will allow you to change weapons. - if (!Game.IsControlPressed(0, Control.SelectWeapon)) - { - Game.DisableControlThisFrame(24, Control.SelectNextWeapon); - Game.DisableControlThisFrame(24, Control.SelectPrevWeapon); - } - } + // When in a vehicle + if (Game.PlayerPed.IsInVehicle()) + { + Game.DisableControlThisFrame(0, Control.VehicleSelectNextWeapon); + Game.DisableControlThisFrame(0, Control.VehicleSelectPrevWeapon); + Game.DisableControlThisFrame(0, Control.VehicleCinCam); + } #endif #if REDM - if (Call(_IS_INPUT_DISABLED, 2)) - { - Call(DISABLE_CONTROL_ACTION, 0, Control.FrontendPauseAlternate, true); - } + DisableControlsRedM(); #endif - // Disable Shared Controls + } -#if FIVEM - // Radio Inputs - Game.DisableControlThisFrame(0, Control.RadioWheelLeftRight); - Game.DisableControlThisFrame(0, Control.RadioWheelUpDown); - Game.DisableControlThisFrame(0, Control.VehicleNextRadio); - Game.DisableControlThisFrame(0, Control.VehicleRadioWheel); - Game.DisableControlThisFrame(0, Control.VehiclePrevRadio); - - // Phone / Arrows Inputs - Game.DisableControlThisFrame(0, Control.Phone); - Game.DisableControlThisFrame(0, Control.PhoneCancel); - Game.DisableControlThisFrame(0, Control.PhoneDown); - Game.DisableControlThisFrame(0, Control.PhoneLeft); - Game.DisableControlThisFrame(0, Control.PhoneRight); - - // Attack Controls - Game.DisableControlThisFrame(0, Control.Attack); - Game.DisableControlThisFrame(0, Control.Attack2); - Game.DisableControlThisFrame(0, Control.MeleeAttack1); - Game.DisableControlThisFrame(0, Control.MeleeAttack2); - Game.DisableControlThisFrame(0, Control.MeleeAttackAlternate); - Game.DisableControlThisFrame(0, Control.MeleeAttackHeavy); - Game.DisableControlThisFrame(0, Control.MeleeAttackLight); - Game.DisableControlThisFrame(0, Control.VehicleAttack); - Game.DisableControlThisFrame(0, Control.VehicleAttack2); - Game.DisableControlThisFrame(0, Control.VehicleFlyAttack); - Game.DisableControlThisFrame(0, Control.VehiclePassengerAttack); - Game.DisableControlThisFrame(0, Control.Aim); - Game.DisableControlThisFrame(0, Control.VehicleAim); // fires vehicle specific weapons when using right click on the mouse sometimes. - - // When in a vehicle - if (Game.PlayerPed.IsInVehicle()) - { - Game.DisableControlThisFrame(0, Control.VehicleSelectNextWeapon); - Game.DisableControlThisFrame(0, Control.VehicleSelectPrevWeapon); - Game.DisableControlThisFrame(0, Control.VehicleCinCam); - } -#endif #if REDM - Call(DISABLE_CONTROL_ACTION, 0, Control.Attack, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.Attack2, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.HorseAim, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.HorseAttack, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.HorseAttack2, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.HorseMelee, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.MeleeAttack, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.MeleeBlock, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.MeleeGrapple, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.MeleeGrappleAttack, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.MeleeGrappleBreakout, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.MeleeGrappleChoke, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.MeleeGrappleMountSwitch, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.MeleeGrappleReversal, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.MeleeGrappleStandSwitch, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.MeleeHorseAttackPrimary, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.MeleeHorseAttackSecondary, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.MeleeModifier, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.VehAttack, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.VehAttack2, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.VehBoatAttack, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.VehBoatAttack2, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.VehCarAttack, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.VehCarAttack2, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.VehDraftAttack, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.VehDraftAttack2, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.VehFlyAttack, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.VehFlyAttack2, true); - Call(DISABLE_CONTROL_ACTION, 0, Control.VehPassengerAttack, true); + private static void DisableControlsRedM() + { + DisableControlAction(0, (uint)Control.Attack, true); + DisableControlAction(0, (uint)Control.Attack2, true); + DisableControlAction(0, (uint)Control.HorseAim, true); + DisableControlAction(0, (uint)Control.HorseAttack, true); + DisableControlAction(0, (uint)Control.HorseAttack2, true); + DisableControlAction(0, (uint)Control.HorseMelee, true); + DisableControlAction(0, (uint)Control.MeleeAttack, true); + DisableControlAction(0, (uint)Control.MeleeBlock, true); + DisableControlAction(0, (uint)Control.MeleeGrapple, true); + DisableControlAction(0, (uint)Control.MeleeGrappleAttack, true); + DisableControlAction(0, (uint)Control.MeleeGrappleBreakout, true); + DisableControlAction(0, (uint)Control.MeleeGrappleChoke, true); + DisableControlAction(0, (uint)Control.MeleeGrappleMountSwitch, true); + DisableControlAction(0, (uint)Control.MeleeGrappleReversal, true); + DisableControlAction(0, (uint)Control.MeleeGrappleStandSwitch, true); + DisableControlAction(0, (uint)Control.MeleeHorseAttackPrimary, true); + DisableControlAction(0, (uint)Control.MeleeHorseAttackSecondary, true); + DisableControlAction(0, (uint)Control.MeleeModifier, true); + DisableControlAction(0, (uint)Control.VehAttack, true); + DisableControlAction(0, (uint)Control.VehAttack2, true); + DisableControlAction(0, (uint)Control.VehBoatAttack, true); + DisableControlAction(0, (uint)Control.VehBoatAttack2, true); + DisableControlAction(0, (uint)Control.VehCarAttack, true); + DisableControlAction(0, (uint)Control.VehCarAttack2, true); + DisableControlAction(0, (uint)Control.VehDraftAttack, true); + DisableControlAction(0, (uint)Control.VehDraftAttack2, true); + DisableControlAction(0, (uint)Control.VehFlyAttack, true); + DisableControlAction(0, (uint)Control.VehFlyAttack2, true); + DisableControlAction(0, (uint)Control.VehPassengerAttack, true); + if (IsInputDisabled(2)) + { + DisableControlAction(0, (uint)Control.FrontendPauseAlternate, true); + } + } #endif +#if FIVEM + /// + /// Disable required game controls when the menu is open. + /// + /// + private static void DisableGenericControls(Menu currMenu) + { + // Disable Gamepad/Controller Specific controls: + if (Game.CurrentInputMode == InputMode.GamePad) + { + Game.DisableControlThisFrame(0, Control.MultiplayerInfo); + // when in a vehicle. + if (Game.PlayerPed.IsInVehicle()) + { + Game.DisableControlThisFrame(0, Control.VehicleHeadlight); + Game.DisableControlThisFrame(0, Control.VehicleDuck); + + // toggles boost in some dlc vehicles, hence it's disabled for controllers only (pressing select in the menu would trigger this). + Game.DisableControlThisFrame(0, Control.VehicleFlyTransform); } + } + else // when not using a controller. + { + Game.DisableControlThisFrame(0, Control.FrontendPauseAlternate); // disable the escape key opening the pause menu, pressing P still works. + // Disable the scrollwheel button changing weapons while the menu is open. + // Only if you press TAB (to show the weapon wheel) then it will allow you to change weapons. + if (!Game.IsControlPressed(0, Control.SelectWeapon)) + { + Game.DisableControlThisFrame(24, Control.SelectNextWeapon); + Game.DisableControlThisFrame(24, Control.SelectPrevWeapon); + } + } + var currentItem = currMenu.GetCurrentMenuItem(); + if (currentItem != null) + { + if (currentItem is MenuSliderItem || currentItem is MenuListItem || currentItem is MenuDynamicListItem) + { + if (Game.CurrentInputMode == InputMode.GamePad) + { + Game.DisableControlThisFrame(0, Control.SelectWeapon); + } + } } - #endregion } + /// + /// Disable conflicting Attack related game controls when the menu is open. + /// + private static void DisableAttackControls() + { + Game.DisableControlThisFrame(0, Control.Attack); + Game.DisableControlThisFrame(0, Control.Attack2); + Game.DisableControlThisFrame(0, Control.MeleeAttack1); + Game.DisableControlThisFrame(0, Control.MeleeAttack2); + Game.DisableControlThisFrame(0, Control.MeleeAttackAlternate); + Game.DisableControlThisFrame(0, Control.MeleeAttackHeavy); + Game.DisableControlThisFrame(0, Control.MeleeAttackLight); + Game.DisableControlThisFrame(0, Control.VehicleAttack); + Game.DisableControlThisFrame(0, Control.VehicleAttack2); + Game.DisableControlThisFrame(0, Control.VehicleFlyAttack); + Game.DisableControlThisFrame(0, Control.VehiclePassengerAttack); + Game.DisableControlThisFrame(0, Control.Aim); + // fires vehicle specific weapons when using right click on the mouse sometimes. + Game.DisableControlThisFrame(0, Control.VehicleAim); + } + + /// + /// Disable conflicting Phone/Navigation related game controls when the menu is open. + /// + private static void DisablePhoneAndArrowKeysInputs() + { + Game.DisableControlThisFrame(0, Control.Phone); + Game.DisableControlThisFrame(0, Control.PhoneCancel); + Game.DisableControlThisFrame(0, Control.PhoneDown); + Game.DisableControlThisFrame(0, Control.PhoneLeft); + Game.DisableControlThisFrame(0, Control.PhoneRight); + } + + /// + /// Disable conflicting Radio related game controls when the menu is open. + /// + private static void DisableRadioInputs() + { + Game.DisableControlThisFrame(0, Control.RadioWheelLeftRight); + Game.DisableControlThisFrame(0, Control.RadioWheelUpDown); + Game.DisableControlThisFrame(0, Control.VehicleNextRadio); + Game.DisableControlThisFrame(0, Control.VehicleRadioWheel); + Game.DisableControlThisFrame(0, Control.VehiclePrevRadio); + } +#endif + /// /// Draws all the menus that are visible on the screen. /// /// private static async Task ProcessMenus() { - - if (Menus.Count > 0 && + if (!( + Menus.Any() && IsAnyMenuOpen() && -#if FIVEM IsScreenFadedIn() && - !Game.IsPaused && - !Game.Player.IsDead && - !IsPlayerSwitchInProgress() -#endif -#if REDM - Call(IS_SCREEN_FADED_IN) && - !Call(IS_PAUSE_MENU_ACTIVE) && - !Call(IS_ENTITY_DEAD, PlayerPedId()) + !IsPauseMenuActive() && + !IsEntityDead(PlayerPedId()) +#if FIVEM + && !IsPlayerSwitchInProgress() #endif ) + ) { - await LoadAssets(); - - DisableControls(); + UnloadAssets(); + return; + } + await LoadAssets(); + DisableControls(); + await DrawMenus(); + PerformGC(); + } - Menu menu = GetCurrentMenu(); - if (menu != null) + private static void PerformGC() + { + if (EnableManualGCs) + { + // once a minute + if (GetGameTimer() - ManualTimerForGC > 60000) { - if (DontOpenAnyMenu) - { - if (menu.Visible && !menu.IgnoreDontOpenMenus) - { - menu.CloseMenu(); - } - } - else if (menu.Visible) - { - menu.Draw(); - } + GC.Collect(); + ManualTimerForGC = GetGameTimer(); } + } + } - if (EnableManualGCs) + private static async Task DrawMenus() + { + Menu menu = GetCurrentMenu(); + if (menu == null) + { + return; + } + if (DontOpenAnyMenu) + { + if (menu.Visible && !menu.IgnoreDontOpenMenus) { - // once a minute - if (GetGameTimer() - ManualTimerForGC > 60000) - { - GC.Collect(); - ManualTimerForGC = GetGameTimer(); - } + menu.CloseMenu(); } } - else + else if (menu.Visible) { - UnloadAssets(); + await menu.Draw(); } } #if FIVEM internal static async Task DrawInstructionalButtons() { - if (!Game.IsPaused && !Game.Player.IsDead && IsScreenFadedIn() && !IsPlayerSwitchInProgress() && !IsWarningMessageActive() && UpdateOnscreenKeyboard() != 0) + if ( + Game.IsPaused || + Game.Player.IsDead || + !IsScreenFadedIn() || + IsPlayerSwitchInProgress() || + IsWarningMessageActive() || + UpdateOnscreenKeyboard() == 0 + ) { - Menu menu = GetCurrentMenu(); - if (menu != null && menu.Visible && menu.EnableInstructionalButtons) - { - if (!HasScaleformMovieLoaded(_scale)) - { - _scale = RequestScaleformMovie("INSTRUCTIONAL_BUTTONS"); - } - while (!HasScaleformMovieLoaded(_scale)) - { - await Delay(0); - } - - BeginScaleformMovieMethod(_scale, "CLEAR_ALL"); - EndScaleformMovieMethod(); - + DisposeInstructionalButtonsScaleform(); + return; + } + Menu menu = GetCurrentMenu(); + if (menu == null || !menu.Visible || !menu.EnableInstructionalButtons) + { + DisposeInstructionalButtonsScaleform(); + return; + } + if (!HasScaleformMovieLoaded(_scale)) + { + _scale = RequestScaleformMovie("INSTRUCTIONAL_BUTTONS"); + } + while (!HasScaleformMovieLoaded(_scale)) + { + await Delay(0); + } + DrawScaleformMovieFullscreen(_scale, 255, 255, 255, 0, 0); + BeginScaleformMovieMethod(_scale, "CLEAR_ALL"); + EndScaleformMovieMethod(); - for (int i = 0; i < menu.InstructionalButtons.Count; i++) - { - string text = menu.InstructionalButtons.ElementAt(i).Value; - Control control = menu.InstructionalButtons.ElementAt(i).Key; - - BeginScaleformMovieMethod(_scale, "SET_DATA_SLOT"); - ScaleformMovieMethodAddParamInt(i); - string buttonName = GetControlInstructionalButton(0, (int)control, 1); - PushScaleformMovieMethodParameterString(buttonName); - PushScaleformMovieMethodParameterString(text); - EndScaleformMovieMethod(); - } - // Use custom instructional buttons FIRST if they're present. - if (menu.CustomInstructionalButtons.Count > 0) - { - for (int i = 0; i < menu.CustomInstructionalButtons.Count; i++) - { - Menu.InstructionalButton button = menu.CustomInstructionalButtons[i]; - BeginScaleformMovieMethod(_scale, "SET_DATA_SLOT"); - ScaleformMovieMethodAddParamInt(i + menu.InstructionalButtons.Count); - PushScaleformMovieMethodParameterString(button.controlString); - PushScaleformMovieMethodParameterString(button.instructionText); - EndScaleformMovieMethod(); - } - } + for (int i = 0; i < menu.InstructionalButtons.Count; i++) + { + string text = menu.InstructionalButtons.ElementAt(i).Value; + Control control = menu.InstructionalButtons.ElementAt(i).Key; + + BeginScaleformMovieMethod(_scale, "SET_DATA_SLOT"); + ScaleformMovieMethodAddParamInt(i); + string buttonName = GetControlInstructionalButton(0, (int)control, 1); + PushScaleformMovieMethodParameterString(buttonName); + PushScaleformMovieMethodParameterString(text); + EndScaleformMovieMethod(); + } - BeginScaleformMovieMethod(_scale, "DRAW_INSTRUCTIONAL_BUTTONS"); - ScaleformMovieMethodAddParamInt(0); + // Use custom instructional buttons FIRST if they're present. + if (menu.CustomInstructionalButtons.Count > 0) + { + for (int i = 0; i < menu.CustomInstructionalButtons.Count; i++) + { + Menu.InstructionalButton button = menu.CustomInstructionalButtons[i]; + BeginScaleformMovieMethod(_scale, "SET_DATA_SLOT"); + ScaleformMovieMethodAddParamInt(i + menu.InstructionalButtons.Count); + PushScaleformMovieMethodParameterString(button.controlString); + PushScaleformMovieMethodParameterString(button.instructionText); EndScaleformMovieMethod(); - - DrawScaleformMovieFullscreen(_scale, 255, 255, 255, 255, 0); - return; } } - DisposeInstructionalButtonsScaleform(); + + BeginScaleformMovieMethod(_scale, "DRAW_INSTRUCTIONAL_BUTTONS"); + ScaleformMovieMethodAddParamInt(0); + EndScaleformMovieMethod(); + + DrawScaleformMovieFullscreen(_scale, 255, 255, 255, 255, 0); } private static void DisposeInstructionalButtonsScaleform() @@ -1048,6 +1159,21 @@ private static void DisposeInstructionalButtonsScaleform() SetScaleformMovieAsNoLongerNeeded(ref _scale); } } +#endif +#if REDM + /// + /// Prevent the UI prompts getting stuck on screen if this resource is ever to be restarted while someone has any menu's open. + /// + /// + [EventHandler("onResourceStop")] + internal static void OnResourceStop(string name) + { + if (name == GetCurrentResourceName()) + { + Debug.WriteLine($"^3[WARNING] [{name}] Closing all menus because this resource is being stopped, to prevent the UI Prompts getting stuck.^7"); + CloseAllMenus(); + } + } #endif } } diff --git a/MenuAPI/items/MenuCheckboxItem.cs b/MenuAPI/items/MenuCheckboxItem.cs index fa47c3d..69f15c9 100644 --- a/MenuAPI/items/MenuCheckboxItem.cs +++ b/MenuAPI/items/MenuCheckboxItem.cs @@ -1,13 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using CitizenFX.Core; +using CitizenFX.Core; using static CitizenFX.Core.Native.API; -using static CitizenFX.Core.Native.Function; -using static CitizenFX.Core.Native.Hash; - namespace MenuAPI { @@ -51,14 +43,13 @@ public MenuCheckboxItem(string text, string description, bool _checked) : base(t Checked = _checked; } - - int GetSpriteColour() + private int GetSpriteColour() { return Enabled ? 255 : 109; } #if FIVEM - string GetSpriteName() + private string GetSpriteName() { if (Checked) { @@ -81,7 +72,7 @@ string GetSpriteName() } else { - if (base.Selected) + if (Selected) { return "shop_box_blankb"; } @@ -90,12 +81,33 @@ string GetSpriteName() } #endif - float GetSpriteX() + private float GetSpriteX() { #if FIVEM bool leftSide = false; bool leftAligned = ParentMenu.LeftAligned; - return leftSide ? (leftAligned ? (20f / MenuController.ScreenWidth) : GetSafeZoneSize() - ((Width - 20f) / MenuController.ScreenWidth)) : (leftAligned ? (Width - 20f) / MenuController.ScreenWidth : (GetSafeZoneSize() - (20f / MenuController.ScreenWidth))); + if (leftSide) + { + if (leftAligned) + { + return 20f / MenuController.ScreenWidth; + } + else + { + return GetSafeZoneSize() - ((Width - 20f) / MenuController.ScreenWidth); + } + } + else + { + if (leftAligned) + { + return (Width - 20f) / MenuController.ScreenWidth; + } + else + { + return GetSafeZoneSize() - (20f / MenuController.ScreenWidth); + } + } #endif #if REDM return (Width - 30f) / MenuController.ScreenWidth; @@ -106,9 +118,7 @@ internal override void Draw(int offset) { RightIcon = Icon.NONE; Label = null; - base.Draw(offset); - #if FIVEM SetScriptGfxAlign(76, 84); SetScriptGfxAlignParams(0f, 0f, 0f, 0f); @@ -126,22 +136,31 @@ internal override void Draw(int offset) float spriteWidth = 45f / MenuController.ScreenWidth; #endif int color = GetSpriteColour(); - #if FIVEM DrawSprite("commonmenu", name, spriteX, spriteY, spriteWidth, spriteHeight, 0f, color, color, color, 255); ResetScriptGfxAlign(); #endif - #if REDM float spriteHeight = 24f / MenuController.ScreenHeight; float spriteWidth = 16f / MenuController.ScreenWidth; - Call(DRAW_SPRITE, "menu_textures", "SELECTION_BOX_SQUARE", spriteX, spriteY, spriteWidth, spriteHeight, 0f, color, color, color, 255); + DrawSprite("menu_textures", "SELECTION_BOX_SQUARE", spriteX, spriteY, spriteWidth, spriteHeight, 0f, color, color, color, 255, false); if (Checked) { int[] sc = Enabled ? (Selected ? new int[3] { 255, 255, 255 } : new int[3] { 181, 17, 18 }) : (Selected ? new int[3] { 109, 109, 109 } : new int[3] { 110, 10, 10 }); - Call(DRAW_SPRITE, "generic_textures", "TICK", spriteX, spriteY, spriteWidth, spriteHeight, 0f, sc[0], sc[1], sc[2], 255); + DrawSprite("generic_textures", "TICK", spriteX, spriteY, spriteWidth, spriteHeight, 0f, sc[0], sc[1], sc[2], 255, false); } #endif } + + internal override void GoRight() + { + ParentMenu.SelectItem(this); + } + + internal override void Select() + { + Checked = !Checked; + ParentMenu.CheckboxChangedEvent(this, Index, Checked); + } } } diff --git a/MenuAPI/items/MenuDynamicListItem.cs b/MenuAPI/items/MenuDynamicListItem.cs index dc3b255..6c29cad 100644 --- a/MenuAPI/items/MenuDynamicListItem.cs +++ b/MenuAPI/items/MenuDynamicListItem.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using CitizenFX.Core; +using static CitizenFX.Core.Native.Function; using static CitizenFX.Core.Native.API; namespace MenuAPI @@ -34,9 +29,42 @@ internal override void Draw(int indexOffset) { Label = $"~s~← {CurrentItem ?? "~r~N/A~s~"} ~s~→"; } - base.Draw(indexOffset); } + internal override void GoRight() + { + string oldValue = CurrentItem; + string newSelectedItem = Callback(this, false); + CurrentItem = newSelectedItem; + ParentMenu.DynamicListItemCurrentItemChanged(ParentMenu, this, oldValue, newSelectedItem); +#if FIVEM + PlaySoundFrontend(-1, "NAV_LEFT_RIGHT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); +#endif +#if REDM + // Has invalid parameter types in API. + Call((CitizenFX.Core.Native.Hash)0xCE5D0FFE83939AF1, -1, "NAV_RIGHT", "HUD_SHOP_SOUNDSET", 1); +#endif + } + + internal override void GoLeft() + { + string oldValue = CurrentItem; + string newSelectedItem = Callback(this, true); + CurrentItem = newSelectedItem; + ParentMenu.DynamicListItemCurrentItemChanged(ParentMenu, this, oldValue, newSelectedItem); +#if FIVEM + PlaySoundFrontend(-1, "NAV_LEFT_RIGHT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); +#endif +#if REDM + // Has invalid parameter types in API. + Call((CitizenFX.Core.Native.Hash)0xCE5D0FFE83939AF1, -1, "NAV_RIGHT", "HUD_SHOP_SOUNDSET", 1); +#endif + } + + internal override void Select() + { + ParentMenu.DynamicListItemSelectEvent(ParentMenu, this, CurrentItem); + } } } diff --git a/MenuAPI/items/MenuItem.cs b/MenuAPI/items/MenuItem.cs index 405235c..a4ff375 100644 --- a/MenuAPI/items/MenuItem.cs +++ b/MenuAPI/items/MenuItem.cs @@ -1,8 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using CitizenFX.Core; using static CitizenFX.Core.Native.API; using static CitizenFX.Core.Native.Function; @@ -12,7 +9,6 @@ namespace MenuAPI { public class MenuItem { - public enum Icon { NONE, @@ -195,6 +191,7 @@ public enum Icon BRAND_WESTERNMOTORCYCLE, BRAND_WILLARD, BRAND_ZIRCONIUM, + INFO #endif #if REDM LOCK, @@ -208,7 +205,6 @@ public enum Icon SELECTION_BOX #endif } - public string Text { get; set; } public string Label { get; set; } public Icon LeftIcon { get; set; } @@ -281,6 +277,11 @@ public MenuItem(string text, string description) Description = description; } + /// + /// Get the sprite dictionary name for the given icon. + /// + /// + /// protected string GetSpriteDictionary(Icon icon) { switch (icon) @@ -444,6 +445,8 @@ protected string GetSpriteDictionary(Icon icon) case Icon.BRAND_PROGEN2: case Icon.BRAND_RUNE: return "mpcarhud2"; + case Icon.INFO: + return "shared"; default: return "commonmenu"; #endif @@ -462,9 +465,14 @@ protected string GetSpriteDictionary(Icon icon) return ""; #endif } - } + /// + /// Get the sprite name for the given icon depending on the selected state of the item. + /// + /// + /// + /// protected string GetSpriteName(Icon icon, bool selected) { switch (icon) @@ -649,6 +657,7 @@ protected string GetSpriteName(Icon icon, bool selected) case Icon.BRAND_LCC: return "lcc"; case Icon.BRAND_PROGEN2: return "progen"; case Icon.BRAND_RUNE: return "rune"; + case Icon.INFO: return "info_icon_32"; default: break; #endif @@ -676,6 +685,12 @@ protected string GetSpriteName(Icon icon, bool selected) return ""; } + /// + /// Get the sprite size for the given icon. + /// + /// + /// + /// protected float GetSpriteSize(Icon icon, bool width) { switch (icon) @@ -863,6 +878,12 @@ protected float GetSpriteSize(Icon icon, bool width) } } + /// + /// Get the sprite color for the provided icon depending on the current state of the item (Enabled & selected values). + /// + /// + /// + /// protected int[] GetSpriteColour(Icon icon, bool selected) { switch (icon) @@ -986,6 +1007,13 @@ protected int[] GetSpriteColour(Icon icon, bool selected) } } + /// + /// Get the sprite x position offset for the provided icon and alignment variables. + /// + /// + /// + /// + /// protected float GetSpriteX(Icon icon, bool leftAligned, bool leftSide) { #if FIVEM @@ -993,204 +1021,307 @@ protected float GetSpriteX(Icon icon, bool leftAligned, bool leftSide) { return 0f; } - return leftSide ? (leftAligned ? (20f / MenuController.ScreenWidth) : GetSafeZoneSize() - ((Width - 20f) / MenuController.ScreenWidth)) : (leftAligned ? (Width - 20f) / MenuController.ScreenWidth : (GetSafeZoneSize() - (20f / MenuController.ScreenWidth))); + if (leftSide) + { + if (leftAligned) + { + return 20f / MenuController.ScreenWidth; + } + else + { + return GetSafeZoneSize() - ((Width - 20f) / MenuController.ScreenWidth); + } + } + else + { + if (leftAligned) + { + return (Width - 20f) / MenuController.ScreenWidth; + } + else + { + return GetSafeZoneSize() - (20f / MenuController.ScreenWidth); + } + } #endif #if REDM - return leftSide ? 30f / MenuController.ScreenWidth : ((Width - 30f) / MenuController.ScreenWidth); + if (leftSide) + { + return 30f / MenuController.ScreenWidth; + } + return (Width - 30f) / MenuController.ScreenWidth; #endif } - protected float GetSpriteY(Icon icon) + /// + /// Handles menu navigation to the right for items that support it, otherwise the item will be selected. + /// + internal virtual void GoRight() { - return 0f; + if (Enabled) + { + ParentMenu.SelectItem(this); + } } + /// + /// Handles menu navigation to the left for items that support it, otherwise the menu will navigate to the parent menu. + /// + internal virtual void GoLeft() + { + if (MenuController.NavigateMenuUsingArrows && !MenuController.DisableBackButton && !(MenuController.PreventExitingMenu && ParentMenu == null)) + { + ParentMenu.GoBack(); + } + } + + /// + /// Handles item selection. + /// + internal virtual void Select() + { + ParentMenu.ItemSelectedEvent(this, Index); + } /// /// Draws the item on the screen. /// internal virtual void Draw(int indexOffset) { - if (ParentMenu != null) + if (ParentMenu == null) { - float yOffset = ParentMenu.MenuItemsYOffset + 1f - (RowHeight * MathUtil.Clamp(ParentMenu.Size, 0, ParentMenu.MaxItemsOnScreen)); - #region Background Rect + return; + } + + int font = 0; + float textSize = (14f * 27f) / MenuController.ScreenHeight; + int textColor = Selected ? (Enabled ? 0 : 50) : (Enabled ? 255 : 109); + + float yOffset = ParentMenu.MenuItemsYOffset + 1f - (RowHeight * MathUtil.Clamp(ParentMenu.Size, 0, ParentMenu.MaxItemsOnScreen)); + float textXOffset = 0f; + float rightTextIconOffset = 0f; + + DrawBackground(indexOffset, yOffset, out float x, out float y); + + float textMinX = (textXOffset / MenuController.ScreenWidth) + (10f / MenuController.ScreenWidth); + float textMaxX = (Width - 10f) / MenuController.ScreenWidth; + float textY = y - ((30f / 2f) / MenuController.ScreenHeight); + + textXOffset = DrawLeftIcon(textXOffset, y); + rightTextIconOffset = DrawRightIcon(rightTextIconOffset, y); #if FIVEM - SetScriptGfxAlign(ParentMenu.LeftAligned ? 76 : 82, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + DrawLabelText(textXOffset, rightTextIconOffset, y, font, textSize, textColor, textY); #endif + DrawItemText(font, textSize, textColor, textMinX, textMaxX, textY, textXOffset, y); + } - float x = (ParentMenu.Position.Key + (Width / 2f)) / MenuController.ScreenWidth; - float y = (ParentMenu.Position.Value + ((Index - indexOffset) * RowHeight) + (20f) + yOffset) / MenuController.ScreenHeight; - float width = Width / MenuController.ScreenWidth; - float height = (RowHeight) / MenuController.ScreenHeight; - - if (Selected) - { + /// + /// Drwa the item text + /// + /// + /// + /// + /// + /// + /// + /// + /// + private void DrawItemText(int font, float textSize, int textColor, float textMinX, float textMaxX, float textY, float textXOffset, float y) + { #if FIVEM - DrawRect(x, y, width, height, 255, 255, 255, 225); + SetScriptGfxAlign(76, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + SetTextFont(font); + SetTextScale(textSize, textSize); + SetTextJustification(1); + BeginTextCommandDisplayText("STRING"); + AddTextComponentSubstringPlayerName(Text ?? "N/A"); + if (Selected || !Enabled) + { + SetTextColour(textColor, textColor, textColor, 255); + } + if (ParentMenu.LeftAligned) + { + SetTextWrap(textMinX, textMaxX); + EndTextCommandDisplayText(textMinX, textY); + } + else + { + textMinX = (textXOffset / MenuController.ScreenWidth) + GetSafeZoneSize() - ((Width - 10f) / MenuController.ScreenWidth); + textMaxX = GetSafeZoneSize() - (10f / MenuController.ScreenWidth); + SetTextWrap(textMinX, textMaxX); + EndTextCommandDisplayText(textMinX, textY); + } + ResetScriptGfxAlign(); #endif #if REDM - Call(DRAW_SPRITE, MenuController._texture_dict, MenuController._header_texture, x, y, width, height, 0f, 181, 17, 18, 255); - //Call(DRAW_RECT, x, y, width, height, 74, 6, 7, 200); -#endif - } -#if FIVEM - ResetScriptGfxAlign(); + SetTextScale(textSize, textSize); + textColor = Enabled ? 255 : 109; + SetTextColor(textColor, textColor, textColor, 255); + textMinX = ((8f + textXOffset) / MenuController.ScreenWidth) + (10f / MenuController.ScreenWidth); + textMaxX = (Width - 10f) / MenuController.ScreenWidth; + textY = y - ((30f / 2f) / MenuController.ScreenHeight); + font = 23; + // Cfx native, undocumented. + Call((CitizenFX.Core.Native.Hash)0xADA9255D, font); + // API version has incorrect parameter types. + long _text = Call(_CREATE_VAR_STRING, 10, "LITERAL_STRING", (Text ?? "N/A") + (" " + Label ?? "")); + DisplayText(_text, textMinX, textY); #endif - #endregion + } - #region Left Icon - float textXOffset = 0f; - if (LeftIcon != Icon.NONE) - { - textXOffset = 25f; #if FIVEM - SetScriptGfxAlign(76, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - - string name = GetSpriteName(LeftIcon, Selected); - float spriteY = y;// GetSpriteY(LeftIcon); - float spriteX = GetSpriteX(LeftIcon, ParentMenu.LeftAligned, true); - float spriteHeight = GetSpriteSize(LeftIcon, false); - float spriteWidth = GetSpriteSize(LeftIcon, true); - int[] spriteColor = GetSpriteColour(LeftIcon, Selected); - string textureDictionary = GetSpriteDictionary(LeftIcon); + /// + /// Draw the item label text if it exists. + /// + /// + /// + /// + /// + /// + /// + /// + private void DrawLabelText(float textXOffset, float rightTextIconOffset, float y, int font, float textSize, int textColor, float textY) + { + if (string.IsNullOrEmpty(Label)) + { + return; + } + SetScriptGfxAlign(76, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - DrawSprite(textureDictionary, name, spriteX, spriteY, spriteWidth, spriteHeight, 0f, spriteColor[0], spriteColor[1], spriteColor[2], 255); - ResetScriptGfxAlign(); -#endif -#if REDM - string spriteName = GetSpriteName(LeftIcon, Selected); - string spriteDict = GetSpriteDictionary(LeftIcon); - float spriteX = GetSpriteX(LeftIcon, true, true); - float spriteY = y; - float spriteHeight = GetSpriteSize(LeftIcon, false); - float spriteWidth = GetSpriteSize(LeftIcon, true); - int[] spriteColor = GetSpriteColour(LeftIcon, Selected); - Call(DRAW_SPRITE, spriteDict, spriteName, spriteX, spriteY, spriteWidth, spriteHeight, 0f, spriteColor[0], spriteColor[1], spriteColor[2], 255); + BeginTextCommandDisplayText("STRING"); + SetTextFont(font); + SetTextScale(textSize, textSize); + SetTextJustification(2); + AddTextComponentSubstringPlayerName(Label); + if (Selected || !Enabled) + { + SetTextColour(textColor, textColor, textColor, 255); + } + if (ParentMenu.LeftAligned) + { + SetTextWrap(0f, ((490f - rightTextIconOffset) / MenuController.ScreenWidth)); + EndTextCommandDisplayText((10f + rightTextIconOffset) / MenuController.ScreenWidth, textY); + } + else + { + SetTextWrap(0f, GetSafeZoneSize() - ((10f + rightTextIconOffset) / MenuController.ScreenWidth)); + EndTextCommandDisplayText(0f, textY); + } + ResetScriptGfxAlign(); + } #endif - } - #endregion - - #region Right Icon - float rightTextIconOffset = 0f; - if (RightIcon != Icon.NONE) - { + /// + /// Draw the right icon if it exists. + /// + /// + /// + /// + private float DrawRightIcon(float rightTextIconOffset, float y) + { + if (RightIcon == Icon.NONE) + { + return rightTextIconOffset; + } #if FIVEM - rightTextIconOffset = 25f; + rightTextIconOffset = 25f; - SetScriptGfxAlign(76, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - string name = GetSpriteName(RightIcon, Selected); - float spriteY = y;// GetSpriteY(RightIcon); - float spriteX = GetSpriteX(RightIcon, ParentMenu.LeftAligned, false); - float spriteHeight = GetSpriteSize(RightIcon, false); - float spriteWidth = GetSpriteSize(RightIcon, true); - int[] spriteColor = GetSpriteColour(RightIcon, Selected); - string textureDictionary = GetSpriteDictionary(RightIcon); - DrawSprite(textureDictionary, name, spriteX, spriteY, spriteWidth, spriteHeight, 0f, spriteColor[0], spriteColor[1], spriteColor[2], 255); - ResetScriptGfxAlign(); + SetScriptGfxAlign(76, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + string name = GetSpriteName(RightIcon, Selected); + float spriteY = y; + float spriteX = GetSpriteX(RightIcon, ParentMenu.LeftAligned, false); + float spriteHeight = GetSpriteSize(RightIcon, false); + float spriteWidth = GetSpriteSize(RightIcon, true); + int[] spriteColor = GetSpriteColour(RightIcon, Selected); + string textureDictionary = GetSpriteDictionary(RightIcon); + DrawSprite(textureDictionary, name, spriteX, spriteY, spriteWidth, spriteHeight, 0f, spriteColor[0], spriteColor[1], spriteColor[2], 255); + ResetScriptGfxAlign(); #endif #if REDM - string spriteName = GetSpriteName(RightIcon, Selected); - string spriteDict = GetSpriteDictionary(RightIcon); - float spriteX = GetSpriteX(RightIcon, true, false); - float spriteY = y; - float spriteHeight = GetSpriteSize(RightIcon, false); - float spriteWidth = GetSpriteSize(RightIcon, true); - int[] spriteColor = GetSpriteColour(RightIcon, Selected); - Call(DRAW_SPRITE, spriteDict, spriteName, spriteX, spriteY, spriteWidth, spriteHeight, 0f, spriteColor[0], spriteColor[1], spriteColor[2], 255); + string spriteName = GetSpriteName(RightIcon, Selected); + string spriteDict = GetSpriteDictionary(RightIcon); + float spriteX = GetSpriteX(RightIcon, true, false); + float spriteY = y; + float spriteHeight = GetSpriteSize(RightIcon, false); + float spriteWidth = GetSpriteSize(RightIcon, true); + int[] spriteColor = GetSpriteColour(RightIcon, Selected); + DrawSprite(spriteDict, spriteName, spriteX, spriteY, spriteWidth, spriteHeight, 0f, spriteColor[0], spriteColor[1], spriteColor[2], 255, false); #endif - } - #endregion + return rightTextIconOffset; + } - #region Label - int font = 0; - float textSize = (14f * 27f) / MenuController.ScreenHeight; + /// + /// Draw the left icon if it exists. + /// + /// + /// + /// + private float DrawLeftIcon(float textXOffset, float y) + { + if (LeftIcon == Icon.NONE) + { + return textXOffset; + } + textXOffset = 25f; #if FIVEM - float textMinX = (textXOffset / MenuController.ScreenWidth) + (10f / MenuController.ScreenWidth); - float textMaxX = (Width - 10f) / MenuController.ScreenWidth; - //float textHeight = GetTextScaleHeight(textSize, font); - float textY = y - ((30f / 2f) / MenuController.ScreenHeight); - int textColor = Selected ? (Enabled ? 0 : 50) : (Enabled ? 255 : 109); - if (!string.IsNullOrEmpty(Label)) - { - SetScriptGfxAlign(76, 84); - SetScriptGfxAlignParams(0f, 0f, 0f, 0f); + SetScriptGfxAlign(76, 84); + SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - BeginTextCommandDisplayText("STRING"); - SetTextFont(font); - SetTextScale(textSize, textSize); - SetTextJustification(2); - AddTextComponentSubstringPlayerName(Label); - if (Selected || !Enabled) - { - SetTextColour(textColor, textColor, textColor, 255); - } - if (ParentMenu.LeftAligned) - { - SetTextWrap(0f, ((490f - rightTextIconOffset) / MenuController.ScreenWidth)); - EndTextCommandDisplayText((10f + rightTextIconOffset) / MenuController.ScreenWidth, textY); - } - else - { - SetTextWrap(0f, GetSafeZoneSize() - ((10f + rightTextIconOffset) / MenuController.ScreenWidth)); - EndTextCommandDisplayText(0f, textY); - } + string name = GetSpriteName(LeftIcon, Selected); + float spriteY = y; + float spriteX = GetSpriteX(LeftIcon, ParentMenu.LeftAligned, true); + float spriteHeight = GetSpriteSize(LeftIcon, false); + float spriteWidth = GetSpriteSize(LeftIcon, true); + int[] spriteColor = GetSpriteColour(LeftIcon, Selected); + string textureDictionary = GetSpriteDictionary(LeftIcon); - ResetScriptGfxAlign(); - } + DrawSprite(textureDictionary, name, spriteX, spriteY, spriteWidth, spriteHeight, 0f, spriteColor[0], spriteColor[1], spriteColor[2], 255); + ResetScriptGfxAlign(); #endif - #endregion +#if REDM + string spriteName = GetSpriteName(LeftIcon, Selected); + string spriteDict = GetSpriteDictionary(LeftIcon); + float spriteX = GetSpriteX(LeftIcon, true, true); + float spriteY = y; + float spriteHeight = GetSpriteSize(LeftIcon, false); + float spriteWidth = GetSpriteSize(LeftIcon, true); + int[] spriteColor = GetSpriteColour(LeftIcon, Selected); + DrawSprite(spriteDict, spriteName, spriteX, spriteY, spriteWidth, spriteHeight, 0f, spriteColor[0], spriteColor[1], spriteColor[2], 255, false); +#endif + return textXOffset; + } - #region Text + /// + /// Draws the background for the menu item if it is selected and output the x/y values for this item. + /// + /// + /// + /// + /// + private void DrawBackground(int indexOffset, float yOffset, out float x, out float y) + { + x = (ParentMenu.Position.Key + (Width / 2f)) / MenuController.ScreenWidth; + y = (ParentMenu.Position.Value + ((Index - indexOffset) * RowHeight) + (20f) + yOffset) / MenuController.ScreenHeight; + if (Selected) + { + float width = Width / MenuController.ScreenWidth; + float height = (RowHeight) / MenuController.ScreenHeight; #if FIVEM - SetScriptGfxAlign(76, 84); + SetScriptGfxAlign(ParentMenu.LeftAligned ? 76 : 82, 84); SetScriptGfxAlignParams(0f, 0f, 0f, 0f); - SetTextFont(font); - SetTextScale(textSize, textSize); - SetTextJustification(1); - BeginTextCommandDisplayText("STRING"); - AddTextComponentSubstringPlayerName(Text ?? "N/A"); - if (Selected || !Enabled) - { - SetTextColour(textColor, textColor, textColor, 255); - } - if (ParentMenu.LeftAligned) - { - SetTextWrap(textMinX, textMaxX); - EndTextCommandDisplayText(textMinX, textY); - } - else - { - textMinX = (textXOffset / MenuController.ScreenWidth) + GetSafeZoneSize() - ((Width - 10f) / MenuController.ScreenWidth); - textMaxX = GetSafeZoneSize() - (10f / MenuController.ScreenWidth); - SetTextWrap(textMinX, textMaxX); - EndTextCommandDisplayText(textMinX, textY); - } + DrawRect(x, y, width, height, 255, 255, 255, 225); ResetScriptGfxAlign(); #endif #if REDM - Call(SET_TEXT_SCALE, textSize, textSize); - - int textColor = Enabled ? 255 : 109; - Call((CitizenFX.Core.Native.Hash)0x50A41AD966910F03, textColor, textColor, textColor, 255); // _SET_TEXT_COLOUR / 0x50A41AD966910F03 - float textMinX = ((8f + textXOffset) / MenuController.ScreenWidth) + (10f / MenuController.ScreenWidth); - float textMaxX = (Width - 10f) / MenuController.ScreenWidth; - float textY = y - ((30f / 2f) / MenuController.ScreenHeight); - font = 23; - Call((CitizenFX.Core.Native.Hash)0xADA9255D, font); - - Call(_DRAW_TEXT, Call(_CREATE_VAR_STRING, 10, "LITERAL_STRING", (Text ?? "N/A") + (" " + Label ?? "")), textMinX, textY); + DrawSprite(MenuController._texture_dict, MenuController._header_texture, x, y, width, height, 0f, 181, 17, 18, 255, false); #endif - #endregion - - } +#if FIVEM +#endif } - } } diff --git a/MenuAPI/items/MenuListItem.cs b/MenuAPI/items/MenuListItem.cs index 4021188..e83ab37 100644 --- a/MenuAPI/items/MenuListItem.cs +++ b/MenuAPI/items/MenuListItem.cs @@ -1,14 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using CitizenFX.Core; +using System.Collections.Generic; +using static CitizenFX.Core.Native.Function; using static CitizenFX.Core.Native.API; namespace MenuAPI { - public class MenuListItem : MenuItem { public int ListIndex { get; set; } = 0; @@ -69,6 +64,63 @@ internal override void Draw(int indexOffset) base.Draw(indexOffset); } - } + internal override void GoRight() + { + if (ItemsCount > 0) + { + int oldIndex = ListIndex; + int newIndex = oldIndex; + if (ListIndex >= ItemsCount - 1) + { + newIndex = 0; + } + else + { + newIndex++; + } + ListIndex = newIndex; + ParentMenu.ListItemIndexChangeEvent(ParentMenu, this, oldIndex, newIndex, Index); +#if FIVEM + PlaySoundFrontend(-1, "NAV_LEFT_RIGHT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); +#endif +#if REDM + // Has invalid parameter types in API. + Call((CitizenFX.Core.Native.Hash)0xCE5D0FFE83939AF1, -1, "NAV_RIGHT", "HUD_SHOP_SOUNDSET", 1); +#endif + } + } + + internal override void GoLeft() + { + if (ItemsCount > 0) + { + int oldIndex = ListIndex; + int newIndex = oldIndex; + if (ListIndex < 1) + { + newIndex = ItemsCount - 1; + } + else + { + newIndex--; + } + ListIndex = newIndex; + + ParentMenu.ListItemIndexChangeEvent(ParentMenu, this, oldIndex, newIndex, Index); +#if FIVEM + PlaySoundFrontend(-1, "NAV_LEFT_RIGHT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); +#endif +#if REDM + // Has invalid parameter types in API. + Call((CitizenFX.Core.Native.Hash)0xCE5D0FFE83939AF1, -1, "NAV_LEFT", "HUD_SHOP_SOUNDSET", 1); +#endif + } + } + + internal override void Select() + { + ParentMenu.ListItemSelectEvent(ParentMenu, this, ListIndex, Index); + } + } } diff --git a/MenuAPI/items/MenuSliderItem.cs b/MenuAPI/items/MenuSliderItem.cs index ab0fba7..442fc4e 100644 --- a/MenuAPI/items/MenuSliderItem.cs +++ b/MenuAPI/items/MenuSliderItem.cs @@ -1,4 +1,5 @@ -using System; +#if FIVEM +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -8,7 +9,6 @@ namespace MenuAPI { -#if FIVEM public class MenuSliderItem : MenuItem { public int Min { get; private set; } = 0; @@ -49,7 +49,6 @@ private float Map(float val, float in_min, float in_max, float out_min, float ou internal override void Draw(int indexOffset) { - RightIcon = SliderRightIcon; Label = null; @@ -60,7 +59,6 @@ internal override void Draw(int indexOffset) Position = (Max - Min) / 2; } - float yOffset = ParentMenu.MenuItemsYOffset + 1f - (RowHeight * MathUtil.Clamp(ParentMenu.Size, 0, ParentMenu.MaxItemsOnScreen)); float width = 150f / MenuController.ScreenWidth; @@ -108,13 +106,24 @@ internal override void Draw(int indexOffset) // background DrawRect(x, y, width, height, BackgroundColor.R, BackgroundColor.G, BackgroundColor.B, BackgroundColor.A); - float xOffset = Map((float)Position, (float)Min, (float)Max, -((width / 4f) * MenuController.ScreenWidth), ((width / 4f) * MenuController.ScreenWidth)) / MenuController.ScreenWidth; + float xOffset = Map( + (float)Position, + (float)Min, + (float)Max, + -((width / 4f) * MenuController.ScreenWidth), + (width / 4f) * MenuController.ScreenWidth + ); + xOffset /= MenuController.ScreenWidth; // bar (foreground) if (!ParentMenu.LeftAligned) + { DrawRect(x - (width / 2f) + xOffset, y, width / 2f, height, BarColor.R, BarColor.G, BarColor.B, BarColor.A); + } else + { DrawRect(x + xOffset, y, width / 2f, height, BarColor.R, BarColor.G, BarColor.B, BarColor.A); + } #endregion @@ -122,16 +131,50 @@ internal override void Draw(int indexOffset) if (ShowDivider) { if (!ParentMenu.LeftAligned) + { DrawRect(x - width + (4f / MenuController.ScreenWidth), y, 4f / MenuController.ScreenWidth, RowHeight / MenuController.ScreenHeight / 2f, 255, 255, 255, 255); + } else + { DrawRect(x + (2f / MenuController.ScreenWidth), y, 4f / MenuController.ScreenWidth, RowHeight / MenuController.ScreenHeight / 2f, 255, 255, 255, 255); + } } #endregion ResetScriptGfxAlign(); + } + internal override void GoRight() + { + if (Position < Max) + { + Position++; + ParentMenu.SliderItemChangedEvent(ParentMenu, this, Position - 1, Position, Index); + PlaySoundFrontend(-1, "NAV_LEFT_RIGHT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); + } + else + { + PlaySoundFrontend(-1, "ERROR", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); + } + } + internal override void GoLeft() + { + if (Position > Min) + { + Position--; + ParentMenu.SliderItemChangedEvent(ParentMenu, this, Position + 1, Position, Index); + PlaySoundFrontend(-1, "NAV_LEFT_RIGHT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); + } + else + { + PlaySoundFrontend(-1, "ERROR", "HUD_FRONTEND_DEFAULT_SOUNDSET", false); + } + } + internal override void Select() + { + ParentMenu.SliderSelectedEvent(ParentMenu, this, Position, Index); } } -#endif } +#endif \ No newline at end of file diff --git a/README.md b/README.md index 9da6d47..9e39eb9 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,58 @@ # MenuAPI -FiveM C# Menu API. -Designed specifically as a replacement of NativeUI for vMenu with improved performance (somewhat), more features, less bugs, and easier to use functions (somewhat). +**FiveM & RedM C# Menu API** -Full safezone scaling supported, both left and right aligned menus supported. +[![Discord](https://discordapp.com/api/guilds/285424882534187008/widget.png)](https://vespura.com/discord) [![CodeFactor](https://www.codefactor.io/repository/github/tomgrobbe/menuapi/badge)](https://www.codefactor.io/repository/github/tomgrobbe/menuapi) [![Build status](https://ci.appveyor.com/api/projects/status/8nqoeyg0e9rn10ih/branch/master?svg=true)](https://ci.appveyor.com/project/TomGrobbe/menuapi/branch/master) [![Patreon](https://img.shields.io/badge/donate-Patreon-orange.svg)](https://www.patreon.com/vespura) -This has been coded from the ground up. Using GTA V Decompiled scripts to figure out what some undocumented natives were used for. +Designed specifically as a replacement of **NativeUI**, MenuAPI features performance improvements, **RedM** _and_ **FiveM** support, improved stability, better features, less bugs, full safezone alignment support for both left and right algined menus (FiveM only) and less (in my opinion) unnecessary features. +This has been coded from the ground up. Using decompiled scripts from GTA V & RedM to figure out what some undocumented natives were used for. -# Copyright -Copyright © Tom Grobbe 2018. +## Installation -# License (custom license) -You can use this API in your own resources, you can edit this API if you want to add features. Feel free to PR them. +_Note, this is only for resource developers, don't install this on your server manually if you're not making a resource with it._ -You can host re-releases of this API, but ONLY as a FORK created via GitHub. If it's not a forked repo, then the release will be taken down by DMCA request. +You have 2 options: -It's very simple, don't steal my stuff and try to take credit. That's all I ask. +1. Download the latest release zip and use the correct version (FiveM/RedM) for your resource. Simply include the DLL as a reference in your C# project and add `using MenuAPI;` to each file where you need to use MenuAPI. +2. Use the NuGet package, which can be found [here](https://www.nuget.org/packages/MenuAPI.FiveM/) for FiveM, and [here](https://www.nuget.org/packages/MenuAPI.RedM/) for RedM. -When creating a resource, you are **not** required to mention/link this API, as long as you do not claim it to be your own work. -If you feel like it you can link it just because you're nice, but there's no need to do this. I'd appreciate it if you just put the link to this repo somewhere in your credits/readme file. :) +After doing either of the above and you're ready to build and publish your resource, add `files {'MenuAPI.dll'}` to your `fxmanifest.lua` file, and make sure that you include the `MenuAPI.dll` file in the folder of your resource. + +## Documentation + +Limited documentation is available [here](https://docs.vespura.com/mapi). + +Feel like contributing to the documentation? The repository for the documentation site can be found [here](https://github.com/TomGrobbe/MenuAPI-Docs), thanks! + +## Copyright / License + +Copyright © Tom Grobbe 2018-2021. + +MenuAPI is a free resource, using a custom license. +Conditions are listed below. + +### You are allowed to + +- Include the pre-built files in your projects, for both commercial and non-commercial use +- Modify this code, feel free to create PR's :) + +### You are NOT allowed to + +- Sell this code or a modified version of it. +- If you release a paid resource that uses MenuAPI, you are not allowed to include MenuAPI in the resource. You will need to provide a free way for anyone to download the MenuAPI version of your resource. +- Re-release this code without using the Fork feature. + +### You must + +- Provide appropritate credits when including this in your project. +- State any changes you made if you want to re-release this code. +- Keep this license when editing the source code or using this code in your own projects. + +### In short + +It's very simple, don't steal my stuff, don't try to take credit for code that isn't yours and don't try to make money using my work. That's all I ask. + +If you'd like to do something that's not allowed per this license, contact me and we might be able to figure something out. + +Nothing is guaranteed to work, I do not take responsibility for any bugs or damages caused by this code. Use at your own risk. diff --git a/TestMenu/ExampleMenu.cs b/TestMenu/ExampleMenu.cs index 74e47e0..f693a6f 100644 --- a/TestMenu/ExampleMenu.cs +++ b/TestMenu/ExampleMenu.cs @@ -1,11 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using CitizenFX.Core; -using static CitizenFX.Core.Native.API; using MenuAPI; +using CitizenFX.Core; namespace TestMenu { @@ -18,19 +14,22 @@ public ExampleMenu() // To test this, checkout one of the checkbox items in this example menu. Clicking it will toggle the menu alignment. MenuController.MenuAlignment = MenuController.MenuAlignmentOption.Right; #endif - //MenuController.MenuToggleKey = Control.InteractionMenu; - // Creating the first menu. Menu menu = new Menu("Main Menu", "Subtitle"); MenuController.AddMenu(menu); - // Adding a new button by directly creating one inline. You could also just store it and then add it but we don't need to do that in this example. - menu.AddMenuItem(new MenuItem("Normal Button", "This is a simple button with a simple description. Scroll down for more button types!") - { - Enabled = false, - LeftIcon = MenuItem.Icon.TICK - }); - + // Adding a new button by directly creating one inline. + // You could also just store it and then add it but we don't need to do that in this example. + menu.AddMenuItem( + new MenuItem( + "Normal Button", + "This is a simple button with a simple description. Scroll down for more button types!" + ) + { + Enabled = false, + LeftIcon = MenuItem.Icon.TICK + } + ); #if FIVEM // Creating 3 sliders, showing off the 3 possible variations and custom colors. MenuSliderItem slider = new MenuSliderItem("Slider", 0, 10, 5, false); @@ -39,34 +38,51 @@ public ExampleMenu() BarColor = System.Drawing.Color.FromArgb(255, 73, 233, 111), BackgroundColor = System.Drawing.Color.FromArgb(255, 25, 100, 43) }; - MenuSliderItem slider3 = new MenuSliderItem("Slider + Bar + Icons", "The icons are currently male/female because that's probably the most common use. But any icon can be used!", 0, 10, 5, true) + MenuSliderItem slider3 = new MenuSliderItem( + "Slider + Bar + Icons", + "The icons are currently male/female because that's probably the most common use. But any icon can be used!", + 0, + 10, + 5, + true + ) { BarColor = System.Drawing.Color.FromArgb(255, 255, 0, 0), BackgroundColor = System.Drawing.Color.FromArgb(255, 100, 0, 0), - SliderLeftIcon = MenuItem.Icon.MALE, SliderRightIcon = MenuItem.Icon.FEMALE }; + // adding the sliders to the menu. menu.AddMenuItem(slider); menu.AddMenuItem(slider2); menu.AddMenuItem(slider3); - #endif - #if FIVEM // Creating 3 checkboxs, 2 different styles and one has a locked icon and it's 'not enabled' (not enabled meaning you can't toggle it). - MenuCheckboxItem box = new MenuCheckboxItem("Checkbox - Style 1 (click me!)", "This checkbox can toggle the menu position! Try it out.", !menu.LeftAligned) + MenuCheckboxItem box = new MenuCheckboxItem( + "Checkbox - Style 1 (click me!)", + "This checkbox can toggle the menu position! Try it out.", + !menu.LeftAligned + ) { Style = MenuCheckboxItem.CheckboxStyle.Cross }; #endif - MenuCheckboxItem box2 = new MenuCheckboxItem("Checkbox - Style 2", "This checkbox does nothing right now.", true) + MenuCheckboxItem box2 = new MenuCheckboxItem( + "Checkbox - Style 2", + "This checkbox does nothing right now.", + true + ) { Style = MenuCheckboxItem.CheckboxStyle.Tick }; - MenuCheckboxItem box3 = new MenuCheckboxItem("Checkbox (unchecked + locked)", "Make this menu right aligned. If you set this to false, then the menu will move to the left.", false) + MenuCheckboxItem box3 = new MenuCheckboxItem( + "Checkbox (unchecked + locked)", + "Make this menu right aligned. If you set this to false, then the menu will move to the left.", + false + ) { Enabled = false, LeftIcon = MenuItem.Icon.LOCK @@ -86,7 +102,12 @@ string ChangeCallback(MenuDynamicListItem item, bool left) return (int.Parse(item.CurrentItem) - 1).ToString(); return (int.Parse(item.CurrentItem) + 1).ToString(); } - MenuDynamicListItem dynList = new MenuDynamicListItem("Dynamic list item.", "0", new MenuDynamicListItem.ChangeItemCallback(ChangeCallback), "Description for this dynamic item. Pressing left will make the value smaller, pressing right will make the value bigger."); + MenuDynamicListItem dynList = new MenuDynamicListItem( + "Dynamic list item.", + "0", + new MenuDynamicListItem.ChangeItemCallback(ChangeCallback), + "Description for this dynamic item. Pressing left will make the value smaller, pressing right will make the value bigger." + ); menu.AddMenuItem(dynList); #if FIVEM // List items (first the 3 special variants, then a normal one) @@ -95,7 +116,12 @@ string ChangeCallback(MenuDynamicListItem item, bool left) { colorList.Add($"Color #{i}"); } - MenuListItem hairColors = new MenuListItem("Hair Color", colorList, 0, "Hair color pallete.") + MenuListItem hairColors = new MenuListItem( + "Hair Color", + colorList, + 0, + "Hair color pallete." + ) { ShowColorPanel = true }; @@ -129,7 +155,12 @@ string ChangeCallback(MenuDynamicListItem item, bool left) #endif // Normal List normalList = new List() { "Item #1", "Item #2", "Item #3" }; - MenuListItem normalListItem = new MenuListItem("Normal List Item", normalList, 0, "And another simple description for yet another simple (list) item. Nothing special about this one."); + MenuListItem normalListItem = new MenuListItem( + "Normal List Item", + normalList, + 0, + "And another simple description for yet another simple (list) item. Nothing special about this one." + ); // Adding the lists to the menu. menu.AddMenuItem(normalListItem); @@ -138,7 +169,10 @@ string ChangeCallback(MenuDynamicListItem item, bool left) Menu submenu = new Menu("Submenu", "Secondary Menu"); MenuController.AddSubmenu(menu, submenu); - MenuItem menuButton = new MenuItem("Submenu", "This button is bound to a submenu. Clicking it will take you to the submenu.") + MenuItem menuButton = new MenuItem( + "Submenu", + "This button is bound to a submenu. Clicking it will take you to the submenu." + ) { #if FIVEM Label = "→→→" @@ -153,7 +187,10 @@ string ChangeCallback(MenuDynamicListItem item, bool left) // Adding items with sprites left & right to the submenu. for (var i = 0; i < Enum.GetValues(typeof(MenuItem.Icon)).Length; i++) { - var tmpItem = new MenuItem($"Icon.{Enum.GetName(typeof(MenuItem.Icon), ((MenuItem.Icon)i))}", "This menu item has a left and right sprite. Press ~r~HOME~s~ to toggle the 'enabled' state on these items.") + var tmpItem = new MenuItem( + $"Icon.{Enum.GetName(typeof(MenuItem.Icon), ((MenuItem.Icon)i))}", + "This menu item has a left and right sprite. Press ~r~HOME~s~ to toggle the 'enabled' state on these items." + ) { Label = $"(#{i})", #if FIVEM @@ -162,19 +199,16 @@ string ChangeCallback(MenuDynamicListItem item, bool left) LeftIcon = (MenuItem.Icon)i }; - //var tmpItem2 = new MenuItem($"Icon.{Enum.GetName(typeof(MenuItem.Icon), ((MenuItem.Icon)i))}", "This menu item has a left and right sprite, and it's ~h~disabled~h~."); - //tmpItem2.LeftIcon = (MenuItem.Icon)i; - //tmpItem2.RightIcon = (MenuItem.Icon)i; - //tmpItem2.Enabled = false; - submenu.AddMenuItem(tmpItem); - //submenu.AddMenuItem(tmpItem2); } - submenu.ButtonPressHandlers.Add(new Menu.ButtonPressHandler(Control.FrontendSocialClubSecondary, Menu.ControlPressCheckType.JUST_RELEASED, new Action((m, c) => - { - m.GetMenuItems().ForEach(a => a.Enabled = !a.Enabled); - }), true)); - + submenu.ButtonPressHandlers.Add( + new Menu.ButtonPressHandler(Control.FrontendSocialClubSecondary, + Menu.ControlPressCheckType.JUST_RELEASED, + new Action((m, c) => + { + m.GetMenuItems().ForEach(a => a.Enabled = !a.Enabled); + }), true) + ); #if FIVEM // Instructional buttons setup for the second (submenu) menu. submenu.InstructionalButtons.Add(Control.CharacterWheel, "Right?!"); @@ -183,19 +217,21 @@ string ChangeCallback(MenuDynamicListItem item, bool left) submenu.InstructionalButtons.Add(Control.Cover, "This"); submenu.InstructionalButtons.Add(Control.Context, "Check"); #endif - // Create a third menu without a banner. Menu menu3 = new Menu(null, "Only a subtitle, no banner."); // you can use AddSubmenu or AddMenu, both will work but if you want to link this menu from another menu, // you should use AddSubmenu. MenuController.AddSubmenu(menu, menu3); - MenuItem thirdSubmenuBtn = new MenuItem("Another submenu", "This is just a submenu without a banner. No big deal. This also has a very long description to test multiple lines and see if they work properly. Let's find out if it works as intended.") + MenuItem thirdSubmenuBtn = new MenuItem( + "Another submenu", + "This is just a submenu without a banner. No big deal. This also has a very long description to test multiple " + + "lines and see if they work properly. Let's find out if it works as intended." + ) { #if FIVEM Label = "→→→" #endif - #if REDM RightIcon = MenuItem.Icon.ARROW_RIGHT #endif @@ -212,12 +248,30 @@ string ChangeCallback(MenuDynamicListItem item, bool left) menu.AddMenuItem(new MenuItem($"Item #{i + 1}.", "With an invisible description.")); } - /* -######################################################## - Event handlers -######################################################## - */ - +#if FIVEM + // Create menu with weapon stats panel + Menu menu4 = new Menu("Weapon Stats", "Weapon Stats Panel") { ShowWeaponStatsPanel = true }; + menu4.AddMenuItem(new MenuItem("dummy item", "You should add at least one item when using weapon stat panels")); + menu4.SetWeaponStats(0.2f, 0.4f, 0.7f, 0.8f); + menu4.SetWeaponComponentStats(0.4f, 0f, -0.05f, 0.1f); + MenuController.AddSubmenu(menu, menu4); + MenuItem weaponStats = new MenuItem("Weapon stats", "Demo menu for weapon stats components"); + menu.AddMenuItem(weaponStats); + MenuController.BindMenuItem(menu, menu4, weaponStats); + + // Create menu with vehicle stats panel + Menu menu5 = new Menu("Vehicle Stats", "Vehicle Stats Panel") { ShowVehicleStatsPanel = true }; + menu5.AddMenuItem(new MenuItem("dummy item", "You should add at least one item when using vehicle stat panels")); + menu5.SetVehicleStats(0.2f, 0.2f, 0.3f, 0.8f); + menu5.SetVehicleUpgradeStats(0.4f, -0.025f, 0.05f, 0.1f); + MenuController.AddSubmenu(menu, menu5); + MenuItem vehicleStats = new MenuItem("Vehicle stats", "Demo menu for vehicle stats components"); + menu.AddMenuItem(vehicleStats); + MenuController.BindMenuItem(menu, menu5, vehicleStats); +#endif + /*-------------- + Event handlers + --------------*/ menu.OnCheckboxChange += (_menu, _item, _index, _checked) => { @@ -300,20 +354,6 @@ Event handlers // Code in here would get executed whenever a dynamic list item is pressed. Debug.WriteLine($"OnDynamicListItemSelect: [{_menu}, {_dynamicListItem}, {_currentItem}]"); }; - - longershit(); - } - - static async Task longershit() - { - Debug.WriteLine("test"); - await Delay(1000); - Debug.WriteLine("test"); - MenuController.MainMenu.OpenMenu(); - await Delay(10000); - Debug.WriteLine(MenuController.MainMenu.Visible.ToString()); } - - } } diff --git a/TestMenu/TestMenu.csproj b/TestMenu/TestMenu.csproj index e6bcc83..95d6e9d 100644 --- a/TestMenu/TestMenu.csproj +++ b/TestMenu/TestMenu.csproj @@ -20,7 +20,7 @@ - + runtime diff --git a/appveyor.yml b/appveyor.yml index 50ee69b..239edc7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,31 +6,39 @@ configuration: - Release FiveM before_build: - nuget restore + - cmd: if %APPVEYOR_REPO_TAG%==true (appveyor SetVariable -Name VERSION_NAME -Value %APPVEYOR_REPO_TAG_NAME%) else (appveyor SetVariable -Name VERSION_NAME -Value dev-%APPVEYOR_BUILD_VERSION%) + - cmd: if "%CONFIGURATION%"=="Release FiveM" (appveyor SetVariable -Name GAME -Value "FiveM") else if "%CONFIGURATION%"=="Release RedM" (appveyor SetVariable -Name GAME -Value "RedM") build: - parallel: true + parallel: false project: MenuAPI.sln include_nuget_references: true verbosity: minimal after_build: - - cmd: if %APPVEYOR_REPO_TAG%==true (appveyor SetVariable -Name VERSION_NAME -Value %APPVEYOR_REPO_TAG_NAME%) else (appveyor SetVariable -Name VERSION_NAME -Value dev) - - cmd: if "%CONFIGURATION%"=="Release FiveM" (appveyor SetVariable -Name GAME -Value "FiveM") else if "%CONFIGURATION%"=="Release RedM" (appveyor SetVariable -Name GAME -Value "RedM") - cmd: copy "README.md" ".\MenuAPI\bin\README.md" - cmd: 7z a MenuAPI-%VERSION_NAME%-%GAME%.zip -r ".\MenuAPI\bin\*" - cmd: appveyor PushArtifact MenuAPI-%VERSION_NAME%-%GAME%.zip deploy: + - provider: NuGet + api_key: $(NUGET_API_KEY) + skip_symbols: true + on: + APPVEYOR_REPO_TAG: true - provider: GitHub release: "[Release] MenuAPI $(VERSION_NAME)" tag: $(VERSION_NAME) artifact: MenuAPI-$(VERSION_NAME)-$(GAME).zip - draft: true + draft: false prerelease: false auth_token: $(github_auth) on: APPVEYOR_REPO_TAG: true - description: "MenuAPI release, version $(VERSION_NAME). For info check the [docs](https://docs.vespura.com/mapi) or checkout the recent commits on GitHub (the latter is your best bet if you want updated info about this version)." + description: "MenuAPI release, version $(VERSION_NAME). Download the **FiveM** or **RedM** versions below, by selecting the corresponding zip files.\n\nFor info check the [docs](https://docs.vespura.com/mapi) or checkout the recent commits on GitHub (the latter is your best bet if you want updated info about this version)." +before_deploy: + - ps: $env:NUGET_VERSION=(($env:VERSION_NAME).Substring(1)) + - cmd: if "%CONFIGURATION%"=="Release FiveM" (cd MenuAPI && nuget pack MenuAPI.csproj -Properties Configuration="Release FiveM";Id="MenuAPI.FiveM" -Version "%NUGET_VERSION%" && appveyor PushArtifact MenuAPI.FiveM.%NUGET_VERSION%.nupkg && cd ..) else (cd MenuAPI && nuget pack MenuAPI.csproj -Properties Configuration="Release RedM";Id="MenuAPI.RedM" -Version "%NUGET_VERSION%" && appveyor PushArtifact MenuAPI.RedM.%NUGET_VERSION%.nupkg && cd ..) after_deploy: - - cmd: curl -H "Content-Type:application/json" -X POST -d "{\"content\":\"^<^@^&540562517806809109^>\",\"embeds\":[{\"title\":\"%APPVEYOR_PROJECT_NAME% (%VERSION_NAME%-%GAME%)\",\"description\":\"A new version of %APPVEYOR_PROJECT_NAME% (**%VERSION_NAME%** for _%GAME%_) is available!\",\"url\":\"https://ci.appveyor.com/project/%APPVEYOR_ACCOUNT_NAME%/%APPVEYOR_PROJECT_SLUG%/builds/%APPVEYOR_BUILD_ID%\",\"color\":3048181,\"author\":{\"name\":\"%APPVEYOR_ACCOUNT_NAME%\",\"url\":\"https://github.com/%APPVEYOR_ACCOUNT_NAME%/%APPVEYOR_PROJECT_NAME%/releases/\"}}]}" -F "file=@MenuAPI-%VERSION_NAME%-%GAME%.zip" %WEBHOOK_URL% + - cmd: appveyor/after_deploy.cmd on_success: - - cmd: curl -H "Content-Type:application/json" -X POST -d "{\"embeds\":[{\"title\":\"%APPVEYOR_PROJECT_NAME% (%VERSION_NAME%-%GAME%)\",\"description\":\"**Build passed!**\",\"url\":\"https://ci.appveyor.com/project/%APPVEYOR_ACCOUNT_NAME%/%APPVEYOR_PROJECT_SLUG%/builds/%APPVEYOR_BUILD_ID%\",\"color\":4502298,\"author\":{\"name\":\"%APPVEYOR_ACCOUNT_NAME%\",\"url\":\"https://github.com/%APPVEYOR_ACCOUNT_NAME%/%APPVEYOR_PROJECT_NAME%/\"}}]}" %WEBHOOK_URL% + - cmd: appveyor/on_success.cmd on_failure: - - cmd: curl -H "Content-Type:application/json" -X POST -d "{\"embeds\":[{\"title\":\"%APPVEYOR_PROJECT_NAME% (%VERSION_NAME%-%GAME%)\",\"description\":\"**Build failed!**\",\"url\":\"https://ci.appveyor.com/project/%APPVEYOR_ACCOUNT_NAME%/%APPVEYOR_PROJECT_SLUG%/builds/%APPVEYOR_BUILD_ID%\",\"color\":13632027,\"author\":{\"name\":\"%APPVEYOR_ACCOUNT_NAME%\",\"url\":\"https://github.com/%APPVEYOR_ACCOUNT_NAME%/%APPVEYOR_PROJECT_NAME%/\"}}]}" %WEBHOOK_URL% \ No newline at end of file + - cmd: appveyor/on_failure.cmd diff --git a/appveyor/after_deploy.cmd b/appveyor/after_deploy.cmd new file mode 100644 index 0000000..1788a04 --- /dev/null +++ b/appveyor/after_deploy.cmd @@ -0,0 +1,6 @@ +if not defined WEBHOOK_URL goto end +if not "%CONFIGURATION%"=="Release FiveM" goto end + +curl -H "Content-Type:application/json" -X POST -d "{\"content\":\"^<^@^&540562517806809109^>\",\"embeds\":[{\"title\":\"%APPVEYOR_PROJECT_NAME% (%VERSION_NAME%)\",\"description\":\"New version of **%APPVEYOR_PROJECT_NAME%** (%VERSION_NAME%) is available for both **FiveM** and **RedM** Download it by using the files in this chanel or by going to the GitHub Tag link!\",\"color\":3048181,\"author\":{\"name\":\"Committed by %APPVEYOR_ACCOUNT_NAME%\",\"url\":\"https://github.com/%APPVEYOR_ACCOUNT_NAME%/\"},\"fields\":[{\"name\":\"AppVeyor Build\",\"value\":\"[Here](%APPVEYOR_URL%/project/%APPVEYOR_ACCOUNT_NAME%/%APPVEYOR_PROJECT_SLUG%/builds/%APPVEYOR_BUILD_ID%)\"},{\"name\":\"GitHub Commit (%APPVEYOR_REPO_COMMIT%)\",\"value\":\"[%APPVEYOR_REPO_COMMIT%](https://github.com/%APPVEYOR_ACCOUNT_NAME%/%APPVEYOR_PROJECT_NAME%/commit/%APPVEYOR_REPO_COMMIT%) - %APPVEYOR_REPO_COMMIT_MESSAGE%%APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED%\"},{\"name\":\"GitHub Branch\",\"value\":\"[%APPVEYOR_REPO_BRANCH%](https://github.com/%APPVEYOR_ACCOUNT_NAME%/%APPVEYOR_PROJECT_NAME%/tree/%APPVEYOR_REPO_BRANCH%)\"},{\"name\":\"GitHub Tag\",\"value\":\"[%APPVEYOR_REPO_TAG_NAME%](https://github.com/%APPVEYOR_ACCOUNT_NAME%/%APPVEYOR_PROJECT_NAME%/releases/tag/%APPVEYOR_REPO_TAG_NAME%)\"}]}]}" %WEBHOOK_URL% + +:end \ No newline at end of file diff --git a/appveyor/on_failure.cmd b/appveyor/on_failure.cmd new file mode 100644 index 0000000..1aaaccc --- /dev/null +++ b/appveyor/on_failure.cmd @@ -0,0 +1,5 @@ +if not defined WEBHOOK_URL goto end + +curl -H "Content-Type:application/json" -X POST -d "{\"embeds\":[{\"title\":\"%APPVEYOR_PROJECT_NAME% (%VERSION_NAME%-%GAME%)\",\"description\":\"Build FAILED! Ouch.\",\"color\":13632027,\"author\":{\"name\":\"Committed by %APPVEYOR_ACCOUNT_NAME%\",\"url\":\"https://github.com/%APPVEYOR_ACCOUNT_NAME%/\"},\"fields\":[{\"name\":\"AppVeyor Build\",\"value\":\"[Here](%APPVEYOR_URL%/project/%APPVEYOR_ACCOUNT_NAME%/%APPVEYOR_PROJECT_SLUG%/builds/%APPVEYOR_BUILD_ID%)\"},{\"name\":\"GitHub Commit (%APPVEYOR_REPO_COMMIT%)\",\"value\":\"[%APPVEYOR_REPO_COMMIT%](https://github.com/%APPVEYOR_ACCOUNT_NAME%/%APPVEYOR_PROJECT_NAME%/commit/%APPVEYOR_REPO_COMMIT%) - %APPVEYOR_REPO_COMMIT_MESSAGE%%APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED%\"},{\"name\":\"GitHub Branch\",\"value\":\"[%APPVEYOR_REPO_BRANCH%](https://github.com/%APPVEYOR_ACCOUNT_NAME%/%APPVEYOR_PROJECT_NAME%/tree/%APPVEYOR_REPO_BRANCH%)\"}]}]}" %WEBHOOK_URL% + +:end \ No newline at end of file diff --git a/appveyor/on_success.cmd b/appveyor/on_success.cmd new file mode 100644 index 0000000..4454420 --- /dev/null +++ b/appveyor/on_success.cmd @@ -0,0 +1,7 @@ +if not defined WEBHOOK_URL goto end +curl -s -o nul -F "file=@MenuAPI-%VERSION_NAME%-%GAME%.zip" %WEBHOOK_URL% + +if %APPVEYOR_REPO_TAG%==true goto end +curl -H "Content-Type:application/json" -X POST -d "{\"embeds\":[{\"title\":\"%APPVEYOR_PROJECT_NAME% (%VERSION_NAME%-%GAME%)\",\"description\":\"Build passed!\",\"color\":4502298,\"author\":{\"name\":\"Committed by %APPVEYOR_ACCOUNT_NAME%\",\"url\":\"https://github.com/%APPVEYOR_ACCOUNT_NAME%/\"},\"fields\":[{\"name\":\"AppVeyor Build\",\"value\":\"[Here](%APPVEYOR_URL%/project/%APPVEYOR_ACCOUNT_NAME%/%APPVEYOR_PROJECT_SLUG%/builds/%APPVEYOR_BUILD_ID%)\"},{\"name\":\"GitHub Commit (%APPVEYOR_REPO_COMMIT%)\",\"value\":\"[%APPVEYOR_REPO_COMMIT%](https://github.com/%APPVEYOR_ACCOUNT_NAME%/%APPVEYOR_PROJECT_NAME%/commit/%APPVEYOR_REPO_COMMIT%) - %APPVEYOR_REPO_COMMIT_MESSAGE%%APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED%\"},{\"name\":\"GitHub Branch\",\"value\":\"[%APPVEYOR_REPO_BRANCH%](https://github.com/%APPVEYOR_ACCOUNT_NAME%/%APPVEYOR_PROJECT_NAME%/tree/%APPVEYOR_REPO_BRANCH%)\"}]}]}" %WEBHOOK_URL% + +:end \ No newline at end of file diff --git a/dependencies/RedM/CitizenFX.Core.dll b/dependencies/RedM/CitizenFX.Core.dll index 14b40ee..401e98f 100644 Binary files a/dependencies/RedM/CitizenFX.Core.dll and b/dependencies/RedM/CitizenFX.Core.dll differ diff --git a/dependencies/RedM/CitizenFX.Core.xml b/dependencies/RedM/CitizenFX.Core.xml new file mode 100644 index 0000000..734fd34 --- /dev/null +++ b/dependencies/RedM/CitizenFX.Core.xml @@ -0,0 +1,12331 @@ + + + + CitizenFX.Core + + + + + An event containing callbacks to attempt to schedule on every game tick. + A callback will only be rescheduled once the associated task completes. + + + + + Returns a task that will delay scheduling of the current interval function by the passed amount of time. + + + await Delay(500); + + The amount of time by which to delay scheduling this interval function. + An awaitable task. + + + + Provides fast reading and writing of generic structures to a memory location using IL emitted functions. + + + + + Retrieve a pointer to the passed generic structure type. This is achieved by emitting a to retrieve a pointer to the structure. + + + + A pointer to the provided structure in memory. + + + + + Loads the generic value type from a pointer. This is achieved by emitting a that returns the value in the memory location as a . + The equivalent non-generic C# code: + + unsafe MyStruct ReadFromPointer(byte* pointer) + { + return *(MyStruct*)pointer; + } + + + Any value/structure type + Unsafe pointer to memory to load the value from + The newly loaded value + + + + Writes the generic value type to the location specified by a pointer. This is achieved by emitting a that copies the value from the referenced structure into the specified memory location. + There is no exact equivalent possible in C#, the closest possible (generates the same IL) is the following code: + + unsafe void WriteToPointer(ref SharedHeader dest, ref SharedHeader src) + { + dest = src; + } + + + + + + + + + Retrieve the cached size of a structure + + + + Caches the size by type + + + + + Reads a number of elements from a memory location into the provided buffer starting at the specified index. + + The structure type + The destination buffer. + The source memory location. + The start index within . + The number of elements to read. + + + + Writes a number of elements to a memory location from the provided buffer starting at the specified index. + + The structure type + The destination memory location. + The source buffer. + The start index within . + The number of elements to write. + + + + Emits optimized IL for the reading and writing of structures to/from memory. + For a 32-byte structure with 1 million iterations: + The method performs approx. 20x faster than + (8ms vs 160ms), and about 1.6x slower than the non-generic equivalent (8ms vs 5ms) + The method performs approx. 8x faster than + (4ms vs 34ms). + + + + + + Delegate that returns a pointer to the provided structure. Use with extreme caution. + + + + + + + Delegate for loading a structure from the specified memory address + + + + + + + Delegate for writing a structure to the specified memory address + + + + + + + The delegate for the generated IL to retrieve a pointer to the structure + + + + + The delegate for the generated IL to retrieve a structure from a specified memory address. + + + + + The delegate for the generated IL to store a structure at the specified memory address. + + + + + Cached size of T as determined by . + + + + + Performs once of type compatibility check. + + Thrown if the type T is incompatible + + + + The value for which all absolute numbers smaller than are considered equal to zero. + + + + + A value specifying the approximation of π which is 180 degrees. + + + + + A value specifying the approximation of 2π which is 360 degrees. + + + + + A value specifying the approximation of π/2 which is 90 degrees. + + + + + A value specifying the approximation of π/4 which is 45 degrees. + + + + + Checks if a and b are almost equals, taking into account the magnitude of floating point numbers (unlike method). See Remarks. + See remarks. + + The left value to compare. + The right value to compare. + true if a almost equal to b, false otherwise + + The code is using the technique described by Bruce Dawson in + Comparing Floating point numbers 2012 edition. + + + + + Determines whether the specified value is close to zero (0.0f). + + The floating value. + true if the specified value is close to zero (0.0f); otherwise, false. + + + + Determines whether the specified value is close to one (1.0f). + + The floating value. + true if the specified value is close to one (1.0f); otherwise, false. + + + + Checks if a - b are almost equals within a float epsilon. + + The left value to compare. + The right value to compare. + Epsilon value + true if a almost equal to b within a float epsilon, false otherwise + + + + Converts revolutions to degrees. + + The value to convert. + The converted value. + + + + Converts revolutions to radians. + + The value to convert. + The converted value. + + + + Converts revolutions to gradians. + + The value to convert. + The converted value. + + + + Converts degrees to revolutions. + + The value to convert. + The converted value. + + + + Converts degrees to radians. + + The value to convert. + The converted value. + + + + Converts radians to revolutions. + + The value to convert. + The converted value. + + + + Converts radians to gradians. + + The value to convert. + The converted value. + + + + Converts gradians to revolutions. + + The value to convert. + The converted value. + + + + Converts gradians to degrees. + + The value to convert. + The converted value. + + + + Converts gradians to radians. + + The value to convert. + The converted value. + + + + Converts radians to degrees. + + The value to convert. + The converted value. + + + + Clamps the specified value. + + The value. + The min. + The max. + The result of clamping a value between min and max + + + + Clamps the specified value. + + The value. + The min. + The max. + The result of clamping a value between min and max + + + + Interpolates between two values using a linear function by a given amount. + + + See http://www.encyclopediaofmath.org/index.php/Linear_interpolation and + http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ + + Value to interpolate from. + Value to interpolate to. + Interpolation amount. + The result of linear interpolation of values based on the amount. + + + + Interpolates between two values using a linear function by a given amount. + + + See http://www.encyclopediaofmath.org/index.php/Linear_interpolation and + http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ + + Value to interpolate from. + Value to interpolate to. + Interpolation amount. + The result of linear interpolation of values based on the amount. + + + + Interpolates between two values using a linear function by a given amount. + + + See http://www.encyclopediaofmath.org/index.php/Linear_interpolation and + http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ + + Value to interpolate from. + Value to interpolate to. + Interpolation amount. + The result of linear interpolation of values based on the amount. + + + + Performs smooth (cubic Hermite) interpolation between 0 and 1. + + + See https://en.wikipedia.org/wiki/Smoothstep + + Value between 0 and 1 indicating interpolation amount. + + + + Performs a smooth(er) interpolation between 0 and 1 with 1st and 2nd order derivatives of zero at endpoints. + + + See https://en.wikipedia.org/wiki/Smoothstep + + Value between 0 and 1 indicating interpolation amount. + + + + Calculates the modulo of the specified value. + + The value. + The modulo. + The result of the modulo applied to value + + + + Calculates the modulo 2*PI of the specified value. + + The value. + The result of the modulo applied to value + + + + Wraps the specified value into a range [min, max] + + The value to wrap. + The min. + The max. + Result of the wrapping. + Is thrown when is greater than . + + + + Wraps the specified value into a range [min, max[ + + The value. + The min. + The max. + Result of the wrapping. + Is thrown when is greater than . + + + + Gauss function. + + Curve amplitude. + Position X. + Position Y + Radius X. + Radius Y. + Curve sigma X. + Curve sigma Y. + The result of Gaussian function. + + + + Gauss function. + + Curve amplitude. + Position X. + Position Y + Radius X. + Radius Y. + Curve sigma X. + Curve sigma Y. + The result of Gaussian function. + + + + Represents a 4x4 mathematical matrix. + + + + + A with all of its components set to zero. + + + + + The identity . + + + + + Value at row 1 column 1 of the matrix. + + + + + Value at row 1 column 2 of the matrix. + + + + + Value at row 1 column 3 of the matrix. + + + + + Value at row 1 column 4 of the matrix. + + + + + Value at row 2 column 1 of the matrix. + + + + + Value at row 2 column 2 of the matrix. + + + + + Value at row 2 column 3 of the matrix. + + + + + Value at row 2 column 4 of the matrix. + + + + + Value at row 3 column 1 of the matrix. + + + + + Value at row 3 column 2 of the matrix. + + + + + Value at row 3 column 3 of the matrix. + + + + + Value at row 3 column 4 of the matrix. + + + + + Value at row 4 column 1 of the matrix. + + + + + Value at row 4 column 2 of the matrix. + + + + + Value at row 4 column 3 of the matrix. + + + + + Value at row 4 column 4 of the matrix. + + + + + Gets or sets the up of the matrix; that is M21, M22, and M23. + + + + + Gets or sets the down of the matrix; that is -M21, -M22, and -M23. + + + + + Gets or sets the right of the matrix; that is M11, M12, and M13. + + + + + Gets or sets the left of the matrix; that is -M11, -M12, and -M13. + + + + + Gets or sets the forward of the matrix; that is -M31, -M32, and -M33. + + + + + Gets or sets the backward of the matrix; that is M31, M32, and M33. + + + + + Initializes a new instance of the struct. + + The value that will be assigned to all components. + + + + Initializes a new instance of the struct. + + The value to assign at row 1 column 1 of the matrix. + The value to assign at row 1 column 2 of the matrix. + The value to assign at row 1 column 3 of the matrix. + The value to assign at row 1 column 4 of the matrix. + The value to assign at row 2 column 1 of the matrix. + The value to assign at row 2 column 2 of the matrix. + The value to assign at row 2 column 3 of the matrix. + The value to assign at row 2 column 4 of the matrix. + The value to assign at row 3 column 1 of the matrix. + The value to assign at row 3 column 2 of the matrix. + The value to assign at row 3 column 3 of the matrix. + The value to assign at row 3 column 4 of the matrix. + The value to assign at row 4 column 1 of the matrix. + The value to assign at row 4 column 2 of the matrix. + The value to assign at row 4 column 3 of the matrix. + The value to assign at row 4 column 4 of the matrix. + + + + Initializes a new instance of the struct. + + The values to assign to the components of the matrix. This must be an array with sixteen elements. + Thrown when is null. + Thrown when contains more or less than sixteen elements. + + + + Gets or sets the first row in the matrix; that is M11, M12, M13, and M14. + + + + + Gets or sets the second row in the matrix; that is M21, M22, M23, and M24. + + + + + Gets or sets the third row in the matrix; that is M31, M32, M33, and M34. + + + + + Gets or sets the fourth row in the matrix; that is M41, M42, M43, and M44. + + + + + Gets or sets the first column in the matrix; that is M11, M21, M31, and M41. + + + + + Gets or sets the second column in the matrix; that is M12, M22, M32, and M42. + + + + + Gets or sets the third column in the matrix; that is M13, M23, M33, and M43. + + + + + Gets or sets the fourth column in the matrix; that is M14, M24, M34, and M44. + + + + + Gets or sets the translation of the matrix; that is M41, M42, and M43. + + + + + Gets or sets the scale of the matrix; that is M11, M22, and M33. + + + + + Gets a value indicating whether this instance is an identity matrix. + + + true if this instance is an identity matrix; otherwise, false. + + + + + Gets or sets the component at the specified index. + + The value of the matrix component, depending on the index. + The zero-based index of the component to access. + The value of the component at the specified index. + Thrown when the is out of the range [0, 15]. + + + + Gets or sets the component at the specified index. + + The value of the matrix component, depending on the index. + The row of the matrix to access. + The column of the matrix to access. + The value of the component at the specified index. + Thrown when the or is out of the range [0, 3]. + + + + Calculates the determinant of the matrix. + + The determinant of the matrix. + + + + Inverts the matrix. + + + + + Transposes the matrix. + + + + + Orthogonalizes the specified matrix. + + + Orthogonalization is the process of making all rows orthogonal to each other. This + means that any given row in the matrix will be orthogonal to any other given row in the + matrix. + Because this method uses the modified Gram-Schmidt process, the resulting matrix + tends to be numerically unstable. The numeric stability decreases according to the rows + so that the first row is the most stable and the last row is the least stable. + This operation is performed on the rows of the matrix rather than the columns. + If you wish for this operation to be performed on the columns, first transpose the + input and than transpose the output. + + + + + Orthonormalizes the specified matrix. + + + Orthonormalization is the process of making all rows and columns orthogonal to each + other and making all rows and columns of unit length. This means that any given row will + be orthogonal to any other given row and any given column will be orthogonal to any other + given column. Any given row will not be orthogonal to any given column. Every row and every + column will be of unit length. + Because this method uses the modified Gram-Schmidt process, the resulting matrix + tends to be numerically unstable. The numeric stability decreases according to the rows + so that the first row is the most stable and the last row is the least stable. + This operation is performed on the rows of the matrix rather than the columns. + If you wish for this operation to be performed on the columns, first transpose the + input and than transpose the output. + + + + + Decomposes a matrix into an orthonormalized matrix Q and a right triangular matrix R. + + When the method completes, contains the orthonormalized matrix of the decomposition. + When the method completes, contains the right triangular matrix of the decomposition. + + + + Decomposes a matrix into a lower triangular matrix L and an orthonormalized matrix Q. + + When the method completes, contains the lower triangular matrix of the decomposition. + When the method completes, contains the orthonormalized matrix of the decomposition. + + + + Decomposes a matrix into a scale, rotation, and translation. + + When the method completes, contains the scaling component of the decomposed matrix. + When the method completes, contains the rotation component of the decomposed matrix. + When the method completes, contains the translation component of the decomposed matrix. + + This method is designed to decompose an SRT transformation matrix only. + + + + + Decomposes a uniform scale matrix into a scale, rotation, and translation. + A uniform scale matrix has the same scale in every axis. + + When the method completes, contains the scaling component of the decomposed matrix. + When the method completes, contains the rotation component of the decomposed matrix. + When the method completes, contains the translation component of the decomposed matrix. + + This method is designed to decompose only an SRT transformation matrix that has the same scale in every axis. + + + + + Exchanges two rows in the matrix. + + The first row to exchange. This is an index of the row starting at zero. + The second row to exchange. This is an index of the row starting at zero. + + + + Exchanges two columns in the matrix. + + The first column to exchange. This is an index of the column starting at zero. + The second column to exchange. This is an index of the column starting at zero. + + + + Creates an array containing the elements of the matrix. + + A sixteen-element array containing the components of the matrix. + + + + Determines the sum of two matrices. + + The first matrix to add. + The second matrix to add. + When the method completes, contains the sum of the two matrices. + + + + Determines the sum of two matrices. + + The first matrix to add. + The second matrix to add. + The sum of the two matrices. + + + + Determines the difference between two matrices. + + The first matrix to subtract. + The second matrix to subtract. + When the method completes, contains the difference between the two matrices. + + + + Determines the difference between two matrices. + + The first matrix to subtract. + The second matrix to subtract. + The difference between the two matrices. + + + + Scales a matrix by the given value. + + The matrix to scale. + The amount by which to scale. + When the method completes, contains the scaled matrix. + + + + Scales a matrix by the given value. + + The matrix to scale. + The amount by which to scale. + The scaled matrix. + + + + Determines the product of two matrices. + + The first matrix to multiply. + The second matrix to multiply. + The product of the two matrices. + + + + Determines the product of two matrices. + + The first matrix to multiply. + The second matrix to multiply. + The product of the two matrices. + + + + Scales a matrix by the given value. + + The matrix to scale. + The amount by which to scale. + When the method completes, contains the scaled matrix. + + + + Scales a matrix by the given value. + + The matrix to scale. + The amount by which to scale. + The scaled matrix. + + + + Determines the quotient of two matrices. + + The first matrix to divide. + The second matrix to divide. + When the method completes, contains the quotient of the two matrices. + + + + Determines the quotient of two matrices. + + The first matrix to divide. + The second matrix to divide. + The quotient of the two matrices. + + + + Performs the exponential operation on a matrix. + + The matrix to perform the operation on. + The exponent to raise the matrix to. + When the method completes, contains the exponential matrix. + Thrown when the is negative. + + + + Performs the exponential operation on a matrix. + + The matrix to perform the operation on. + The exponent to raise the matrix to. + The exponential matrix. + Thrown when the is negative. + + + + Negates a matrix. + + The matrix to be negated. + When the method completes, contains the negated matrix. + + + + Negates a matrix. + + The matrix to be negated. + The negated matrix. + + + + Performs a linear interpolation between two matrices. + + Start matrix. + End matrix. + Value between 0 and 1 indicating the weight of . + When the method completes, contains the linear interpolation of the two matrices. + + Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + + + + + Performs a linear interpolation between two matrices. + + Start matrix. + End matrix. + Value between 0 and 1 indicating the weight of . + The linear interpolation of the two matrices. + + Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + + + + + Performs a cubic interpolation between two matrices. + + Start matrix. + End matrix. + Value between 0 and 1 indicating the weight of . + When the method completes, contains the cubic interpolation of the two matrices. + + + + Performs a cubic interpolation between two matrices. + + Start matrix. + End matrix. + Value between 0 and 1 indicating the weight of . + The cubic interpolation of the two matrices. + + + + Calculates the transpose of the specified matrix. + + The matrix whose transpose is to be calculated. + When the method completes, contains the transpose of the specified matrix. + + + + Calculates the transpose of the specified matrix. + + The matrix whose transpose is to be calculated. + When the method completes, contains the transpose of the specified matrix. + + + + Calculates the transpose of the specified matrix. + + The matrix whose transpose is to be calculated. + The transpose of the specified matrix. + + + + Calculates the inverse of the specified matrix. + + The matrix whose inverse is to be calculated. + When the method completes, contains the inverse of the specified matrix. + + + + Calculates the inverse of the specified matrix. + + The matrix whose inverse is to be calculated. + The inverse of the specified matrix. + + + + Orthogonalizes the specified matrix. + + The matrix to orthogonalize. + When the method completes, contains the orthogonalized matrix. + + Orthogonalization is the process of making all rows orthogonal to each other. This + means that any given row in the matrix will be orthogonal to any other given row in the + matrix. + Because this method uses the modified Gram-Schmidt process, the resulting matrix + tends to be numerically unstable. The numeric stability decreases according to the rows + so that the first row is the most stable and the last row is the least stable. + This operation is performed on the rows of the matrix rather than the columns. + If you wish for this operation to be performed on the columns, first transpose the + input and than transpose the output. + + + + + Orthogonalizes the specified matrix. + + The matrix to orthogonalize. + The orthogonalized matrix. + + Orthogonalization is the process of making all rows orthogonal to each other. This + means that any given row in the matrix will be orthogonal to any other given row in the + matrix. + Because this method uses the modified Gram-Schmidt process, the resulting matrix + tends to be numerically unstable. The numeric stability decreases according to the rows + so that the first row is the most stable and the last row is the least stable. + This operation is performed on the rows of the matrix rather than the columns. + If you wish for this operation to be performed on the columns, first transpose the + input and than transpose the output. + + + + + Orthonormalizes the specified matrix. + + The matrix to orthonormalize. + When the method completes, contains the orthonormalized matrix. + + Orthonormalization is the process of making all rows and columns orthogonal to each + other and making all rows and columns of unit length. This means that any given row will + be orthogonal to any other given row and any given column will be orthogonal to any other + given column. Any given row will not be orthogonal to any given column. Every row and every + column will be of unit length. + Because this method uses the modified Gram-Schmidt process, the resulting matrix + tends to be numerically unstable. The numeric stability decreases according to the rows + so that the first row is the most stable and the last row is the least stable. + This operation is performed on the rows of the matrix rather than the columns. + If you wish for this operation to be performed on the columns, first transpose the + input and than transpose the output. + + + + + Orthonormalizes the specified matrix. + + The matrix to orthonormalize. + The orthonormalized matrix. + + Orthonormalization is the process of making all rows and columns orthogonal to each + other and making all rows and columns of unit length. This means that any given row will + be orthogonal to any other given row and any given column will be orthogonal to any other + given column. Any given row will not be orthogonal to any given column. Every row and every + column will be of unit length. + Because this method uses the modified Gram-Schmidt process, the resulting matrix + tends to be numerically unstable. The numeric stability decreases according to the rows + so that the first row is the most stable and the last row is the least stable. + This operation is performed on the rows of the matrix rather than the columns. + If you wish for this operation to be performed on the columns, first transpose the + input and than transpose the output. + + + + + Brings the matrix into upper triangular form using elementary row operations. + + The matrix to put into upper triangular form. + When the method completes, contains the upper triangular matrix. + + If the matrix is not invertible (i.e. its determinant is zero) than the result of this + method may produce Single.Nan and Single.Inf values. When the matrix represents a system + of linear equations, than this often means that either no solution exists or an infinite + number of solutions exist. + + + + + Brings the matrix into upper triangular form using elementary row operations. + + The matrix to put into upper triangular form. + The upper triangular matrix. + + If the matrix is not invertible (i.e. its determinant is zero) than the result of this + method may produce Single.Nan and Single.Inf values. When the matrix represents a system + of linear equations, than this often means that either no solution exists or an infinite + number of solutions exist. + + + + + Brings the matrix into lower triangular form using elementary row operations. + + The matrix to put into lower triangular form. + When the method completes, contains the lower triangular matrix. + + If the matrix is not invertible (i.e. its determinant is zero) than the result of this + method may produce Single.Nan and Single.Inf values. When the matrix represents a system + of linear equations, than this often means that either no solution exists or an infinite + number of solutions exist. + + + + + Brings the matrix into lower triangular form using elementary row operations. + + The matrix to put into lower triangular form. + The lower triangular matrix. + + If the matrix is not invertible (i.e. its determinant is zero) than the result of this + method may produce Single.Nan and Single.Inf values. When the matrix represents a system + of linear equations, than this often means that either no solution exists or an infinite + number of solutions exist. + + + + + Brings the matrix into row echelon form using elementary row operations; + + The matrix to put into row echelon form. + When the method completes, contains the row echelon form of the matrix. + + + + Brings the matrix into row echelon form using elementary row operations; + + The matrix to put into row echelon form. + When the method completes, contains the row echelon form of the matrix. + + + + Brings the matrix into reduced row echelon form using elementary row operations. + + The matrix to put into reduced row echelon form. + The fifth column of the matrix. + When the method completes, contains the resultant matrix after the operation. + When the method completes, contains the resultant fifth column of the matrix. + + The fifth column is often called the augmented part of the matrix. This is because the fifth + column is really just an extension of the matrix so that there is a place to put all of the + non-zero components after the operation is complete. + Often times the resultant matrix will the identity matrix or a matrix similar to the identity + matrix. Sometimes, however, that is not possible and numbers other than zero and one may appear. + This method can be used to solve systems of linear equations. Upon completion of this method, + the will contain the solution for the system. It is up to the user + to analyze both the input and the result to determine if a solution really exists. + + + + + Creates a left-handed spherical billboard that rotates around a specified object position. + + The position of the object around which the billboard will rotate. + The position of the camera. + The up vector of the camera. + The forward vector of the camera. + When the method completes, contains the created billboard matrix. + + + + Creates a left-handed spherical billboard that rotates around a specified object position. + + The position of the object around which the billboard will rotate. + The position of the camera. + The up vector of the camera. + The forward vector of the camera. + The created billboard matrix. + + + + Creates a right-handed spherical billboard that rotates around a specified object position. + + The position of the object around which the billboard will rotate. + The position of the camera. + The up vector of the camera. + The forward vector of the camera. + When the method completes, contains the created billboard matrix. + + + + Creates a right-handed spherical billboard that rotates around a specified object position. + + The position of the object around which the billboard will rotate. + The position of the camera. + The up vector of the camera. + The forward vector of the camera. + The created billboard matrix. + + + + Creates a left-handed, look-at matrix. + + The position of the viewer's eye. + The camera look-at target. + The camera's up vector. + When the method completes, contains the created look-at matrix. + + + + Creates a left-handed, look-at matrix. + + The position of the viewer's eye. + The camera look-at target. + The camera's up vector. + The created look-at matrix. + + + + Creates a right-handed, look-at matrix. + + The position of the viewer's eye. + The camera look-at target. + The camera's up vector. + When the method completes, contains the created look-at matrix. + + + + Creates a right-handed, look-at matrix. + + The position of the viewer's eye. + The camera look-at target. + The camera's up vector. + The created look-at matrix. + + + + Creates a left-handed, orthographic projection matrix. + + Width of the viewing volume. + Height of the viewing volume. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + When the method completes, contains the created projection matrix. + + + + Creates a left-handed, orthographic projection matrix. + + Width of the viewing volume. + Height of the viewing volume. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + The created projection matrix. + + + + Creates a right-handed, orthographic projection matrix. + + Width of the viewing volume. + Height of the viewing volume. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + When the method completes, contains the created projection matrix. + + + + Creates a right-handed, orthographic projection matrix. + + Width of the viewing volume. + Height of the viewing volume. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + The created projection matrix. + + + + Creates a left-handed, customized orthographic projection matrix. + + Minimum x-value of the viewing volume. + Maximum x-value of the viewing volume. + Minimum y-value of the viewing volume. + Maximum y-value of the viewing volume. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + When the method completes, contains the created projection matrix. + + + + Creates a left-handed, customized orthographic projection matrix. + + Minimum x-value of the viewing volume. + Maximum x-value of the viewing volume. + Minimum y-value of the viewing volume. + Maximum y-value of the viewing volume. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + The created projection matrix. + + + + Creates a right-handed, customized orthographic projection matrix. + + Minimum x-value of the viewing volume. + Maximum x-value of the viewing volume. + Minimum y-value of the viewing volume. + Maximum y-value of the viewing volume. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + When the method completes, contains the created projection matrix. + + + + Creates a right-handed, customized orthographic projection matrix. + + Minimum x-value of the viewing volume. + Maximum x-value of the viewing volume. + Minimum y-value of the viewing volume. + Maximum y-value of the viewing volume. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + The created projection matrix. + + + + Creates a left-handed, perspective projection matrix. + + Width of the viewing volume. + Height of the viewing volume. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + When the method completes, contains the created projection matrix. + + + + Creates a left-handed, perspective projection matrix. + + Width of the viewing volume. + Height of the viewing volume. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + The created projection matrix. + + + + Creates a right-handed, perspective projection matrix. + + Width of the viewing volume. + Height of the viewing volume. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + When the method completes, contains the created projection matrix. + + + + Creates a right-handed, perspective projection matrix. + + Width of the viewing volume. + Height of the viewing volume. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + The created projection matrix. + + + + Creates a left-handed, perspective projection matrix based on a field of view. + + Field of view in the y direction, in radians. + Aspect ratio, defined as view space width divided by height. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + When the method completes, contains the created projection matrix. + + + + Creates a left-handed, perspective projection matrix based on a field of view. + + Field of view in the y direction, in radians. + Aspect ratio, defined as view space width divided by height. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + The created projection matrix. + + + + Creates a right-handed, perspective projection matrix based on a field of view. + + Field of view in the y direction, in radians. + Aspect ratio, defined as view space width divided by height. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + When the method completes, contains the created projection matrix. + + + + Creates a right-handed, perspective projection matrix based on a field of view. + + Field of view in the y direction, in radians. + Aspect ratio, defined as view space width divided by height. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + The created projection matrix. + + + + Creates a left-handed, customized perspective projection matrix. + + Minimum x-value of the viewing volume. + Maximum x-value of the viewing volume. + Minimum y-value of the viewing volume. + Maximum y-value of the viewing volume. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + When the method completes, contains the created projection matrix. + + + + Creates a left-handed, customized perspective projection matrix. + + Minimum x-value of the viewing volume. + Maximum x-value of the viewing volume. + Minimum y-value of the viewing volume. + Maximum y-value of the viewing volume. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + The created projection matrix. + + + + Creates a right-handed, customized perspective projection matrix. + + Minimum x-value of the viewing volume. + Maximum x-value of the viewing volume. + Minimum y-value of the viewing volume. + Maximum y-value of the viewing volume. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + When the method completes, contains the created projection matrix. + + + + Creates a right-handed, customized perspective projection matrix. + + Minimum x-value of the viewing volume. + Maximum x-value of the viewing volume. + Minimum y-value of the viewing volume. + Maximum y-value of the viewing volume. + Minimum z-value of the viewing volume. + Maximum z-value of the viewing volume. + The created projection matrix. + + + + Creates a matrix that scales along the x-axis, y-axis, and y-axis. + + Scaling factor for all three axes. + When the method completes, contains the created scaling matrix. + + + + Creates a matrix that scales along the x-axis, y-axis, and y-axis. + + Scaling factor for all three axes. + The created scaling matrix. + + + + Creates a matrix that scales along the x-axis, y-axis, and y-axis. + + Scaling factor that is applied along the x-axis. + Scaling factor that is applied along the y-axis. + Scaling factor that is applied along the z-axis. + When the method completes, contains the created scaling matrix. + + + + Creates a matrix that scales along the x-axis, y-axis, and y-axis. + + Scaling factor that is applied along the x-axis. + Scaling factor that is applied along the y-axis. + Scaling factor that is applied along the z-axis. + The created scaling matrix. + + + + Creates a matrix that uniformly scales along all three axis. + + The uniform scale that is applied along all axis. + When the method completes, contains the created scaling matrix. + + + + Creates a matrix that uniformly scales along all three axis. + + The uniform scale that is applied along all axis. + The created scaling matrix. + + + + Creates a matrix that rotates around the x-axis. + + Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + When the method completes, contains the created rotation matrix. + + + + Creates a matrix that rotates around the x-axis. + + Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + The created rotation matrix. + + + + Creates a matrix that rotates around the y-axis. + + Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + When the method completes, contains the created rotation matrix. + + + + Creates a matrix that rotates around the y-axis. + + Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + The created rotation matrix. + + + + Creates a matrix that rotates around the z-axis. + + Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + When the method completes, contains the created rotation matrix. + + + + Creates a matrix that rotates around the z-axis. + + Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + The created rotation matrix. + + + + Creates a matrix that rotates around an arbitrary axis. + + The axis around which to rotate. This parameter is assumed to be normalized. + Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + When the method completes, contains the created rotation matrix. + + + + Creates a matrix that rotates around an arbitrary axis. + + The axis around which to rotate. This parameter is assumed to be normalized. + Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + The created rotation matrix. + + + + Creates a rotation matrix from a quaternion. + + The quaternion to use to build the matrix. + The created rotation matrix. + + + + Creates a rotation matrix from a quaternion. + + The quaternion to use to build the matrix. + The created rotation matrix. + + + + Creates a rotation matrix with a specified yaw, pitch, and roll. + + Yaw around the y-axis, in radians. + Pitch around the x-axis, in radians. + Roll around the z-axis, in radians. + When the method completes, contains the created rotation matrix. + + + + Creates a rotation matrix with a specified yaw, pitch, and roll. + + Yaw around the y-axis, in radians. + Pitch around the x-axis, in radians. + Roll around the z-axis, in radians. + The created rotation matrix. + + + + Creates a translation matrix using the specified offsets. + + The offset for all three coordinate planes. + When the method completes, contains the created translation matrix. + + + + Creates a translation matrix using the specified offsets. + + The offset for all three coordinate planes. + The created translation matrix. + + + + Creates a translation matrix using the specified offsets. + + X-coordinate offset. + Y-coordinate offset. + Z-coordinate offset. + When the method completes, contains the created translation matrix. + + + + Creates a translation matrix using the specified offsets. + + X-coordinate offset. + Y-coordinate offset. + Z-coordinate offset. + The created translation matrix. + + + + Creates a skew/shear matrix by means of a translation vector, a rotation vector, and a rotation angle. + shearing is performed in the direction of translation vector, where translation vector and rotation vector define the shearing plane. + The effect is such that the skewed rotation vector has the specified angle with rotation itself. + + The rotation angle. + The rotation vector + The translation vector + Contains the created skew/shear matrix. + + + + Creates a 3D affine transformation matrix. + + Scaling factor. + The rotation of the transformation. + The translation factor of the transformation. + When the method completes, contains the created affine transformation matrix. + + + + Creates a 3D affine transformation matrix. + + Scaling factor. + The rotation of the transformation. + The translation factor of the transformation. + The created affine transformation matrix. + + + + Creates a 3D affine transformation matrix. + + Scaling factor. + The center of the rotation. + The rotation of the transformation. + The translation factor of the transformation. + When the method completes, contains the created affine transformation matrix. + + + + Creates a 3D affine transformation matrix. + + Scaling factor. + The center of the rotation. + The rotation of the transformation. + The translation factor of the transformation. + The created affine transformation matrix. + + + + Creates a 2D affine transformation matrix. + + Scaling factor. + The rotation of the transformation. + The translation factor of the transformation. + When the method completes, contains the created affine transformation matrix. + + + + Creates a 2D affine transformation matrix. + + Scaling factor. + The rotation of the transformation. + The translation factor of the transformation. + The created affine transformation matrix. + + + + Creates a 2D affine transformation matrix. + + Scaling factor. + The center of the rotation. + The rotation of the transformation. + The translation factor of the transformation. + When the method completes, contains the created affine transformation matrix. + + + + Creates a 2D affine transformation matrix. + + Scaling factor. + The center of the rotation. + The rotation of the transformation. + The translation factor of the transformation. + The created affine transformation matrix. + + + + Creates a transformation matrix. + + Center point of the scaling operation. + Scaling rotation amount. + Scaling factor. + The center of the rotation. + The rotation of the transformation. + The translation factor of the transformation. + When the method completes, contains the created transformation matrix. + + + + Creates a transformation matrix. + + Center point of the scaling operation. + Scaling rotation amount. + Scaling factor. + The center of the rotation. + The rotation of the transformation. + The translation factor of the transformation. + The created transformation matrix. + + + + Creates a 2D transformation matrix. + + Center point of the scaling operation. + Scaling rotation amount. + Scaling factor. + The center of the rotation. + The rotation of the transformation. + The translation factor of the transformation. + When the method completes, contains the created transformation matrix. + + + + Creates a 2D transformation matrix. + + Center point of the scaling operation. + Scaling rotation amount. + Scaling factor. + The center of the rotation. + The rotation of the transformation. + The translation factor of the transformation. + The created transformation matrix. + + + + Adds two matrices. + + The first matrix to add. + The second matrix to add. + The sum of the two matrices. + + + + Assert a matrix (return it unchanged). + + The matrix to assert (unchanged). + The asserted (unchanged) matrix. + + + + Subtracts two matrices. + + The first matrix to subtract. + The second matrix to subtract. + The difference between the two matrices. + + + + Negates a matrix. + + The matrix to negate. + The negated matrix. + + + + Scales a matrix by a given value. + + The matrix to scale. + The amount by which to scale. + The scaled matrix. + + + + Scales a matrix by a given value. + + The matrix to scale. + The amount by which to scale. + The scaled matrix. + + + + Multiplies two matrices. + + The first matrix to multiply. + The second matrix to multiply. + The product of the two matrices. + + + + Scales a matrix by a given value. + + The matrix to scale. + The amount by which to scale. + The scaled matrix. + + + + Divides two matrices. + + The first matrix to divide. + The second matrix to divide. + The quotient of the two matrices. + + + + Tests for equality between two objects. + + The first value to compare. + The second value to compare. + true if has the same value as ; otherwise, false. + + + + Tests for inequality between two objects. + + The first value to compare. + The second value to compare. + true if has a different value than ; otherwise, false. + + + + Returns a that represents this instance. + + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format provider. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + The format provider. + + A that represents this instance. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Represents a 3x3 Matrix ( contains only Scale and Rotation ). + + + + + A with all of its components set to zero. + + + + + The identity . + + + + + Value at row 1 column 1 of the Matrix3x3. + + + + + Value at row 1 column 2 of the Matrix3x3. + + + + + Value at row 1 column 3 of the Matrix3x3. + + + + + Value at row 2 column 1 of the Matrix3x3. + + + + + Value at row 2 column 2 of the Matrix3x3. + + + + + Value at row 2 column 3 of the Matrix3x3. + + + + + Value at row 3 column 1 of the Matrix3x3. + + + + + Value at row 3 column 2 of the Matrix3x3. + + + + + Value at row 3 column 3 of the Matrix3x3. + + + + + Initializes a new instance of the struct. + + The value that will be assigned to all components. + + + + Initializes a new instance of the struct. + + The value to assign at row 1 column 1 of the Matrix3x3. + The value to assign at row 1 column 2 of the Matrix3x3. + The value to assign at row 1 column 3 of the Matrix3x3. + The value to assign at row 2 column 1 of the Matrix3x3. + The value to assign at row 2 column 2 of the Matrix3x3. + The value to assign at row 2 column 3 of the Matrix3x3. + The value to assign at row 3 column 1 of the Matrix3x3. + The value to assign at row 3 column 2 of the Matrix3x3. + The value to assign at row 3 column 3 of the Matrix3x3. + + + + Initializes a new instance of the struct. + + The values to assign to the components of the Matrix3x3. This must be an array with sixteen elements. + Thrown when is null. + Thrown when contains more or less than sixteen elements. + + + + Gets or sets the first row in the Matrix3x3; that is M11, M12, M13 + + + + + Gets or sets the second row in the Matrix3x3; that is M21, M22, M23 + + + + + Gets or sets the third row in the Matrix3x3; that is M31, M32, M33 + + + + + Gets or sets the first column in the Matrix3x3; that is M11, M21, M31 + + + + + Gets or sets the second column in the Matrix3x3; that is M12, M22, M32 + + + + + Gets or sets the third column in the Matrix3x3; that is M13, M23, M33 + + + + + Gets or sets the scale of the Matrix3x3; that is M11, M22, and M33. + + + + + Gets a value indicating whether this instance is an identity Matrix3x3. + + + true if this instance is an identity Matrix3x3; otherwise, false. + + + + + Gets or sets the component at the specified index. + + The value of the Matrix3x3 component, depending on the index. + The zero-based index of the component to access. + The value of the component at the specified index. + Thrown when the is out of the range [0, 15]. + + + + Gets or sets the component at the specified index. + + The value of the Matrix3x3 component, depending on the index. + The row of the Matrix3x3 to access. + The column of the Matrix3x3 to access. + The value of the component at the specified index. + Thrown when the or is out of the range [0, 3]. + + + + Calculates the determinant of the Matrix3x3. + + The determinant of the Matrix3x3. + + + + Inverts the Matrix3x3. + + + + + Transposes the Matrix3x3. + + + + + Orthogonalizes the specified Matrix3x3. + + + Orthogonalization is the process of making all rows orthogonal to each other. This + means that any given row in the Matrix3x3 will be orthogonal to any other given row in the + Matrix3x3. + Because this method uses the modified Gram-Schmidt process, the resulting Matrix3x3 + tends to be numerically unstable. The numeric stability decreases according to the rows + so that the first row is the most stable and the last row is the least stable. + This operation is performed on the rows of the Matrix3x3 rather than the columns. + If you wish for this operation to be performed on the columns, first transpose the + input and than transpose the output. + + + + + Orthonormalizes the specified Matrix3x3. + + + Orthonormalization is the process of making all rows and columns orthogonal to each + other and making all rows and columns of unit length. This means that any given row will + be orthogonal to any other given row and any given column will be orthogonal to any other + given column. Any given row will not be orthogonal to any given column. Every row and every + column will be of unit length. + Because this method uses the modified Gram-Schmidt process, the resulting Matrix3x3 + tends to be numerically unstable. The numeric stability decreases according to the rows + so that the first row is the most stable and the last row is the least stable. + This operation is performed on the rows of the Matrix3x3 rather than the columns. + If you wish for this operation to be performed on the columns, first transpose the + input and than transpose the output. + + + + + Decomposes a Matrix3x3 into an orthonormalized Matrix3x3 Q and a right triangular Matrix3x3 R. + + When the method completes, contains the orthonormalized Matrix3x3 of the decomposition. + When the method completes, contains the right triangular Matrix3x3 of the decomposition. + + + + Decomposes a Matrix3x3 into a lower triangular Matrix3x3 L and an orthonormalized Matrix3x3 Q. + + When the method completes, contains the lower triangular Matrix3x3 of the decomposition. + When the method completes, contains the orthonormalized Matrix3x3 of the decomposition. + + + + Decomposes a Matrix3x3 into a scale, rotation, and translation. + + When the method completes, contains the scaling component of the decomposed Matrix3x3. + When the method completes, contains the rotation component of the decomposed Matrix3x3. + + This method is designed to decompose an SRT transformation Matrix3x3 only. + + + + + Decomposes a uniform scale matrix into a scale, rotation, and translation. + A uniform scale matrix has the same scale in every axis. + + When the method completes, contains the scaling component of the decomposed matrix. + When the method completes, contains the rotation component of the decomposed matrix. + + This method is designed to decompose only an SRT transformation matrix that has the same scale in every axis. + + + + + Exchanges two rows in the Matrix3x3. + + The first row to exchange. This is an index of the row starting at zero. + The second row to exchange. This is an index of the row starting at zero. + + + + Exchanges two columns in the Matrix3x3. + + The first column to exchange. This is an index of the column starting at zero. + The second column to exchange. This is an index of the column starting at zero. + + + + Creates an array containing the elements of the Matrix3x3. + + A 9-element array containing the components of the Matrix3x3. + + + + Determines the sum of two matrices. + + The first Matrix3x3 to add. + The second Matrix3x3 to add. + When the method completes, contains the sum of the two matrices. + + + + Determines the sum of two matrices. + + The first Matrix3x3 to add. + The second Matrix3x3 to add. + The sum of the two matrices. + + + + Determines the difference between two matrices. + + The first Matrix3x3 to subtract. + The second Matrix3x3 to subtract. + When the method completes, contains the difference between the two matrices. + + + + Determines the difference between two matrices. + + The first Matrix3x3 to subtract. + The second Matrix3x3 to subtract. + The difference between the two matrices. + + + + Scales a Matrix3x3 by the given value. + + The Matrix3x3 to scale. + The amount by which to scale. + When the method completes, contains the scaled Matrix3x3. + + + + Scales a Matrix3x3 by the given value. + + The Matrix3x3 to scale. + The amount by which to scale. + The scaled Matrix3x3. + + + + Determines the product of two matrices. + + The first Matrix3x3 to multiply. + The second Matrix3x3 to multiply. + The product of the two matrices. + + + + Determines the product of two matrices. + + The first Matrix3x3 to multiply. + The second Matrix3x3 to multiply. + The product of the two matrices. + + + + Scales a Matrix3x3 by the given value. + + The Matrix3x3 to scale. + The amount by which to scale. + When the method completes, contains the scaled Matrix3x3. + + + + Scales a Matrix3x3 by the given value. + + The Matrix3x3 to scale. + The amount by which to scale. + The scaled Matrix3x3. + + + + Determines the quotient of two matrices. + + The first Matrix3x3 to divide. + The second Matrix3x3 to divide. + When the method completes, contains the quotient of the two matrices. + + + + Determines the quotient of two matrices. + + The first Matrix3x3 to divide. + The second Matrix3x3 to divide. + The quotient of the two matrices. + + + + Performs the exponential operation on a Matrix3x3. + + The Matrix3x3 to perform the operation on. + The exponent to raise the Matrix3x3 to. + When the method completes, contains the exponential Matrix3x3. + Thrown when the is negative. + + + + Performs the exponential operation on a Matrix3x3. + + The Matrix3x3 to perform the operation on. + The exponent to raise the Matrix3x3 to. + The exponential Matrix3x3. + Thrown when the is negative. + + + + Negates a Matrix3x3. + + The Matrix3x3 to be negated. + When the method completes, contains the negated Matrix3x3. + + + + Negates a Matrix3x3. + + The Matrix3x3 to be negated. + The negated Matrix3x3. + + + + Performs a linear interpolation between two matrices. + + Start Matrix3x3. + End Matrix3x3. + Value between 0 and 1 indicating the weight of . + When the method completes, contains the linear interpolation of the two matrices. + + Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + + + + + Performs a linear interpolation between two matrices. + + Start Matrix3x3. + End Matrix3x3. + Value between 0 and 1 indicating the weight of . + The linear interpolation of the two matrices. + + Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + + + + + Performs a cubic interpolation between two matrices. + + Start Matrix3x3. + End Matrix3x3. + Value between 0 and 1 indicating the weight of . + When the method completes, contains the cubic interpolation of the two matrices. + + + + Performs a cubic interpolation between two matrices. + + Start Matrix3x3. + End Matrix3x3. + Value between 0 and 1 indicating the weight of . + The cubic interpolation of the two matrices. + + + + Calculates the transpose of the specified Matrix3x3. + + The Matrix3x3 whose transpose is to be calculated. + When the method completes, contains the transpose of the specified Matrix3x3. + + + + Calculates the transpose of the specified Matrix3x3. + + The Matrix3x3 whose transpose is to be calculated. + When the method completes, contains the transpose of the specified Matrix3x3. + + + + Calculates the transpose of the specified Matrix3x3. + + The Matrix3x3 whose transpose is to be calculated. + The transpose of the specified Matrix3x3. + + + + Calculates the inverse of the specified Matrix3x3. + + The Matrix3x3 whose inverse is to be calculated. + When the method completes, contains the inverse of the specified Matrix3x3. + + + + Calculates the inverse of the specified Matrix3x3. + + The Matrix3x3 whose inverse is to be calculated. + The inverse of the specified Matrix3x3. + + + + Orthogonalizes the specified Matrix3x3. + + The Matrix3x3 to orthogonalize. + When the method completes, contains the orthogonalized Matrix3x3. + + Orthogonalization is the process of making all rows orthogonal to each other. This + means that any given row in the Matrix3x3 will be orthogonal to any other given row in the + Matrix3x3. + Because this method uses the modified Gram-Schmidt process, the resulting Matrix3x3 + tends to be numerically unstable. The numeric stability decreases according to the rows + so that the first row is the most stable and the last row is the least stable. + This operation is performed on the rows of the Matrix3x3 rather than the columns. + If you wish for this operation to be performed on the columns, first transpose the + input and than transpose the output. + + + + + Orthogonalizes the specified Matrix3x3. + + The Matrix3x3 to orthogonalize. + The orthogonalized Matrix3x3. + + Orthogonalization is the process of making all rows orthogonal to each other. This + means that any given row in the Matrix3x3 will be orthogonal to any other given row in the + Matrix3x3. + Because this method uses the modified Gram-Schmidt process, the resulting Matrix3x3 + tends to be numerically unstable. The numeric stability decreases according to the rows + so that the first row is the most stable and the last row is the least stable. + This operation is performed on the rows of the Matrix3x3 rather than the columns. + If you wish for this operation to be performed on the columns, first transpose the + input and than transpose the output. + + + + + Orthonormalizes the specified Matrix3x3. + + The Matrix3x3 to orthonormalize. + When the method completes, contains the orthonormalized Matrix3x3. + + Orthonormalization is the process of making all rows and columns orthogonal to each + other and making all rows and columns of unit length. This means that any given row will + be orthogonal to any other given row and any given column will be orthogonal to any other + given column. Any given row will not be orthogonal to any given column. Every row and every + column will be of unit length. + Because this method uses the modified Gram-Schmidt process, the resulting Matrix3x3 + tends to be numerically unstable. The numeric stability decreases according to the rows + so that the first row is the most stable and the last row is the least stable. + This operation is performed on the rows of the Matrix3x3 rather than the columns. + If you wish for this operation to be performed on the columns, first transpose the + input and than transpose the output. + + + + + Orthonormalizes the specified Matrix3x3. + + The Matrix3x3 to orthonormalize. + The orthonormalized Matrix3x3. + + Orthonormalization is the process of making all rows and columns orthogonal to each + other and making all rows and columns of unit length. This means that any given row will + be orthogonal to any other given row and any given column will be orthogonal to any other + given column. Any given row will not be orthogonal to any given column. Every row and every + column will be of unit length. + Because this method uses the modified Gram-Schmidt process, the resulting Matrix3x3 + tends to be numerically unstable. The numeric stability decreases according to the rows + so that the first row is the most stable and the last row is the least stable. + This operation is performed on the rows of the Matrix3x3 rather than the columns. + If you wish for this operation to be performed on the columns, first transpose the + input and than transpose the output. + + + + + Brings the Matrix3x3 into upper triangular form using elementary row operations. + + The Matrix3x3 to put into upper triangular form. + When the method completes, contains the upper triangular Matrix3x3. + + If the Matrix3x3 is not invertible (i.e. its determinant is zero) than the result of this + method may produce Single.Nan and Single.Inf values. When the Matrix3x3 represents a system + of linear equations, than this often means that either no solution exists or an infinite + number of solutions exist. + + + + + Brings the Matrix3x3 into upper triangular form using elementary row operations. + + The Matrix3x3 to put into upper triangular form. + The upper triangular Matrix3x3. + + If the Matrix3x3 is not invertible (i.e. its determinant is zero) than the result of this + method may produce Single.Nan and Single.Inf values. When the Matrix3x3 represents a system + of linear equations, than this often means that either no solution exists or an infinite + number of solutions exist. + + + + + Brings the Matrix3x3 into lower triangular form using elementary row operations. + + The Matrix3x3 to put into lower triangular form. + When the method completes, contains the lower triangular Matrix3x3. + + If the Matrix3x3 is not invertible (i.e. its determinant is zero) than the result of this + method may produce Single.Nan and Single.Inf values. When the Matrix3x3 represents a system + of linear equations, than this often means that either no solution exists or an infinite + number of solutions exist. + + + + + Brings the Matrix3x3 into lower triangular form using elementary row operations. + + The Matrix3x3 to put into lower triangular form. + The lower triangular Matrix3x3. + + If the Matrix3x3 is not invertible (i.e. its determinant is zero) than the result of this + method may produce Single.Nan and Single.Inf values. When the Matrix3x3 represents a system + of linear equations, than this often means that either no solution exists or an infinite + number of solutions exist. + + + + + Brings the Matrix3x3 into row echelon form using elementary row operations; + + The Matrix3x3 to put into row echelon form. + When the method completes, contains the row echelon form of the Matrix3x3. + + + + Brings the Matrix3x3 into row echelon form using elementary row operations; + + The Matrix3x3 to put into row echelon form. + When the method completes, contains the row echelon form of the Matrix3x3. + + + + Creates a left-handed spherical billboard that rotates around a specified object position. + + The position of the object around which the billboard will rotate. + The position of the camera. + The up vector of the camera. + The forward vector of the camera. + When the method completes, contains the created billboard Matrix3x3. + + + + Creates a left-handed spherical billboard that rotates around a specified object position. + + The position of the object around which the billboard will rotate. + The position of the camera. + The up vector of the camera. + The forward vector of the camera. + The created billboard Matrix3x3. + + + + Creates a right-handed spherical billboard that rotates around a specified object position. + + The position of the object around which the billboard will rotate. + The position of the camera. + The up vector of the camera. + The forward vector of the camera. + When the method completes, contains the created billboard Matrix3x3. + + + + Creates a right-handed spherical billboard that rotates around a specified object position. + + The position of the object around which the billboard will rotate. + The position of the camera. + The up vector of the camera. + The forward vector of the camera. + The created billboard Matrix3x3. + + + + Creates a left-handed, look-at Matrix3x3. + + The position of the viewer's eye. + The camera look-at target. + The camera's up vector. + When the method completes, contains the created look-at Matrix3x3. + + + + Creates a left-handed, look-at Matrix3x3. + + The position of the viewer's eye. + The camera look-at target. + The camera's up vector. + The created look-at Matrix3x3. + + + + Creates a right-handed, look-at Matrix3x3. + + The position of the viewer's eye. + The camera look-at target. + The camera's up vector. + When the method completes, contains the created look-at Matrix3x3. + + + + Creates a right-handed, look-at Matrix3x3. + + The position of the viewer's eye. + The camera look-at target. + The camera's up vector. + The created look-at Matrix3x3. + + + + Creates a Matrix3x3 that scales along the x-axis, y-axis, and y-axis. + + Scaling factor for all three axes. + When the method completes, contains the created scaling Matrix3x3. + + + + Creates a Matrix3x3 that scales along the x-axis, y-axis, and y-axis. + + Scaling factor for all three axes. + The created scaling Matrix3x3. + + + + Creates a Matrix3x3 that scales along the x-axis, y-axis, and y-axis. + + Scaling factor that is applied along the x-axis. + Scaling factor that is applied along the y-axis. + Scaling factor that is applied along the z-axis. + When the method completes, contains the created scaling Matrix3x3. + + + + Creates a Matrix3x3 that scales along the x-axis, y-axis, and y-axis. + + Scaling factor that is applied along the x-axis. + Scaling factor that is applied along the y-axis. + Scaling factor that is applied along the z-axis. + The created scaling Matrix3x3. + + + + Creates a Matrix3x3 that uniformly scales along all three axis. + + The uniform scale that is applied along all axis. + When the method completes, contains the created scaling Matrix3x3. + + + + Creates a Matrix3x3 that uniformly scales along all three axis. + + The uniform scale that is applied along all axis. + The created scaling Matrix3x3. + + + + Creates a Matrix3x3 that rotates around the x-axis. + + Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + When the method completes, contains the created rotation Matrix3x3. + + + + Creates a Matrix3x3 that rotates around the x-axis. + + Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + The created rotation Matrix3x3. + + + + Creates a Matrix3x3 that rotates around the y-axis. + + Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + When the method completes, contains the created rotation Matrix3x3. + + + + Creates a Matrix3x3 that rotates around the y-axis. + + Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + The created rotation Matrix3x3. + + + + Creates a Matrix3x3 that rotates around the z-axis. + + Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + When the method completes, contains the created rotation Matrix3x3. + + + + Creates a Matrix3x3 that rotates around the z-axis. + + Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + The created rotation Matrix3x3. + + + + Creates a Matrix3x3 that rotates around an arbitrary axis. + + The axis around which to rotate. This parameter is assumed to be normalized. + Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + When the method completes, contains the created rotation Matrix3x3. + + + + Creates a Matrix3x3 that rotates around an arbitrary axis. + + The axis around which to rotate. This parameter is assumed to be normalized. + Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. + The created rotation Matrix3x3. + + + + Creates a rotation Matrix3x3 from a quaternion. + + The quaternion to use to build the Matrix3x3. + The created rotation Matrix3x3. + + + + Creates a rotation Matrix3x3 from a quaternion. + + The quaternion to use to build the Matrix3x3. + The created rotation Matrix3x3. + + + + Creates a rotation Matrix3x3 with a specified yaw, pitch, and roll. + + Yaw around the y-axis, in radians. + Pitch around the x-axis, in radians. + Roll around the z-axis, in radians. + When the method completes, contains the created rotation Matrix3x3. + + + + Creates a rotation Matrix3x3 with a specified yaw, pitch, and roll. + + Yaw around the y-axis, in radians. + Pitch around the x-axis, in radians. + Roll around the z-axis, in radians. + The created rotation Matrix3x3. + + + + Adds two matrices. + + The first Matrix3x3 to add. + The second Matrix3x3 to add. + The sum of the two matrices. + + + + Assert a Matrix3x3 (return it unchanged). + + The Matrix3x3 to assert (unchanged). + The asserted (unchanged) Matrix3x3. + + + + Subtracts two matrices. + + The first Matrix3x3 to subtract. + The second Matrix3x3 to subtract. + The difference between the two matrices. + + + + Negates a Matrix3x3. + + The Matrix3x3 to negate. + The negated Matrix3x3. + + + + Scales a Matrix3x3 by a given value. + + The Matrix3x3 to scale. + The amount by which to scale. + The scaled Matrix3x3. + + + + Scales a Matrix3x3 by a given value. + + The Matrix3x3 to scale. + The amount by which to scale. + The scaled Matrix3x3. + + + + Multiplies two matrices. + + The first Matrix3x3 to multiply. + The second Matrix3x3 to multiply. + The product of the two matrices. + + + + Scales a Matrix3x3 by a given value. + + The Matrix3x3 to scale. + The amount by which to scale. + The scaled Matrix3x3. + + + + Divides two matrices. + + The first Matrix3x3 to divide. + The second Matrix3x3 to divide. + The quotient of the two matrices. + + + + Tests for equality between two objects. + + The first value to compare. + The second value to compare. + true if has the same value as ; otherwise, false. + + + + Tests for inequality between two objects. + + The first value to compare. + The second value to compare. + true if has a different value than ; otherwise, false. + + + + Convert the 3x3 Matrix to a 4x4 Matrix. + + A 4x4 Matrix with zero translation and M44=1 + + + + Convert the 4x4 Matrix to a 3x3 Matrix. + + A 3x3 Matrix + + + + Returns a that represents this instance. + + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format provider. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + The format provider. + + A that represents this instance. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Determines whether the specified are equal. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Represents a four dimensional mathematical quaternion. + + + + + A with all of its components set to zero. + + + + + A with all of its components set to one. + + + + + The identity (0, 0, 0, 1). + + + + + The X component of the quaternion. + + + + + The Y component of the quaternion. + + + + + The Z component of the quaternion. + + + + + The W component of the quaternion. + + + + + Initializes a new instance of the struct. + + The value that will be assigned to all components. + + + + Initializes a new instance of the struct. + + A vector containing the values with which to initialize the components. + + + + Initializes a new instance of the struct. + + A vector containing the values with which to initialize the X, Y, and Z components. + Initial value for the W component of the quaternion. + + + + Initializes a new instance of the struct. + + A vector containing the values with which to initialize the X and Y components. + Initial value for the Z component of the quaternion. + Initial value for the W component of the quaternion. + + + + Initializes a new instance of the struct. + + Initial value for the X component of the quaternion. + Initial value for the Y component of the quaternion. + Initial value for the Z component of the quaternion. + Initial value for the W component of the quaternion. + + + + Initializes a new instance of the struct. + + The values to assign to the X, Y, Z, and W components of the quaternion. This must be an array with four elements. + Thrown when is null. + Thrown when contains more or less than four elements. + + + + Gets a value indicating whether this instance is equivalent to the identity quaternion. + + + true if this instance is an identity quaternion; otherwise, false. + + + + + Gets a value indicting whether this instance is normalized. + + + + + Gets the angle of the quaternion. + + The quaternion's angle. + + + + Gets the axis components of the quaternion. + + The axis components of the quaternion. + + + + Gets or sets the component at the specified index. + + The value of the X, Y, Z, or W component, depending on the index. + The index of the component to access. Use 0 for the X component, 1 for the Y component, 2 for the Z component, and 3 for the W component. + The value of the component at the specified index. + Thrown when the is out of the range [0, 3]. + + + + Conjugates the quaternion. + + + + + Conjugates and renormalizes the quaternion. + + + + + Calculates the length of the quaternion. + + The length of the quaternion. + + may be preferred when only the relative length is needed + and speed is of the essence. + + + + + Calculates the squared length of the quaternion. + + The squared length of the quaternion. + + This method may be preferred to when only a relative length is needed + and speed is of the essence. + + + + + Converts the quaternion into a unit quaternion. + + + + + Creates an array containing the elements of the quaternion. + + A four-element array containing the components of the quaternion. + + + + Adds two quaternions. + + The first quaternion to add. + The second quaternion to add. + When the method completes, contains the sum of the two quaternions. + + + + Adds two quaternions. + + The first quaternion to add. + The second quaternion to add. + The sum of the two quaternions. + + + + Subtracts two quaternions. + + The first quaternion to subtract. + The second quaternion to subtract. + When the method completes, contains the difference of the two quaternions. + + + + Subtracts two quaternions. + + The first quaternion to subtract. + The second quaternion to subtract. + The difference of the two quaternions. + + + + Scales a quaternion by the given value. + + The quaternion to scale. + The amount by which to scale the quaternion. + When the method completes, contains the scaled quaternion. + + + + Scales a quaternion by the given value. + + The quaternion to scale. + The amount by which to scale the quaternion. + The scaled quaternion. + + + + Multiplies a quaternion by another. + + The first quaternion to multiply. + The second quaternion to multiply. + When the method completes, contains the multiplied quaternion. + + + + Multiplies a quaternion by another. + + The first quaternion to multiply. + The second quaternion to multiply. + The multiplied quaternion. + + + + Reverses the direction of a given quaternion. + + The quaternion to negate. + When the method completes, contains a quaternion facing in the opposite direction. + + + + Reverses the direction of a given quaternion. + + The quaternion to negate. + A quaternion facing in the opposite direction. + + + + Returns a containing the 4D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 2D triangle. + + A containing the 4D Cartesian coordinates of vertex 1 of the triangle. + A containing the 4D Cartesian coordinates of vertex 2 of the triangle. + A containing the 4D Cartesian coordinates of vertex 3 of the triangle. + Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). + Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). + When the method completes, contains a new containing the 4D Cartesian coordinates of the specified point. + + + + Returns a containing the 4D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 2D triangle. + + A containing the 4D Cartesian coordinates of vertex 1 of the triangle. + A containing the 4D Cartesian coordinates of vertex 2 of the triangle. + A containing the 4D Cartesian coordinates of vertex 3 of the triangle. + Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). + Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). + A new containing the 4D Cartesian coordinates of the specified point. + + + + Conjugates a quaternion. + + The quaternion to conjugate. + When the method completes, contains the conjugated quaternion. + + + + Conjugates a quaternion. + + The quaternion to conjugate. + The conjugated quaternion. + + + + Calculates the dot product of two quaternions. + + First source quaternion. + Second source quaternion. + When the method completes, contains the dot product of the two quaternions. + + + + Calculates the dot product of two quaternions. + + First source quaternion. + Second source quaternion. + The dot product of the two quaternions. + + + + Exponentiates a quaternion. + + The quaternion to exponentiate. + When the method completes, contains the exponentiated quaternion. + + + + Exponentiates a quaternion. + + The quaternion to exponentiate. + The exponentiated quaternion. + + + + Conjugates and renormalizes the quaternion. + + The quaternion to conjugate and renormalize. + When the method completes, contains the conjugated and renormalized quaternion. + + + + Conjugates and renormalizes the quaternion. + + The quaternion to conjugate and renormalize. + The conjugated and renormalized quaternion. + + + + Performs a linear interpolation between two quaternions. + + Start quaternion. + End quaternion. + Value between 0 and 1 indicating the weight of . + When the method completes, contains the linear interpolation of the two quaternions. + + This method performs the linear interpolation based on the following formula. + start + (end - start) * amount + Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + + + + + Performs a linear interpolation between two quaternion. + + Start quaternion. + End quaternion. + Value between 0 and 1 indicating the weight of . + The linear interpolation of the two quaternions. + + This method performs the linear interpolation based on the following formula. + start + (end - start) * amount + Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + + + + + Calculates the natural logarithm of the specified quaternion. + + The quaternion whose logarithm will be calculated. + When the method completes, contains the natural logarithm of the quaternion. + + + + Calculates the natural logarithm of the specified quaternion. + + The quaternion whose logarithm will be calculated. + The natural logarithm of the quaternion. + + + + Converts the quaternion into a unit quaternion. + + The quaternion to normalize. + When the method completes, contains the normalized quaternion. + + + + Converts the quaternion into a unit quaternion. + + The quaternion to normalize. + The normalized quaternion. + + + + Creates a quaternion given a rotation and an axis. + + The axis of rotation. + The angle of rotation. + When the method completes, contains the newly created quaternion. + + + + Creates a quaternion given a rotation and an axis. + + The axis of rotation. + The angle of rotation. + The newly created quaternion. + + + + Creates a quaternion given a rotation matrix. + + The rotation matrix. + When the method completes, contains the newly created quaternion. + + + + Creates a quaternion given a rotation matrix. + + The rotation matrix. + When the method completes, contains the newly created quaternion. + + + + Creates a left-handed, look-at quaternion. + + The position of the viewer's eye. + The camera look-at target. + The camera's up vector. + When the method completes, contains the created look-at quaternion. + + + + Creates a left-handed, look-at quaternion. + + The position of the viewer's eye. + The camera look-at target. + The camera's up vector. + The created look-at quaternion. + + + + Creates a left-handed, look-at quaternion. + + The camera's forward direction. + The camera's up vector. + When the method completes, contains the created look-at quaternion. + + + + Creates a left-handed, look-at quaternion. + + The camera's forward direction. + The camera's up vector. + The created look-at quaternion. + + + + Creates a right-handed, look-at quaternion. + + The position of the viewer's eye. + The camera look-at target. + The camera's up vector. + When the method completes, contains the created look-at quaternion. + + + + Creates a right-handed, look-at quaternion. + + The position of the viewer's eye. + The camera look-at target. + The camera's up vector. + The created look-at quaternion. + + + + Creates a right-handed, look-at quaternion. + + The camera's forward direction. + The camera's up vector. + When the method completes, contains the created look-at quaternion. + + + + Creates a right-handed, look-at quaternion. + + The camera's forward direction. + The camera's up vector. + The created look-at quaternion. + + + + Creates a left-handed spherical billboard that rotates around a specified object position. + + The position of the object around which the billboard will rotate. + The position of the camera. + The up vector of the camera. + The forward vector of the camera. + When the method completes, contains the created billboard quaternion. + + + + Creates a left-handed spherical billboard that rotates around a specified object position. + + The position of the object around which the billboard will rotate. + The position of the camera. + The up vector of the camera. + The forward vector of the camera. + The created billboard quaternion. + + + + Creates a right-handed spherical billboard that rotates around a specified object position. + + The position of the object around which the billboard will rotate. + The position of the camera. + The up vector of the camera. + The forward vector of the camera. + When the method completes, contains the created billboard quaternion. + + + + Creates a right-handed spherical billboard that rotates around a specified object position. + + The position of the object around which the billboard will rotate. + The position of the camera. + The up vector of the camera. + The forward vector of the camera. + The created billboard quaternion. + + + + Creates a quaternion given a rotation matrix. + + The rotation matrix. + The newly created quaternion. + + + + Creates a quaternion given a yaw, pitch, and roll value. + + The yaw of rotation. + The pitch of rotation. + The roll of rotation. + When the method completes, contains the newly created quaternion. + + + + Creates a quaternion given a yaw, pitch, and roll value. + + The yaw of rotation. + The pitch of rotation. + The roll of rotation. + The newly created quaternion. + + + + Interpolates between two quaternions, using spherical linear interpolation. + + Start quaternion. + End quaternion. + Value between 0 and 1 indicating the weight of . + When the method completes, contains the spherical linear interpolation of the two quaternions. + + + + Interpolates between two quaternions, using spherical linear interpolation. + + Start quaternion. + End quaternion. + Value between 0 and 1 indicating the weight of . + The spherical linear interpolation of the two quaternions. + + + + Interpolates between quaternions, using spherical quadrangle interpolation. + + First source quaternion. + Second source quaternion. + Third source quaternion. + Fourth source quaternion. + Value between 0 and 1 indicating the weight of interpolation. + When the method completes, contains the spherical quadrangle interpolation of the quaternions. + + + + Interpolates between quaternions, using spherical quadrangle interpolation. + + First source quaternion. + Second source quaternion. + Third source quaternion. + Fourth source quaternion. + Value between 0 and 1 indicating the weight of interpolation. + The spherical quadrangle interpolation of the quaternions. + + + + Sets up control points for spherical quadrangle interpolation. + + First source quaternion. + Second source quaternion. + Third source quaternion. + Fourth source quaternion. + An array of three quaternions that represent control points for spherical quadrangle interpolation. + + + + Adds two quaternions. + + The first quaternion to add. + The second quaternion to add. + The sum of the two quaternions. + + + + Subtracts two quaternions. + + The first quaternion to subtract. + The second quaternion to subtract. + The difference of the two quaternions. + + + + Reverses the direction of a given quaternion. + + The quaternion to negate. + A quaternion facing in the opposite direction. + + + + Scales a quaternion by the given value. + + The quaternion to scale. + The amount by which to scale the quaternion. + The scaled quaternion. + + + + Scales a quaternion by the given value. + + The quaternion to scale. + The amount by which to scale the quaternion. + The scaled quaternion. + + + + Multiplies a quaternion by another. + + The first quaternion to multiply. + The second quaternion to multiply. + The multiplied quaternion. + + + + Tests for equality between two objects. + + The first value to compare. + The second value to compare. + true if has the same value as ; otherwise, false. + + + + Tests for inequality between two objects. + + The first value to compare. + The second value to compare. + true if has a different value than ; otherwise, false. + + + + Returns a that represents this instance. + + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format provider. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + The format provider. + + A that represents this instance. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Represents a two dimensional mathematical vector. + + + + + A with all of its components set to zero. + + + + + The X unit (1, 0). + + + + + The Y unit (0, 1). + + + + + A with all of its components set to one. + + + + + The X component of the vector. + + + + + The Y component of the vector. + + + + + Initializes a new instance of the struct. + + The value that will be assigned to all components. + + + + Initializes a new instance of the struct. + + Initial value for the X component of the vector. + Initial value for the Y component of the vector. + + + + Initializes a new instance of the struct. + + The values to assign to the X and Y components of the vector. This must be an array with two elements. + Thrown when is null. + Thrown when contains more or less than two elements. + + + + Gets a value indicting whether this instance is normalized. + + + + + Gets a value indicting whether this vector is zero + + + + + Gets or sets the component at the specified index. + + The value of the X or Y component, depending on the index. + The index of the component to access. Use 0 for the X component and 1 for the Y component. + The value of the component at the specified index. + Thrown when the is out of the range [0, 1]. + + + + Calculates the length of the vector. + + The length of the vector. + + may be preferred when only the relative length is needed + and speed is of the essence. + + + + + Calculates the squared length of the vector. + + The squared length of the vector. + + This method may be preferred to when only a relative length is needed + and speed is of the essence. + + + + + Converts the vector into a unit vector. + + + + + Creates an array containing the elements of the vector. + + A two-element array containing the components of the vector. + + + + Adds two vectors. + + The first vector to add. + The second vector to add. + When the method completes, contains the sum of the two vectors. + + + + Adds two vectors. + + The first vector to add. + The second vector to add. + The sum of the two vectors. + + + + Perform a component-wise addition + + The input vector + The scalar value to be added to elements + The vector with added scalar for each element. + + + + Perform a component-wise addition + + The input vector + The scalar value to be added to elements + The vector with added scalar for each element. + + + + Subtracts two vectors. + + The first vector to subtract. + The second vector to subtract. + When the method completes, contains the difference of the two vectors. + + + + Subtracts two vectors. + + The first vector to subtract. + The second vector to subtract. + The difference of the two vectors. + + + + Perform a component-wise subtraction + + The input vector + The scalar value to be subtraced from elements + The vector with subtracted scalar for each element. + + + + Perform a component-wise subtraction + + The input vector + The scalar value to be subtraced from elements + The vector with subtracted scalar for each element. + + + + Perform a component-wise subtraction + + The scalar value to be subtraced from elements + The input vector + The vector with subtracted scalar for each element. + + + + Perform a component-wise subtraction + + The scalar value to be subtraced from elements + The input vector + The vector with subtracted scalar for each element. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + When the method completes, contains the scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Multiplies a vector with another by performing component-wise multiplication. + + The first vector to multiply. + The second vector to multiply. + When the method completes, contains the multiplied vector. + + + + Multiplies a vector with another by performing component-wise multiplication. + + The first vector to multiply. + The second vector to multiply. + The multiplied vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + When the method completes, contains the scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Scales a vector by the given value. + + The amount by which to scale the vector. + The vector to scale. + When the method completes, contains the scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Reverses the direction of a given vector. + + The vector to negate. + When the method completes, contains a vector facing in the opposite direction. + + + + Reverses the direction of a given vector. + + The vector to negate. + A vector facing in the opposite direction. + + + + Returns a containing the 2D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 2D triangle. + + A containing the 2D Cartesian coordinates of vertex 1 of the triangle. + A containing the 2D Cartesian coordinates of vertex 2 of the triangle. + A containing the 2D Cartesian coordinates of vertex 3 of the triangle. + Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). + Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). + When the method completes, contains the 2D Cartesian coordinates of the specified point. + + + + Returns a containing the 2D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 2D triangle. + + A containing the 2D Cartesian coordinates of vertex 1 of the triangle. + A containing the 2D Cartesian coordinates of vertex 2 of the triangle. + A containing the 2D Cartesian coordinates of vertex 3 of the triangle. + Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). + Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). + A new containing the 2D Cartesian coordinates of the specified point. + + + + Restricts a value to be within a specified range. + + The value to clamp. + The minimum value. + The maximum value. + When the method completes, contains the clamped value. + + + + Restricts a value to be within a specified range. + + The value to clamp. + The minimum value. + The maximum value. + The clamped value. + + + + Saturates this instance in the range [0,1] + + + + + Calculates the distance between two vectors. + + The first vector. + The second vector. + When the method completes, contains the distance between the two vectors. + + may be preferred when only the relative distance is needed + and speed is of the essence. + + + + + Calculates the distance between two vectors. + + The first vector. + The second vector. + The distance between the two vectors. + + may be preferred when only the relative distance is needed + and speed is of the essence. + + + + + Calculates the squared distance between two vectors. + + The first vector. + The second vector + When the method completes, contains the squared distance between the two vectors. + Distance squared is the value before taking the square root. + Distance squared can often be used in place of distance if relative comparisons are being made. + For example, consider three points A, B, and C. To determine whether B or C is further from A, + compare the distance between A and B to the distance between A and C. Calculating the two distances + involves two square roots, which are computationally expensive. However, using distance squared + provides the same information and avoids calculating two square roots. + + + + + Calculates the squared distance between two vectors. + + The first vector. + The second vector. + The squared distance between the two vectors. + Distance squared is the value before taking the square root. + Distance squared can often be used in place of distance if relative comparisons are being made. + For example, consider three points A, B, and C. To determine whether B or C is further from A, + compare the distance between A and B to the distance between A and C. Calculating the two distances + involves two square roots, which are computationally expensive. However, using distance squared + provides the same information and avoids calculating two square roots. + + + + + Calculates the dot product of two vectors. + + First source vector. + Second source vector. + When the method completes, contains the dot product of the two vectors. + + + + Calculates the dot product of two vectors. + + First source vector. + Second source vector. + The dot product of the two vectors. + + + + Converts the vector into a unit vector. + + The vector to normalize. + When the method completes, contains the normalized vector. + + + + Converts the vector into a unit vector. + + The vector to normalize. + The normalized vector. + + + + Performs a linear interpolation between two vectors. + + Start vector. + End vector. + Value between 0 and 1 indicating the weight of . + When the method completes, contains the linear interpolation of the two vectors. + + Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + + + + + Performs a linear interpolation between two vectors. + + Start vector. + End vector. + Value between 0 and 1 indicating the weight of . + The linear interpolation of the two vectors. + + Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + + + + + Performs a cubic interpolation between two vectors. + + Start vector. + End vector. + Value between 0 and 1 indicating the weight of . + When the method completes, contains the cubic interpolation of the two vectors. + + + + Performs a cubic interpolation between two vectors. + + Start vector. + End vector. + Value between 0 and 1 indicating the weight of . + The cubic interpolation of the two vectors. + + + + Performs a Hermite spline interpolation. + + First source position vector. + First source tangent vector. + Second source position vector. + Second source tangent vector. + Weighting factor. + When the method completes, contains the result of the Hermite spline interpolation. + + + + Performs a Hermite spline interpolation. + + First source position vector. + First source tangent vector. + Second source position vector. + Second source tangent vector. + Weighting factor. + The result of the Hermite spline interpolation. + + + + Performs a Catmull-Rom interpolation using the specified positions. + + The first position in the interpolation. + The second position in the interpolation. + The third position in the interpolation. + The fourth position in the interpolation. + Weighting factor. + When the method completes, contains the result of the Catmull-Rom interpolation. + + + + Performs a Catmull-Rom interpolation using the specified positions. + + The first position in the interpolation. + The second position in the interpolation. + The third position in the interpolation. + The fourth position in the interpolation. + Weighting factor. + A vector that is the result of the Catmull-Rom interpolation. + + + + Returns a vector containing the largest components of the specified vectors. + + The first source vector. + The second source vector. + When the method completes, contains an new vector composed of the largest components of the source vectors. + + + + Returns a vector containing the largest components of the specified vectors. + + The first source vector. + The second source vector. + A vector containing the largest components of the source vectors. + + + + Returns a vector containing the smallest components of the specified vectors. + + The first source vector. + The second source vector. + When the method completes, contains an new vector composed of the smallest components of the source vectors. + + + + Returns a vector containing the smallest components of the specified vectors. + + The first source vector. + The second source vector. + A vector containing the smallest components of the source vectors. + + + + Returns the reflection of a vector off a surface that has the specified normal. + + The source vector. + Normal of the surface. + When the method completes, contains the reflected vector. + Reflect only gives the direction of a reflection off a surface, it does not determine + whether the original vector was close enough to the surface to hit it. + + + + Returns the reflection of a vector off a surface that has the specified normal. + + The source vector. + Normal of the surface. + The reflected vector. + Reflect only gives the direction of a reflection off a surface, it does not determine + whether the original vector was close enough to the surface to hit it. + + + + Orthogonalizes a list of vectors. + + The list of orthogonalized vectors. + The list of vectors to orthogonalize. + + Orthogonalization is the process of making all vectors orthogonal to each other. This + means that any given vector in the list will be orthogonal to any other given vector in the + list. + Because this method uses the modified Gram-Schmidt process, the resulting vectors + tend to be numerically unstable. The numeric stability decreases according to the vectors + position in the list so that the first vector is the most stable and the last vector is the + least stable. + + Thrown when or is null. + Thrown when is shorter in length than . + + + + Orthonormalizes a list of vectors. + + The list of orthonormalized vectors. + The list of vectors to orthonormalize. + + Orthonormalization is the process of making all vectors orthogonal to each + other and making all vectors of unit length. This means that any given vector will + be orthogonal to any other given vector in the list. + Because this method uses the modified Gram-Schmidt process, the resulting vectors + tend to be numerically unstable. The numeric stability decreases according to the vectors + position in the list so that the first vector is the most stable and the last vector is the + least stable. + + Thrown when or is null. + Thrown when is shorter in length than . + + + + Transforms a 2D vector by the given rotation. + + The vector to rotate. + The rotation to apply. + When the method completes, contains the transformed . + + + + Transforms a 2D vector by the given rotation. + + The vector to rotate. + The rotation to apply. + The transformed . + + + + Transforms an array of vectors by the given rotation. + + The array of vectors to transform. + The rotation to apply. + The array for which the transformed vectors are stored. + This array may be the same array as . + Thrown when or is null. + Thrown when is shorter in length than . + + + + Transforms a 2D vector by the given . + + The source vector. + The transformation . + When the method completes, contains the transformed . + + + + Transforms a 2D vector by the given . + + The source vector. + The transformation . + The transformed . + + + + Transforms an array of 2D vectors by the given . + + The array of vectors to transform. + The transformation . + The array for which the transformed vectors are stored. + Thrown when or is null. + Thrown when is shorter in length than . + + + + Performs a coordinate transformation using the given . + + The coordinate vector to transform. + The transformation . + When the method completes, contains the transformed coordinates. + + A coordinate transform performs the transformation with the assumption that the w component + is one. The four dimensional vector obtained from the transformation operation has each + component in the vector divided by the w component. This forces the w component to be one and + therefore makes the vector homogeneous. The homogeneous vector is often preferred when working + with coordinates as the w component can safely be ignored. + + + + + Performs a coordinate transformation using the given . + + The coordinate vector to transform. + The transformation . + The transformed coordinates. + + A coordinate transform performs the transformation with the assumption that the w component + is one. The four dimensional vector obtained from the transformation operation has each + component in the vector divided by the w component. This forces the w component to be one and + therefore makes the vector homogeneous. The homogeneous vector is often preferred when working + with coordinates as the w component can safely be ignored. + + + + + Performs a coordinate transformation on an array of vectors using the given . + + The array of coordinate vectors to transform. + The transformation . + The array for which the transformed vectors are stored. + This array may be the same array as . + Thrown when or is null. + Thrown when is shorter in length than . + + A coordinate transform performs the transformation with the assumption that the w component + is one. The four dimensional vector obtained from the transformation operation has each + component in the vector divided by the w component. This forces the w component to be one and + therefore makes the vector homogeneous. The homogeneous vector is often preferred when working + with coordinates as the w component can safely be ignored. + + + + + Performs a normal transformation using the given . + + The normal vector to transform. + The transformation . + When the method completes, contains the transformed normal. + + A normal transform performs the transformation with the assumption that the w component + is zero. This causes the fourth row and fourth column of the matrix to be unused. The + end result is a vector that is not translated, but all other transformation properties + apply. This is often preferred for normal vectors as normals purely represent direction + rather than location because normal vectors should not be translated. + + + + + Performs a normal transformation using the given . + + The normal vector to transform. + The transformation . + The transformed normal. + + A normal transform performs the transformation with the assumption that the w component + is zero. This causes the fourth row and fourth column of the matrix to be unused. The + end result is a vector that is not translated, but all other transformation properties + apply. This is often preferred for normal vectors as normals purely represent direction + rather than location because normal vectors should not be translated. + + + + + Performs a normal transformation on an array of vectors using the given . + + The array of normal vectors to transform. + The transformation . + The array for which the transformed vectors are stored. + This array may be the same array as . + Thrown when or is null. + Thrown when is shorter in length than . + + A normal transform performs the transformation with the assumption that the w component + is zero. This causes the fourth row and fourth column of the matrix to be unused. The + end result is a vector that is not translated, but all other transformation properties + apply. This is often preferred for normal vectors as normals purely represent direction + rather than location because normal vectors should not be translated. + + + + + Adds two vectors. + + The first vector to add. + The second vector to add. + The sum of the two vectors. + + + + Multiplies a vector with another by performing component-wise multiplication equivalent to . + + The first vector to multiply. + The second vector to multiply. + The multiplication of the two vectors. + + + + Assert a vector (return it unchanged). + + The vector to assert (unchanged). + The asserted (unchanged) vector. + + + + Subtracts two vectors. + + The first vector to subtract. + The second vector to subtract. + The difference of the two vectors. + + + + Reverses the direction of a given vector. + + The vector to negate. + A vector facing in the opposite direction. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Scales a vector by the given value. + + The amount by which to scale the vector. + The vector to scale. + The scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Perform a component-wise addition + + The input vector. + The scalar value to be added on elements + The vector with added scalar for each element. + + + + Perform a component-wise addition + + The input vector. + The scalar value to be added on elements + The vector with added scalar for each element. + + + + Perform a component-wise subtraction + + The input vector. + The scalar value to be subtraced from elements + The vector with subtraced scalar from each element. + + + + Perform a component-wise subtraction + + The input vector. + The scalar value to be subtraced from elements + The vector with subtraced scalar from each element. + + + + Tests for equality between two objects. + + The first value to compare. + The second value to compare. + true if has the same value as ; otherwise, false. + + + + Tests for inequality between two objects. + + The first value to compare. + The second value to compare. + true if has a different value than ; otherwise, false. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Returns a that represents this instance. + + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format provider. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + The format provider. + + A that represents this instance. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Represents a three dimensional mathematical vector. + + + + + A with all of its components set to zero. + + + + + The X unit (1, 0, 0). + + + + + The Y unit (0, 1, 0). + + + + + The Z unit (0, 0, 1). + + + + + A with all of its components set to one. + + + + + A unit designating up (0, 1, 0). + + + + + A unit designating down (0, -1, 0). + + + + + A unit designating left (-1, 0, 0). + + + + + A unit designating right (1, 0, 0). + + + + + A unit designating forward in a right-handed coordinate system (0, 0, -1). + + + + + A unit designating forward in a left-handed coordinate system (0, 0, 1). + + + + + A unit designating backward in a right-handed coordinate system (0, 0, 1). + + + + + A unit designating backward in a left-handed coordinate system (0, 0, -1). + + + + + The X component of the vector. + + + + + The Y component of the vector. + + + + + The Z component of the vector. + + + + + Initializes a new instance of the struct. + + The value that will be assigned to all components. + + + + Initializes a new instance of the struct. + + Initial value for the X component of the vector. + Initial value for the Y component of the vector. + Initial value for the Z component of the vector. + + + + Initializes a new instance of the struct. + + A vector containing the values with which to initialize the X and Y components. + Initial value for the Z component of the vector. + + + + Initializes a new instance of the struct. + + The values to assign to the X, Y, and Z components of the vector. This must be an array with three elements. + Thrown when is null. + Thrown when contains more or less than three elements. + + + + Gets a value indicting whether this instance is normalized. + + + + + Gets a value indicting whether this vector is zero + + + + + Gets or sets the component at the specified index. + + The value of the X, Y, or Z component, depending on the index. + The index of the component to access. Use 0 for the X component, 1 for the Y component, and 2 for the Z component. + The value of the component at the specified index. + Thrown when the is out of the range [0, 2]. + + + + Calculates the length of the vector. + + The length of the vector. + + may be preferred when only the relative length is needed + and speed is of the essence. + + + + + Calculates the squared length of the vector. + + The squared length of the vector. + + This method may be preferred to when only a relative length is needed + and speed is of the essence. + + + + + Converts the vector into a unit vector. + + + + + Creates an array containing the elements of the vector. + + A three-element array containing the components of the vector. + + + + Adds two vectors. + + The first vector to add. + The second vector to add. + When the method completes, contains the sum of the two vectors. + + + + Adds two vectors. + + The first vector to add. + The second vector to add. + The sum of the two vectors. + + + + Perform a component-wise addition + + The input vector + The scalar value to be added to elements + The vector with added scalar for each element. + + + + Perform a component-wise addition + + The input vector + The scalar value to be added to elements + The vector with added scalar for each element. + + + + Subtracts two vectors. + + The first vector to subtract. + The second vector to subtract. + When the method completes, contains the difference of the two vectors. + + + + Subtracts two vectors. + + The first vector to subtract. + The second vector to subtract. + The difference of the two vectors. + + + + Perform a component-wise subtraction + + The input vector + The scalar value to be subtraced from elements + The vector with subtracted scalar for each element. + + + + Perform a component-wise subtraction + + The input vector + The scalar value to be subtraced from elements + The vector with subtracted scalar for each element. + + + + Perform a component-wise subtraction + + The scalar value to be subtraced from elements + The input vector. + The vector with subtracted scalar for each element. + + + + Perform a component-wise subtraction + + The scalar value to be subtraced from elements + The input vector. + The vector with subtracted scalar for each element. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + When the method completes, contains the scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Multiply a vector with another by performing component-wise multiplication. + + The first vector to multiply. + The second vector to multiply. + When the method completes, contains the multiplied vector. + + + + Multiply a vector with another by performing component-wise multiplication. + + The first vector to Multiply. + The second vector to multiply. + The multiplied vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + When the method completes, contains the scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Scales a vector by the given value. + + The amount by which to scale the vector. + The vector to scale. + When the method completes, contains the scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Reverses the direction of a given vector. + + The vector to negate. + When the method completes, contains a vector facing in the opposite direction. + + + + Reverses the direction of a given vector. + + The vector to negate. + A vector facing in the opposite direction. + + + + Returns a containing the 3D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 3D triangle. + + A containing the 3D Cartesian coordinates of vertex 1 of the triangle. + A containing the 3D Cartesian coordinates of vertex 2 of the triangle. + A containing the 3D Cartesian coordinates of vertex 3 of the triangle. + Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). + Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). + When the method completes, contains the 3D Cartesian coordinates of the specified point. + + + + Returns a containing the 3D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 3D triangle. + + A containing the 3D Cartesian coordinates of vertex 1 of the triangle. + A containing the 3D Cartesian coordinates of vertex 2 of the triangle. + A containing the 3D Cartesian coordinates of vertex 3 of the triangle. + Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). + Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). + A new containing the 3D Cartesian coordinates of the specified point. + + + + Restricts a value to be within a specified range. + + The value to clamp. + The minimum value. + The maximum value. + When the method completes, contains the clamped value. + + + + Restricts a value to be within a specified range. + + The value to clamp. + The minimum value. + The maximum value. + The clamped value. + + + + Calculates the cross product of two vectors. + + First source vector. + Second source vector. + When the method completes, contains he cross product of the two vectors. + + + + Calculates the cross product of two vectors. + + First source vector. + Second source vector. + The cross product of the two vectors. + + + + Calculates the distance between two vectors. + + The first vector. + The second vector. + When the method completes, contains the distance between the two vectors. + + may be preferred when only the relative distance is needed + and speed is of the essence. + + + + + Calculates the distance between two vectors. + + The first vector. + The second vector. + The distance between the two vectors. + + may be preferred when only the relative distance is needed + and speed is of the essence. + + + + + Calculates the squared distance between two vectors. + + The first vector. + The second vector. + When the method completes, contains the squared distance between the two vectors. + Distance squared is the value before taking the square root. + Distance squared can often be used in place of distance if relative comparisons are being made. + For example, consider three points A, B, and C. To determine whether B or C is further from A, + compare the distance between A and B to the distance between A and C. Calculating the two distances + involves two square roots, which are computationally expensive. However, using distance squared + provides the same information and avoids calculating two square roots. + + + + + Calculates the squared distance between two vectors. + + The first vector. + The second vector. + The squared distance between the two vectors. + Distance squared is the value before taking the square root. + Distance squared can often be used in place of distance if relative comparisons are being made. + For example, consider three points A, B, and C. To determine whether B or C is further from A, + compare the distance between A and B to the distance between A and C. Calculating the two distances + involves two square roots, which are computationally expensive. However, using distance squared + provides the same information and avoids calculating two square roots. + + + + + Tests whether one 3D vector is near another 3D vector. + + The left vector. + The right vector. + The epsilon. + true if left and right are near another 3D, false otherwise + + + + Tests whether one 3D vector is near another 3D vector. + + The left vector. + The right vector. + The epsilon. + true if left and right are near another 3D, false otherwise + + + + Calculates the dot product of two vectors. + + First source vector. + Second source vector. + When the method completes, contains the dot product of the two vectors. + + + + Calculates the dot product of two vectors. + + First source vector. + Second source vector. + The dot product of the two vectors. + + + + Converts the vector into a unit vector. + + The vector to normalize. + When the method completes, contains the normalized vector. + + + + Converts the vector into a unit vector. + + The vector to normalize. + The normalized vector. + + + + Performs a linear interpolation between two vectors. + + Start vector. + End vector. + Value between 0 and 1 indicating the weight of . + When the method completes, contains the linear interpolation of the two vectors. + + Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + + + + + Performs a linear interpolation between two vectors. + + Start vector. + End vector. + Value between 0 and 1 indicating the weight of . + The linear interpolation of the two vectors. + + Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + + + + + Performs a cubic interpolation between two vectors. + + Start vector. + End vector. + Value between 0 and 1 indicating the weight of . + When the method completes, contains the cubic interpolation of the two vectors. + + + + Performs a cubic interpolation between two vectors. + + Start vector. + End vector. + Value between 0 and 1 indicating the weight of . + The cubic interpolation of the two vectors. + + + + Performs a Hermite spline interpolation. + + First source position vector. + First source tangent vector. + Second source position vector. + Second source tangent vector. + Weighting factor. + When the method completes, contains the result of the Hermite spline interpolation. + + + + Performs a Hermite spline interpolation. + + First source position vector. + First source tangent vector. + Second source position vector. + Second source tangent vector. + Weighting factor. + The result of the Hermite spline interpolation. + + + + Performs a Catmull-Rom interpolation using the specified positions. + + The first position in the interpolation. + The second position in the interpolation. + The third position in the interpolation. + The fourth position in the interpolation. + Weighting factor. + When the method completes, contains the result of the Catmull-Rom interpolation. + + + + Performs a Catmull-Rom interpolation using the specified positions. + + The first position in the interpolation. + The second position in the interpolation. + The third position in the interpolation. + The fourth position in the interpolation. + Weighting factor. + A vector that is the result of the Catmull-Rom interpolation. + + + + Returns a vector containing the largest components of the specified vectors. + + The first source vector. + The second source vector. + When the method completes, contains an new vector composed of the largest components of the source vectors. + + + + Returns a vector containing the largest components of the specified vectors. + + The first source vector. + The second source vector. + A vector containing the largest components of the source vectors. + + + + Returns a vector containing the smallest components of the specified vectors. + + The first source vector. + The second source vector. + When the method completes, contains an new vector composed of the smallest components of the source vectors. + + + + Returns a vector containing the smallest components of the specified vectors. + + The first source vector. + The second source vector. + A vector containing the smallest components of the source vectors. + + + + Projects a 3D vector from object space into screen space. + + The vector to project. + The X position of the viewport. + The Y position of the viewport. + The width of the viewport. + The height of the viewport. + The minimum depth of the viewport. + The maximum depth of the viewport. + The combined world-view-projection matrix. + When the method completes, contains the vector in screen space. + + + + Projects a 3D vector from object space into screen space. + + The vector to project. + The X position of the viewport. + The Y position of the viewport. + The width of the viewport. + The height of the viewport. + The minimum depth of the viewport. + The maximum depth of the viewport. + The combined world-view-projection matrix. + The vector in screen space. + + + + Projects a 3D vector from screen space into object space. + + The vector to project. + The X position of the viewport. + The Y position of the viewport. + The width of the viewport. + The height of the viewport. + The minimum depth of the viewport. + The maximum depth of the viewport. + The combined world-view-projection matrix. + When the method completes, contains the vector in object space. + + + + Projects a 3D vector from screen space into object space. + + The vector to project. + The X position of the viewport. + The Y position of the viewport. + The width of the viewport. + The height of the viewport. + The minimum depth of the viewport. + The maximum depth of the viewport. + The combined world-view-projection matrix. + The vector in object space. + + + + Returns the reflection of a vector off a surface that has the specified normal. + + The source vector. + Normal of the surface. + When the method completes, contains the reflected vector. + Reflect only gives the direction of a reflection off a surface, it does not determine + whether the original vector was close enough to the surface to hit it. + + + + Returns the reflection of a vector off a surface that has the specified normal. + + The source vector. + Normal of the surface. + The reflected vector. + Reflect only gives the direction of a reflection off a surface, it does not determine + whether the original vector was close enough to the surface to hit it. + + + + Orthogonalizes a list of vectors. + + The list of orthogonalized vectors. + The list of vectors to orthogonalize. + + Orthogonalization is the process of making all vectors orthogonal to each other. This + means that any given vector in the list will be orthogonal to any other given vector in the + list. + Because this method uses the modified Gram-Schmidt process, the resulting vectors + tend to be numerically unstable. The numeric stability decreases according to the vectors + position in the list so that the first vector is the most stable and the last vector is the + least stable. + + Thrown when or is null. + Thrown when is shorter in length than . + + + + Orthonormalizes a list of vectors. + + The list of orthonormalized vectors. + The list of vectors to orthonormalize. + + Orthonormalization is the process of making all vectors orthogonal to each + other and making all vectors of unit length. This means that any given vector will + be orthogonal to any other given vector in the list. + Because this method uses the modified Gram-Schmidt process, the resulting vectors + tend to be numerically unstable. The numeric stability decreases according to the vectors + position in the list so that the first vector is the most stable and the last vector is the + least stable. + + Thrown when or is null. + Thrown when is shorter in length than . + + + + Transforms a 3D vector by the given rotation. + + The vector to rotate. + The rotation to apply. + When the method completes, contains the transformed . + + + + Transforms a 3D vector by the given rotation. + + The vector to rotate. + The rotation to apply. + The transformed . + + + + Transforms an array of vectors by the given rotation. + + The array of vectors to transform. + The rotation to apply. + The array for which the transformed vectors are stored. + This array may be the same array as . + Thrown when or is null. + Thrown when is shorter in length than . + + + + Transforms a 3D vector by the given . + + The source vector. + The transformation . + When the method completes, contains the transformed . + + + + Transforms a 3D vector by the given . + + The source vector. + The transformation . + The transformed . + + + + Transforms a 3D vector by the given . + + The source vector. + The transformation . + When the method completes, contains the transformed . + + + + Transforms a 3D vector by the given . + + The source vector. + The transformation . + When the method completes, contains the transformed . + + + + Transforms a 3D vector by the given . + + The source vector. + The transformation . + The transformed . + + + + Transforms an array of 3D vectors by the given . + + The array of vectors to transform. + The transformation . + The array for which the transformed vectors are stored. + Thrown when or is null. + Thrown when is shorter in length than . + + + + Performs a coordinate transformation using the given . + + The coordinate vector to transform. + The transformation . + When the method completes, contains the transformed coordinates. + + A coordinate transform performs the transformation with the assumption that the w component + is one. The four dimensional vector obtained from the transformation operation has each + component in the vector divided by the w component. This forces the w component to be one and + therefore makes the vector homogeneous. The homogeneous vector is often preferred when working + with coordinates as the w component can safely be ignored. + + + + + Performs a coordinate transformation using the given . + + The coordinate vector to transform. + The transformation . + The transformed coordinates. + + A coordinate transform performs the transformation with the assumption that the w component + is one. The four dimensional vector obtained from the transformation operation has each + component in the vector divided by the w component. This forces the w component to be one and + therefore makes the vector homogeneous. The homogeneous vector is often preferred when working + with coordinates as the w component can safely be ignored. + + + + + Performs a coordinate transformation on an array of vectors using the given . + + The array of coordinate vectors to transform. + The transformation . + The array for which the transformed vectors are stored. + This array may be the same array as . + Thrown when or is null. + Thrown when is shorter in length than . + + A coordinate transform performs the transformation with the assumption that the w component + is one. The four dimensional vector obtained from the transformation operation has each + component in the vector divided by the w component. This forces the w component to be one and + therefore makes the vector homogeneous. The homogeneous vector is often preferred when working + with coordinates as the w component can safely be ignored. + + + + + Performs a normal transformation using the given . + + The normal vector to transform. + The transformation . + When the method completes, contains the transformed normal. + + A normal transform performs the transformation with the assumption that the w component + is zero. This causes the fourth row and fourth column of the matrix to be unused. The + end result is a vector that is not translated, but all other transformation properties + apply. This is often preferred for normal vectors as normals purely represent direction + rather than location because normal vectors should not be translated. + + + + + Performs a normal transformation using the given . + + The normal vector to transform. + The transformation . + The transformed normal. + + A normal transform performs the transformation with the assumption that the w component + is zero. This causes the fourth row and fourth column of the matrix to be unused. The + end result is a vector that is not translated, but all other transformation properties + apply. This is often preferred for normal vectors as normals purely represent direction + rather than location because normal vectors should not be translated. + + + + + Performs a normal transformation on an array of vectors using the given . + + The array of normal vectors to transform. + The transformation . + The array for which the transformed vectors are stored. + This array may be the same array as . + Thrown when or is null. + Thrown when is shorter in length than . + + A normal transform performs the transformation with the assumption that the w component + is zero. This causes the fourth row and fourth column of the matrix to be unused. The + end result is a vector that is not translated, but all other transformation properties + apply. This is often preferred for normal vectors as normals purely represent direction + rather than location because normal vectors should not be translated. + + + + + Adds two vectors. + + The first vector to add. + The second vector to add. + The sum of the two vectors. + + + + Multiplies a vector with another by performing component-wise multiplication equivalent to . + + The first vector to multiply. + The second vector to multiply. + The multiplication of the two vectors. + + + + Assert a vector (return it unchanged). + + The vector to assert (unchanged). + The asserted (unchanged) vector. + + + + Subtracts two vectors. + + The first vector to subtract. + The second vector to subtract. + The difference of the two vectors. + + + + Reverses the direction of a given vector. + + The vector to negate. + A vector facing in the opposite direction. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Scales a vector by the given value. + + The amount by which to scale the vector. + The vector to scale. + The scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Perform a component-wise addition + + The input vector. + The scalar value to be added on elements + The vector with added scalar for each element. + + + + Perform a component-wise addition + + The input vector. + The scalar value to be added on elements + The vector with added scalar for each element. + + + + Perform a component-wise subtraction + + The input vector. + The scalar value to be subtraced from elements + The vector with added scalar from each element. + + + + Perform a component-wise subtraction + + The input vector. + The scalar value to be subtraced from elements + The vector with subtraced scalar from each element. + + + + Tests for equality between two objects. + + The first value to compare. + The second value to compare. + true if has the same value as ; otherwise, false. + + + + Tests for inequality between two objects. + + The first value to compare. + The second value to compare. + true if has a different value than ; otherwise, false. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Returns a that represents this instance. + + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format provider. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + The format provider. + + A that represents this instance. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Represents a four dimensional mathematical vector. + + + + + A with all of its components set to zero. + + + + + The X unit (1, 0, 0, 0). + + + + + The Y unit (0, 1, 0, 0). + + + + + The Z unit (0, 0, 1, 0). + + + + + The W unit (0, 0, 0, 1). + + + + + A with all of its components set to one. + + + + + The X component of the vector. + + + + + The Y component of the vector. + + + + + The Z component of the vector. + + + + + The W component of the vector. + + + + + Initializes a new instance of the struct. + + The value that will be assigned to all components. + + + + Initializes a new instance of the struct. + + Initial value for the X component of the vector. + Initial value for the Y component of the vector. + Initial value for the Z component of the vector. + Initial value for the W component of the vector. + + + + Initializes a new instance of the struct. + + A vector containing the values with which to initialize the X, Y, and Z components. + Initial value for the W component of the vector. + + + + Initializes a new instance of the struct. + + A vector containing the values with which to initialize the X and Y components. + Initial value for the Z component of the vector. + Initial value for the W component of the vector. + + + + Initializes a new instance of the struct. + + The values to assign to the X, Y, Z, and W components of the vector. This must be an array with four elements. + Thrown when is null. + Thrown when contains more or less than four elements. + + + + Gets a value indicting whether this instance is normalized. + + + + + Gets a value indicting whether this vector is zero + + + + + Gets or sets the component at the specified index. + + The value of the X, Y, Z, or W component, depending on the index. + The index of the component to access. Use 0 for the X component, 1 for the Y component, 2 for the Z component, and 3 for the W component. + The value of the component at the specified index. + Thrown when the is out of the range [0, 3]. + + + + Calculates the length of the vector. + + The length of the vector. + + may be preferred when only the relative length is needed + and speed is of the essence. + + + + + Calculates the squared length of the vector. + + The squared length of the vector. + + This method may be preferred to when only a relative length is needed + and speed is of the essence. + + + + + Converts the vector into a unit vector. + + + + + Creates an array containing the elements of the vector. + + A four-element array containing the components of the vector. + + + + Adds two vectors. + + The first vector to add. + The second vector to add. + When the method completes, contains the sum of the two vectors. + + + + Adds two vectors. + + The first vector to add. + The second vector to add. + The sum of the two vectors. + + + + Perform a component-wise addition + + The input vector + The scalar value to be added to elements + The vector with added scalar for each element. + + + + Perform a component-wise addition + + The input vector + The scalar value to be added to elements + The vector with added scalar for each element. + + + + Subtracts two vectors. + + The first vector to subtract. + The second vector to subtract. + When the method completes, contains the difference of the two vectors. + + + + Subtracts two vectors. + + The first vector to subtract. + The second vector to subtract. + The difference of the two vectors. + + + + Perform a component-wise subtraction + + The input vector + The scalar value to be subtraced from elements + The vector with subtracted scalar for each element. + + + + Perform a component-wise subtraction + + The input vector + The scalar value to be subtraced from elements + The vector with subtracted scalar for each element. + + + + Perform a component-wise subtraction + + The scalar value to be subtraced from elements + The input vector. + The vector with subtracted scalar for each element. + + + + Perform a component-wise subtraction + + The scalar value to be subtraced from elements + The input vector. + The vector with subtracted scalar for each element. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + When the method completes, contains the scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Multiplies a vector with another by performing component-wise multiplication. + + The first vector to multiply. + The second vector to multiply. + When the method completes, contains the multiplied vector. + + + + Multiplies a vector with another by performing component-wise multiplication. + + The first vector to multiply. + The second vector to multiply. + The multiplied vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + When the method completes, contains the scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Scales a vector by the given value. + + The amount by which to scale the vector. + The vector to scale. + When the method completes, contains the scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Reverses the direction of a given vector. + + The vector to negate. + When the method completes, contains a vector facing in the opposite direction. + + + + Reverses the direction of a given vector. + + The vector to negate. + A vector facing in the opposite direction. + + + + Returns a containing the 4D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 4D triangle. + + A containing the 4D Cartesian coordinates of vertex 1 of the triangle. + A containing the 4D Cartesian coordinates of vertex 2 of the triangle. + A containing the 4D Cartesian coordinates of vertex 3 of the triangle. + Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). + Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). + When the method completes, contains the 4D Cartesian coordinates of the specified point. + + + + Returns a containing the 4D Cartesian coordinates of a point specified in Barycentric coordinates relative to a 4D triangle. + + A containing the 4D Cartesian coordinates of vertex 1 of the triangle. + A containing the 4D Cartesian coordinates of vertex 2 of the triangle. + A containing the 4D Cartesian coordinates of vertex 3 of the triangle. + Barycentric coordinate b2, which expresses the weighting factor toward vertex 2 (specified in ). + Barycentric coordinate b3, which expresses the weighting factor toward vertex 3 (specified in ). + A new containing the 4D Cartesian coordinates of the specified point. + + + + Restricts a value to be within a specified range. + + The value to clamp. + The minimum value. + The maximum value. + When the method completes, contains the clamped value. + + + + Restricts a value to be within a specified range. + + The value to clamp. + The minimum value. + The maximum value. + The clamped value. + + + + Calculates the distance between two vectors. + + The first vector. + The second vector. + When the method completes, contains the distance between the two vectors. + + may be preferred when only the relative distance is needed + and speed is of the essence. + + + + + Calculates the distance between two vectors. + + The first vector. + The second vector. + The distance between the two vectors. + + may be preferred when only the relative distance is needed + and speed is of the essence. + + + + + Calculates the squared distance between two vectors. + + The first vector. + The second vector. + When the method completes, contains the squared distance between the two vectors. + Distance squared is the value before taking the square root. + Distance squared can often be used in place of distance if relative comparisons are being made. + For example, consider three points A, B, and C. To determine whether B or C is further from A, + compare the distance between A and B to the distance between A and C. Calculating the two distances + involves two square roots, which are computationally expensive. However, using distance squared + provides the same information and avoids calculating two square roots. + + + + + Calculates the squared distance between two vectors. + + The first vector. + The second vector. + The squared distance between the two vectors. + Distance squared is the value before taking the square root. + Distance squared can often be used in place of distance if relative comparisons are being made. + For example, consider three points A, B, and C. To determine whether B or C is further from A, + compare the distance between A and B to the distance between A and C. Calculating the two distances + involves two square roots, which are computationally expensive. However, using distance squared + provides the same information and avoids calculating two square roots. + + + + + Calculates the dot product of two vectors. + + First source vector + Second source vector. + When the method completes, contains the dot product of the two vectors. + + + + Calculates the dot product of two vectors. + + First source vector. + Second source vector. + The dot product of the two vectors. + + + + Converts the vector into a unit vector. + + The vector to normalize. + When the method completes, contains the normalized vector. + + + + Converts the vector into a unit vector. + + The vector to normalize. + The normalized vector. + + + + Performs a linear interpolation between two vectors. + + Start vector. + End vector. + Value between 0 and 1 indicating the weight of . + When the method completes, contains the linear interpolation of the two vectors. + + Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + + + + + Performs a linear interpolation between two vectors. + + Start vector. + End vector. + Value between 0 and 1 indicating the weight of . + The linear interpolation of the two vectors. + + Passing a value of 0 will cause to be returned; a value of 1 will cause to be returned. + + + + + Performs a cubic interpolation between two vectors. + + Start vector. + End vector. + Value between 0 and 1 indicating the weight of . + When the method completes, contains the cubic interpolation of the two vectors. + + + + Performs a cubic interpolation between two vectors. + + Start vector. + End vector. + Value between 0 and 1 indicating the weight of . + The cubic interpolation of the two vectors. + + + + Performs a Hermite spline interpolation. + + First source position vector. + First source tangent vector. + Second source position vector. + Second source tangent vector. + Weighting factor. + When the method completes, contains the result of the Hermite spline interpolation. + + + + Performs a Hermite spline interpolation. + + First source position vector. + First source tangent vector. + Second source position vector. + Second source tangent vector. + Weighting factor. + The result of the Hermite spline interpolation. + + + + Performs a Catmull-Rom interpolation using the specified positions. + + The first position in the interpolation. + The second position in the interpolation. + The third position in the interpolation. + The fourth position in the interpolation. + Weighting factor. + When the method completes, contains the result of the Catmull-Rom interpolation. + + + + Performs a Catmull-Rom interpolation using the specified positions. + + The first position in the interpolation. + The second position in the interpolation. + The third position in the interpolation. + The fourth position in the interpolation. + Weighting factor. + A vector that is the result of the Catmull-Rom interpolation. + + + + Returns a vector containing the largest components of the specified vectors. + + The first source vector. + The second source vector. + When the method completes, contains an new vector composed of the largest components of the source vectors. + + + + Returns a vector containing the largest components of the specified vectors. + + The first source vector. + The second source vector. + A vector containing the largest components of the source vectors. + + + + Returns a vector containing the smallest components of the specified vectors. + + The first source vector. + The second source vector. + When the method completes, contains an new vector composed of the smallest components of the source vectors. + + + + Returns a vector containing the smallest components of the specified vectors. + + The first source vector. + The second source vector. + A vector containing the smallest components of the source vectors. + + + + Orthogonalizes a list of vectors. + + The list of orthogonalized vectors. + The list of vectors to orthogonalize. + + Orthogonalization is the process of making all vectors orthogonal to each other. This + means that any given vector in the list will be orthogonal to any other given vector in the + list. + Because this method uses the modified Gram-Schmidt process, the resulting vectors + tend to be numerically unstable. The numeric stability decreases according to the vectors + position in the list so that the first vector is the most stable and the last vector is the + least stable. + + Thrown when or is null. + Thrown when is shorter in length than . + + + + Orthonormalizes a list of vectors. + + The list of orthonormalized vectors. + The list of vectors to orthonormalize. + + Orthonormalization is the process of making all vectors orthogonal to each + other and making all vectors of unit length. This means that any given vector will + be orthogonal to any other given vector in the list. + Because this method uses the modified Gram-Schmidt process, the resulting vectors + tend to be numerically unstable. The numeric stability decreases according to the vectors + position in the list so that the first vector is the most stable and the last vector is the + least stable. + + Thrown when or is null. + Thrown when is shorter in length than . + + + + Transforms a 4D vector by the given rotation. + + The vector to rotate. + The rotation to apply. + When the method completes, contains the transformed . + + + + Transforms a 4D vector by the given rotation. + + The vector to rotate. + The rotation to apply. + The transformed . + + + + Transforms an array of vectors by the given rotation. + + The array of vectors to transform. + The rotation to apply. + The array for which the transformed vectors are stored. + This array may be the same array as . + Thrown when or is null. + Thrown when is shorter in length than . + + + + Transforms a 4D vector by the given . + + The source vector. + The transformation . + When the method completes, contains the transformed . + + + + Transforms a 4D vector by the given . + + The source vector. + The transformation . + The transformed . + + + + Transforms an array of 4D vectors by the given . + + The array of vectors to transform. + The transformation . + The array for which the transformed vectors are stored. + This array may be the same array as . + Thrown when or is null. + Thrown when is shorter in length than . + + + + Adds two vectors. + + The first vector to add. + The second vector to add. + The sum of the two vectors. + + + + Multiplies a vector with another by performing component-wise multiplication equivalent to . + + The first vector to multiply. + The second vector to multiply. + The multiplication of the two vectors. + + + + Assert a vector (return it unchanged). + + The vector to assert (unchanged). + The asserted (unchanged) vector. + + + + Subtracts two vectors. + + The first vector to subtract. + The second vector to subtract. + The difference of the two vectors. + + + + Reverses the direction of a given vector. + + The vector to negate. + A vector facing in the opposite direction. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Scales a vector by the given value. + + The amount by which to scale the vector. + The vector to scale. + The scaled vector. + + + + Scales a vector by the given value. + + The vector to scale. + The amount by which to scale the vector. + The scaled vector. + + + + Perform a component-wise addition + + The input vector. + The scalar value to be added on elements + The vector with added scalar for each element. + + + + Perform a component-wise addition + + The input vector. + The scalar value to be added on elements + The vector with added scalar for each element. + + + + Perform a component-wise subtraction + + The input vector. + The scalar value to be subtraced from elements + The vector with subtraced scalar from each element. + + + + Perform a component-wise subtraction + + The input vector. + The scalar value to be subtraced from elements + The vector with subtraced scalar from each element. + + + + Tests for equality between two objects. + + The first value to compare. + The second value to compare. + true if has the same value as ; otherwise, false. + + + + Tests for inequality between two objects. + + The first value to compare. + The second value to compare. + true if has a different value than ; otherwise, false. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Returns a that represents this instance. + + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format provider. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + The format provider. + + A that represents this instance. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Loads a minimap overlay from a GFx file in the current resource. + + + + + Loads a minimap overlay from a GFx file in the current resource. + + + + + Experimental natives, please do not use in a live environment. + + + + + Experimental natives, please do not use in a live environment. + + + + + Deletes the given context from the background scripts context map. + + + + + Hashed version of BG_END_CONTEXT + + + + + Inserts the given context into the background scripts context map. + + + + + Hashed version of BG_START_CONTEXT + + + + + This is similar to the PushScaleformMovieFunction natives, except it calls in the `TIMELINE` of a minimap overlay. + + + + + This is similar to the PushScaleformMovieFunction natives, except it calls in the `TIMELINE` of a minimap overlay. + + + Cancels the currently executing event. + + + + + Cancels the currently executing event. + + + + + Commits the backing pixels to the specified runtime texture. + + + + + Commits the backing pixels to the specified runtime texture. + + + + + Creates a DUI browser. This can be used to draw on a runtime texture using CREATE_RUNTIME_TEXTURE_FROM_DUI_HANDLE. + + + + + Creates a DUI browser. This can be used to draw on a runtime texture using CREATE_RUNTIME_TEXTURE_FROM_DUI_HANDLE. + + + + + Creates a blank runtime texture. + + + + + Creates a blank runtime texture. + + + Creates a runtime texture from a DUI handle. + + + + + Creates a runtime texture from a DUI handle. + + + Creates a runtime texture from the specified file in the current resource. + + + + + Creates a runtime texture from the specified file in the current resource. + + + Creates a runtime texture dictionary with the specified name. + Example: + + ```lua + local txd = CreateRuntimeTxd('meow') + ``` + + + + + Creates a runtime texture dictionary with the specified name. + Example: + + ```lua + local txd = CreateRuntimeTxd('meow') + ``` + + + + + Destroys a DUI browser. + + + + + Destroys a DUI browser. + + + + + Returns a list of door system entries: a door system hash (see [ADD_DOOR_TO_SYSTEM](#_0x6F8838D03D1DC226)) and its object handle. + + The data returned adheres to the following layout: + + ``` + [{doorHash1, doorHandle1}, ..., {doorHashN, doorHandleN}] + ``` + + + + + This native is not implemented. + + + + + This native is not implemented. + + + This native is not implemented. + + + + + This native is not implemented. + + + This native is not implemented. + + + + + This native is not implemented. + + + This native is not implemented. + + + + + This native is not implemented. + + + + + Forces the game snow pass to render. + + + + + Returns all player indices for 'active' physical players known to the client. + The data returned adheres to the following layout: + + ``` + [127, 42, 13, 37] + ``` + + + + + Returns all player indices for 'active' physical players known to the client. + The data returned adheres to the following layout: + + ``` + [127, 42, 13, 37] + ``` + + + + + A getter for [SET_AMBIENT_PED_RANGE_MULTIPLIER_THIS_FRAME](#_0x0B919E1FB47CC4E0). + + + + + A getter for [SET_AMBIENT_VEHICLE_RANGE_MULTIPLIER_THIS_FRAME](#_0x90B6DA738A9A25DA). + + + + + Returns the world matrix of the specified camera. To turn this into a view matrix, calculate the inverse. + + + + + Returns the world matrix of the specified camera. To turn this into a view matrix, calculate the inverse. + + + + + Returns the name of the currently executing resource. + + + + + Returns the name of the currently executing resource. + + + + + Returns the peer address of the remote game server that the user is currently connected to. + + + + + Returns the peer address of the remote game server that the user is currently connected to. + + + + + Returns the NUI window handle for a specified DUI browser object. + + + + + Returns the NUI window handle for a specified DUI browser object. + + + + + Returns all pool handles for the given pool name; the data returned adheres to the following layout: + + ``` + [ 770, 1026, 1282, 1538, 1794, 2050, 2306, 2562, 2818, 3074, 3330, 3586, 3842, 4098, 4354, 4610, ...] + ``` + + ### Supported Pools + + **1**: CPed + **2**: CObject + **3**: CVehicle + **4**: CPickup + + + + + Returns the zoom level data by index from mapzoomdata.meta file. + + + + + Returns the zoom level data by index from mapzoomdata.meta file. + + + + + Gets the amount of metadata values with the specified key existing in the specified resource's manifest. + See also: [Resource manifest](https://docs.fivem.net/resources/manifest/) + + + + + Gets the amount of metadata values with the specified key existing in the specified resource's manifest. + See also: [Resource manifest](https://docs.fivem.net/resources/manifest/) + + + + + A getter for [SET_PARKED_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME](#_0xEAE6DCC7EEE3DB1D). + + + + + A getter for [SET_PED_DENSITY_MULTIPLIER_THIS_FRAME](#_0x95E3D6257B166CF2). + + + + + A getter for [\_SET_PED_EYE_COLOR](#_0x50B56988B170AFDF). Returns -1 if fails to get. + + + + + A getter for [\_SET_PED_EYE_COLOR](#_0x50B56988B170AFDF). Returns -1 if fails to get. + + + A getter for [\_SET_PED_FACE_FEATURE](#_0x71A5C1DBA060049E). Returns 0.0 if fails to get. + + + + + A getter for [\_SET_PED_FACE_FEATURE](#_0x71A5C1DBA060049E). Returns 0.0 if fails to get. + + + + + A getter for [\_SET_PED_HAIR_COLOR](#_0x4CFFC65454C93A49). Returns -1 if fails to get. + + + + + A getter for [\_SET_PED_HAIR_COLOR](#_0x4CFFC65454C93A49). Returns -1 if fails to get. + + + A getter for [\_SET_PED_HAIR_COLOR](#_0x4CFFC65454C93A49). Returns -1 if fails to get. + + + + + A getter for [\_SET_PED_HAIR_COLOR](#_0x4CFFC65454C93A49). Returns -1 if fails to get. + + + A getter for [SET_PED_HEAD_OVERLAY](#_0x48F44967FA05CC1E) and [\_SET_PED_HEAD_OVERLAY_COLOR](#_0x497BF74A7B9CB952) natives. + + + + + A getter for [SET_PED_HEAD_OVERLAY](#_0x48F44967FA05CC1E) and [\_SET_PED_HEAD_OVERLAY_COLOR](#_0x497BF74A7B9CB952) natives. + + + + + A getter for [SET_PLAYER_MELEE_WEAPON_DAMAGE_MODIFIER](#_0x4A3DC7ECCC321032). + + + + + A getter for [SET_PLAYER_MELEE_WEAPON_DEFENSE_MODIFIER](#_0xAE540335B4ABC4E2). + + + + + A getter for [SET_PLAYER_VEHICLE_DAMAGE_MODIFIER](#_0xA50E117CDDF82F0C). + + + + + A getter for [SET_PLAYER_VEHICLE_DEFENSE_MODIFIER](#_0x4C60E6EFDAFF2462). + + + + + A getter for [SET_PLAYER_WEAPON_DAMAGE_MODIFIER](#_0xCE07B9F7817AADA3). + + + + + A getter for [SET_PLAYER_WEAPON_DEFENSE_MODIFIER](#_0x2D83BC011CA14A3C). + + + + + A getter for [\_SET_PLAYER_WEAPON_DEFENSE_MODIFIER_2](#_0xBCFDE9EDE4CF27DC). + + + + + A getter for [SET_RANDOM_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME](#_0xB3B3359379FE77D3). + Same as vehicle density multiplier. + + + + + Returns all commands that are registered in the command system. + The data returned adheres to the following layout: + + ``` + [ + { + "name": "cmdlist" + }, + { + "name": "command1" + } + ] + ``` + + + + + Returns all commands that are registered in the command system. + The data returned adheres to the following layout: + + ``` + [ + { + "name": "cmdlist" + }, + { + "name": "command1" + } + ] + ``` + + + + + Gets the metadata value at a specified key/index from a resource's manifest. + See also: [Resource manifest](https://docs.fivem.net/resources/manifest/) + + + + + Gets the metadata value at a specified key/index from a resource's manifest. + See also: [Resource manifest](https://docs.fivem.net/resources/manifest/) + + + Returns the current state of the specified resource. + + + + + Returns the current state of the specified resource. + + + + + Gets the height of the specified runtime texture. + + + + + Gets the height of the specified runtime texture. + + + Gets the row pitch of the specified runtime texture, for use when creating data for `SET_RUNTIME_TEXTURE_ARGB_DATA`. + + + + + Gets the row pitch of the specified runtime texture, for use when creating data for `SET_RUNTIME_TEXTURE_ARGB_DATA`. + + + Gets the width of the specified runtime texture. + + + + + Gets the width of the specified runtime texture. + + + + + A getter for [SET_SCENARIO_PED_DENSITY_MULTIPLIER_THIS_FRAME](#_0x7A556143A1C03898). + + + + + Returns the value of a state bag key. + + + + + A getter for [SET_VEHICLE_CHEAT_POWER_INCREASE](#_0xB59E4BD37AE292DB). + + + + + A getter for [SET_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME](#_0x245A6883D966D537). + + + + + Gets a vehicle's multiplier used with a wheel's GET_VEHICLE_WHEEL_STEERING_ANGLE to determine the angle the wheel is rendered. + + + + + Returns the effective handling data of a vehicle as a floating-point value. + Example: `local fSteeringLock = GetVehicleHandlingFloat(vehicle, 'CHandlingData', 'fSteeringLock')` + + + + + Returns the effective handling data of a vehicle as a floating-point value. + Example: `local fSteeringLock = GetVehicleHandlingFloat(vehicle, 'CHandlingData', 'fSteeringLock')` + + + Returns the effective handling data of a vehicle as an integer value. + Example: `local modelFlags = GetVehicleHandlingInt(vehicle, 'CHandlingData', 'strModelFlags')` + + + + + Returns the effective handling data of a vehicle as an integer value. + Example: `local modelFlags = GetVehicleHandlingInt(vehicle, 'CHandlingData', 'strModelFlags')` + + + Returns the effective handling data of a vehicle as a vector value. + Example: `local inertiaMultiplier = GetVehicleHandlingVector(vehicle, 'CHandlingData', 'vecInertiaMultiplier')` + + + + + Returns the effective handling data of a vehicle as a vector value. + Example: `local inertiaMultiplier = GetVehicleHandlingVector(vehicle, 'CHandlingData', 'vecInertiaMultiplier')` + + + + + Gets the vehicle indicator light state. 0 = off, 1 = left, 2 = right, 3 = both + + + + + Gets the vehicle indicator light state. 0 = off, 1 = left, 2 = right, 3 = both + + + + + A getter for [MODIFY_VEHICLE_TOP_SPEED](#_0x93A3996368C94158). Returns -1.0 if a modifier is not set. + + + + + List of known states: + + ``` + 1: Not wheeling. + 65: Vehicle is ready to do wheelie (burnouting). + 129: Vehicle is doing wheelie. + ``` + + + + + List of known states: + + ``` + 1: Not wheeling. + 65: Vehicle is ready to do wheelie (burnouting). + 129: Vehicle is doing wheelie. + ``` + + + Gets brake pressure of a wheel. + Max number of wheels can be retrieved with the native GET_VEHICLE_NUMBER_OF_WHEELS. + + + + + Returns vehicle's wheels' size (size is the same for all the wheels, cannot get/set specific wheel of vehicle). + Only works on non-default wheels (returns 0 in case of default wheels). + + + + + Gets speed of a wheel at the tyre. + Max number of wheels can be retrieved with the native GET_VEHICLE_NUMBER_OF_WHEELS. + + + + + Gets speed of a wheel at the tyre. + Max number of wheels can be retrieved with the native GET_VEHICLE_NUMBER_OF_WHEELS. + + + Gets steering angle of a wheel. + Max number of wheels can be retrieved with the native GET_VEHICLE_NUMBER_OF_WHEELS. + + + + + Returns vehicle's wheels' width (width is the same for all the wheels, cannot get/set specific wheel of vehicle). + Only works on non-default wheels (returns 0 in case of default wheels). + + + + + Returns the offset of the specified wheel relative to the wheel's axle center. + + + + + Returns the offset of the specified wheel relative to the wheel's axle center. + + + + + A getter for [\_SET_WEAPON_DAMAGE_MODIFIER](#_0x4757F00BC6323CFE). + + + + + Returns whether or not the specific minimap overlay has loaded. + + + + + Returns whether or not the specific minimap overlay has loaded. + + + + + <!-- Native implemented by Disquse. 0xFFF65C63 --> + + Returns true if the minimap is currently expanded. False if it's the normal minimap state. + Use [`IsBigmapFull`](#_0x66EE14B2) to check if the full map is currently revealed on the minimap. + + + + + <!-- Native implemented by Disquse. 0xFFF65C63 --> + + Returns true if the minimap is currently expanded. False if it's the normal minimap state. + Use [`IsBigmapFull`](#_0x66EE14B2) to check if the full map is currently revealed on the minimap. + + + <!-- Native implemented by Disquse. 0x66EE14B2 --> + + Returns true if the full map is currently revealed on the minimap. + Use [`IsBigmapActive`](#_0xFFF65C63) to check if the minimap is currently expanded or in it's normal state. + + + + + <!-- Native implemented by Disquse. 0x66EE14B2 --> + + Returns true if the full map is currently revealed on the minimap. + Use [`IsBigmapActive`](#_0xFFF65C63) to check if the minimap is currently expanded or in it's normal state. + + + + + Returns whether or not a browser is created for a specified DUI browser object. + + + + + Returns whether or not a browser is created for a specified DUI browser object. + + + Gets whether or not this is the CitizenFX server. + + + + + Gets whether or not this is the CitizenFX server. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + + Returns whether an asynchronous streaming file registration completed. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + + Returns whether an asynchronous streaming file registration completed. + + + + + Reads the contents of a text file in a specified resource. + If executed on the client, this file has to be included in `files` in the resource manifest. + Example: `local data = LoadResourceFile("devtools", "data.json")` + + + + + Reads the contents of a text file in a specified resource. + If executed on the client, this file has to be included in `files` in the resource manifest. + Example: `local data = LoadResourceFile("devtools", "data.json")` + + + + + Starts listening to the specified channel, when available. + + + + + Adds the specified channel to the target list for the specified Mumble voice target ID. + + + + + Adds the specified player to the target list for the specified Mumble voice target ID. + + + + + Adds the specified player to the target list for the specified Mumble voice target ID. + + + + + Clears the target list for the specified Mumble voice target ID. + + + + + Clears channels from the target list for the specified Mumble voice target ID. + + + + + Clears players from the target list for the specified Mumble voice target ID. + + + + + Returns the mumble voice channel from a player's server id. + + + + + This native will return true if the user succesfully connected to the voice server. + If the user disabled the voice-chat setting it will return false. + + + + + Stops listening to the specified channel. + + + + + Changes the Mumble server address to connect to, and reconnects to the new address. + + + + + Sets the current Mumble voice target ID to broadcast voice to. + + + + + Overrides the output volume for a particular player on Mumble. This will also bypass 3D audio and distance calculations. -1.0 to reset the override. + + Set to -1.0 to reset the Volume override. + + + + + Overrides the output volume for a particular player with the specified server id and player name on Mumble. This will also bypass 3D audio and distance calculations. -1.0 to reset the override. + + + + + Returns the owner ID of the specified entity. + + + + + Returns the owner ID of the specified entity. + + + + + Scope entry for profiler. + + + + + Scope entry for profiler. + + + Scope exit for profiler. + + + + + Scope exit for profiler. + + + Returns true if the profiler is active. + + + + + Returns true if the profiler is active. + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + + Registers a set of archetypes with the game engine. These should match `CBaseArchetypeDef` class information from the game. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + + Registers a set of archetypes with the game engine. These should match `CBaseArchetypeDef` class information from the game. + + + Registered commands can be executed by entering them in the client console (this works for client side and server side registered commands). Or by entering them in the server console/through an RCON client (only works for server side registered commands). Or if you use a supported chat resource, like the default one provided in the cfx-server-data repository, then you can enter the command in chat by prefixing it with a `/`. + + Commands registered using this function can also be executed by resources, using the [`ExecuteCommand` native](#_0x561C060B). + + The restricted bool is not used on the client side. Permissions can only be checked on the server side, so if you want to limit your command with an ace permission automatically, make it a server command (by registering it in a server script). + + **Example result**: + + ![](https://i.imgur.com/TaCnG09.png) + + + + + Registered commands can be executed by entering them in the client console (this works for client side and server side registered commands). Or by entering them in the server console/through an RCON client (only works for server side registered commands). Or if you use a supported chat resource, like the default one provided in the cfx-server-data repository, then you can enter the command in chat by prefixing it with a `/`. + + Commands registered using this function can also be executed by resources, using the [`ExecuteCommand` native](#_0x561C060B). + + The restricted bool is not used on the client side. Permissions can only be checked on the server side, so if you want to limit your command with an ace permission automatically, make it a server command (by registering it in a server script). + + **Example result**: + + ![](https://i.imgur.com/TaCnG09.png) + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + + Registers a set of entities with the game engine. These should match `CEntityDef` class information from the game. + At this time, this function **should not be used in a live environment**. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + + Registers a set of entities with the game engine. These should match `CEntityDef` class information from the game. + At this time, this function **should not be used in a live environment**. + + + Registers a specified .gfx file as GFx font library. + The .gfx file has to be registered with the streamer already. + + + + + Registers a specified .gfx file as GFx font library. + The .gfx file has to be registered with the streamer already. + + + Registers a specified font name for use with text draw commands. + + + + + Registers a specified font name for use with text draw commands. + + + + + Registers a key mapping for the current resource. + + See the related [cookbook post](https://cookbook.fivem.net/2020/01/06/using-the-new-console-key-bindings/) for more information. + + + + + An internal function which allows the current resource's HLL script runtimes to receive state for the specified event. + + + + + An internal function which allows the current resource's HLL script runtimes to receive state for the specified event. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + + Registers a dynamic streaming asset from the server with the GTA streaming module system. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + + Registers a dynamic streaming asset from the server with the GTA streaming module system. + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + + Registers a KVP value as an asset with the GTA streaming module system. This function currently won't work. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + + Registers a KVP value as an asset with the GTA streaming module system. This function currently won't work. + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + + Registers a file from an URL as a streaming asset in the GTA streaming subsystem. This will asynchronously register the asset, and caching is done based on the URL itself - cache headers are ignored. + + Use `IS_STREAMING_FILE_READY` to check if the asset has been registered successfully. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + + Registers a file from an URL as a streaming asset in the GTA streaming subsystem. This will asynchronously register the asset, and caching is done based on the URL itself - cache headers are ignored. + + Use `IS_STREAMING_FILE_READY` to check if the asset has been registered successfully. + + + + + Experimental natives, please do not use in a live environment. + + + + + Experimental natives, please do not use in a live environment. + + + + + Resets values from the zoom level data by index to defaults from mapzoomdata.meta. + + + + + Resets values from the zoom level data by index to defaults from mapzoomdata.meta. + + + + + Sends a message to the specific DUI root page. This is similar to SEND_NUI_MESSAGE. + + + + + Sends a message to the specific DUI root page. This is similar to SEND_NUI_MESSAGE. + + + Injects a 'mouse down' event for a DUI object. Coordinates are expected to be set using SEND_DUI_MOUSE_MOVE. + + + + + Injects a 'mouse down' event for a DUI object. Coordinates are expected to be set using SEND_DUI_MOUSE_MOVE. + + + Injects a 'mouse move' event for a DUI object. Coordinates are in browser space. + + + + + Injects a 'mouse move' event for a DUI object. Coordinates are in browser space. + + + Injects a 'mouse up' event for a DUI object. Coordinates are expected to be set using SEND_DUI_MOUSE_MOVE. + + + + + Injects a 'mouse up' event for a DUI object. Coordinates are expected to be set using SEND_DUI_MOUSE_MOVE. + + + Injects a 'mouse wheel' event for a DUI object. + + + + + Injects a 'mouse wheel' event for a DUI object. + + + Sends a message to the `loadingScreen` NUI frame, which contains the HTML page referenced in `loadscreen` resources. + + + + + Sends a message to the `loadingScreen` NUI frame, which contains the HTML page referenced in `loadscreen` resources. + + + + + This native sets the app id for the discord rich presence implementation. + + + + + This native sets the app id for the discord rich presence implementation. + + + This native sets the image asset for the discord rich presence implementation. + + + + + This native sets the image asset for the discord rich presence implementation. + + + This native sets the small image asset for the discord rich presence implementation. + + + + + This native sets the small image asset for the discord rich presence implementation. + + + This native sets the hover text of the small image asset for the discord rich presence implementation. + + + + + This native sets the hover text of the small image asset for the discord rich presence implementation. + + + This native sets the hover text of the image asset for the discord rich presence implementation. + + + + + This native sets the hover text of the image asset for the discord rich presence implementation. + + + + + Navigates the specified DUI browser to a different URL. + + + + + Navigates the specified DUI browser to a different URL. + + + + + Sets a global handling override for a specific vehicle class. The name is supposed to match the `handlingName` field from handling.meta. + Example: `SetHandlingField('AIRTUG', 'CHandlingData', 'fSteeringLock', 360.0)` + + + + + Sets a global handling override for a specific vehicle class. The name is supposed to match the `handlingName` field from handling.meta. + Example: `SetHandlingField('AIRTUG', 'CHandlingData', 'fSteeringLock', 360.0)` + + + Sets a global handling override for a specific vehicle class. The name is supposed to match the `handlingName` field from handling.meta. + Example: `SetHandlingFloat('AIRTUG', 'CHandlingData', 'fSteeringLock', 360.0)` + + + + + Sets a global handling override for a specific vehicle class. The name is supposed to match the `handlingName` field from handling.meta. + Example: `SetHandlingFloat('AIRTUG', 'CHandlingData', 'fSteeringLock', 360.0)` + + + Sets a global handling override for a specific vehicle class. The name is supposed to match the `handlingName` field from handling.meta. + + + + + Sets a global handling override for a specific vehicle class. The name is supposed to match the `handlingName` field from handling.meta. + + + Sets a global handling override for a specific vehicle class. The name is supposed to match the `handlingName` field from handling.meta. + Example: `SetHandlingVector('AIRTUG', 'CHandlingData', 'vecCentreOfMassOffset', vector3(0.0, 0.0, -5.0))` + + + + + Sets a global handling override for a specific vehicle class. The name is supposed to match the `handlingName` field from handling.meta. + Example: `SetHandlingVector('AIRTUG', 'CHandlingData', 'vecCentreOfMassOffset', vector3(0.0, 0.0, -5.0))` + + + + + Sets whether or not `SHUTDOWN_LOADING_SCREEN` automatically shuts down the NUI frame for the loading screen. If this is enabled, + you will have to manually invoke `SHUTDOWN_LOADING_SCREEN_NUI` whenever you want to hide the NUI loading screen. + + + + + Sets whether or not `SHUTDOWN_LOADING_SCREEN` automatically shuts down the NUI frame for the loading screen. If this is enabled, + you will have to manually invoke `SHUTDOWN_LOADING_SCREEN_NUI` whenever you want to hide the NUI loading screen. + + + + + Sets values to the zoom level data by index. + + + + + Sets values to the zoom level data by index. + + + + + Overrides how many real ms are equal to one game minute. + A setter for [`GetMillisecondsPerGameMinute`](#_0x2F8B4D1C595B11DB). + + + + + Overrides how many real ms are equal to one game minute. + A setter for [`GetMillisecondsPerGameMinute`](#_0x2F8B4D1C595B11DB). + + + Sets the type for the minimap blip clipping object to be either rectangular or rounded. + + + + + Overrides the minimap component data (from `common:/data/ui/frontend.xml`) for a specified component. + + + + + Reveals the entire minimap (FOW = Fog of War) + + + + + Sets the display info for a minimap overlay. + + + + + Sets the display info for a minimap overlay. + + + + + the status of default voip system. It affects on `NETWORK_IS_PLAYER_TALKING` and `mp_facial` animation. + This function doesn't need to be called every frame, it works like a switcher. + + + + + the status of default voip system. It affects on `NETWORK_IS_PLAYER_TALKING` and `mp_facial` animation. + This function doesn't need to be called every frame, it works like a switcher. + + + + + Sets the player's rich presence detail state for social platform providers to a specified string. + + + + + Sets the player's rich presence detail state for social platform providers to a specified string. + + + + + Sets a pixel in the specified runtime texture. This will have to be committed using `COMMIT_RUNTIME_TEXTURE` to have any effect. + + + + + Sets a pixel in the specified runtime texture. This will have to be committed using `COMMIT_RUNTIME_TEXTURE` to have any effect. + + + + + Internal function for setting a state bag value. + + + + + Disables the vehicle from being repaired when a vehicle extra is enabled. + + + + + Disables the vehicle from being repaired when a vehicle extra is enabled. + + + + + Sets a handling override for a specific vehicle. Certain handling flags can only be set globally using `SET_HANDLING_FIELD`, this might require some experimentation. + Example: `SetVehicleHandlingField(vehicle, 'CHandlingData', 'fSteeringLock', 360.0)` + + + + + Sets a handling override for a specific vehicle. Certain handling flags can only be set globally using `SET_HANDLING_FIELD`, this might require some experimentation. + Example: `SetVehicleHandlingField(vehicle, 'CHandlingData', 'fSteeringLock', 360.0)` + + + Sets a handling override for a specific vehicle. Certain handling flags can only be set globally using `SET_HANDLING_FLOAT`, this might require some experimentation. + Example: `SetVehicleHandlingFloat(vehicle, 'CHandlingData', 'fSteeringLock', 360.0)` + + + + + Sets a handling override for a specific vehicle. Certain handling flags can only be set globally using `SET_HANDLING_FLOAT`, this might require some experimentation. + Example: `SetVehicleHandlingFloat(vehicle, 'CHandlingData', 'fSteeringLock', 360.0)` + + + Sets a handling override for a specific vehicle. Certain handling flags can only be set globally using `SET_HANDLING_INT`, this might require some experimentation. + + + + + Sets a handling override for a specific vehicle. Certain handling flags can only be set globally using `SET_HANDLING_INT`, this might require some experimentation. + + + Sets a handling override for a specific vehicle. Certain handling flags can only be set globally using `SET_HANDLING_VECTOR`, this might require some experimentation. + + + + + Sets a handling override for a specific vehicle. Certain handling flags can only be set globally using `SET_HANDLING_VECTOR`, this might require some experimentation. + + + + + Example script: <https://pastebin.com/J6XGbkCW> + + List of known states: + + ``` + 1: Not wheeling. + 65: Vehicle is ready to do wheelie (burnouting). + 129: Vehicle is doing wheelie. + ``` + + + + + Example script: <https://pastebin.com/J6XGbkCW> + + List of known states: + + ``` + 1: Not wheeling. + 65: Vehicle is ready to do wheelie (burnouting). + 129: Vehicle is doing wheelie. + ``` + + + + + Not sure what this changes, probably determines physical rim size in case the tire is blown. + + + + + Sets vehicle's wheels' size (size is the same for all the wheels, cannot get/set specific wheel of vehicle). + Only works on non-default wheels. + Returns whether change was successful (can be false if trying to set size for non-default wheels). + + + + + Use along with SetVehicleWheelSize to resize the wheels (this native sets the collider size affecting physics while SetVehicleWheelSize will change visual size). + + + + + Use along with SetVehicleWheelWidth to resize the wheels (this native sets the collider width affecting physics while SetVehicleWheelWidth will change visual width). + + + + + Sets vehicle's wheels' width (width is the same for all the wheels, cannot get/set specific wheel of vehicle). + Only works on non-default wheels. + Returns whether change was successful (can be false if trying to set width for non-default wheels). + + + + + Adjusts the offset of the specified wheel relative to the wheel's axle center. + Needs to be called every frame in order to function properly, as GTA will reset the offset otherwise. + This function can be especially useful to set the track width of a vehicle, for example: + + ``` + function SetVehicleFrontTrackWidth(vehicle, width) + SetVehicleWheelXOffset(vehicle, 0, -width/2) + SetVehicleWheelXOffset(vehicle, 1, width/2) + end + ``` + + + + + Adjusts the offset of the specified wheel relative to the wheel's axle center. + Needs to be called every frame in order to function properly, as GTA will reset the offset otherwise. + This function can be especially useful to set the track width of a vehicle, for example: + + ``` + function SetVehicleFrontTrackWidth(vehicle, width) + SetVehicleWheelXOffset(vehicle, 0, -width/2) + SetVehicleWheelXOffset(vehicle, 1, width/2) + end + ``` + + + + + Overrides a floating point value from `visualsettings.dat` temporarily. + + + + + Overrides a floating point value from `visualsettings.dat` temporarily. + + + + + Shuts down the `loadingScreen` NUI frame, similarly to `SHUTDOWN_LOADING_SCREEN`. + + + + + Shuts down the `loadingScreen` NUI frame, similarly to `SHUTDOWN_LOADING_SCREEN`. + + + + + statId: see 0xC48FE1971C9743FF + + + + + statId: see 0xC48FE1971C9743FF + + + + + statId: see 0xC48FE1971C9743FF + + + + + statId: see 0xC48FE1971C9743FF + + + + + statId: see 0xC48FE1971C9743FF + + + + + statId: see 0xC48FE1971C9743FF + + + + + statId: see 0xC48FE1971C9743FF + + + + + statId: see 0xC48FE1971C9743FF + + + + + statId: see 0xC48FE1971C9743FF + + + + + statId: see 0xC48FE1971C9743FF + + + + + Dismounts the ped from the animal it's mounted on. taskFlag affects what side the rider gets off. 1 << 18 will get off on the left side, where any other value will get off on the right side. The only other known value are 1 << 17 and 1 << 24, which has the behavior of any other value (getting off the animal from the right side). p2-p5 are almost always 0. + + + + + Has the ped react to another entity. The reactionType determines how the ped reacts. p3 is 7.5f in the scripts. p4 is 0f. unkFlag is always 4. The rest of the parameters are unknown, but 0 is acceptable input. Here is a list of the different reaction type values by Mooshe: https://pastebin.com/Ju7BbmMt + + + + + The backing function for TriggerEvent. + + + + + The backing function for TriggerEvent. + + + The backing function for TriggerLatentServerEvent. + + + + + The backing function for TriggerLatentServerEvent. + + + + + The backing function for TriggerServerEvent. + + + + + The backing function for TriggerServerEvent. + + + + + Returns whether or not the currently executing event was canceled. + + + + + Returns whether or not the currently executing event was canceled. + + + + + Returns a formatted string (0x%x) + + + + + Note: you must use _CREATE_VAR_STRING + + + + + Gets the ped's core value on a scale of 0 to 100. The coreIndex is as follows: + - health = 0, + - stamina = 1, + - deadeye = 2 + + + + + Return example: 1207.69_dev_pc + + + + + Returns the label text given the hash. + + + + + 0 = invalid + 1 = CEntity + 2 = 0x2A72C62B + 3 = 0xE63A0D71 + 4 = 0x9FDE1AC6 + 5 = 0x6D766374 + 6 = 0x27ACC35B + 7 = CScriptedCoverPoint + 8 = ptfxScriptInfo + 9 = CPed + 10 = CVehicle + 11 = CObject + 12 = CItemSet + 13 = 0x830B8272 + + + + + Gets the model hash from the weapon hash. + + + + + Gives the ped the weapon. p7 is 0.5f, and p8 is 1.0f. p11 and p12 are both 0. + For a list of weapon groups, here is a weapons enum by Mooshe with all weapon-related hashes: https://pastebin.com/n72eW6zd + + + + + Note: the buffer should be exactly 32 bytes long + + + + + Same as GET_IS_LOADING_SCREEN_ACTIVE + + + + + Returns value of fwuiCachedSetting "general.onlineNotificationsInStoryMode" + + + + + Sets the entity's health. healthAmount sets the health value to that, and sets the maximum health core value. Setting healthAmount to 0 will kill the entity. Unclear what role p2 serves, but it's either 0 or an entity handle. + + + + + Sets the outfit preset for the ped. The presetId is an index which determines it's preset outfit. p2 is always 0. + + + + + 0 = high + 1 = normal + 2 = low + + + + + Same as SHOULD_USE_METRIC_MEASUREMENTS + + + + + struct StatId + { + alignas(8) Hash BaseId; + alignas(8) Hash PermutationId; + } + + + + + Works in MP only. + + + + + Deprecated name, use GET_VEHICLE_WHEEL_Y_ROTATION instead + + + + + Deprecated name, use SET_VEHICLE_WHEEL_Y_ROTATION instead + + + + + Loads a minimap overlay from a GFx file in the current resource. + + + The path to a `.gfx` file in the current resource. It has to be specified as a `file`. + + + A minimap overlay ID. + + + + + Loads a minimap overlay from a GFx file in the current resource. + + + The path to a `.gfx` file in the current resource. It has to be specified as a `file`. + + + A minimap overlay ID. + + + + + Experimental natives, please do not use in a live environment. + + + + + Experimental natives, please do not use in a live environment. + + + + + + + + + Deletes the given context from the background scripts context map. + + + : + + + + + Hashed version of BG_END_CONTEXT + + + : + + + + + Inserts the given context into the background scripts context map. + + + : + + + + + Hashed version of BG_START_CONTEXT + + + : + + + + + This is similar to the PushScaleformMovieFunction natives, except it calls in the `TIMELINE` of a minimap overlay. + + + The minimap overlay ID. + + + A function in the overlay's TIMELINE. + + + + + This is similar to the PushScaleformMovieFunction natives, except it calls in the `TIMELINE` of a minimap overlay. + + + The minimap overlay ID. + + + A function in the overlay's TIMELINE. + + + + + Cancels the currently executing event. + + + + + Cancels the currently executing event. + + + + + Commits the backing pixels to the specified runtime texture. + + + The runtime texture handle. + + + + + Commits the backing pixels to the specified runtime texture. + + + The runtime texture handle. + + + + + Returns a formatted string (0x%x) + + + : + + + + + Creates a DUI browser. This can be used to draw on a runtime texture using CREATE_RUNTIME_TEXTURE_FROM_DUI_HANDLE. + + + The initial URL to load in the browser. + + + The width of the backing surface. + + + The height of the backing surface. + + + A DUI object. + + + + + Creates a DUI browser. This can be used to draw on a runtime texture using CREATE_RUNTIME_TEXTURE_FROM_DUI_HANDLE. + + + The initial URL to load in the browser. + + + The width of the backing surface. + + + The height of the backing surface. + + + A DUI object. + + + + + Creates a blank runtime texture. + + + A handle to the runtime TXD to create the runtime texture in. + + + The name for the texture in the runtime texture dictionary. + + + The width of the new texture. + + + The height of the new texture. + + + A runtime texture handle. + + + + + Creates a blank runtime texture. + + + A handle to the runtime TXD to create the runtime texture in. + + + The name for the texture in the runtime texture dictionary. + + + The width of the new texture. + + + The height of the new texture. + + + A runtime texture handle. + + + + + Creates a runtime texture from a DUI handle. + + + A handle to the runtime TXD to create the runtime texture in. + + + The name for the texture in the runtime texture dictionary. + + + The DUI handle returned from GET_DUI_HANDLE. + + + The runtime texture handle. + + + + + Creates a runtime texture from a DUI handle. + + + A handle to the runtime TXD to create the runtime texture in. + + + The name for the texture in the runtime texture dictionary. + + + The DUI handle returned from GET_DUI_HANDLE. + + + The runtime texture handle. + + + + + Creates a runtime texture from the specified file in the current resource. + + + A handle to the runtime TXD to create the runtime texture in. + + + The name for the texture in the runtime texture dictionary. + + + The file name of an image to load. This should preferably be a PNG, and has to be specified as a `file` in the resource manifest. + + + A runtime texture handle. + + + + + Creates a runtime texture from the specified file in the current resource. + + + A handle to the runtime TXD to create the runtime texture in. + + + The name for the texture in the runtime texture dictionary. + + + The file name of an image to load. This should preferably be a PNG, and has to be specified as a `file` in the resource manifest. + + + A runtime texture handle. + + + + + Creates a runtime texture dictionary with the specified name. + Example: + ```lua + local txd = CreateRuntimeTxd('meow') + ``` + + + The name for the runtime TXD. + + + A handle to the runtime TXD. + + + + + Creates a runtime texture dictionary with the specified name. + Example: + ```lua + local txd = CreateRuntimeTxd('meow') + ``` + + + The name for the runtime TXD. + + + A handle to the runtime TXD. + + + + + Destroys a DUI browser. + + + The DUI browser handle. + + + + + Destroys a DUI browser. + + + The DUI browser handle. + + + + + Note: you must use _CREATE_VAR_STRING + + + : + + + : + + + : + + + + + Returns a list of door system entries: a door system hash (see [ADD_DOOR_TO_SYSTEM](#_0x6F8838D03D1DC226)) and its object handle. + The data returned adheres to the following layout: + ``` + [{doorHash1, doorHandle1}, ..., {doorHashN, doorHandleN}] + ``` + + + An object containing a list of door system entries. + + + + + This native is not implemented. + + + + + + + + This native is not implemented. + + + + + This native is not implemented. + + + + + + + This native is not implemented. + + + + + This native is not implemented. + + + + + This native is not implemented. + + + + + + This native is not implemented. + + + + + This native is not implemented. + + + + + + Forces the game snow pass to render. + + + Whether or not to force rendering to use a snow pass. + + + + + Returns all player indices for 'active' physical players known to the client. + The data returned adheres to the following layout: + ``` + [127, 42, 13, 37] + ``` + + + An object containing a list of player indices. + + + + + Returns all player indices for 'active' physical players known to the client. + The data returned adheres to the following layout: + ``` + [127, 42, 13, 37] + ``` + + + An object containing a list of player indices. + + + + + A getter for [SET_AMBIENT_PED_RANGE_MULTIPLIER_THIS_FRAME](#_0x0B919E1FB47CC4E0). + + + Returns ambient ped range multiplier value. + + + + + A getter for [SET_AMBIENT_VEHICLE_RANGE_MULTIPLIER_THIS_FRAME](#_0x90B6DA738A9A25DA). + + + Returns ambient vehicle range multiplier value. + + + + + Gets the ped's core value on a scale of 0 to 100. The coreIndex is as follows: + - health = 0, + - stamina = 1, + - deadeye = 2 + + + : + + + : + + + + + Returns the world matrix of the specified camera. To turn this into a view matrix, calculate the inverse. + + + + + Returns the world matrix of the specified camera. To turn this into a view matrix, calculate the inverse. + + + + + + + + + + Returns the name of the currently executing resource. + + + The name of the resource. + + + + + Returns the name of the currently executing resource. + + + The name of the resource. + + + + + Returns the peer address of the remote game server that the user is currently connected to. + + + The peer address of the game server (e.g. `127.0.0.1:30120`), or NULL if not available. + + + + + Returns the peer address of the remote game server that the user is currently connected to. + + + The peer address of the game server (e.g. `127.0.0.1:30120`), or NULL if not available. + + + + + Returns the NUI window handle for a specified DUI browser object. + + + The DUI browser handle. + + + The NUI window handle, for use in e.g. CREATE_RUNTIME_TEXTURE_FROM_DUI_HANDLE. + + + + + Returns the NUI window handle for a specified DUI browser object. + + + The DUI browser handle. + + + The NUI window handle, for use in e.g. CREATE_RUNTIME_TEXTURE_FROM_DUI_HANDLE. + + + + + Return example: 1207.69_dev_pc + + + + + Returns all pool handles for the given pool name; the data returned adheres to the following layout: + ``` + [ 770, 1026, 1282, 1538, 1794, 2050, 2306, 2562, 2818, 3074, 3330, 3586, 3842, 4098, 4354, 4610, ...] + ``` + ### Supported Pools + **1**: CPed + **2**: CObject + **3**: CVehicle + **4**: CPickup + + + An object containing a list of all pool handles + + + + + Returns the label text given the hash. + + + : + + + + + Returns the zoom level data by index from mapzoomdata.meta file. + + + Zoom level index. + + + fZoomScale value. + + + fZoomSpeed value. + + + fScrollSpeed value. + + + vTiles X. + + + vTiles Y. + + + A boolean indicating TRUE if the data was received successfully. + + + + + Returns the zoom level data by index from mapzoomdata.meta file. + + + Zoom level index. + + + fZoomScale value. + + + fZoomSpeed value. + + + fScrollSpeed value. + + + vTiles X. + + + vTiles Y. + + + A boolean indicating TRUE if the data was received successfully. + + + + + Gets the amount of metadata values with the specified key existing in the specified resource's manifest. + See also: [Resource manifest](https://docs.fivem.net/resources/manifest/) + + + The resource name. + + + The key to look up in the resource manifest. + + + + + Gets the amount of metadata values with the specified key existing in the specified resource's manifest. + See also: [Resource manifest](https://docs.fivem.net/resources/manifest/) + + + The resource name. + + + The key to look up in the resource manifest. + + + + + A getter for [SET_PARKED_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME](#_0xEAE6DCC7EEE3DB1D). + + + Returns parked vehicle density multiplier value. + + + + + A getter for [SET_PED_DENSITY_MULTIPLIER_THIS_FRAME](#_0x95E3D6257B166CF2). + + + Returns ped density multiplier value. + + + + + A getter for [\_SET_PED_EYE_COLOR](#_0x50B56988B170AFDF). Returns -1 if fails to get. + + + The target ped + + + Returns ped's eye colour, or -1 if fails to get. + + + + + A getter for [\_SET_PED_EYE_COLOR](#_0x50B56988B170AFDF). Returns -1 if fails to get. + + + The target ped + + + Returns ped's eye colour, or -1 if fails to get. + + + + + A getter for [\_SET_PED_FACE_FEATURE](#_0x71A5C1DBA060049E). Returns 0.0 if fails to get. + + + The target ped + + + Face feature index + + + Returns ped's face feature value, or 0.0 if fails to get. + + + + + A getter for [\_SET_PED_FACE_FEATURE](#_0x71A5C1DBA060049E). Returns 0.0 if fails to get. + + + The target ped + + + Face feature index + + + Returns ped's face feature value, or 0.0 if fails to get. + + + + + A getter for [\_SET_PED_HAIR_COLOR](#_0x4CFFC65454C93A49). Returns -1 if fails to get. + + + The target ped + + + Returns ped's primary hair colour. + + + + + A getter for [\_SET_PED_HAIR_COLOR](#_0x4CFFC65454C93A49). Returns -1 if fails to get. + + + The target ped + + + Returns ped's primary hair colour. + + + + + A getter for [\_SET_PED_HAIR_COLOR](#_0x4CFFC65454C93A49). Returns -1 if fails to get. + + + The target ped + + + Returns ped's secondary hair colour. + + + + + A getter for [\_SET_PED_HAIR_COLOR](#_0x4CFFC65454C93A49). Returns -1 if fails to get. + + + The target ped + + + Returns ped's secondary hair colour. + + + + + A getter for [SET_PED_HEAD_OVERLAY](#_0x48F44967FA05CC1E) and [\_SET_PED_HEAD_OVERLAY_COLOR](#_0x497BF74A7B9CB952) natives. + + + The target ped + + + Overlay index + + + Overlay value pointer + + + Colour type pointer + + + First colour pointer + + + Second colour pointer + + + Opacity pointer + + + Returns ped's head overlay data. + + + + + A getter for [SET_PED_HEAD_OVERLAY](#_0x48F44967FA05CC1E) and [\_SET_PED_HEAD_OVERLAY_COLOR](#_0x497BF74A7B9CB952) natives. + + + The target ped + + + Overlay index + + + Overlay value pointer + + + Colour type pointer + + + First colour pointer + + + Second colour pointer + + + Opacity pointer + + + Returns ped's head overlay data. + + + + + A getter for [SET_PLAYER_MELEE_WEAPON_DAMAGE_MODIFIER](#_0x4A3DC7ECCC321032). + + + Returns player melee weapon damage modifier value. + + + + + A getter for [SET_PLAYER_MELEE_WEAPON_DEFENSE_MODIFIER](#_0xAE540335B4ABC4E2). + + + The player index. + + + The value of player melee weapon defense modifier. + + + + + A getter for [SET_PLAYER_VEHICLE_DAMAGE_MODIFIER](#_0xA50E117CDDF82F0C). + + + The player index. + + + The value of player vehicle damage modifier. + + + + + A getter for [SET_PLAYER_VEHICLE_DEFENSE_MODIFIER](#_0x4C60E6EFDAFF2462). + + + The player index. + + + The value of player vehicle defense modifier. + + + + + A getter for [SET_PLAYER_WEAPON_DAMAGE_MODIFIER](#_0xCE07B9F7817AADA3). + + + The player index. + + + The value of player weapon damage modifier. + + + + + A getter for [SET_PLAYER_WEAPON_DEFENSE_MODIFIER](#_0x2D83BC011CA14A3C). + + + The player index. + + + The value of player weapon defense modifier. + + + + + A getter for [\_SET_PLAYER_WEAPON_DEFENSE_MODIFIER_2](#_0xBCFDE9EDE4CF27DC). + + + The player index. + + + The value of player weapon defense modifier 2. + + + + + A getter for [SET_RANDOM_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME](#_0xB3B3359379FE77D3). + Same as vehicle density multiplier. + + + Returns random vehicle density multiplier value. + + + + + Returns all commands that are registered in the command system. + The data returned adheres to the following layout: + ``` + [ + { + "name": "cmdlist" + }, + { + "name": "command1" + } + ] + ``` + + + An object containing registered commands. + + + + + Returns all commands that are registered in the command system. + The data returned adheres to the following layout: + ``` + [ + { + "name": "cmdlist" + }, + { + "name": "command1" + } + ] + ``` + + + An object containing registered commands. + + + + + Gets the metadata value at a specified key/index from a resource's manifest. + See also: [Resource manifest](https://docs.fivem.net/resources/manifest/) + + + The resource name. + + + The key in the resource manifest. + + + The value index, in a range from [0..GET_NUM_RESOURCE_METDATA-1]. + + + + + Gets the metadata value at a specified key/index from a resource's manifest. + See also: [Resource manifest](https://docs.fivem.net/resources/manifest/) + + + The resource name. + + + The key in the resource manifest. + + + The value index, in a range from [0..GET_NUM_RESOURCE_METDATA-1]. + + + + + Returns the current state of the specified resource. + + + The name of the resource. + + + The resource state. One of `"missing", "started", "starting", "stopped", "stopping", "uninitialized" or "unknown"`. + + + + + Returns the current state of the specified resource. + + + The name of the resource. + + + The resource state. One of `"missing", "started", "starting", "stopped", "stopping", "uninitialized" or "unknown"`. + + + + + Gets the height of the specified runtime texture. + + + A handle to the runtime texture. + + + The height in pixels. + + + + + Gets the height of the specified runtime texture. + + + A handle to the runtime texture. + + + The height in pixels. + + + + + Gets the row pitch of the specified runtime texture, for use when creating data for `SET_RUNTIME_TEXTURE_ARGB_DATA`. + + + A handle to the runtime texture. + + + The row pitch in bytes. + + + + + Gets the row pitch of the specified runtime texture, for use when creating data for `SET_RUNTIME_TEXTURE_ARGB_DATA`. + + + A handle to the runtime texture. + + + The row pitch in bytes. + + + + + Gets the width of the specified runtime texture. + + + A handle to the runtime texture. + + + The width in pixels. + + + + + Gets the width of the specified runtime texture. + + + A handle to the runtime texture. + + + The width in pixels. + + + + + A getter for [SET_SCENARIO_PED_DENSITY_MULTIPLIER_THIS_FRAME](#_0x7A556143A1C03898). + + + Returns scenario ped density multiplier value. + + + + + 0 = invalid + 1 = CEntity + 2 = 0x2A72C62B + 3 = 0xE63A0D71 + 4 = 0x9FDE1AC6 + 5 = 0x6D766374 + 6 = 0x27ACC35B + 7 = CScriptedCoverPoint + 8 = ptfxScriptInfo + 9 = CPed + 10 = CVehicle + 11 = CObject + 12 = CItemSet + 13 = 0x830B8272 + + + : + + + + + Returns the value of a state bag key. + + + Value. + + + + + A getter for [SET_VEHICLE_CHEAT_POWER_INCREASE](#_0xB59E4BD37AE292DB). + + + The target vehicle. + + + Returns vehicle's cheat power increase modifier value. + + + + + A getter for [SET_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME](#_0x245A6883D966D537). + + + Returns vehicle density multiplier value. + + + + + Gets a vehicle's multiplier used with a wheel's GET_VEHICLE_WHEEL_STEERING_ANGLE to determine the angle the wheel is rendered. + + + : + + + + + Returns the effective handling data of a vehicle as a floating-point value. + Example: `local fSteeringLock = GetVehicleHandlingFloat(vehicle, 'CHandlingData', 'fSteeringLock')` + + + The vehicle to obtain data for. + + + The handling class to get. Only "CHandlingData" is supported at this time. + + + The field name to get. These match the keys in `handling.meta`. + + + A floating-point value. + + + + + Returns the effective handling data of a vehicle as a floating-point value. + Example: `local fSteeringLock = GetVehicleHandlingFloat(vehicle, 'CHandlingData', 'fSteeringLock')` + + + The vehicle to obtain data for. + + + The handling class to get. Only "CHandlingData" is supported at this time. + + + The field name to get. These match the keys in `handling.meta`. + + + A floating-point value. + + + + + Returns the effective handling data of a vehicle as an integer value. + Example: `local modelFlags = GetVehicleHandlingInt(vehicle, 'CHandlingData', 'strModelFlags')` + + + The vehicle to obtain data for. + + + The handling class to get. Only "CHandlingData" is supported at this time. + + + The field name to get. These match the keys in `handling.meta`. + + + An integer. + + + + + Returns the effective handling data of a vehicle as an integer value. + Example: `local modelFlags = GetVehicleHandlingInt(vehicle, 'CHandlingData', 'strModelFlags')` + + + The vehicle to obtain data for. + + + The handling class to get. Only "CHandlingData" is supported at this time. + + + The field name to get. These match the keys in `handling.meta`. + + + An integer. + + + + + Returns the effective handling data of a vehicle as a vector value. + Example: `local inertiaMultiplier = GetVehicleHandlingVector(vehicle, 'CHandlingData', 'vecInertiaMultiplier')` + + + The vehicle to obtain data for. + + + The handling class to get. Only "CHandlingData" is supported at this time. + + + The field name to get. These match the keys in `handling.meta`. + + + An integer. + + + + + Returns the effective handling data of a vehicle as a vector value. + Example: `local inertiaMultiplier = GetVehicleHandlingVector(vehicle, 'CHandlingData', 'vecInertiaMultiplier')` + + + The vehicle to obtain data for. + + + The handling class to get. Only "CHandlingData" is supported at this time. + + + The field name to get. These match the keys in `handling.meta`. + + + An integer. + + + + + Gets the vehicle indicator light state. 0 = off, 1 = left, 2 = right, 3 = both + + + + An integer. + + + + + Gets the vehicle indicator light state. 0 = off, 1 = left, 2 = right, 3 = both + + + An integer. + + + + + A getter for [MODIFY_VEHICLE_TOP_SPEED](#_0x93A3996368C94158). Returns -1.0 if a modifier is not set. + + + The target vehicle. + + + Returns vehicle's modified top speed. + + + + + Gets brake pressure of a wheel. + Max number of wheels can be retrieved with the native GET_VEHICLE_NUMBER_OF_WHEELS. + + + : + + + : + + + + + Returns vehicle's wheels' size (size is the same for all the wheels, cannot get/set specific wheel of vehicle). + Only works on non-default wheels (returns 0 in case of default wheels). + + + The vehicle to obtain data for. + + + Float representing size of the wheel (usually between 0.5 and 1.5) + + + + + Gets speed of a wheel at the tyre. + Max number of wheels can be retrieved with the native GET_VEHICLE_NUMBER_OF_WHEELS. + + + + + An integer. + + + + + Gets speed of a wheel at the tyre. + Max number of wheels can be retrieved with the native GET_VEHICLE_NUMBER_OF_WHEELS. + + + An integer. + + + + + Gets steering angle of a wheel. + Max number of wheels can be retrieved with the native GET_VEHICLE_NUMBER_OF_WHEELS. + + + : + + + : + + + The steering angle of the wheel, with 0 being straight. + + + + + Returns vehicle's wheels' width (width is the same for all the wheels, cannot get/set specific wheel of vehicle). + Only works on non-default wheels (returns 0 in case of default wheels). + + + The vehicle to obtain data for. + + + Float representing width of the wheel (usually between 0.1 and 1.5) + + + + + Returns the offset of the specified wheel relative to the wheel's axle center. + + + + + Returns the offset of the specified wheel relative to the wheel's axle center. + + + + + + + List of known states: + ``` + 1: Not wheeling. + 65: Vehicle is ready to do wheelie (burnouting). + 129: Vehicle is doing wheelie. + ``` + + + Vehicle + + + Vehicle's current wheelie state. + + + + + List of known states: + ``` + 1: Not wheeling. + 65: Vehicle is ready to do wheelie (burnouting). + 129: Vehicle is doing wheelie. + ``` + + + Vehicle + + + Vehicle's current wheelie state. + + + + + A getter for [\_SET_WEAPON_DAMAGE_MODIFIER](#_0x4757F00BC6323CFE). + + + Weapon name hash. + + + A weapon damage modifier. + + + + + Gets the model hash from the weapon hash. + + + : + + + + + Gives the ped the weapon. p7 is 0.5f, and p8 is 1.0f. p11 and p12 are both 0. + For a list of weapon groups, here is a weapons enum by Mooshe with all weapon-related hashes: https://pastebin.com/n72eW6zd + + + : + + + : + + + : + + + : + + + : + + + : + + + : + + + : + + + : + + + : + + + : + + + : + + + : + + + + + Returns whether or not the specific minimap overlay has loaded. + + + A minimap overlay ID. + + + A boolean indicating load status. + + + + + Returns whether or not the specific minimap overlay has loaded. + + + A minimap overlay ID. + + + A boolean indicating load status. + + + + + Note: the buffer should be exactly 32 bytes long + + + : + + + : + + + : + + + + + <!-- Native implemented by Disquse. 0xFFF65C63 --> + Returns true if the minimap is currently expanded. False if it's the normal minimap state. + Use [`IsBigmapFull`](#_0x66EE14B2) to check if the full map is currently revealed on the minimap. + + + A bool indicating if the minimap is currently expanded or normal state. + + + + + <!-- Native implemented by Disquse. 0xFFF65C63 --> + Returns true if the minimap is currently expanded. False if it's the normal minimap state. + Use [`IsBigmapFull`](#_0x66EE14B2) to check if the full map is currently revealed on the minimap. + + + A bool indicating if the minimap is currently expanded or normal state. + + + + + <!-- Native implemented by Disquse. 0x66EE14B2 --> + Returns true if the full map is currently revealed on the minimap. + Use [`IsBigmapActive`](#_0xFFF65C63) to check if the minimap is currently expanded or in it's normal state. + + + Returns true if the full map is currently revealed on the minimap. + + + + + <!-- Native implemented by Disquse. 0x66EE14B2 --> + Returns true if the full map is currently revealed on the minimap. + Use [`IsBigmapActive`](#_0xFFF65C63) to check if the minimap is currently expanded or in it's normal state. + + + Returns true if the full map is currently revealed on the minimap. + + + + + Returns whether or not a browser is created for a specified DUI browser object. + + + The DUI browser handle. + + + A boolean indicating TRUE if the browser is created. + + + + + Returns whether or not a browser is created for a specified DUI browser object. + + + The DUI browser handle. + + + A boolean indicating TRUE if the browser is created. + + + + + Gets whether or not this is the CitizenFX server. + + + A boolean value. + + + + + Gets whether or not this is the CitizenFX server. + + + A boolean value. + + + + + Same as GET_IS_LOADING_SCREEN_ACTIVE + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + Returns whether an asynchronous streaming file registration completed. + + + The file name to check, for example `asset.ydr`. + + + Whether or not the streaming file has been registered. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + Returns whether an asynchronous streaming file registration completed. + + + The file name to check, for example `asset.ydr`. + + + Whether or not the streaming file has been registered. + + + + + Reads the contents of a text file in a specified resource. + If executed on the client, this file has to be included in `files` in the resource manifest. + Example: `local data = LoadResourceFile("devtools", "data.json")` + + + The resource name. + + + The file in the resource. + + + The file contents + + + + + Reads the contents of a text file in a specified resource. + If executed on the client, this file has to be included in `files` in the resource manifest. + Example: `local data = LoadResourceFile("devtools", "data.json")` + + + The resource name. + + + The file in the resource. + + + The file contents + + + + + Starts listening to the specified channel, when available. + + + A game voice channel ID. + + + + + Adds the specified channel to the target list for the specified Mumble voice target ID. + + + A Mumble voice target ID, ranging from 1..30 (inclusive). + + + A game voice channel ID. + + + + + Adds the specified player to the target list for the specified Mumble voice target ID. + + + A Mumble voice target ID, ranging from 1..30 (inclusive). + + + A game player index. + + + + + Adds the specified player to the target list for the specified Mumble voice target ID. + + + A Mumble voice target ID, ranging from 1..30 (inclusive). + + + The player's server id. + + + + + Clears the target list for the specified Mumble voice target ID. + + + A Mumble voice target ID, ranging from 1..30 (inclusive). + + + + + Clears channels from the target list for the specified Mumble voice target ID. + + + A Mumble voice target ID, ranging from 1..30 (inclusive). + + + + + Clears players from the target list for the specified Mumble voice target ID. + + + A Mumble voice target ID, ranging from 1..30 (inclusive). + + + + + Returns the mumble voice channel from a player's server id. + + + The player's server id. + + + Int representing the identifier of the voice channel. + + + + + This native will return true if the user succesfully connected to the voice server. + If the user disabled the voice-chat setting it will return false. + + + True if the player is connected to a mumble server. + + + + + Stops listening to the specified channel. + + + A game voice channel ID. + + + + + Changes the Mumble server address to connect to, and reconnects to the new address. + + + The address of the mumble server. + + + The port of the mumble server. + + + + + Sets the current Mumble voice target ID to broadcast voice to. + + + A Mumble voice target ID, ranging from 1..30 (inclusive). 0 disables voice targets, and 31 is server loopback. + + + + + Overrides the output volume for a particular player on Mumble. This will also bypass 3D audio and distance calculations. -1.0 to reset the override. + Set to -1.0 to reset the Volume override. + + + A game player index. + + + The volume, ranging from 0.0 to 1.0 (or above). + + + + + Overrides the output volume for a particular player with the specified server id and player name on Mumble. This will also bypass 3D audio and distance calculations. -1.0 to reset the override. + + + The player's server id. + + + The volume, ranging from 0.0 to 1.0 (or above). + + + + + Returns true if GtaThread+0x77C is equal to 1. + + + + + Sets bit 0 in GtaThread+0x784 + + + + + BG_* + + + : + + + : + + + + + SET_PED_CAN_* + + + : + + + : + + + + + BG_* + + + : + + + : + + + + + BG_* + + + : + + + + + nullsub, doesn't do anything + + + + + nullsub, doesn't do anything + + + : + + + + + nullsub, doesn't do anything + + + + + SET_ENTITY_LO* + + + : + + + : + + + : + + + : + + + + + Sorts some unknown data. + Likely SORT_* + + + + + SET_PED_CAN_* + + + : + + + : + + + + + SET_PED_CAN_* + + + : + + + : + + + + + SET_ENTITY_LO* + + + : + + + : + + + + + Returns value of fwuiCachedSetting "general.onlineNotificationsInStoryMode" + + + + + Returns the owner ID of the specified entity. + + + The entity to get the owner for. + + + On the server, the server ID of the entity owner. On the client, returns the player/slot ID of the entity owner. + + + + + Returns the owner ID of the specified entity. + + + The entity to get the owner for. + + + On the server, the server ID of the entity owner. On the client, returns the player/slot ID of the entity owner. + + + + + Scope entry for profiler. + + + Scope name. + + + + + Scope entry for profiler. + + + Scope name. + + + + + Scope exit for profiler. + + + + + Scope exit for profiler. + + + + + Returns true if the profiler is active. + + + True or false. + + + + + Returns true if the profiler is active. + + + True or false. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + Registers a set of archetypes with the game engine. These should match `CBaseArchetypeDef` class information from the game. + + + A function returning a list of archetypes. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + Registers a set of archetypes with the game engine. These should match `CBaseArchetypeDef` class information from the game. + + + A function returning a list of archetypes. + + + + + Registered commands can be executed by entering them in the client console (this works for client side and server side registered commands). Or by entering them in the server console/through an RCON client (only works for server side registered commands). Or if you use a supported chat resource, like the default one provided in the cfx-server-data repository, then you can enter the command in chat by prefixing it with a `/`. + Commands registered using this function can also be executed by resources, using the [`ExecuteCommand` native](#_0x561C060B). + The restricted bool is not used on the client side. Permissions can only be checked on the server side, so if you want to limit your command with an ace permission automatically, make it a server command (by registering it in a server script). + **Example result**: + ![](https://i.imgur.com/TaCnG09.png) + + + The command you want to register. + + + A handler function that gets called whenever the command is executed. + + + If this is a server command and you set this to true, then players will need the command.yourCommandName ace permission to execute this command. + + + + + Registered commands can be executed by entering them in the client console (this works for client side and server side registered commands). Or by entering them in the server console/through an RCON client (only works for server side registered commands). Or if you use a supported chat resource, like the default one provided in the cfx-server-data repository, then you can enter the command in chat by prefixing it with a `/`. + Commands registered using this function can also be executed by resources, using the [`ExecuteCommand` native](#_0x561C060B). + The restricted bool is not used on the client side. Permissions can only be checked on the server side, so if you want to limit your command with an ace permission automatically, make it a server command (by registering it in a server script). + **Example result**: + ![](https://i.imgur.com/TaCnG09.png) + + + The command you want to register. + + + A handler function that gets called whenever the command is executed. + + + If this is a server command and you set this to true, then players will need the command.yourCommandName ace permission to execute this command. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + Registers a set of entities with the game engine. These should match `CEntityDef` class information from the game. + At this time, this function **should not be used in a live environment**. + + + A function returning a list of entities. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + Registers a set of entities with the game engine. These should match `CEntityDef` class information from the game. + At this time, this function **should not be used in a live environment**. + + + A function returning a list of entities. + + + + + Registers a specified .gfx file as GFx font library. + The .gfx file has to be registered with the streamer already. + + + The name of the .gfx file, without extension. + + + + + Registers a specified .gfx file as GFx font library. + The .gfx file has to be registered with the streamer already. + + + The name of the .gfx file, without extension. + + + + + Registers a specified font name for use with text draw commands. + + + The name of the font in the GFx font library. + + + An index to use with [SET_TEXT_FONT](#_0x66E0276CC5F6B9DA) and similar natives. + + + + + Registers a specified font name for use with text draw commands. + + + The name of the font in the GFx font library. + + + An index to use with [SET_TEXT_FONT](#_0x66E0276CC5F6B9DA) and similar natives. + + + + + Registers a key mapping for the current resource. + See the related [cookbook post](https://cookbook.fivem.net/2020/01/06/using-the-new-console-key-bindings/) for more information. + + + The command to execute, and the identifier of the binding. + + + A description for in the settings menu. + + + The mapper ID to use for the default binding, e.g. `keyboard`. + + + The IO parameter ID to use for the default binding, e.g. `f3`. + + + + + An internal function which allows the current resource's HLL script runtimes to receive state for the specified event. + + + An event name, or "\*" to disable HLL event filtering for this resource. + + + + + An internal function which allows the current resource's HLL script runtimes to receive state for the specified event. + + + An event name, or "\*" to disable HLL event filtering for this resource. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + Registers a dynamic streaming asset from the server with the GTA streaming module system. + + + The resource to add the asset to. + + + A file name in the resource. + + + The string returned from `REGISTER_RESOURCE_ASSET` on the server. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + Registers a dynamic streaming asset from the server with the GTA streaming module system. + + + The resource to add the asset to. + + + A file name in the resource. + + + The string returned from `REGISTER_RESOURCE_ASSET` on the server. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + Registers a KVP value as an asset with the GTA streaming module system. This function currently won't work. + + + The KVP key in the current resource to register as an asset. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + Registers a KVP value as an asset with the GTA streaming module system. This function currently won't work. + + + The KVP key in the current resource to register as an asset. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + Registers a file from an URL as a streaming asset in the GTA streaming subsystem. This will asynchronously register the asset, and caching is done based on the URL itself - cache headers are ignored. + Use `IS_STREAMING_FILE_READY` to check if the asset has been registered successfully. + + + The file name to register as, for example `asset.ydr`. + + + The URL to fetch the asset from. + + + + + **Experimental**: This native may be altered or removed in future versions of CitizenFX without warning. + Registers a file from an URL as a streaming asset in the GTA streaming subsystem. This will asynchronously register the asset, and caching is done based on the URL itself - cache headers are ignored. + Use `IS_STREAMING_FILE_READY` to check if the asset has been registered successfully. + + + The file name to register as, for example `asset.ydr`. + + + The URL to fetch the asset from. + + + + + Experimental natives, please do not use in a live environment. + + + + + + + Experimental natives, please do not use in a live environment. + + + + + Resets values from the zoom level data by index to defaults from mapzoomdata.meta. + + + Zoom level index. + + + + + Resets values from the zoom level data by index to defaults from mapzoomdata.meta. + + + Zoom level index. + + + + + Sends a message to the specific DUI root page. This is similar to SEND_NUI_MESSAGE. + + + The DUI browser handle. + + + The message, encoded as JSON. + + + + + Sends a message to the specific DUI root page. This is similar to SEND_NUI_MESSAGE. + + + The DUI browser handle. + + + The message, encoded as JSON. + + + + + Injects a 'mouse down' event for a DUI object. Coordinates are expected to be set using SEND_DUI_MOUSE_MOVE. + + + The DUI browser handle. + + + Either `'left'`, `'middle'` or `'right'`. + + + + + Injects a 'mouse down' event for a DUI object. Coordinates are expected to be set using SEND_DUI_MOUSE_MOVE. + + + The DUI browser handle. + + + Either `'left'`, `'middle'` or `'right'`. + + + + + Injects a 'mouse move' event for a DUI object. Coordinates are in browser space. + + + The DUI browser handle. + + + The mouse X position. + + + The mouse Y position. + + + + + Injects a 'mouse move' event for a DUI object. Coordinates are in browser space. + + + The DUI browser handle. + + + The mouse X position. + + + The mouse Y position. + + + + + Injects a 'mouse up' event for a DUI object. Coordinates are expected to be set using SEND_DUI_MOUSE_MOVE. + + + The DUI browser handle. + + + Either `'left'`, `'middle'` or `'right'`. + + + + + Injects a 'mouse up' event for a DUI object. Coordinates are expected to be set using SEND_DUI_MOUSE_MOVE. + + + The DUI browser handle. + + + Either `'left'`, `'middle'` or `'right'`. + + + + + Injects a 'mouse wheel' event for a DUI object. + + + The DUI browser handle. + + + The wheel Y delta. + + + The wheel X delta. + + + + + Injects a 'mouse wheel' event for a DUI object. + + + The DUI browser handle. + + + The wheel Y delta. + + + The wheel X delta. + + + + + Sends a message to the `loadingScreen` NUI frame, which contains the HTML page referenced in `loadscreen` resources. + + + The JSON-encoded message. + + + A success value. + + + + + Sends a message to the `loadingScreen` NUI frame, which contains the HTML page referenced in `loadscreen` resources. + + + The JSON-encoded message. + + + A success value. + + + + + This native sets the app id for the discord rich presence implementation. + + + + + This native sets the app id for the discord rich presence implementation. + + + + + This native sets the image asset for the discord rich presence implementation. + + + The name of a valid asset registered on Discordapp's developer dashboard. note that the asset has to be registered under the same discord API application set using the SET_DISCORD_APP_ID native. + + + + + This native sets the image asset for the discord rich presence implementation. + + + The name of a valid asset registered on Discordapp's developer dashboard. note that the asset has to be registered under the same discord API application set using the SET_DISCORD_APP_ID native. + + + + + This native sets the small image asset for the discord rich presence implementation. + + + The name of a valid asset registered on Discordapp's developer dashboard. Note that the asset has to be registered under the same discord API application set using the SET_DISCORD_APP_ID native. + + + + + This native sets the small image asset for the discord rich presence implementation. + + + The name of a valid asset registered on Discordapp's developer dashboard. Note that the asset has to be registered under the same discord API application set using the SET_DISCORD_APP_ID native. + + + + + This native sets the hover text of the small image asset for the discord rich presence implementation. + + + Text to be displayed when hovering over small image asset. Note that you must also set a valid small image asset using the SET_DISCORD_RICH_PRESENCE_ASSET_SMALL native. + + + + + This native sets the hover text of the small image asset for the discord rich presence implementation. + + + Text to be displayed when hovering over small image asset. Note that you must also set a valid small image asset using the SET_DISCORD_RICH_PRESENCE_ASSET_SMALL native. + + + + + This native sets the hover text of the image asset for the discord rich presence implementation. + + + Text to be displayed when hovering over image asset. Note that you must also set a valid image asset using the SET_DISCORD_RICH_PRESENCE_ASSET native. + + + + + This native sets the hover text of the image asset for the discord rich presence implementation. + + + Text to be displayed when hovering over image asset. Note that you must also set a valid image asset using the SET_DISCORD_RICH_PRESENCE_ASSET native. + + + + + Navigates the specified DUI browser to a different URL. + + + The DUI browser handle. + + + The new URL. + + + + + Navigates the specified DUI browser to a different URL. + + + The DUI browser handle. + + + The new URL. + + + + + Sets the entity's health. healthAmount sets the health value to that, and sets the maximum health core value. Setting healthAmount to 0 will kill the entity. Unclear what role p2 serves, but it's either 0 or an entity handle. + + + : + + + : + + + : + + + + + Sets a global handling override for a specific vehicle class. The name is supposed to match the `handlingName` field from handling.meta. + Example: `SetHandlingField('AIRTUG', 'CHandlingData', 'fSteeringLock', 360.0)` + + + The vehicle class to set data for. + + + The handling class to set. Only "CHandlingData" is supported at this time. + + + The field name to set. These match the keys in `handling.meta`. + + + The value to set. + + + + + Sets a global handling override for a specific vehicle class. The name is supposed to match the `handlingName` field from handling.meta. + Example: `SetHandlingField('AIRTUG', 'CHandlingData', 'fSteeringLock', 360.0)` + + + The vehicle class to set data for. + + + The handling class to set. Only "CHandlingData" is supported at this time. + + + The field name to set. These match the keys in `handling.meta`. + + + The value to set. + + + + + Sets a global handling override for a specific vehicle class. The name is supposed to match the `handlingName` field from handling.meta. + Example: `SetHandlingFloat('AIRTUG', 'CHandlingData', 'fSteeringLock', 360.0)` + + + The vehicle class to set data for. + + + The handling class to set. Only "CHandlingData" is supported at this time. + + + The field name to set. These match the keys in `handling.meta`. + + + The floating-point value to set. + + + + + Sets a global handling override for a specific vehicle class. The name is supposed to match the `handlingName` field from handling.meta. + Example: `SetHandlingFloat('AIRTUG', 'CHandlingData', 'fSteeringLock', 360.0)` + + + The vehicle class to set data for. + + + The handling class to set. Only "CHandlingData" is supported at this time. + + + The field name to set. These match the keys in `handling.meta`. + + + The floating-point value to set. + + + + + Sets a global handling override for a specific vehicle class. The name is supposed to match the `handlingName` field from handling.meta. + + + The vehicle class to set data for. + + + The handling class to set. Only "CHandlingData" is supported at this time. + + + The field name to set. These match the keys in `handling.meta`. + + + The integer value to set. + + + + + Sets a global handling override for a specific vehicle class. The name is supposed to match the `handlingName` field from handling.meta. + + + The vehicle class to set data for. + + + The handling class to set. Only "CHandlingData" is supported at this time. + + + The field name to set. These match the keys in `handling.meta`. + + + The integer value to set. + + + + + Sets a global handling override for a specific vehicle class. The name is supposed to match the `handlingName` field from handling.meta. + Example: `SetHandlingVector('AIRTUG', 'CHandlingData', 'vecCentreOfMassOffset', vector3(0.0, 0.0, -5.0))` + + + The vehicle class to set data for. + + + The handling class to set. Only "CHandlingData" is supported at this time. + + + The field name to set. These match the keys in `handling.meta`. + + + The Vector3 value to set. + + + + + Sets a global handling override for a specific vehicle class. The name is supposed to match the `handlingName` field from handling.meta. + Example: `SetHandlingVector('AIRTUG', 'CHandlingData', 'vecCentreOfMassOffset', vector3(0.0, 0.0, -5.0))` + + + The vehicle class to set data for. + + + The handling class to set. Only "CHandlingData" is supported at this time. + + + The field name to set. These match the keys in `handling.meta`. + + + The Vector3 value to set. + + + + + Sets whether or not `SHUTDOWN_LOADING_SCREEN` automatically shuts down the NUI frame for the loading screen. If this is enabled, + you will have to manually invoke `SHUTDOWN_LOADING_SCREEN_NUI` whenever you want to hide the NUI loading screen. + + + TRUE to manually shut down the loading screen NUI. + + + + + Sets whether or not `SHUTDOWN_LOADING_SCREEN` automatically shuts down the NUI frame for the loading screen. If this is enabled, + you will have to manually invoke `SHUTDOWN_LOADING_SCREEN_NUI` whenever you want to hide the NUI loading screen. + + + TRUE to manually shut down the loading screen NUI. + + + + + Sets values to the zoom level data by index. + + + Zoom level index. + + + fZoomScale value. + + + fZoomSpeed value. + + + fScrollSpeed value. + + + vTiles X. + + + vTiles Y. + + + + + Sets values to the zoom level data by index. + + + Zoom level index. + + + fZoomScale value. + + + fZoomSpeed value. + + + fScrollSpeed value. + + + vTiles X. + + + vTiles Y. + + + + + Overrides how many real ms are equal to one game minute. + A setter for [`GetMillisecondsPerGameMinute`](#_0x2F8B4D1C595B11DB). + + + Milliseconds. + + + + + Overrides how many real ms are equal to one game minute. + A setter for [`GetMillisecondsPerGameMinute`](#_0x2F8B4D1C595B11DB). + + + Milliseconds. + + + + + Sets the type for the minimap blip clipping object to be either rectangular or rounded. + + + 0 for rectangular, 1 for rounded. + + + + + Overrides the minimap component data (from `common:/data/ui/frontend.xml`) for a specified component. + + + The name of the minimap component to override. + + + Equivalent to the `alignX` field in `frontend.xml`. + + + Equivalent to the `alignY` field in `frontend.xml`. + + + Equivalent to the `posX` field in `frontend.xml`. + + + Equivalent to the `posY` field in `frontend.xml`. + + + Equivalent to the `sizeX` field in `frontend.xml`. + + + Equivalent to the `sizeY` field in `frontend.xml`. + + + + + Reveals the entire minimap (FOW = Fog of War) + + + : + + + + + Sets the display info for a minimap overlay. + + + The minimap overlay ID. + + + The X position for the overlay. This is equivalent to a game coordinate X. + + + The Y position for the overlay. This is equivalent to a game coordinate Y, except that it's inverted (gfxY = -gameY). + + + The X scale for the overlay. This is equivalent to the Flash \_xscale property, therefore 100 = 100%. + + + The Y scale for the overlay. This is equivalent to the Flash \_yscale property. + + + The alpha value for the overlay. This is equivalent to the Flash \_alpha property, therefore 100 = 100%. + + + + + Sets the display info for a minimap overlay. + + + The minimap overlay ID. + + + The X position for the overlay. This is equivalent to a game coordinate X. + + + The Y position for the overlay. This is equivalent to a game coordinate Y, except that it's inverted (gfxY = -gameY). + + + The X scale for the overlay. This is equivalent to the Flash \_xscale property, therefore 100 = 100%. + + + The Y scale for the overlay. This is equivalent to the Flash \_yscale property. + + + The alpha value for the overlay. This is equivalent to the Flash \_alpha property, therefore 100 = 100%. + + + + + Sets the outfit preset for the ped. The presetId is an index which determines it's preset outfit. p2 is always 0. + + + : + + + : + + + : + + + + + the status of default voip system. It affects on `NETWORK_IS_PLAYER_TALKING` and `mp_facial` animation. + This function doesn't need to be called every frame, it works like a switcher. + + + The target player. + + + Overriding state. + + + + + the status of default voip system. It affects on `NETWORK_IS_PLAYER_TALKING` and `mp_facial` animation. + This function doesn't need to be called every frame, it works like a switcher. + + + The target player. + + + Overriding state. + + + + + Sets the player's rich presence detail state for social platform providers to a specified string. + + + The rich presence string to set. + + + + + Sets the player's rich presence detail state for social platform providers to a specified string. + + + The rich presence string to set. + + + + + Sets a pixel in the specified runtime texture. This will have to be committed using `COMMIT_RUNTIME_TEXTURE` to have any effect. + + + A handle to the runtime texture. + + + The X position of the pixel to change. + + + The Y position of the pixel to change. + + + The new R value (0-255). + + + The new G value (0-255). + + + The new B value (0-255). + + + The new A value (0-255). + + + + + Sets a pixel in the specified runtime texture. This will have to be committed using `COMMIT_RUNTIME_TEXTURE` to have any effect. + + + A handle to the runtime texture. + + + The X position of the pixel to change. + + + The Y position of the pixel to change. + + + The new R value (0-255). + + + The new G value (0-255). + + + The new B value (0-255). + + + The new A value (0-255). + + + + + Internal function for setting a state bag value. + + + : + + + + + 0 = high + 1 = normal + 2 = low + + + : + + + + + Disables the vehicle from being repaired when a vehicle extra is enabled. + + + The vehicle to set disable auto vehicle repair. + + + Setting the value to true prevents the vehicle from being repaired when a extra is enabled. Setting the value to false allows the vehicle from being repaired when a extra is enabled. + + + + + Disables the vehicle from being repaired when a vehicle extra is enabled. + + + The vehicle to set disable auto vehicle repair. + + + Setting the value to true prevents the vehicle from being repaired when a extra is enabled. Setting the value to false allows the vehicle from being repaired when a extra is enabled. + + + + + Sets a handling override for a specific vehicle. Certain handling flags can only be set globally using `SET_HANDLING_FIELD`, this might require some experimentation. + Example: `SetVehicleHandlingField(vehicle, 'CHandlingData', 'fSteeringLock', 360.0)` + + + The vehicle to set data for. + + + The handling class to set. Only "CHandlingData" is supported at this time. + + + The field name to set. These match the keys in `handling.meta`. + + + The value to set. + + + + + Sets a handling override for a specific vehicle. Certain handling flags can only be set globally using `SET_HANDLING_FIELD`, this might require some experimentation. + Example: `SetVehicleHandlingField(vehicle, 'CHandlingData', 'fSteeringLock', 360.0)` + + + The vehicle to set data for. + + + The handling class to set. Only "CHandlingData" is supported at this time. + + + The field name to set. These match the keys in `handling.meta`. + + + The value to set. + + + + + Sets a handling override for a specific vehicle. Certain handling flags can only be set globally using `SET_HANDLING_FLOAT`, this might require some experimentation. + Example: `SetVehicleHandlingFloat(vehicle, 'CHandlingData', 'fSteeringLock', 360.0)` + + + The vehicle to set data for. + + + The handling class to set. Only "CHandlingData" is supported at this time. + + + The field name to set. These match the keys in `handling.meta`. + + + The floating-point value to set. + + + + + Sets a handling override for a specific vehicle. Certain handling flags can only be set globally using `SET_HANDLING_FLOAT`, this might require some experimentation. + Example: `SetVehicleHandlingFloat(vehicle, 'CHandlingData', 'fSteeringLock', 360.0)` + + + The vehicle to set data for. + + + The handling class to set. Only "CHandlingData" is supported at this time. + + + The field name to set. These match the keys in `handling.meta`. + + + The floating-point value to set. + + + + + Sets a handling override for a specific vehicle. Certain handling flags can only be set globally using `SET_HANDLING_INT`, this might require some experimentation. + + + The vehicle to set data for. + + + The handling class to set. Only "CHandlingData" is supported at this time. + + + The field name to set. These match the keys in `handling.meta`. + + + The integer value to set. + + + + + Sets a handling override for a specific vehicle. Certain handling flags can only be set globally using `SET_HANDLING_INT`, this might require some experimentation. + + + The vehicle to set data for. + + + The handling class to set. Only "CHandlingData" is supported at this time. + + + The field name to set. These match the keys in `handling.meta`. + + + The integer value to set. + + + + + Sets a handling override for a specific vehicle. Certain handling flags can only be set globally using `SET_HANDLING_VECTOR`, this might require some experimentation. + + + The vehicle to set data for. + + + The handling class to set. Only "CHandlingData" is supported at this time. + + + The field name to set. These match the keys in `handling.meta`. + + + The Vector3 value to set. + + + + + Sets a handling override for a specific vehicle. Certain handling flags can only be set globally using `SET_HANDLING_VECTOR`, this might require some experimentation. + + + The vehicle to set data for. + + + The handling class to set. Only "CHandlingData" is supported at this time. + + + The field name to set. These match the keys in `handling.meta`. + + + The Vector3 value to set. + + + + + Not sure what this changes, probably determines physical rim size in case the tire is blown. + + + The vehicle to obtain data for. + + + Index of wheel, 0-3. + + + Size of rim collider. + + + + + Sets vehicle's wheels' size (size is the same for all the wheels, cannot get/set specific wheel of vehicle). + Only works on non-default wheels. + Returns whether change was successful (can be false if trying to set size for non-default wheels). + + + The vehicle to set data for. + + + Size of the wheels (usually between 0.5 and 1.5 is reasonable). + + + Bool - whether change was successful or not + + + + + Use along with SetVehicleWheelSize to resize the wheels (this native sets the collider size affecting physics while SetVehicleWheelSize will change visual size). + + + The vehicle to obtain data for. + + + Index of wheel, 0-3. + + + Radius of tire collider. + + + + + Use along with SetVehicleWheelWidth to resize the wheels (this native sets the collider width affecting physics while SetVehicleWheelWidth will change visual width). + + + The vehicle to obtain data for. + + + Index of wheel, 0-3. + + + Width of tire collider. + + + + + Sets vehicle's wheels' width (width is the same for all the wheels, cannot get/set specific wheel of vehicle). + Only works on non-default wheels. + Returns whether change was successful (can be false if trying to set width for non-default wheels). + + + The vehicle to set data for. + + + Width of the wheels (usually between 0.1 and 1.5 is reasonable). + + + Bool - whether change was successful or not + + + + + Adjusts the offset of the specified wheel relative to the wheel's axle center. + Needs to be called every frame in order to function properly, as GTA will reset the offset otherwise. + This function can be especially useful to set the track width of a vehicle, for example: + ``` + function SetVehicleFrontTrackWidth(vehicle, width) + SetVehicleWheelXOffset(vehicle, 0, -width/2) + SetVehicleWheelXOffset(vehicle, 1, width/2) + end + ``` + + + + + Adjusts the offset of the specified wheel relative to the wheel's axle center. + Needs to be called every frame in order to function properly, as GTA will reset the offset otherwise. + This function can be especially useful to set the track width of a vehicle, for example: + ``` + function SetVehicleFrontTrackWidth(vehicle, width) + SetVehicleWheelXOffset(vehicle, 0, -width/2) + SetVehicleWheelXOffset(vehicle, 1, width/2) + end + ``` + + + + + + + + Example script: <https://pastebin.com/J6XGbkCW> + List of known states: + ``` + 1: Not wheeling. + 65: Vehicle is ready to do wheelie (burnouting). + 129: Vehicle is doing wheelie. + ``` + + + Vehicle + + + Wheelie state + + + + + Example script: <https://pastebin.com/J6XGbkCW> + List of known states: + ``` + 1: Not wheeling. + 65: Vehicle is ready to do wheelie (burnouting). + 129: Vehicle is doing wheelie. + ``` + + + Vehicle + + + Wheelie state + + + + + Overrides a floating point value from `visualsettings.dat` temporarily. + + + The name of the value to set, such as `pedLight.color.red`. + + + The value to write. + + + + + Overrides a floating point value from `visualsettings.dat` temporarily. + + + The name of the value to set, such as `pedLight.color.red`. + + + The value to write. + + + + + Same as SHOULD_USE_METRIC_MEASUREMENTS + + + + + Shuts down the `loadingScreen` NUI frame, similarly to `SHUTDOWN_LOADING_SCREEN`. + + + + + Shuts down the `loadingScreen` NUI frame, similarly to `SHUTDOWN_LOADING_SCREEN`. + + + + + statId: see 0xC48FE1971C9743FF + + + : + + + : + + + + + statId: see 0xC48FE1971C9743FF + + + : + + + : + + + + + statId: see 0xC48FE1971C9743FF + + + : + + + : + + + + + statId: see 0xC48FE1971C9743FF + + + : + + + : + + + + + struct StatId + { + alignas(8) Hash BaseId; + alignas(8) Hash PermutationId; + } + + + : + + + + + statId: see 0xC48FE1971C9743FF + + + : + + + : + + + : + + + + + statId: see 0xC48FE1971C9743FF + + + : + + + : + + + : + + + + + statId: see 0xC48FE1971C9743FF + + + : + + + : + + + : + + + + + statId: see 0xC48FE1971C9743FF + + + : + + + : + + + : + + + + + statId: see 0xC48FE1971C9743FF + + + : + + + : + + + : + + + + + statId: see 0xC48FE1971C9743FF + + + : + + + + + Dismounts the ped from the animal it's mounted on. taskFlag affects what side the rider gets off. 1 << 18 will get off on the left side, where any other value will get off on the right side. The only other known value are 1 << 17 and 1 << 24, which has the behavior of any other value (getting off the animal from the right side). p2-p5 are almost always 0. + + + : + + + : + + + : + + + : + + + : + + + : + + + + + Has the ped react to another entity. The reactionType determines how the ped reacts. p3 is 7.5f in the scripts. p4 is 0f. unkFlag is always 4. The rest of the parameters are unknown, but 0 is acceptable input. Here is a list of the different reaction type values by Mooshe: https://pastebin.com/Ju7BbmMt + + + : + + + : + + + : + + + : + + + : + + + : + + + : + + + : + + + : + + + + + Works in MP only. + + + : + + + + + The backing function for TriggerEvent. + + + + + + + + The backing function for TriggerEvent. + + + + + The backing function for TriggerLatentServerEvent. + + + + + The backing function for TriggerLatentServerEvent. + + + + + + + + + The backing function for TriggerServerEvent. + + + + + + + + The backing function for TriggerServerEvent. + + + + + Returns whether or not the currently executing event was canceled. + + + A boolean. + + + + + Returns whether or not the currently executing event was canceled. + + + A boolean. + + + + + Allow copying memory from one IntPtr to another. Required as the implementation does not provide an appropriate override. + + + + + + + + Empty Shared Field + + + + An uninitialized Color Structure + + + + + Equality Operator + + + + Compares two Color objects. The return value is + based on the equivalence of the A,R,G,B properties + of the two Colors. + + + + + Inequality Operator + + + + Compares two Color objects. The return value is + based on the equivalence of the A,R,G,B properties + of the two colors. + + + + + IsEmpty Property + + + + Indicates transparent black. R,G,B = 0; A=0? + + + + + Equals Method + + + + Checks equivalence of this Color and another object. + + + + + GetHashCode Method + + + + Calculates a hashing value. + + + + + ToString Method + + + + Formats the Color as a string in ARGB notation. + + + + + Empty Shared Field + + + + An uninitialized Point Structure. + + + + + Ceiling Shared Method + + + + Produces a Point structure from a PointF structure by + taking the ceiling of the X and Y properties. + + + + + Round Shared Method + + + + Produces a Point structure from a PointF structure by + rounding the X and Y properties. + + + + + Truncate Shared Method + + + + Produces a Point structure from a PointF structure by + truncating the X and Y properties. + + + + + Addition Operator + + + + Translates a Point using the Width and Height + properties of the given Size. + + + + + Equality Operator + + + + Compares two Point objects. The return value is + based on the equivalence of the X and Y properties + of the two points. + + + + + Inequality Operator + + + + Compares two Point objects. The return value is + based on the equivalence of the X and Y properties + of the two points. + + + + + Subtraction Operator + + + + Translates a Point using the negation of the Width + and Height properties of the given Size. + + + + + Point to Size Conversion + + + + Returns a Size based on the Coordinates of a given + Point. Requires explicit cast. + + + + + Point to PointF Conversion + + + + Creates a PointF based on the coordinates of a given + Point. No explicit cast is required. + + + + + Point Constructor + + + + Creates a Point from an integer which holds the Y + coordinate in the high order 16 bits and the X + coordinate in the low order 16 bits. + + + + + Point Constructor + + + + Creates a Point from a Size value. + + + + + Point Constructor + + + + Creates a Point from a specified x,y coordinate pair. + + + + + IsEmpty Property + + + + Indicates if both X and Y are zero. + + + + + X Property + + + + The X coordinate of the Point. + + + + + Y Property + + + + The Y coordinate of the Point. + + + + + Equals Method + + + + Checks equivalence of this Point and another object. + + + + + GetHashCode Method + + + + Calculates a hashing value. + + + + + Offset Method + + + + Moves the Point a specified distance. + + + + + ToString Method + + + + Formats the Point as a string in coordinate notation. + + + + + Empty Shared Field + + + + An uninitialized PointF Structure. + + + + + Addition Operator + + + + Translates a PointF using the Width and Height + properties of the given Size. + + + + + Equality Operator + + + + Compares two PointF objects. The return value is + based on the equivalence of the X and Y properties + of the two points. + + + + + Inequality Operator + + + + Compares two PointF objects. The return value is + based on the equivalence of the X and Y properties + of the two points. + + + + + Subtraction Operator + + + + Translates a PointF using the negation of the Width + and Height properties of the given Size. + + + + + PointF Constructor + + + + Creates a PointF from a specified x,y coordinate pair. + + + + + IsEmpty Property + + + + Indicates if both X and Y are zero. + + + + + X Property + + + + The X coordinate of the PointF. + + + + + Y Property + + + + The Y coordinate of the PointF. + + + + + Equals Method + + + + Checks equivalence of this PointF and another object. + + + + + GetHashCode Method + + + + Calculates a hashing value. + + + + + ToString Method + + + + Formats the PointF as a string in coordinate notation. + + + + + Empty Shared Field + + + + An uninitialized Size Structure. + + + + + Ceiling Shared Method + + + + Produces a Size structure from a SizeF structure by + taking the ceiling of the Width and Height properties. + + + + + Round Shared Method + + + + Produces a Size structure from a SizeF structure by + rounding the Width and Height properties. + + + + + Truncate Shared Method + + + + Produces a Size structure from a SizeF structure by + truncating the Width and Height properties. + + + + + Addition Operator + + + + Addition of two Size structures. + + + + + Equality Operator + + + + Compares two Size objects. The return value is + based on the equivalence of the Width and Height + properties of the two Sizes. + + + + + Inequality Operator + + + + Compares two Size objects. The return value is + based on the equivalence of the Width and Height + properties of the two Sizes. + + + + + Subtraction Operator + + + + Subtracts two Size structures. + + + + + Size to Point Conversion + + + + Returns a Point based on the dimensions of a given + Size. Requires explicit cast. + + + + + Size to SizeF Conversion + + + + Creates a SizeF based on the dimensions of a given + Size. No explicit cast is required. + + + + + Size Constructor + + + + Creates a Size from a Point value. + + + + + Size Constructor + + + + Creates a Size from specified dimensions. + + + + + IsEmpty Property + + + + Indicates if both Width and Height are zero. + + + + + Width Property + + + + The Width coordinate of the Size. + + + + + Height Property + + + + The Height coordinate of the Size. + + + + + Equals Method + + + + Checks equivalence of this Size and another object. + + + + + GetHashCode Method + + + + Calculates a hashing value. + + + + + ToString Method + + + + Formats the Size as a string in coordinate notation. + + + + + Empty Shared Field + + + + An uninitialized SizeF Structure. + + + + + Addition Operator + + + + Addition of two SizeF structures. + + + + + Equality Operator + + + + Compares two SizeF objects. The return value is + based on the equivalence of the Width and Height + properties of the two Sizes. + + + + + Inequality Operator + + + + Compares two SizeF objects. The return value is + based on the equivalence of the Width and Height + properties of the two Sizes. + + + + + Subtraction Operator + + + + Subtracts two SizeF structures. + + + + + SizeF to PointF Conversion + + + + Returns a PointF based on the dimensions of a given + SizeF. Requires explicit cast. + + + + + SizeF Constructor + + + + Creates a SizeF from a PointF value. + + + + + SizeF Constructor + + + + Creates a SizeF from an existing SizeF value. + + + + + SizeF Constructor + + + + Creates a SizeF from specified dimensions. + + + + + IsEmpty Property + + + + Indicates if both Width and Height are zero. + + + + + Width Property + + + + The Width coordinate of the SizeF. + + + + + Height Property + + + + The Height coordinate of the SizeF. + + + + + Equals Method + + + + Checks equivalence of this SizeF and another object. + + + + + GetHashCode Method + + + + Calculates a hashing value. + + + + + ToString Method + + + + Formats the SizeF as a string in coordinate notation. + + + + + Gets the column number in the file that contains the code that is executing. + This information is typically extracted from the debugging symbols for the executable. + + The file column number, or 0 (zero) if the file column number cannot be determined. + + + + Gets the line number in the file that contains the code that is executing. + This information is typically extracted from the debugging symbols for the executable. + + The file line number, or 0 (zero) if the file line number cannot be determined. + + + + Gets the file name that contains the code that is executing. + This information is typically extracted from the debugging symbols for the executable. + + The file name, or null if the file name cannot be determined. + + + + Gets the offset from the start of the Microsoft intermediate language (MSIL) + code for the method that is executing. This offset might be an approximation + depending on whether or not the just-in-time (JIT) compiler is generating debugging + code. The generation of this debugging information is controlled by the System.Diagnostics.DebuggableAttribute. + + The offset from the start of the MSIL code for the method that is executing. + + + + Gets the method in which the frame is executing. + + The method in which the frame is executing. + + + + Gets the offset from the start of the native just-in-time (JIT)-compiled code + for the method that is being executed. The generation of this debugging information + is controlled by the System.Diagnostics.DebuggableAttribute class. + + The offset from the start of the JIT-compiled code for the method that is being executed. + + + + Builds a readable representation of the stack trace. + + A readable representation of the stack trace. + + + + Gets the number of frames in the stack trace. + + The number of frames in the stack trace. + + + + Gets the specified stack frame. + + The index of the stack frame requested. + The specified stack frame. + + + + Returns a copy of all stack frames in the current stack trace. + + + An array of type System.Diagnostics.StackFrame representing the function calls + in the stack trace. + + + + + Builds a readable representation of the stack trace. + + A readable representation of the stack trace. + + + + Tries to convert a given to a full path. + Returns original value if the conversion isn't possible or a given path is relative. + + + + + + + + Demystifies the given and tracks the original stack traces for the whole exception tree. + + + + + Gets demystified string representation of the . + + + method mutates the exception instance that can cause + issues if a system relies on the stack trace be in the specific form. + Unlike this method is pure. It calls first, + computes a demystified string representation and then restores the original state of the exception back. + + + + + A helper class that contains utilities methods for dealing with reflection. + + + + + Returns true if is System.Runtime.CompilerServices.IsReadOnlyAttribute. + + + + + Returns true if the is a value tuple type. + + + + + Returns true if the given is of type TupleElementNameAttribute. + + + To avoid compile-time depencency hell with System.ValueTuple, this method uses reflection and not checks statically that + the given is TupleElementNameAttribute. + + + + + Returns 'TransformNames' property value from a given . + + + To avoid compile-time depencency hell with System.ValueTuple, this method uses reflection + instead of casting the attribute to a specific type. + + + + + Pretty print a type name. + + The . + true to print a fully qualified name. + true to include generic parameter names. + The pretty printed type name. + + + + Returns a name of given generic type without '`'. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +