Skip to content

Instantly share code, notes, and snippets.

@CoffeeVampir3
Last active April 7, 2021 08:12
Show Gist options
  • Save CoffeeVampir3/bc2f4ab2469eb7d1c47548294db274c2 to your computer and use it in GitHub Desktop.
Save CoffeeVampir3/bc2f4ab2469eb7d1c47548294db274c2 to your computer and use it in GitHub Desktop.
Unity UITK Auto Drawer
public static class FieldFactory
{
private delegate VisualElement CreationDelegate(Type t, object o);
private static readonly Dictionary<Type, CreationDelegate> creationDictionary =
new Dictionary<Type, CreationDelegate>();
private static readonly List<Type> creationTypes = new List<Type>();
private static bool initialized = false;
private static void Register<T>(CreationDelegate creationAction)
{
creationTypes.Add(typeof(T));
creationDictionary.Add(typeof(T), creationAction);
}
private static void FastRegister<ArgType, FieldType>()
where FieldType: BaseField<ArgType>, new()
{
Register<ArgType>(ConstructField<ArgType, FieldType>);
}
private static FieldType ConstructField<ArgType, FieldType>(Type t, object o)
where FieldType: BaseField<ArgType>, new()
{
var m = new FieldType();
if(o != null)
m.SetValueWithoutNotify((ArgType)o);
return m;
}
private static void RegisterAll()
{
FastRegister<float, FloatField>();
FastRegister<int, IntegerField>();
FastRegister<string, TextField>();
FastRegister<Vector2, Vector2Field>();
FastRegister<Vector3, Vector3Field>();
FastRegister<Vector4, Vector4Field>();
FastRegister<Vector2Int, Vector2IntField>();
FastRegister<Vector3Int, Vector3IntField>();
FastRegister<Bounds, BoundsField>();
FastRegister<BoundsInt, BoundsIntField>();
FastRegister<Color, ColorField>();
FastRegister<AnimationCurve, CurveField>();
FastRegister<Gradient, GradientField>();
FastRegister<Rect, RectField>();
FastRegister<RectInt, RectIntField>();
FastRegister<bool, Toggle>();
Register<UnityEngine.Object>((t, o) =>
{
var m = new ObjectField {objectType = t, allowSceneObjects = true};
if (o != null)
{
m.SetValueWithoutNotify((UnityEngine.Object) o);
}
return m;
});
Register<Enum>(CreateEnum);
}
private static VisualElement CreateEnum(Type t, object o)
{
if (o == null)
return null;
var en = (Enum)o;
bool isFlags = t.GetCustomAttributes<FlagsAttribute>().Any();
static EnumFlagsField CreateFlagsEnums(Enum someEnum)
{
EnumFlagsField ff = new EnumFlagsField(someEnum);
return ff;
}
static PopupField<string> CreateNormalEnumField(Enum someEnum, Type t)
{
Array vals = Enum.GetValues(t);
List<string> strings = new List<string>();
foreach (var item in vals)
{
strings.Add(item.ToString());
}
if (strings.Count == 0)
return null;
PopupField<string> pf = new PopupField<string>(strings, someEnum.ToString());
pf.SetValueWithoutNotify(someEnum.ToString());
return pf;
}
return isFlags ? CreateFlagsEnums(en) as VisualElement : CreateNormalEnumField(en, t);
}
private static CreationDelegate CheckIfRegistered(Type t)
{
if (!initialized)
{
RegisterAll();
initialized = true;
}
//Check for exact matches
if (creationDictionary.TryGetValue(t, out var creationFunc))
return creationFunc;
//We found no exact match, our fall back is checking the entire inheritance tree.
return (from item
in creationTypes
where item.IsAssignableFrom(t)
select creationDictionary[item]).FirstOrDefault();
}
public static VisualElement Create(Type t, object someObject)
{
CreationDelegate func = CheckIfRegistered(t);
return func?.Invoke(t, someObject);
}
public static VisualElement Create<T>(object someObject = null)
{
CreationDelegate func = CheckIfRegistered(typeof(T));
return func?.Invoke(typeof(T), someObject);
}
public static VisualElement Create<T>(T someObject)
{
CreationDelegate func = CheckIfRegistered(typeof(T));
return func?.Invoke(typeof(T), someObject);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment