# Changelog (/docs/menu-api/changelog)

---------------

## 4.1.0 [#410]

### Instructional buttons are drawn with NUI [#instructional-buttons-are-drawn-with-nui]

The button hints in the bottom right are now drawn on your NUI page, just like the menu, instead of with the game's own button bar. They look the same as the game's, they hide while the pause menu is open, and a theme can now change their colours, fonts, sizes and spacing. See [Theming](./reference/theming.md#instructional-buttons) for every setting.

Button strings in `CustomInstructionalButtons` work the same as before. Every icon the game can hand out is supported, including mouse movement, the mouse wheel, every controller button and the keyboard keys of the German, French, Italian and Spanish layouts.

### Global instructional buttons [#global-instructional-buttons]

New: [GlobalInstructionalButtons](./reference/globalinstructionalbuttons.md). Button hints that belong to your resource instead of a menu, for anything you like, for example a noclip. They show with or without a menu open, until you hide them. Up to 5 sets stack on top of the menu's own row, and slide down into its place when the menu closes. Hint text can be a function, so it updates by itself.

### Upgrading [#upgrading]

You do **not** have to change your `index.html` or your `fxmanifest.lua`. The button bar lives in `menuapi.min.js` and `menuapi.min.css`, which your page already loads for the menu, and it adds itself to the page.

What you do need is the new version of the files in the `menuapi` folder, because the old ones do not know about the button bar. Without them your menus still work, but the button hints are gone.

- **Using the NuGet package?** Update the package and build your resource. The new files are copied into the `menuapi` folder for you.
- **Using the zip?** Replace the whole `menuapi` folder of your resource with the one from the new zip, next to the new `MenuAPI.dll`.

If your theme stylesheet only sets `#menuapi` tokens, nothing changes for you. The button bar keeps the game's look until your theme sets `#menuapi-buttons` tokens too.

---------------

## 4.0.1 [#401]

### Submenus survive a refresh [#submenus-survive-a-refresh]

Clearing or removing a submenu button no longer removes its submenu. A list that was cleared and rebuilt with buttons for the same submenu, like an online players list, showed that submenu empty and without its events. Call [MenuController.RemoveMenu()](./reference/menucontroller.md#removemenumenu-menu) for a submenu you no longer need.

---------------

## 4.0.0 [#400]

One version number for everything. FiveM Enhanced, FiveM Legacy and RedM are released together with the same version, which is why Enhanced jumps from 1.x to 4.0.

### Enhanced and Legacy are built from the same code [#enhanced-and-legacy-are-built-from-the-same-code]

Everything below, which used to be Enhanced only, now works on Legacy too: NUI menus, themes, custom banners, rebindable key bindings and pagination. The package names stay `MenuAPI.FiveM` (Legacy) and `MenuAPI.FiveM.Enhanced`.

### Menus are always drawn with NUI [#menus-are-always-drawn-with-nui]

:::danger[Breaking change]
Native drawing is gone. Every resource needs the `index.html` page and the manifest lines from [Setup](./setup.mdx). `MenuController.RenderMode` still compiles but does nothing. See the [Migration Guide (v4)](./migration.md).
:::

`Menu.Position`, `Menu.SplitString()`, `MenuItem.PositionOnScreen`, `MenuController.ScreenWidth` and `MenuController.ScreenHeight` are obsolete, nothing uses them anymore.

Only title fonts 0, 1, 2, 4 and 7 render. Other font ids, including fonts registered with `RegisterFontId`, fall back to the item font.

### Packages [#packages]

The packages now include the XML docs, so your editor shows a description for every public member. The `menuapi` web files now also reach the build output in old `packages.config` projects.

### Turning off the toggle key [#turning-off-the-toggle-key]

New: [MenuController.EnableMenuToggleKey](./reference/menucontroller.md#properties). Set it to `false` when your resource opens its menus itself. It turns off the toggle on keyboard and controller.

---------------

## Enhanced 1.x [#enhanced-1x]

:::note
The changes in MenuAPI for FiveM Enhanced 1.x. Coming from 3.x? The [Migration Guide (v4)](./migration.md#coming-from-menuapi-3x) has the short version.
:::

### Inserting and moving items [#inserting-and-moving-items]

Two new ways to change a menu without clearing and refilling it.

**[InsertMenuItem()](./reference/menu.md#insertmenuitemint-index-menuitem-item)** puts an item at a chosen spot instead of at the bottom.

**[MoveMenuItem()](./reference/menu.md#movemenuitemmenuitem-item-int-index)** moves an item that is already in the menu. A submenu button keeps the menu it opens, which removing and adding it again would not.

Both keep the highlighted item highlighted, except in a paginated menu.

### Themes, custom banners, and smaller downloads [#themes-custom-banners-and-smaller-downloads]

:::danger[Breaking change]
The NUI css and js are minified and renamed with `.min`, and only the minified files ship. Using NUI
render mode means updating the six paths in your `index.html`. See the
[Migration Guide (v4)](./migration.md#the-nui-web-files-are-minified-and-renamed). Native mode is
unaffected.
:::

Three changes to the page NUI render mode draws. All of it is NUI only, native mode has nothing to
attach a stylesheet or an image to.

**Minified assets.** 64 KB down to 40 KB shipped. Readable sources stay in the repository.

**Themes.** A stylesheet you ship, layered over the default one, covering colours, radius, shadow
and font. Anything you leave alone keeps the default. Register by name, swap at any time, an open
menu changes on the next frame.

```cs
NuiTuning.RegisterTheme("midnight", "themes/midnight.css");

NuiTuning.SetTheme("midnight");
NuiTuning.SetTheme(null);
```

**Custom banners,** two routes, both from a `menuapi-banners` folder in your resource. Name a file
after the game sprite it replaces and every menu drawing that sprite picks it up, no API call. Or
name it freely and point one menu at it with the new `Menu.HeaderImage`.

```cs
// menuapi-banners/outlaw.png
menu.HeaderImage = "outlaw";
```

`HeaderImage` wins over a sprite replacement, and a missing file falls through rather than leaving
an empty header.

NUI render mode now has [a setup page](./nui.md), and both features are documented in
[Theming and banners](./reference/theming.md).

### Controllers and the mouse are rebindable too [#controllers-and-the-mouse-are-rebindable-too]

:::danger[Breaking change]
`Menu.ButtonPressHandlers`, `Menu.ButtonPressHandler`, `Menu.ControlPressCheckType` and the
`Menu.InstructionalButtons` dictionary have been **removed**. Every one of them was built around a fixed
`Control`, which is exactly what this change is getting rid of. Use
[Menu.AddKeyBinding()](./reference/menu.md#addkeybinding) instead, and see the
[Migration Guide (v4)](./migration.md#custom-controls-are-key-bindings-now).
:::


Every menu control is now a FiveM key binding, on all three devices. The controller buttons and the mouse used
to be read straight from the game's controls, which meant they were fixed and a player who did not like them
was stuck with them. They now sit in the same **Settings, Key Bindings** screen the keyboard controls have
always been in, each with its own row, so they can be changed or removed one at a time.

The defaults are the buttons the menu has always used, so nothing moves for a player who was happy with them.
The controller toggle is still a 400ms hold of the back/select button, on purpose, because a tap of that
button is the game's own interaction menu.

**Things that just behave differently now:**

- <kbd>Esc</kbd> goes back one menu, or closes the menu, the same as <kbd>Backspace</kbd> does. It used to do
  nothing at all while a menu was open, since MenuAPI stops it opening the pause menu.
- Holding the controller toggle button while a menu is open **closes** it. It used to only ever open a menu,
  which meant a controller could open a menu it then could not close.
- The scroll wheel moves one item per notch instead of scrolling faster the longer you keep scrolling. A wheel
  notch can not be held down, so a binding can only see the notch itself.
- Nothing polls the game's controls for menu input any more, with one exception: scrolling the wheel while
  holding <kbd>TAB</kbd> on foot is still left to the weapon wheel, and that check has to ask the game.

Lists, dynamic lists and sliders now get their own hint too. Whenever one of those rows is highlighted, a
left/right hint appears next to select and back, so it is obvious that the row has a value to change. Its text
is [ChangeValueButtonText](./reference/menu.md#properties) and it can be turned off per menu.

See [Key bindings](./reference/keybindings.md) for the full list.

### The menu is drawn without describing it sixty times a second [#the-menu-is-drawn-without-describing-it-sixty-times-a-second]

The NUI renderer used to build a full description of the open menu on every single frame, purely to
find out whether anything about it had changed. Nothing usually had, so almost all of that work, and
the few kilobytes of garbage that came with it, was thrown straight away again.

Now every property that is on screen says so when you write to it, and the description is only built
when something actually said it changed. A menu nobody is touching costs nothing at all beyond the
draw itself.

**Things you have to change in your own code:**

- `MenuListItem.ListItems` is now a `MenuItemList` instead of a `List<string>`. It is used the same
  way, and a `List<string>` can still be assigned straight to it, so most code needs no change. The
  two things that do: a variable typed `List<string> values = item.ListItems;` has to become
  `MenuItemList` (or call `.ToList()`), and the list you pass to the constructor is now **copied**,
  so change the values through `item.ListItems` rather than through your own copy of the list. See
  the [Migration Guide (v4)](./migration.md).

**Things that just behave differently now:**

- If you build part of a row's text from something MenuAPI does not own, such as a label you resolve
  yourself, call `MenuController.RefreshNui()` when it changes. Everything MenuAPI owns already says
  so on its own.
- The instructional buttons bar fills its slots a few times a second instead of every frame. Swapping
  between keyboard and controller still changes the icons, it just no longer costs a dozen scaleform
  calls per frame to notice.

### Menus can be split into groups with a heading [#menus-can-be-split-into-groups-with-a-heading]

There is a new item type, [SeparatorMenuItem](./reference/menuitems/separatormenuitem.md). It is a heading that labels the rows underneath it, so a long menu can be broken into readable groups without pushing anything into a submenu.

The text is centred properly, using the game's own text justification, and it sits on exactly the same baseline as the rows around it. `ShowArrows` is on by default and draws it as `↓ Protection ↓`, and turning it off leaves just the centred word.

The cursor scrolls onto a separator like any other row, and it highlights like any other row. What it will not do is act: select, left and right are all ignored, and without the error sound a disabled row would have made, because scrolling onto a label is not a mistake. Give it a description and that gets shown too, which is a free place to say what the whole group below is for.

Scrolling deliberately does not skip over them. A cursor that jumped rows feels like the menu is eating key presses, and it is worse to use than the row it was trying to save you from.

This is the thing people were building by hand: a disabled item whose text had been padded with spaces until it looked roughly centred. That never actually lined up, the padding had to be recalculated for the text, and pressing it gave you an error sound.

**Things you have to change in your own code:** nothing, `SeparatorMenuItem` is a new type. Nothing about how menus scroll or count their rows has changed.

**Things that just behave differently now:**

- If you were faking a heading with a space padded disabled `MenuItem`, swap it for a `SeparatorMenuItem` and drop both the padding and the arrows you were typing into the text yourself. Do not swap it if you were using that trick as a "there is nothing here" message in an otherwise empty menu, since a real heading is not what that is. Keep a disabled plain item for that.

### Menu banners can have their own font, and GTA Online's glare [#menu-banners-can-have-their-own-font-and-gta-onlines-glare]

The banner at the top of a menu used to be fixed. The only thing you could change about it was swapping the whole image out for your own. It now has three settings, all covered on the [Header styling](./reference/menu.md#header-styling) page.

`MenuTitleFont` picks the font the title is drawn in, from the game's own set. `MenuFont` has names for the ones worth using, so `menu.MenuTitleFont = MenuFont.Pricedown` gets you the Grand Theft Auto logo font. Any font id the game knows works, including one your resource registered itself, so a custom font goes straight in. The size and the vertical position are worked out per font, because fonts disagree about both and a shared number would leave half of them sitting crooked.

`MenuTitleAlignment` moves the title to the left, the centre or the right of the banner. This is separate from `MenuController.MenuAlignment`, which is about which side of the *screen* the menu is on.

`ShowHeaderGlare` draws the soft moving glow GTA Online has behind its own pause menu title, the one that drifts as you turn the camera. It is the game's own `mp_menu_glare` scaleform, so nothing is streamed and no NUI is involved. It is loaded the first time a menu asks for it and released when every menu closes.

All three exist twice: on a menu, where they are nullable, and on `MenuController` as `DefaultTitleFont`, `DefaultTitleAlignment` and `DefaultShowHeaderGlare`. Set the defaults once and every menu follows them, and any single menu can still say otherwise.

**Things you have to change in your own code:** nothing. All three are opt in.

**Things that just behave differently now:**

- An untouched banner is drawn very slightly smaller than before. The title size was one hardcoded number picked for the default font, and it is now the measured size for that font, which came out a little lower. Nothing moves, it is the same font in the same place.

### Menus can be removed again [#menus-can-be-removed-again]

Until now, anything you handed to MenuAPI stayed forever. There was no way to remove a menu, so a resource that rebuilt part of its menu structure while running slowly filled memory with menus nobody could open anymore. There are now two ways to clean up: `MenuController.RemoveMenu(menu)` for a single menu, and `MenuController.RemoveAllMenus()` for everything.

Removing a menu closes it if it is open, empties its buttons, forgets the event handlers you attached to it, and takes it out of `MenuController.Menus`. After that your own variable is the only thing still pointing at it, so letting go of that variable is enough for the game to clean it up.

The nice part is that you usually will not have to call any of this. Removing a button now takes the submenu behind it with it, because once the button is gone there is no way to reach that submenu. So `RemoveMenuItem()` and `ClearMenuItems()` clean up after themselves, which is exactly what a resource rebuilding a menu from live data was quietly leaking before.

**Things you have to change in your own code:** nothing.

**Things that just behave differently now:**

- Removing or clearing a button that was bound with `BindMenuItem()` also removes the menu it opened, unless another button still opens that same menu. If you were deliberately keeping a menu alive by holding your own reference to it while removing its button, bind it to a new button before removing the old one.
- Binding an already bound button to a different menu removes the menu it used to open, on the same "nothing points at it anymore" rule.
- Removing a button clears its `ParentMenu`, so an item you have taken out of a menu reports `Index` as -1 instead of still pointing into the menu it used to be in.
- `RemoveAllMenus()` clears `MainMenu` too, so register a menu again before expecting the toggle key to open anything.

### Coloured subtitles actually come out coloured [#coloured-subtitles-actually-come-out-coloured]

The subtitle and the counter are drawn in capitals, and MenuAPI was uppercasing the whole string to do it. The game's formatting tokens are lowercase, so `~r~` was going to the game as `~R~`, which it does not recognise, and the colour silently went missing. Uppercasing now skips whatever sits between a pair of tildes, so `menu.MenuSubtitle = "~r~Out of date"` renders red like it always should have.

**Things you have to change in your own code:** nothing. If you were working around this, you can stop.

### Menus can be split into pages [#menus-can-be-split-into-pages]

A menu can now hold thousands of items without the player having to scroll through all of them. Call `menu.SetPageSize(48)` and the menu is split into pages of 48, moved between with left and right. Everything is on the new [Pagination](./reference/pagination.md) page.

**Things you have to change in your own code:**

- Nothing. Pagination is off by default, and a menu that never calls `SetPageSize()` behaves exactly as it did.

**Things that just behave differently now:**

- In a menu you *have* paginated, left and right turn the page instead of going back and selecting. List, dynamic list and slider items are unaffected, they still change their own value.
- `Size`, `CurrentIndex`, `GetMenuItems()` and `GetCurrentMenuItem()` describe the current page of a paginated menu, not the whole item list.
- Two long standing bugs got fixed on the way. `ClearMenuItems()` used to leave an active filter switched on, so an emptied menu stayed stuck at `Size` 0 even after you refilled it. And `RemoveMenuItem(int)` counted against the filtered list while indexing the unfiltered one, so it could remove the wrong item while a filter was active.

### Menus stop costing anything while they are closed [#menus-stop-costing-anything-while-they-are-closed]

MenuAPI used to run seven loops that never stopped. Four of them did real work on every single frame even with every menu closed, which added up to roughly 24 wasted calls into the game per frame, forever. All of that work now sits behind a small scheduler, and a loop that is switched off genuinely **ends** instead of running and immediately returning. With no menu open, MenuAPI does almost nothing at all.

You can see this for yourself. Type `menuapi:yourresourcename:ticks` in the console and it prints every loop and whether it is running. You can also read the same thing from code through the new [MenuTicks](./reference/ticks.md) class, which is handy if your resource has its own debug overlay.

**Things you have to change in your own code:**

- `MenuController.EnableManualGCs` is **gone**, along with the manual garbage collect it controlled. The .NET runtime handles this on its own, and forcing a collect on the game thread was a stutter nobody asked for.
- MenuAPI is now built with **nullable reference types** switched on, so things that really can be null now say so. `MenuController.GetCurrentMenu()`, `MenuController.MainMenu`, `Menu.ParentMenu`, `Menu.GetCurrentMenuItem()`, `Menu.MenuTitle`, `Menu.MenuSubtitle`, `Menu.CounterPreText`, `MenuItem.Label`, `MenuItem.Description` and `MenuDynamicListItem.CurrentItem` are all nullable now. If your own resource has nullable switched on too, you may get new warnings where you use one of these without checking it first. Those warnings are pointing at real crashes waiting to happen, so it is worth fixing them rather than silencing them. Nothing needs to change if you do not use nullable yourself.

**Things that just behave differently now:**

- The controller open gesture is checked ten times a second instead of every frame. It is a 400ms hold, so it still opens at exactly the same moment.
- A few genuine crashes are fixed along the way. Holding a direction key while something else closed the menu could crash, and so could selecting an item that opens a submenu if a handler closed the menu first.
- Menu textures stay loaded while the pause menu is open instead of being thrown away and re-requested. Nothing visible changes, there is just less streaming churn.

### Keyboard controls are now FiveM key bindings [#keyboard-controls-are-now-fivem-key-bindings]

Every keyboard menu control is registered as a proper FiveM key mapping, so players can rebind all of them from their own **Settings, Key Bindings** screen. Full details on the [Key bindings](./reference/keybindings.md) page.

**Things you have to change in your own code:**

- `MenuController.MenuToggleKey` and `MenuController.MenuToggleKeyIsValid` are **gone**. The key that opens the menu is now the player's choice. A resource can still pick the starting default with the new `MenuController.MenuToggleKeyDefault` (a key name like `"M"` or `"F5"`, set in your constructor), but that only applies to players who have never rebound it.
- `Menu.InstructionalButtons` now starts **empty**. It used to come with a select and a back entry in it. Those two moved to their own properties, because on a keyboard they follow the player's binding instead of a fixed `Control`. Use the new `Menu.SelectButtonText`, `Menu.BackButtonText`, `Menu.ShowSelectInstructionalButton` and `Menu.ShowBackInstructionalButton` instead.

**Things that just behave differently now:**

- Right click goes back, matching left click selecting.
- <kbd>Escape</kbd> no longer opens the pause menu while a MenuAPI menu is open. That was always the intent, but a keyboard/controller check was the wrong way around so it never actually happened. <kbd>P</kbd> still opens the pause menu.
- `MenuController.PreventExitingMenu` really does stop a top level menu being closed with the back button now. The branch that handled it could never be reached.
- A few controls that were meant to be disabled only for controller players were being disabled only for keyboard players, and the other way around. Same wrong check as the Escape issue.

---------------

## Versions v3.0.0 - v3.0.3 [#versions-v300---v303]

Automatic package upload to NuGet added. MenuAPI is now availabe on NuGet! Simply search for MenuAPI.FiveM.Enhanced.

There's also been bug fixes. Things like instructional buttons, different button types, sound effects, different font styles etc.

Full changelog available here: https://github.com/TomGrobbe/MenuAPI/compare/v2.2.0...v3.0.3


---------------

## Versions 1.0.1 - v2.2.0 [#versions-101---v220]
Lots of bug fixes, new features and more. I know this isn't a great changelog, but it's all nicely listed in git logs.
For a full changelog for these versions see: https://github.com/TomGrobbe/MenuAPI/compare/v1.0.1...v2.2.0
