LocalParameter property drawer

While integrating FMOD into our project at Salty Games, I created a property drawer to set up parameters in the property inspector, used like this:

public EventReference engineIdleEvent;
[LocalParamRef(nameof(engineIdleEvent))]
public string engineStateParam;

and this will give you a drop down of the available parameters for the event.
image

You only need two files:

LocalParamRefAttribute.cs in the game assembly

using UnityEngine;

public class LocalParamRefAttribute : PropertyAttribute
{
    public LocalParamRefAttribute(string eventReferenceMemberName)
    {
        EventReferenceMemberName = eventReferenceMemberName;
    }

    public string EventReferenceMemberName { get; }
}

and LocalParamRefDrawer.cs in the editor assembly

using FMODUnity;
using System.Linq;
using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(LocalParamRefAttribute))]
public class LocalParamRefDrawer : PropertyDrawer
{
    string[] choices;
    string lastEventPath;
    EditorEventRef editorEventRef;
    bool invalid;

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        var localParamRef = attribute as LocalParamRefAttribute;

        if (property.propertyType != SerializedPropertyType.String)
        {
            Debug.LogError($"{nameof(LocalParamRefAttribute)} must be used on string fields");
        }

        int selectedIndex = -1;

        var eventProperty = property.serializedObject.FindProperty(localParamRef.EventReferenceMemberName);

        var eventPath = eventProperty.FindPropertyRelative("Path").stringValue;

        if (editorEventRef == null || eventPath != lastEventPath)
        {
            editorEventRef = EventManager.EventFromPath(eventPath);

            var choiceList = editorEventRef.LocalParameters.Select(p => p.Name).ToList();

            selectedIndex = choiceList.IndexOf(property.stringValue);

            // if the current value isn't in the list, add it first and select it to keep it.
            if (selectedIndex < 0)
            {
                choiceList.Insert(0, property.stringValue);
                selectedIndex = 0;
                invalid = true;
            }
            choices = choiceList.ToArray();
        }

        EditorGUI.BeginProperty(position, label, property);

        EditorGUI.BeginChangeCheck();
        var choiceIndex = EditorGUI.Popup(position, label.text, selectedIndex, choices);
        if (EditorGUI.EndChangeCheck())
        {
            selectedIndex = choiceIndex;
            if (selectedIndex >= 0)
            {
                property.stringValue = choices[selectedIndex];
            }
        }

        EditorGUI.EndProperty();
    }
}

I will probably do another pass on this later but it works quite well now. Feel free to steal it FMOD folks :slight_smile:

1 Like

Thanks for providing your code. I can see this being potentially useful for users wishing to make use of the existing integration functionality to create their own editor-facing tools, so I’ve passed it along to the development team for further investigation.