Note
This project was developed collaboratively by the repository author and AI.
A MetaHookSv plugin that overlays a radial menu (pie menu) using the IMGUIExtension plugin context for GoldSrc engine games (such as Sven Co-op). It intercepts player input, displays menus configured via JSON, and executes client/server console commands on selection.
- Grid and Dynamic Layouts: Supports automatic angular sector division or fixed slot counts (e.g. 8 slots) to place items in specific positions.
- Split Center: The center button can be split horizontally into left and right zones (Note: Split centers bypass automatic contextual
BACKbutton behavior in submenus). - Contextual BACK Button: Submenus automatically treat an empty or unconfigured center button as a
BACKbutton (displaysBACKand navigates to the parent menu). If the center has explicit commands, submenus, or is split, this auto-behavior is bypassed. - Item Styling Overrides: Supports custom per-item overrides for descriptions, icon/text colors, and sector background/hover colors.
- Unified Sector Mapping: Uses cached calculated sector angles to ensure rendering, hover calculation, and execution are perfectly synchronized.
- Input Interception: Prevents keyboard and mouse messages from bleeding into the game while the menu is open, except for whitelisted keys (like console toggles).
| Command / Variable | Type | Description |
|---|---|---|
+rm_show |
Command | Opens the radial menu overlay (hold-to-open). |
-rm_show |
Command | Closes the menu. Never executes a selection. |
rm_show |
Command | Toggles the menu visibility (tap-to-open / tap-to-close). |
cl_radialmenu_close_on_select |
CVAR (0/1) | Determines whether the menu closes automatically after executing a sector command. Default is 1. |
The menu is configured via radialmenu/radialmenu.json in the game directory.
| Parameter | Type | Default | Description |
|---|---|---|---|
hover_color |
Array [R,G,B,A] |
[255, 160, 0, 250] |
Color of the hovered sector background. |
sector_color |
Array [R,G,B,A] |
[45, 45, 45, 200] |
Color of the normal sector background. |
service_color |
Array [R,G,B,A] |
[70, 80, 95, 220] |
Color of normal navigation sectors (e.g. submenus, PREV, NEXT, or BACK). |
service_hover_color |
Array [R,G,B,A] |
[100, 120, 140, 250] |
Color of hovered navigation sectors. |
deadzone_ratio |
Float | 0.4 |
Radius ratio of the central deadzone. |
radius_min |
Float | 55.0 |
Inner radius of the outer circle. |
radius_max |
Float | 190.0 |
Outer radius of the outer circle. |
pagination_arrow_offset |
Float | 40.0 |
Distance (px) beyond radius_max where the PREV/NEXT arrow buttons are drawn. |
pagination_arrow_radius |
Float | 22.0 |
Hit-test radius of each pagination arrow button. |
click_cooldown_ms |
Integer | 100 |
Minimum time (ms) the menu must be open before a click is registered — guards against an accidental click right as the menu opens. Has no effect on -rm_show, which always just closes. |
animation_duration_ms |
Integer | 75 |
Duration (ms) of the opening radial expansion animation. |
move_threshold_px |
Float | 15.0 |
Mouse movement distance required to trigger g_bMouseMovedSinceOpen. |
| Parameter | Type | Description |
|---|---|---|
label |
String | Text label of the sector. |
description |
String | Sub-text displayed below the label (e.g. price). |
symbolic_icon |
String | UTF-8 character representing the icon. |
command |
String | Console command executed when the sector is activated. |
submenu |
String | Name of the sub-profile to open when the sector is activated. |
autoclose |
Boolean | Overrides the default menu close behavior on action selection. |
color_override |
Array [R,G,B,A] |
Overrides the normal background color for this sector. |
hover_color_override |
Array [R,G,B,A] |
Overrides the hover background color for this sector. |
description_color |
Array [R,G,B,A] |
Overrides the text color for the description sub-text. |
icon_color |
Array [R,G,B,A] |
Overrides the color of the symbolic icon. |
Menus with more than 8 items are paginated automatically (8 per page); there is no manual slot assignment. Navigate pages with the two arrow buttons drawn outside the ring, or
PREV/NEXTare not injected as items anymore.
Click to view radialmenu.json structure example
{
"style": {
"hover_color": [0, 150, 136, 220],
"sector_color": [33, 33, 33, 220],
"service_color": [70, 80, 95, 220],
"service_hover_color": [100, 120, 140, 250],
"deadzone_ratio": 0.4,
"radius_min": 55.0,
"radius_max": 190.0,
"click_cooldown_ms": 100,
"animation_duration_ms": 75,
"move_threshold_px": 15.0
},
"menus": {
"root": {
"autoclose": false,
"center": {
"left": {
"label": "AMMO",
"symbolic_icon": "⦾",
"icon_scale": 1.2,
"command": "say /buyammo",
"autoclose": false
},
"right": {
"label": "HE",
"symbolic_icon": "✹",
"icon_scale": 1.2,
"command": "say /buyhe",
"autoclose": true
}
},
"items": [
{
"label": "Weapons",
"symbolic_icon": "⚔",
"icon_scale": 1.2,
"submenu": "weapons"
},
{
"label": "Equipment",
"symbolic_icon": "✚",
"icon_scale": 1.2,
"submenu": "equipment"
}
]
},
"weapons": {
"autoclose": true,
"items": [
{
"label": "Glock",
"symbolic_icon": "⚔",
"icon_scale": 1.2,
"command": "say /buy glock",
"description": "FREE",
"description_color": [76, 175, 80, 255]
},
{
"label": "Shotgun",
"symbolic_icon": "▰",
"icon_scale": 1.2,
"command": "say /buy shotgun",
"description": "1500$",
"description_color": [255, 235, 59, 255]
}
]
}
}
}By default, the radial menu utilizes the unified font atlas loaded by the IMGUIExtension core.
To use custom vector icons:
- Place your TrueType icon font (e.g. Font Awesome Free or Material Design Icons) in the
<game_directory>/imguiextension/fonts/directory. - Register the font, size, and glyph ranges in
<game_directory>/imguiextension/imguiextension.json. - In
radialmenu.json, set"symbolic_icon"to the corresponding UTF-8 character or code of the icon you wish to display.
- Cursor visibility: on rare occasions the cursor may appear frozen at the crosshair position after closing a menu; a single click resolves it. Root cause not fully isolated.
- HUD text overlap: native engine messages (e.g.
print_center) may render underneath the menu's dim overlay. The overlay currently darkens the full screen rather than just the menu area. center_split+ pagination on the same menu is untested and structurally risky: pagination arrows andcenter_splithalves both reuse sector codes-3/-4. Priority logic makes them coexist correctly when only one is active per menu (verified in the shipped config), but no menu currently combines bothcenter_splitand >8 items on the same level. Doing so will likely misroute center clicks as page navigation. A startup warning now fires inLoadMenuConfigif this combination is detected (see console on load) - treat it as "don't do this yet" rather than "this works."
- Build
RadialMenu.dllusingMetaHook.sln. - Add the compiled DLL to your MetaHookSv plugins folder and register it in
plugins.lst. - Place
radialmenu.jsonunder<game_directory>/radialmenu/radialmenu.json. - Bind a key to
+rm_showin the console.