> For the complete documentation index, see [llms.txt](https://raia-software-inc.gitbook.io/tacview-2-documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://raia-software-inc.gitbook.io/tacview-2-documentation/api-reference/api-reference/menus.md).

# Menus

Menus are one of the simplest ways for an add-on to become part of Tacview's user interface.

A good menu item does more than expose a function. It tells the user that a feature exists, places it where the user naturally expects to find it, and makes the add-on feel like it belongs to Tacview instead of floating beside it.

Tacview owns the menu system. Add-ons do not create menu windows or manage menu widgets directly. Instead, they retrieve a menu handle, add commands to that menu, react to user clicks, and update the menu display when their own state changes.

This keeps menus predictable for users and simple for add-ons.

The same model works for small commands, complex tools, context-sensitive actions, view options, filters, chart selectors, and add-on-specific workflows. An add-on can add a single command to the main menu, extend a viewport context menu, or build a complete menu for its own toolbar or window.

## Menus describe possibilities

Menus should help users discover what they can do.

A command can open a tool, export data, change a view, toggle an overlay, select a mode, or apply an action to the object currently under the mouse. The add-on remains responsible for the real behavior, but the menu gives that behavior a clear place in the interface.

A useful way to think about menus is:

```
the add-on owns the logic
the menu exposes the intent
Tacview handles the presentation
```

This separation keeps add-on code clear. The add-on does not need to know how Tacview draws menus, inserts separators, displays shortcuts, or represents checked and disabled items. It only needs to describe the commands it wants to expose.

## Menu handles

A menu handle identifies one complete menu hierarchy.

For example, the main menu is one hierarchy. A viewport context menu is another hierarchy. An object context menu in a 3D view is another hierarchy.

A hierarchy may contain items and submenus. Item ids must be unique inside the hierarchy identified by the menu handle. The same id may be reused in another independent menu.

```lua
local mainMenuHandle = GetMainMenuHandle()
```

Once an add-on has a menu handle, it can use that handle to add items, detect clicks, update visual state, and remove items when they are no longer needed.

## Commands, paths, and groups

Menu items are identified by stable ids.

The visible label can change. The icon can change. The menu can be reorganized. But the item id should remain stable, because it is the link between the menu and the add-on logic.

The `path` field tells Tacview where the item should be inserted. It is a path of existing parent item ids.

The `group` field tells Tacview which related commands should appear together inside that parent menu. Groups are also used by Tacview to place separators automatically when needed.

A useful way to think about it is:

```
path  = where the item goes
group = which nearby commands it belongs with
id    = how the add-on recognizes the command
```

The parent path must already exist. Groups are created as needed inside an existing parent menu.

## Visual state is output

Menus can show state: an item can be checked, unchecked, enabled, disabled, or part of an exclusive selection.

That state is visual output. It reflects the add-on state, but it is not the source of truth.

For example, if the user clicks a command to show or hide an overlay, the add-on should update its own variable first, then update the check mark displayed in the menu.

This keeps the logic explicit and avoids storing the same state in two places.

Independent toggles, exclusive choices, disabled commands, filters, and mode selectors all follow the same idea: the add-on decides what is true, and the menu shows it to the user.

## Exclusive choices

Many features are not simple on/off switches. They are choices: one chart type, one display mode, one unit system, one view, one filter preset.

Tacview supports this with exclusive menu selections. The add-on chooses the selected item, and Tacview clears the other items from the same exclusive selection.

By default, an exclusive selection belongs to one visual group.

When a menu contains many choices, the add-on can split them into several visual groups to keep the menu readable while still treating them as one selection set. This lets menus remain clean without forcing the underlying feature to become artificially limited by how the menu is arranged.

The visual organization should help the user read the menu. The selection logic should follow the feature.

## Menu clicks

Menu clicks are checked from the add-on update logic.

```lua
if WasMenuItemClicked(mainMenuHandle, "DogfightAnalysis") then

	CreateWindow("dogfight-analysis")

end
```

The click state is frame-based. It is cleared once per frame by Tacview, not when `WasMenuItemClicked()` is called. This makes it safe for several parts of an add-on to query the same item during the same frame if needed.

This polling model is intentional. It keeps command execution explicit in the add-on and avoids callback ownership problems.

## Shortcuts

A menu item can display a keyboard shortcut.

```lua
shortcut = {
	modifiers = Modifiers.Primary,
	key = Keys.O
}
```

The displayed shortcut is not executed automatically by the menu. The add-on should check the matching shortcut in its update logic, usually with `WasShortcutPressed()`.

```lua
if WasMenuItemClicked(mainMenuHandle, LoadFilesMenuId) or WasShortcutPressed(0, Modifiers.Primary, Keys.O) then

	RequestFilesToLoad()

end
```

The displayed shortcut and the shortcut checked by the add-on should match. The menu tells the user what to press; the add-on should make that command work.

For normal user-interface shortcuts, prefer `Modifiers.Primary` instead of hard-coding `Modifiers.Control`. This lets Tacview display the shortcut using the expected platform convention, such as Control on Windows and Linux, and Command on macOS.

## Cleaning up

Add-ons should remove items they add to shared menus when they shut down.

This includes the main menu and shared context menus. It prevents Tacview from keeping inactive commands visible if the add-on is disabled or unloaded while Tacview continues running.

```lua
RemoveMenuItem(mainMenuHandle, "DogfightAnalysis")
```

It is usually not necessary to remove items from menus owned only by the add-on itself, such as menus that belong to a viewport or window that will be destroyed with the add-on.

## Functions

### Menu handles

* `GetMainMenuHandle()`
* `GetViewportContextMenuHandle()`
* `GetObjectContextMenuHandle()`
* `GetContextMenuObjectHandle()`

### Menu items

* `AddMenuItem()`
* `WasMenuItemClicked()`
* `SetMenuItemEnabled()`
* `SetMenuItemChecked()`
* `CheckExclusiveMenuItem()`
* `RemoveMenuItem()`

### Related input values

* `Modifiers`
* `Keys`
