Skip to content

Instantly share code, notes, and snippets.

@karljj1
Last active September 16, 2024 13:51
Show Gist options
  • Save karljj1/8313a4a6d0fe6688bd5f8b90db3f72c8 to your computer and use it in GitHub Desktop.
Save karljj1/8313a4a6d0fe6688bd5f8b90db3f72c8 to your computer and use it in GitHub Desktop.
Polymorphism using UxmlAttribute
using System;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
// Our Interface.
public interface IMyInterface
{
}
// Example implementations of the interface.
[Serializable]
public class MyInterfaceImplementation : IMyInterface
{
public int someValue;
}
[Serializable]
public class MyOtherInterfaceImplementation : IMyInterface
{
public string someString;
public float someFloat;
}
// Our class that contains a reference to the interface.
[Serializable]
public class MyClass
{
[SerializeReference]
public IMyInterface myInterface;
}
// The converter class. This converts to and from the string representation of the interface instance
public class MyClassConverter : UxmlAttributeConverter<MyClass>
{
public override MyClass FromString(string value)
{
return JsonUtility.FromJson<MyClass>(value);
}
public override string ToString(MyClass value)
{
return JsonUtility.ToJson(value);
}
}
// The UXML element that uses the MyClass type.
[UxmlElement]
public partial class MyElement : VisualElement
{
[UxmlAttribute]
public MyClass myClass { get; set; }
}
// The property drawer for the MyClass type. So we can give users options on what type to create.
[CustomPropertyDrawer(typeof(MyClass))]
public class MyDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var p = property.FindPropertyRelative("myInterface");
var root = new VisualElement();
root.Add(new Button(() =>
{
p.managedReferenceValue = new MyInterfaceImplementation();
property.serializedObject.ApplyModifiedProperties();
})
{ text = "MyterfaceImplementation" });
root.Add(new Button(() =>
{
p.managedReferenceValue = new MyOtherInterfaceImplementation();
property.serializedObject.ApplyModifiedProperties();
})
{ text = "MyOtherInterfaceImplementation" });
root.Add(new PropertyField(p));
return root;
}
}
@karljj1
Copy link
Author

karljj1 commented Sep 16, 2024

Example UXML

<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
    <MyElement my-class="{&quot;myInterface&quot;:{&quot;rid&quot;:1000},&quot;references&quot;:{&quot;version&quot;:2,&quot;RefIds&quot;:[{&quot;rid&quot;:1000,&quot;type&quot;:{&quot;class&quot;:&quot;MyInterfaceImplementation&quot;,&quot;ns&quot;:&quot;&quot;,&quot;asm&quot;:&quot;Unity.UI.Builder.EditorTests&quot;},&quot;data&quot;:{&quot;someValue&quot;:123}}]}}" />
    <MyElement my-class="{&quot;myInterface&quot;:{&quot;rid&quot;:1000},&quot;references&quot;:{&quot;version&quot;:2,&quot;RefIds&quot;:[{&quot;rid&quot;:1000,&quot;type&quot;:{&quot;class&quot;:&quot;MyOtherInterfaceImplementation&quot;,&quot;ns&quot;:&quot;&quot;,&quot;asm&quot;:&quot;Unity.UI.Builder.EditorTests&quot;},&quot;data&quot;:{&quot;someString&quot;:&quot;some text&quot;,&quot;someFloat&quot;:321.0}}]}}" />
</ui:UXML>

@karljj1
Copy link
Author

karljj1 commented Sep 16, 2024

image

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