Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 22 additions & 26 deletions Alchemy/Assets/Alchemy/Editor/AlchemyAttributeDrawer.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine.UIElements;

namespace Alchemy.Editor
{
public interface IAlchemyAttributeDrawer
{
void SetContext(SerializedObject serializedObject, SerializedProperty serializedProperty, object target, MemberInfo memberInfo, Attribute attribute, VisualElement targetElement);
void OnCreateElement();
}

/// <summary>
/// Base class for extending drawing processing for fields with Alchemy attributes.
/// </summary>
public abstract class AlchemyAttributeDrawer
public abstract class AlchemyAttributeDrawer<T> : IAlchemyAttributeDrawer where T : Attribute
{
SerializedObject serializedObject;
SerializedProperty serializedProperty;
object target;
MemberInfo memberInfo;
Attribute attribute;
VisualElement targetElement;
private SerializedObject serializedObject;
private SerializedProperty serializedProperty;
private object target;
private MemberInfo memberInfo;
private T attribute;
private VisualElement targetElement;

/// <summary>
/// Target serialized object.
Expand All @@ -41,7 +48,7 @@ public abstract class AlchemyAttributeDrawer
/// <summary>
/// Target attribute.
/// </summary>
public Attribute Attribute => attribute;
public T Attribute => attribute;

/// <summary>
/// Target visual element.
Expand All @@ -53,25 +60,14 @@ public abstract class AlchemyAttributeDrawer
/// </summary>
public abstract void OnCreateElement();

internal static void ExecutePropertyDrawers(SerializedObject serializedObject, SerializedProperty property, object target, MemberInfo memberInfo, VisualElement memberElement)
void IAlchemyAttributeDrawer.SetContext(SerializedObject serializedObject, SerializedProperty serializedProperty, object target, MemberInfo memberInfo, Attribute attribute, VisualElement targetElement)
{
var attributes = memberInfo.GetCustomAttributes();
var processorTypes = TypeCache.GetTypesWithAttribute(typeof(CustomAttributeDrawerAttribute));
foreach (var attribute in attributes)
{
var processorType = processorTypes.FirstOrDefault(x => x.IsSubclassOf(typeof(AlchemyAttributeDrawer)) && x.GetCustomAttribute<CustomAttributeDrawerAttribute>().targetAttributeType == attribute.GetType());
if (processorType == null) continue;

var processor = (AlchemyAttributeDrawer)Activator.CreateInstance(processorType);
processor.serializedObject = serializedObject;
processor.serializedProperty = property;
processor.target = target;
processor.memberInfo = memberInfo;
processor.attribute = attribute;
processor.targetElement = memberElement;

processor.OnCreateElement();
}
this.serializedObject = serializedObject;
this.serializedProperty = serializedProperty;
this.target = target;
this.memberInfo = memberInfo;
this.attribute = attribute as T;
this.targetElement = targetElement;
}
}
}
27 changes: 27 additions & 0 deletions Alchemy/Assets/Alchemy/Editor/AlchemyAttributeDrawerHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine.UIElements;

namespace Alchemy.Editor
{
internal static class AlchemyAttributeDrawerHelper
{
internal static void ExecutePropertyDrawers(SerializedObject serializedObject, SerializedProperty property, object target, MemberInfo memberInfo, VisualElement memberElement)
{
var attributes = memberInfo.GetCustomAttributes();
var processorTypes = TypeCache.GetTypesWithAttribute(typeof(CustomAttributeDrawerAttribute)).Where(x => x.IsSubclassOfGeneric(typeof(AlchemyAttributeDrawer<>)));
foreach (var attribute in attributes)
{
var processorType = processorTypes.FirstOrDefault(x => x.GetCustomAttribute<CustomAttributeDrawerAttribute>().targetAttributeType == attribute.GetType());
if (processorType == null) continue;

var processor = (IAlchemyAttributeDrawer)Activator.CreateInstance(processorType);
processor.SetContext(serializedObject, property, target, memberInfo, attribute, memberElement);

processor.OnCreateElement();
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

72 changes: 36 additions & 36 deletions Alchemy/Assets/Alchemy/Editor/BuiltinAttributeDrawers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
namespace Alchemy.Editor.Drawers
{
[CustomAttributeDrawer(typeof(ReadOnlyAttribute))]
public sealed class ReadOnlyDrawer : AlchemyAttributeDrawer
public sealed class ReadOnlyDrawer : AlchemyAttributeDrawer<ReadOnlyAttribute>
{
public override void OnCreateElement()
{
Expand All @@ -18,7 +18,7 @@ public override void OnCreateElement()
}

[CustomAttributeDrawer(typeof(IndentAttribute))]
public sealed class IndentDrawer : AlchemyAttributeDrawer
public sealed class IndentDrawer : AlchemyAttributeDrawer<IndentAttribute>
{
const float IndentPadding = 15f;

Expand All @@ -36,7 +36,7 @@ void AddPadding()
}

[CustomAttributeDrawer(typeof(HideInPlayModeAttribute))]
public sealed class HideInPlayModeDrawer : AlchemyAttributeDrawer
public sealed class HideInPlayModeDrawer : AlchemyAttributeDrawer<HideInPlayModeAttribute>
{
public override void OnCreateElement()
{
Expand All @@ -45,7 +45,7 @@ public override void OnCreateElement()
}

[CustomAttributeDrawer(typeof(HideInEditModeAttribute))]
public sealed class HideInEditModeDrawer : AlchemyAttributeDrawer
public sealed class HideInEditModeDrawer : AlchemyAttributeDrawer<HideInEditModeAttribute>
{
public override void OnCreateElement()
{
Expand All @@ -54,7 +54,7 @@ public override void OnCreateElement()
}

[CustomAttributeDrawer(typeof(DisableInPlayModeAttribute))]
public sealed class DisableInPlayModeDrawer : AlchemyAttributeDrawer
public sealed class DisableInPlayModeDrawer : AlchemyAttributeDrawer<DisableInEditModeAttribute>
{
public override void OnCreateElement()
{
Expand All @@ -63,7 +63,7 @@ public override void OnCreateElement()
}

[CustomAttributeDrawer(typeof(DisableInEditModeAttribute))]
public sealed class DisableInEditModeDrawer : AlchemyAttributeDrawer
public sealed class DisableInEditModeDrawer : AlchemyAttributeDrawer<DisableInEditModeAttribute>
{
public override void OnCreateElement()
{
Expand All @@ -72,7 +72,7 @@ public override void OnCreateElement()
}

[CustomAttributeDrawer(typeof(HideLabelAttribute))]
public sealed class HideLabelDrawer : AlchemyAttributeDrawer
public sealed class HideLabelDrawer : AlchemyAttributeDrawer<HideLabelAttribute>
{
public override void OnCreateElement()
{
Expand All @@ -89,11 +89,11 @@ public override void OnCreateElement()
}

[CustomAttributeDrawer(typeof(LabelTextAttribute))]
public sealed class LabelTextDrawer : AlchemyAttributeDrawer
public sealed class LabelTextDrawer : AlchemyAttributeDrawer<LabelTextAttribute>
{
public override void OnCreateElement()
{
var labelTextAttribute = (LabelTextAttribute)Attribute;
var labelTextAttribute = Attribute;

switch (TargetElement)
{
Expand All @@ -116,11 +116,11 @@ public override void OnCreateElement()
}

[CustomAttributeDrawer(typeof(LabelWidthAttribute))]
public sealed class LabelWidthDrawer : AlchemyAttributeDrawer
public sealed class LabelWidthDrawer : AlchemyAttributeDrawer<LabelWidthAttribute>
{
public override void OnCreateElement()
{
var width = ((LabelWidthAttribute)Attribute).Width;
var width = Attribute.Width;

if (TargetElement is AlchemyPropertyField field && field.FieldElement is PropertyField)
{
Expand All @@ -141,55 +141,55 @@ public override void OnCreateElement()
}

[CustomAttributeDrawer(typeof(HideIfAttribute))]
public sealed class HideIfDrawer : TrackSerializedObjectAttributeDrawer
public sealed class HideIfDrawer : TrackSerializedObjectAttributeDrawer<HideIfAttribute>
{
protected override void OnInspectorChanged()
{
var condition = ReflectionHelper.GetValueBool(Target, ((HideIfAttribute)Attribute).Condition);
var condition = ReflectionHelper.GetValueBool(Target, Attribute.Condition);
TargetElement.style.display = condition ? DisplayStyle.None : DisplayStyle.Flex;
}
}

[CustomAttributeDrawer(typeof(ShowIfAttribute))]
public sealed class ShowIfDrawer : TrackSerializedObjectAttributeDrawer
public sealed class ShowIfDrawer : TrackSerializedObjectAttributeDrawer<ShowIfAttribute>
{
protected override void OnInspectorChanged()
{
var condition = ReflectionHelper.GetValueBool(Target, ((ShowIfAttribute)Attribute).Condition);
var condition = ReflectionHelper.GetValueBool(Target, Attribute.Condition);
TargetElement.style.display = !condition ? DisplayStyle.None : DisplayStyle.Flex;
}
}

[CustomAttributeDrawer(typeof(DisableIfAttribute))]
public sealed class DisableIfDrawer : TrackSerializedObjectAttributeDrawer
public sealed class DisableIfDrawer : TrackSerializedObjectAttributeDrawer<DisableIfAttribute>
{
protected override void OnInspectorChanged()
{
var condition = ReflectionHelper.GetValueBool(Target, ((DisableIfAttribute)Attribute).Condition);
var condition = ReflectionHelper.GetValueBool(Target, Attribute.Condition);
TargetElement.SetEnabled(!condition);
}
}

[CustomAttributeDrawer(typeof(EnableIfAttribute))]
public sealed class EnableIfDrawer : TrackSerializedObjectAttributeDrawer
public sealed class EnableIfDrawer : TrackSerializedObjectAttributeDrawer<EnableIfAttribute>
{
protected override void OnInspectorChanged()
{
var condition = ReflectionHelper.GetValueBool(Target, ((EnableIfAttribute)Attribute).Condition);
var condition = ReflectionHelper.GetValueBool(Target, Attribute.Condition);
TargetElement.SetEnabled(condition);
}
}

[CustomAttributeDrawer(typeof(RequiredAttribute))]
public sealed class RequiredDrawer : TrackSerializedObjectAttributeDrawer
public sealed class RequiredDrawer : TrackSerializedObjectAttributeDrawer<RequiredAttribute>
{
HelpBox helpBox;

public override void OnCreateElement()
{
if (SerializedProperty.propertyType != SerializedPropertyType.ObjectReference) return;

var message = ((RequiredAttribute)Attribute).Message ?? ObjectNames.NicifyVariableName(SerializedProperty.displayName) + " is required.";
var message = Attribute.Message ?? ObjectNames.NicifyVariableName(SerializedProperty.displayName) + " is required.";
helpBox = new HelpBox(message, HelpBoxMessageType.Error);

var parent = TargetElement.parent;
Expand All @@ -205,13 +205,13 @@ protected override void OnInspectorChanged()
}

[CustomAttributeDrawer(typeof(ValidateInputAttribute))]
public sealed class ValidateInputDrawer : TrackSerializedObjectAttributeDrawer
public sealed class ValidateInputDrawer : TrackSerializedObjectAttributeDrawer<ValidateInputAttribute>
{
HelpBox helpBox;

public override void OnCreateElement()
{
var message = ((ValidateInputAttribute)Attribute).Message ?? ObjectNames.NicifyVariableName(SerializedProperty.displayName) + " is not valid.";
var message = Attribute.Message ?? ObjectNames.NicifyVariableName(SerializedProperty.displayName) + " is not valid.";
helpBox = new HelpBox(message, HelpBoxMessageType.Error);

var parent = TargetElement.parent;
Expand All @@ -222,19 +222,19 @@ public override void OnCreateElement()

protected override void OnInspectorChanged()
{
var result = ReflectionHelper.Invoke(Target, ((ValidateInputAttribute)Attribute).Condition, SerializedProperty.GetValue<object>());
var result = ReflectionHelper.Invoke(Target, Attribute.Condition, SerializedProperty.GetValue<object>());
helpBox.style.display = result is bool flag && flag ? DisplayStyle.None : DisplayStyle.Flex;
}
}

[CustomAttributeDrawer(typeof(HelpBoxAttribute))]
public sealed class HelpBoxDrawer : AlchemyAttributeDrawer
public sealed class HelpBoxDrawer : AlchemyAttributeDrawer<HelpBoxAttribute>
{
HelpBox helpBox;

public override void OnCreateElement()
{
var att = (HelpBoxAttribute)Attribute;
var att = Attribute;
helpBox = new HelpBox(att.Message, att.MessageType);

var parent = TargetElement.parent;
Expand All @@ -243,7 +243,7 @@ public override void OnCreateElement()
}

[CustomAttributeDrawer(typeof(PreviewAttribute))]
public sealed class PreviewDrawer : TrackSerializedObjectAttributeDrawer
public sealed class PreviewDrawer : TrackSerializedObjectAttributeDrawer<PreviewAttribute>
{
private Image image;
private const float BorderWidth = 1f;
Expand All @@ -253,7 +253,7 @@ public override void OnCreateElement()
{
if (SerializedProperty == null || SerializedProperty.propertyType != SerializedPropertyType.ObjectReference) return;

var att = (PreviewAttribute)Attribute;
var att = Attribute;

image = new Image
{
Expand Down Expand Up @@ -306,11 +306,11 @@ protected override void OnInspectorChanged()
}

[CustomAttributeDrawer(typeof(HorizontalLineAttribute))]
public sealed class HorizontalLineDrawer : AlchemyAttributeDrawer
public sealed class HorizontalLineDrawer : AlchemyAttributeDrawer<HorizontalLineAttribute>
{
public override void OnCreateElement()
{
var att = (HorizontalLineAttribute)Attribute;
var att = Attribute;
var parent = TargetElement.parent;
var lineColor = att.Color == default ? GUIHelper.LineColor : att.Color;
var line = GUIHelper.CreateLine(lineColor, EditorGUIUtility.standardVerticalSpacing * 4f);
Expand All @@ -319,11 +319,11 @@ public override void OnCreateElement()
}

[CustomAttributeDrawer(typeof(TitleAttribute))]
public sealed class TitleDrawer : AlchemyAttributeDrawer
public sealed class TitleDrawer : AlchemyAttributeDrawer<TitleAttribute>
{
public override void OnCreateElement()
{
var att = (TitleAttribute)Attribute;
var att = Attribute;
var parent = TargetElement.parent;

var title = new Label(att.TitleText)
Expand Down Expand Up @@ -358,7 +358,7 @@ public override void OnCreateElement()
}

[CustomAttributeDrawer(typeof(BlockquoteAttribute))]
public sealed class BlockquoteDrawer : AlchemyAttributeDrawer
public sealed class BlockquoteDrawer : AlchemyAttributeDrawer<BlockquoteAttribute>
{
public BlockquoteDrawer()
{
Expand All @@ -370,7 +370,7 @@ public BlockquoteDrawer()

public override void OnCreateElement()
{
var att = (BlockquoteAttribute)Attribute;
var att = Attribute;
var blockquote = new IMGUIContainer(() =>
{
var width = EditorGUIUtility.currentViewWidth;
Expand All @@ -397,13 +397,13 @@ public override void OnCreateElement()
}

[CustomAttributeDrawer(typeof(OnValueChangedAttribute))]
public sealed class OnValueChangedDrawer : AlchemyAttributeDrawer
public sealed class OnValueChangedDrawer : AlchemyAttributeDrawer<OnValueChangedAttribute>
{
public override void OnCreateElement()
{
TargetElement.TrackPropertyValue(SerializedProperty, property =>
{
var methodName = ((OnValueChangedAttribute)Attribute).MethodName;
var methodName = Attribute.MethodName;

var methods = ReflectionHelper.GetAllMethodsIncludingBaseNonPublic(Target.GetType())
.Where(x => x.Name == methodName);
Expand Down
2 changes: 1 addition & 1 deletion Alchemy/Assets/Alchemy/Editor/Elements/ClassField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public ClassField(object obj, Type type, string label)
var e = node.Drawer?.GetGroupElement(member.GetCustomAttribute<PropertyGroupAttribute>());
if (e == null) node.VisualElement.Add(element);
else e.Add(element);
AlchemyAttributeDrawer.ExecutePropertyDrawers(null, null, obj, member, element);
AlchemyAttributeDrawerHelper.ExecutePropertyDrawers(null, null, obj, member, element);
}
}

Expand Down
Loading