Skip to content

Instantly share code, notes, and snippets.

@AngryAnt
Last active October 6, 2021 20:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save AngryAnt/b5995c9b2cf2a0979758ad17f6a59ef0 to your computer and use it in GitHub Desktop.
Save AngryAnt/b5995c9b2cf2a0979758ad17f6a59ef0 to your computer and use it in GitHub Desktop.
Attempting to override the default UnityEvent drawer.
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine.Events;
using System.Reflection;
namespace Test
{
[CustomPropertyDrawer (typeof (UnityEventBase), true)]
public class Drawer : UnityEventDrawer
{
[InitializeOnLoadMethod]
static void OnLoad ()
{
Debug.LogFormat ("Attempting to disable built-in property drawer");
/*object drawer = typeof (UnityEventDrawer).GetCustomAttributes (true).FirstOrDefault (attribute => attribute is CustomPropertyDrawer);
typeof (CustomPropertyDrawer).GetField ("m_Type", BindingFlags.Instance | BindingFlags.NonPublic).SetValue (drawer, null);*/
ReplaceDrawer<UnityEventBase, Drawer> ();
}
static void ReplaceDrawer<TType, TDrawer> ()
where TType : class
where TDrawer : PropertyDrawer
{
MethodInfo dictionarySetter = ScriptAttributeUtility.DrawerTypeForTypeField.FieldType.GetMethod ("set_Item");
dictionarySetter.Invoke (
ScriptAttributeUtility.DrawerTypeForType,
new []
{
typeof (TType),
ScriptAttributeUtility.DrawerKeySet.Create<TType, TDrawer>()
}
);
}
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label)
{
base.OnGUI (position, property, label);
GUI.Label (position, "OVERRIDDEN");
Debug.Log ("PING");
}
}
}
using System;
using System.Reflection;
using UnityEditor;
namespace Test
{
public static class ScriptAttributeUtility
{
public static class DrawerKeySet
{
static Type s_Type;
public static Type Type
{
get
{
return s_Type ?? (s_Type = ScriptAttributeUtility.Type.GetNestedType ("DrawerKeySet", BindingFlags.NonPublic));
}
}
public static object Create<TType, TDrawer> ()
where TType : class
where TDrawer : PropertyDrawer
{
object instance = Activator.CreateInstance (Type);
Type.GetField ("drawer").SetValue (instance, typeof (TDrawer));
Type.GetField ("type").SetValue (instance, typeof (TType));
return instance;
}
}
static Type s_Type;
static FieldInfo s_DrawerTypeForTypeField;
static object s_DrawerTypeForType;
public static Type Type
{
get
{
return s_Type ?? (s_Type = typeof (EditorWindow).Assembly.
GetType ("UnityEditor.ScriptAttributeUtility", throwOnError: true, ignoreCase: false));
}
}
public static FieldInfo DrawerTypeForTypeField
{
get
{
return s_DrawerTypeForTypeField ?? (s_DrawerTypeForTypeField = Type.
GetField ("s_DrawerTypeForType", BindingFlags.Static | BindingFlags.NonPublic));
}
}
public static object DrawerTypeForType
{
get
{
if ((s_DrawerTypeForType ?? (s_DrawerTypeForType = DrawerTypeForTypeField.GetValue (null))) != null)
{
return s_DrawerTypeForType;
}
Type.GetMethod ("BuildDrawerTypeForTypeDictionary", BindingFlags.NonPublic | BindingFlags.Static).Invoke (null, null);
return s_DrawerTypeForType = DrawerTypeForTypeField.GetValue (null);
}
}
}
}
@nukadelic
Copy link

nukadelic commented Mar 5, 2021

What's the point of this ? You can just use it as it is without calling the ReplaceDrawer method , here is mine :

using UnityEngine;
using System.Collections;

using UnityEditor;
using UnityEngine.Events;
using UnityEditorInternal;
using UnityEngine.UIElements;

[CustomPropertyDrawer( typeof( UnityEventBase ), true )]
public class UnityEventDrawerEx : PropertyDrawer
{
    string title = "";

    public override void OnGUI( Rect position, SerializedProperty property, GUIContent label )
    {
        //if( list == null ) Init( property );

        title = label?.text ?? "";

        property.serializedObject.Update( );

        SerializedProperty listenersArray = property.FindPropertyRelative("m_PersistentCalls.m_Calls");

        var line = position;

        for(var i = 0; i < listenersArray.arraySize; ++i)
        {
            line.height = 30f;
            line.y = position.y + 30f * i;

            var prop = listenersArray.GetArrayElementAtIndex( 0 );
            var target = prop.FindPropertyRelative("m_Target");

            EditorGUI.PropertyField( line, target, GUIContent.none );
        }

        //list.DoLayoutList();

        property.serializedObject.ApplyModifiedProperties( );
    }

    public override float GetPropertyHeight( SerializedProperty property, GUIContent label )
    {
        SerializedProperty listenersArray = property.FindPropertyRelative("m_PersistentCalls.m_Calls");

        return listenersArray.arraySize * 30f;
    }

so this

image

becomes this ( just realized i had a typo with the 0 index ) :

image

@AngryAnt
Copy link
Author

AngryAnt commented Mar 6, 2021

You most definitely can. There was a point to this in 2017. There is no point to it in 2021.

But thank you for taking the time to post an update for anyone else who might come across this gist :)

@nukadelic
Copy link

ah lol didn't notice the date

@AngryAnt
Copy link
Author

AngryAnt commented Mar 6, 2021

No worries. Thanks again for the thorough assist :)

@marcusx2
Copy link

marcusx2 commented Mar 18, 2021

Do you guys know how to make Unity Events show up conditionally in the inspector? Please see the last post here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment