Skip to content

How to render mod options

newman55 edited this page Sep 6, 2024 · 2 revisions

Functions

Use the built-in functions of the GUILayout class and UnityModManager.UI. Below is a list of additional functions for the GUI.

GUILayout.Label(string);
GUILayout.TextField(string);
GUILayout.TextArea(string);
GUILayout.Toggle(string)
GUILayout.HorizontalSlider(float, float, float);
GUILayout.BeginHorizontal();
GUILayout.EndHorizontal();
GUILayout.BeginVertical();
GUILayout.EndVertical();
UnityModManager.UI.DrawVector(ref Vector);
UnityModManager.UI.DrawColor(ref Color);
UnityModManager.UI.DrawFloatField(ref float, string);
UnityModManager.UI.DrawIntField(ref int, string);
UnityModManager.UI.ToggleGroup(ref int, string[]);
UnityModManager.UI.PopupToggleGroup(ref int, string[]);
UnityModManager.UI.DrawKeybinding(ref Keybinding);
UnityModManager.UI.DrawFields<T>(ref T, ModEntry, DrawFieldMask, Action);

DrawFields helps to automatically generate GUI from your data.

Settings

I will create a class that saves my data to disk and generate a GUI. To do this, all fields must be marked with the Draw attribute, and the class inherits the IDrawable interface.

public class Settings : UnityModManager.ModSettings, IDrawable
{
    [Draw("HD Models")] public bool EnableHDModels = true;
    [Draw("Settings", Collapsible = true)] public ModelsSettings ModelsSettings = new ModelsSettings();

    [Draw("Subpixel Morphological Anti-Aliasing"), Space(10)] public bool SMAAEnable = true;
    [Draw("Quality")] public SMAA.QualityPreset SMAAQuality = SMAA.QualityPreset.High;

    public override void Save(UnityModManager.ModEntry modEntry)
    {
        Save(this, modEntry);
    }

    public void OnChange()
    {
    }
}

The OnChange method will be called every time at least one value is changed using GUI.

Add DrawFields attribute if you need to render the fields not only with the Draw attribute.

[DrawFields(DrawFieldMask.Public)]
public class ModelsSettings
{
    public WheelsRotate WheelsRotate = WheelsRotate.SchemeA;
    public float VisibleDistance = 300f;
    public bool WithDrivers;
}
static class Main
{
    public static Settings settings;

    static bool Load(UnityModManager.ModEntry modEntry)
    {
        settings = Settings.Load<settings>(modEntry);
        modEntry.OnGUI = OnGUI;
        modEntry.OnSaveGUI = OnSaveGUI;

        return true;
    }

    static void OnGUI(UnityModManager.ModEntry modEntry)
    {
        settings.Draw(modEntry);
    }

    static void OnSaveGUI(UnityModManager.ModEntry modEntry)
    {
        settings.Save(modEntry);
    }
}

The Save method writes the data to an XML file, and the Draw method generates a GUI.

result


Next example.

For numeric data types you can specify additional parameters such as Precision, Min and Max.

public class SpeedSet
{
    [Header("Frontend")]
    [Draw("1", Precision = 1, Min = 0), Space(5)] public float Frontend = 1f;
    [Header("Simulation"), Space(5)]
    [Draw("1", Precision = 0, Min = 0)] public float Simulation1 = 20f;
    [Draw("2", Precision = 0, Min = 0)] public float Simulation2 = 30f;
    [Draw("3", Precision = 0, Min = 0)] public float Simulation3 = 40f;
    [Header("OnTrack"), Space(5)]
    [Draw("1", Precision = 2, Min = 0)] public float Race1 = 1f;
    [Draw("2", Precision = 1, Min = 0)] public float Race2 = 2f;
    [Draw("3", Precision = 1, Min = 0)] public float Race3 = 4f;

    public static SpeedSet Fast()
    {
        return new SpeedSet { Frontend = 2f, Race1 = 2f, Race2 = 4f, Race3 = 8f, Simulation1 = 30f, Simulation2 = 45f, Simulation3 = 60f };
    }
}

By specifying the DrawType argument in the Draw attribute, you can choose how to display the field. There are several possible values for DrawType: Auto, Ignore, Field, Slider, Toggle, ToggleGroup, PopupList, KeyBinding and CustomGUI.

public enum SpeedSets { Fast, Slow };

public class Settings : UnityModManager.ModSettings, IDrawable
{
    [Draw(DrawType.ToggleGroup)] public SpeedSets Preset = SpeedSets.Fast;
    [Draw("", VisibleOn = "Preset|Fast")] public SpeedSet Fast = SpeedSet.Fast();
    [Draw("", VisibleOn = "Preset|Slow")] public SpeedSet Slow = new SpeedSet();

    public void OnChange()
    {
        Main.ApplySettings(Preset);
    }

    public override void Save(UnityModManager.ModEntry modEntry)
    {
        Save(this, modEntry);
    }
}

VisibleOn parameter changes visibility depending on the value of the specified fields.

result

CustomGUI is a delegate that allows you to add any GUI to complement the generated one.

All supported field types: bool, int, long, float, double, int[], long[], float[], double[], string, Vector2, Vector3, Vector4, Color, KeyBinding, Enum (w/o flags). If some field type does not support DrawType, will be thrown an exception.

If you need several separate configuration files, implement the GetPath method from UnityModManager.ModSettings

public class Settings : UnityModManager.ModSettings
{
    public override string GetPath(UnityModManager.ModEntry modEntry)
    {
        return Path.Combine(modEntry.Path, "OtherSettings.xml");
    }
}

Layout

Attributes DrawSpace, DrawFlexibleSpace, DrawBeginHorizontal, DrawEndHorizontal, DrawBeginVertical, DrawEndVertical will help you to change the layout.

If necessary, you can create your own attribute by inheriting the DrawPropertyAttribute.

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class DrawLabelAttribute : DrawPropertyAttribute
{
    public string Text;

    public override void Draw()
    {
        GUILayout.Label(Text);
    }
}

Some examples can be found here.

Clone this wiki locally