Skip to main content

Quickstart

This guide shows how to build a functional 4-sector action wheel in a ScriptHookVDotNet script.


Minimal Example

Create a standard SHVDN Script class:

using System;
using System.Drawing;
using System.Windows.Forms;
using GTA;
using RadialMenuUI;

public class MyRadialMod : Script
{
private readonly RadialMenuController _controller;
private readonly RadialMenuTheme _theme;

public MyRadialMod()
{
// 1. Initialize the theme pointing to the default skins directory
_theme = new RadialMenuTheme("default")
{
BaseDirectory = @"RadialMenuUI\",
AssetRoot = @"skins\default",
IconRoot = @"skins\default\icons",
WheelTint = Color.White,
HoverTint = Color.FromArgb(255, 215, 0) // Golden hover highlight
};

// Map stable icon keys to the PNGs shipped with the default skin.
_theme.RegisterIcon("repair", "wheel_support_backup.png");
_theme.RegisterIcon("heal", "wheel_category_support.png");
_theme.RegisterIcon("police", "wheel_police_routine_check.png");

// 2. Initialize the input adapter (right-stick + mouse)
var input = new GtaRadialMenuInput();

// 3. Create the controller
_controller = new RadialMenuController(input);
_controller.ResultConfirmed += OnActionConfirmed;

// 4. Prewarm textures in background for instant first open
_controller.QueueWarmup(_theme);

Tick += OnTick;
KeyUp += OnKeyUp;
}

private void OnKeyUp(object sender, KeyEventArgs e)
{
// Toggle the wheel with F5 key
if (e.KeyCode == Keys.F5)
{
if (_controller.IsOpen)
{
_controller.CancelAndClose();
}
else
{
_controller.Open(CreateMainMenu());
}
}
}

private void OnTick(object sender, EventArgs e)
{
// Process controller every frame (handles input, hovers, and rendering)
_controller.WarmupOneTexture();

if (_controller.IsOpen)
{
_controller.Update();

// When R2 (gamepad) or Enter/Click is pressed, confirm the hovered entry
if (_controller.PressedThisFrame)
{
_controller.ConfirmAndClose();
}
}
}

private RadialMenuDef CreateMainMenu()
{
var menu = new RadialMenuDef("main", 4).WithTheme(_theme);

menu.AddEntry(new RadialEntryDef("repair", 0) { Label = "Repair Vehicle" }.WithIcon("repair"));
menu.AddEntry(new RadialEntryDef("heal", 1) { Label = "Heal Player" }.WithIcon("heal"));
menu.AddEntry(new RadialEntryDef("police", 2) { Label = "Clear Wanted Level" }.WithIcon("police"));
// Slot 3 (bottom / 18h) left empty for easy cancellation gesture

return menu;
}

private void OnActionConfirmed(RadialMenuResult result)
{
Ped player = Game.Player.Character;

switch (result.EntryId)
{
case "repair":
player.CurrentVehicle?.Repair();
GTA.UI.Notification.PostTicker("~g~Vehicle repaired!", false, false);
break;

case "heal":
player.Health = player.MaxHealth;
player.Armor = 100;
GTA.UI.Notification.PostTicker("~g~Player healed!", false, false);
break;

case "police":
Game.Player.Wanted.SetWantedLevel(0, false);
GTA.UI.Notification.PostTicker("~b~Wanted level cleared!", false, false);
break;
}
}
}

Explanation

  1. RadialMenuTheme: Configures colors, paths, and opacity.
  2. GtaRadialMenuInput: Reads GTA native controls (right stick ScriptRightAxisX/Y, mouse CursorX/Y, and buttons).
  3. RadialMenuController: Manages open/close states, hovers, sound effects, and emits ResultConfirmed.
  4. RadialMenuDef: Declares slot count (e.g. 4 sectors) and entries.
  5. WarmupOneTexture(): Lazily registers one ScriptHookV texture per frame at startup to avoid hiccups when opening the wheel for the first time.