refactoring

This commit is contained in:
Mikhail 2024-10-02 14:01:18 +08:00
parent e2fca85636
commit 1517c944a0
8 changed files with 120 additions and 158 deletions

View File

@ -1,12 +1,15 @@
using System; using DCFApixels.DragonECS.Unity.Editors;
using System;
using UnityEngine; using UnityEngine;
namespace DCFApixels.DragonECS.Unity.Internal namespace DCFApixels.DragonECS
{ {
internal sealed class ReferenceButtonAttribute : PropertyAttribute public sealed class ReferenceButtonAttribute : PropertyAttribute, IReferenceButtonAttribute
{ {
public readonly Type[] PredicateTypes; public readonly Type[] PredicateTypes;
public readonly bool IsHideButtonIfNotNull; public readonly bool IsHideButtonIfNotNull;
Type[] IReferenceButtonAttribute.PredicateTypes { get { return PredicateTypes; } }
bool IReferenceButtonAttribute.IsHideButtonIfNotNull { get { return IsHideButtonIfNotNull; } }
public ReferenceButtonAttribute(bool isHideButtonIfNotNull = false) : this(isHideButtonIfNotNull, Array.Empty<Type>()) { } public ReferenceButtonAttribute(bool isHideButtonIfNotNull = false) : this(isHideButtonIfNotNull, Array.Empty<Type>()) { }
public ReferenceButtonAttribute(params Type[] predicateTypes) : this(false, predicateTypes) { } public ReferenceButtonAttribute(params Type[] predicateTypes) : this(false, predicateTypes) { }
public ReferenceButtonAttribute(bool isHideButtonIfNotNull, params Type[] predicateTypes) public ReferenceButtonAttribute(bool isHideButtonIfNotNull, params Type[] predicateTypes)
@ -17,6 +20,14 @@ namespace DCFApixels.DragonECS.Unity.Internal
} }
} }
} }
namespace DCFApixels.DragonECS.Unity.Editors
{
public interface IReferenceButtonAttribute
{
Type[] PredicateTypes { get; }
bool IsHideButtonIfNotNull { get; }
}
}
#if UNITY_EDITOR #if UNITY_EDITOR
namespace DCFApixels.DragonECS.Unity.Editors namespace DCFApixels.DragonECS.Unity.Editors
@ -25,8 +36,9 @@ namespace DCFApixels.DragonECS.Unity.Editors
using System; using System;
using UnityEditor; using UnityEditor;
[CustomPropertyDrawer(typeof(ReferenceButtonAttribute))] [CustomPropertyDrawer(typeof(ComponentTemplateReferenceAttribute), true)]
internal sealed class ReferenceButtonAttributeDrawer : ExtendedPropertyDrawer<ReferenceButtonAttribute> [CustomPropertyDrawer(typeof(ReferenceButtonAttribute), true)]
internal sealed class ReferenceButtonAttributeDrawer : ExtendedPropertyDrawer<IReferenceButtonAttribute>
{ {
protected override void OnInit() protected override void OnInit()
{ {

View File

@ -527,21 +527,21 @@ namespace DCFApixels.DragonECS.Unity.Editors
{ {
return DrawTypeMetaBlockPadding * 2 + contentHeight; return DrawTypeMetaBlockPadding * 2 + contentHeight;
} }
public static bool DrawTypeMetaElementBlock(ref Rect position, SerializedProperty arrayProperty, int elementIndex, SerializedProperty elementProperty, ITypeMeta meta) public static bool DrawTypeMetaElementBlock(ref Rect position, SerializedProperty arrayProperty, int elementIndex, SerializedProperty elementRootProperty, ITypeMeta meta)
{ {
var result = DrawTypeMetaBlock_Internal(ref position, elementProperty, meta, elementIndex, arrayProperty.arraySize); var result = DrawTypeMetaBlock_Internal(ref position, elementRootProperty, meta, elementIndex, arrayProperty.arraySize);
if (result.HasFlag(DrawTypeMetaBlockResult.CloseButtonClicked)) if (result.HasFlag(DrawTypeMetaBlockResult.CloseButtonClicked))
{ {
arrayProperty.DeleteArrayElementAtIndex(elementIndex); arrayProperty.DeleteArrayElementAtIndex(elementIndex);
} }
return result != DrawTypeMetaBlockResult.None; return result != DrawTypeMetaBlockResult.None;
} }
public static bool DrawTypeMetaBlock(ref Rect position, SerializedProperty property, ITypeMeta meta) public static bool DrawTypeMetaBlock(ref Rect position, SerializedProperty rootProperty, ITypeMeta meta, int index = -1, int total = -1)
{ {
var result = DrawTypeMetaBlock_Internal(ref position, property, meta); var result = DrawTypeMetaBlock_Internal(ref position, rootProperty, meta, index, total);
if (result.HasFlag(DrawTypeMetaBlockResult.CloseButtonClicked)) if (result.HasFlag(DrawTypeMetaBlockResult.CloseButtonClicked))
{ {
property.ResetValues(); rootProperty.ResetValues();
} }
return result.HasFlag(DrawTypeMetaBlockResult.Drop); return result.HasFlag(DrawTypeMetaBlockResult.Drop);
} }
@ -552,7 +552,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
Drop = 1 << 0, Drop = 1 << 0,
CloseButtonClicked = 1 << 1, CloseButtonClicked = 1 << 1,
} }
private static DrawTypeMetaBlockResult DrawTypeMetaBlock_Internal(ref Rect position, SerializedProperty property, ITypeMeta meta, int index = -1, int total = -1) private static DrawTypeMetaBlockResult DrawTypeMetaBlock_Internal(ref Rect position, SerializedProperty rootProperty, ITypeMeta meta, int index = -1, int total = -1)
{ {
Color alphaPanelColor; Color alphaPanelColor;
if (meta == null) if (meta == null)
@ -567,24 +567,23 @@ namespace DCFApixels.DragonECS.Unity.Editors
string name = meta.Name; string name = meta.Name;
string description = meta.Description.Text; string description = meta.Description.Text;
int positionCountr; int positionIndex;
if (index < 0) if (index < 0)
{ {
positionCountr = int.MaxValue; positionIndex = int.MaxValue;
var counter = property.Copy(); var counter = rootProperty.Copy();
int depth = -1; int depth = -1;
while (counter.NextVisibleDepth(false, ref depth)) while (counter.NextVisibleDepth(false, ref depth))
{ {
positionCountr--; positionIndex--;
} }
} }
else else
{ {
positionCountr = index; positionIndex = index;
} }
alphaPanelColor = SelectPanelColor(meta, positionCountr, total).Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE); alphaPanelColor = SelectPanelColor(meta, positionIndex, total).Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE).SetAlpha(EscEditorConsts.COMPONENT_DRAWER_ALPHA);
alphaPanelColor.a = EscEditorConsts.COMPONENT_DRAWER_ALPHA;
DrawTypeMetaBlockResult result = DrawTypeMetaBlockResult.None; DrawTypeMetaBlockResult result = DrawTypeMetaBlockResult.None;
using (CheckChanged()) using (CheckChanged())
@ -601,10 +600,10 @@ namespace DCFApixels.DragonECS.Unity.Editors
optionButton.center += Vector2.up * DrawTypeMetaBlockPadding * 1f; optionButton.center += Vector2.up * DrawTypeMetaBlockPadding * 1f;
//Canceling isExpanded //Canceling isExpanded
bool oldIsExpanded = property.isExpanded; bool oldIsExpanded = rootProperty.isExpanded;
if (ClickTest(optionButton)) if (ClickTest(optionButton))
{ {
property.isExpanded = oldIsExpanded; rootProperty.isExpanded = oldIsExpanded;
result |= DrawTypeMetaBlockResult.Drop; result |= DrawTypeMetaBlockResult.Drop;
} }
@ -639,7 +638,8 @@ namespace DCFApixels.DragonECS.Unity.Editors
{ {
depth = property.depth; depth = property.depth;
} }
return property.NextVisible(child) && property.depth >= depth; var next = property.NextVisible(child);
return next && property.depth >= depth;
} }
internal static bool NextDepth(this SerializedProperty property, bool child, ref int depth) internal static bool NextDepth(this SerializedProperty property, bool child, ref int depth)
{ {

View File

@ -53,13 +53,13 @@ namespace DCFApixels.DragonECS.Unity.Editors
protected virtual bool IsStaticInit { get { return _isStaticInit; } } protected virtual bool IsStaticInit { get { return _isStaticInit; } }
protected virtual bool IsInit { get { return _isInit; } } protected virtual bool IsInit { get { return _isInit; } }
protected void StaticInit() public void StaticInit()
{ {
if (IsStaticInit) { return; } if (IsStaticInit) { return; }
_isStaticInit = true; _isStaticInit = true;
OnStaticInit(); OnStaticInit();
} }
protected void Init() public void Init()
{ {
if (IsInit) { return; } if (IsInit) { return; }
_isInit = true; _isInit = true;
@ -165,13 +165,13 @@ namespace DCFApixels.DragonECS.Unity.Editors
} }
protected virtual bool IsStaticInit { get { return _isStaticInit; } } protected virtual bool IsStaticInit { get { return _isStaticInit; } }
protected virtual bool IsInit { get { return _isInit; } } protected virtual bool IsInit { get { return _isInit; } }
protected void StaticInit() public void StaticInit()
{ {
if (IsStaticInit) { return; } if (IsStaticInit) { return; }
_isStaticInit = true; _isStaticInit = true;
OnStaticInit(); OnStaticInit();
} }
protected void Init() public void Init()
{ {
if (IsInit) { return; } if (IsInit) { return; }
_isInit = true; _isInit = true;
@ -180,14 +180,20 @@ namespace DCFApixels.DragonECS.Unity.Editors
protected virtual void OnStaticInit() { } protected virtual void OnStaticInit() { }
protected virtual void OnInit() { } protected virtual void OnInit() { }
//private Stopwatch _stopwatch = new Stopwatch();
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{ {
//_stopwatch.Restart();
using (EcsGUI.CheckChanged(property.serializedObject)) using (EcsGUI.CheckChanged(property.serializedObject))
{ {
StaticInit(); StaticInit();
Init(); Init();
DrawCustom(position, property, label); DrawCustom(position, property, label);
} }
//_stopwatch.Stop();
//var result = _stopwatch.Elapsed;
//UnityEngine.Debug.Log($"{result.Minutes}:{result.Seconds}:{result.Milliseconds}");
} }
protected abstract void DrawCustom(Rect position, SerializedProperty property, GUIContent label); protected abstract void DrawCustom(Rect position, SerializedProperty property, GUIContent label);
} }

View File

@ -118,6 +118,13 @@ namespace DCFApixels.DragonECS.Unity.Editors
{ {
base.ItemSelected(item); base.ItemSelected(item);
if (item.Obj == null)
{
_fieldProperty.managedReferenceValue = null;
_fieldProperty.serializedObject.ApplyModifiedProperties();
return;
}
Type componentType = item.Obj.GetType(); Type componentType = item.Obj.GetType();
IComponentTemplate cmptmp = item.Obj; IComponentTemplate cmptmp = item.Obj;

View File

@ -102,7 +102,6 @@ namespace DCFApixels.DragonECS.Unity.Editors
#if UNITY_EDITOR #if UNITY_EDITOR
namespace DCFApixels.DragonECS.Unity.Editors namespace DCFApixels.DragonECS.Unity.Editors
{ {
using System.Reflection;
using UnityEditor; using UnityEditor;
[InitializeOnLoad] [InitializeOnLoad]

View File

@ -16,5 +16,10 @@ namespace DCFApixels.DragonECS.Unity.Internal
b = b + (gray - b) * (1 - t); b = b + (gray - b) * (1 - t);
return new Color(r, g, b, self.a); return new Color(r, g, b, self.a);
} }
public static Color SetAlpha(this Color self, float a)
{
self.a = a;
return self;
}
} }
} }

View File

@ -1,4 +1,5 @@
using System; using DCFApixels.DragonECS.Unity.Editors;
using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using UnityEngine; using UnityEngine;
@ -61,5 +62,16 @@ namespace DCFApixels.DragonECS
public readonly struct Null { } public readonly struct Null { }
} }
public sealed class ComponentTemplateReferenceAttribute : PropertyAttribute { } public sealed class ComponentTemplateReferenceAttribute : PropertyAttribute, IReferenceButtonAttribute
{
public readonly Type[] PredicateTypes;
public readonly bool IsHideButtonIfNotNull;
Type[] IReferenceButtonAttribute.PredicateTypes { get { return PredicateTypes; } }
bool IReferenceButtonAttribute.IsHideButtonIfNotNull { get { return IsHideButtonIfNotNull; } }
public ComponentTemplateReferenceAttribute()
{
PredicateTypes = new Type[] { typeof(IComponentTemplate) };
IsHideButtonIfNotNull = true;
}
}
} }

View File

@ -1,25 +1,29 @@
#if UNITY_EDITOR #if UNITY_EDITOR
using DCFApixels.DragonECS.Unity.Internal; using DCFApixels.DragonECS.Unity.Internal;
using System; using System;
using System.Reflection;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
namespace DCFApixels.DragonECS.Unity.Editors namespace DCFApixels.DragonECS.Unity.Editors
{ {
[CustomPropertyDrawer(typeof(ComponentTemplateProperty), true)] [CustomPropertyDrawer(typeof(ComponentTemplateProperty), true)]
internal class ComponentTemplatePropertyDrawer : PropertyDrawer internal class ComponentTemplatePropertyDrawer : ExtendedPropertyDrawer
{ {
private ComponentTemplateReferenceDrawer _drawer = new ComponentTemplateReferenceDrawer(); private ComponentTemplateReferenceDrawer _drawer = new ComponentTemplateReferenceDrawer();
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{ {
property.Next(true); property.Next(true);
_drawer.StaticInit();
_drawer.Init();
return _drawer.GetPropertyHeight(property, label); return _drawer.GetPropertyHeight(property, label);
} }
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) protected override void DrawCustom(Rect position, SerializedProperty property, GUIContent label)
{ {
var root = property.Copy();
property.Next(true); property.Next(true);
_drawer.OnGUI(position, property, label); _drawer.StaticInit();
_drawer.Init();
_drawer.Draw(position, root, property, label);
} }
} }
[CustomPropertyDrawer(typeof(ComponentTemplateReferenceAttribute), true)] [CustomPropertyDrawer(typeof(ComponentTemplateReferenceAttribute), true)]
@ -29,9 +33,11 @@ namespace DCFApixels.DragonECS.Unity.Editors
private static readonly Rect HeadIconsRect = new Rect(0f, 0f, 19f, 19f); private static readonly Rect HeadIconsRect = new Rect(0f, 0f, 19f, 19f);
private static ComponentDropDown _componentDropDown; private static ComponentDropDown _componentDropDown;
#region Properties
private float SingleLineWithPadding => OneLineHeight + Padding * 4f; private float SingleLineWithPadding => OneLineHeight + Padding * 4f;
private float Padding => Spacing; private float Padding => Spacing;
protected override bool IsInit => _componentDropDown != null; protected override bool IsStaticInit => _componentDropDown != null;
#endregion
#region Init #region Init
protected override void OnStaticInit() protected override void OnStaticInit()
@ -53,25 +59,29 @@ namespace DCFApixels.DragonECS.Unity.Editors
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{ {
if (property.propertyType == SerializedPropertyType.ManagedReference == false) #region No SerializeReference
if (property.propertyType != SerializedPropertyType.ManagedReference)
{ {
return EditorGUI.GetPropertyHeight(property, label); return EditorGUI.GetPropertyHeight(property, label);
} }
IComponentTemplate template = property.managedReferenceValue as IComponentTemplate; #endregion
if (template == null || property.managedReferenceValue == null)
var instance = property.managedReferenceValue;
IComponentTemplate template = instance as IComponentTemplate;
if (template == null || instance == null)
{ {
return EditorGUIUtility.singleLineHeight + Padding * 2f; return EditorGUIUtility.singleLineHeight + Padding * 2f;
} }
try try
{ {
ComponentTemplateBase customTemplate = property.managedReferenceValue as ComponentTemplateBase; if (instance is ComponentTemplateBase customTemplate)
if (customTemplate != null)
{ {
property = property.FindPropertyRelative("component"); property = property.FindPropertyRelative("component");
} }
} }
catch (Exception) catch
{ {
property = null; property = null;
} }
@ -85,155 +95,66 @@ namespace DCFApixels.DragonECS.Unity.Editors
return (propCount <= 0 ? EditorGUIUtility.singleLineHeight : EditorGUI.GetPropertyHeight(property, label)) + Padding * 4f; return (propCount <= 0 ? EditorGUIUtility.singleLineHeight : EditorGUI.GetPropertyHeight(property, label)) + Padding * 4f;
} }
protected override void DrawCustom(Rect position, SerializedProperty property, GUIContent label)
{
Draw(position, property, property, label);
}
public void Draw(Rect position, SerializedProperty rootProperty, SerializedProperty property, GUIContent label)
{
#region No SerializeReference
if (property.propertyType != SerializedPropertyType.ManagedReference)
{
EditorGUI.PropertyField(position, property, label, true);
return;
}
#endregion
protected override void DrawCustom(Rect position, SerializedProperty componentRefProp, GUIContent label) var instance = property.managedReferenceValue;
IComponentTemplate template = instance as IComponentTemplate;
if (template == null || instance == null)
{ {
if (componentRefProp.propertyType == SerializedPropertyType.ManagedReference == false) DrawSelectionPopup(position, property, label);
{
EditorGUI.PropertyField(position, componentRefProp, label, true);
return; return;
} }
Init(); SerializedProperty componentProp = property;
var counter = componentRefProp.Copy(); if (componentProp.managedReferenceValue is ComponentTemplateBase customTemplate)
int positionCountr = int.MaxValue;
while (counter.NextVisible(false))
{ {
positionCountr--; componentProp = property.FindPropertyRelative("component");
} }
if (componentProp == null)
IComponentTemplate template = componentRefProp.managedReferenceValue as IComponentTemplate;
if (template == null || componentRefProp.managedReferenceValue == null)
{ {
DrawSelectionPopup(position, componentRefProp, label);
return;
}
Type componentType;
SerializedProperty componentProperty = componentRefProp;
try
{
ComponentTemplateBase customTemplate = componentProperty.managedReferenceValue as ComponentTemplateBase;
if (customTemplate != null)
{
componentProperty = componentRefProp.FindPropertyRelative("component");
componentType = customTemplate.GetType().GetField("component", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FieldType;
}
else
{
componentType = componentProperty.managedReferenceValue.GetType();
}
if (componentType == null || componentProperty == null)
{
throw new NullReferenceException();
}
}
catch (Exception e)
{
Debug.LogException(e, componentRefProp.serializedObject.targetObject);
DrawDamagedComponent(position, "Damaged component template."); DrawDamagedComponent(position, "Damaged component template.");
return; return;
} }
//сюда попадают уже валидные компоненты
ITypeMeta meta = template is ITypeMeta metaOverride ? metaOverride : template.Type.ToMeta(); ITypeMeta meta = template is ITypeMeta metaOverride ? metaOverride : template.Type.ToMeta();
string name = meta.Name;
string description = meta.Description.Text;
int propCount = EcsGUI.GetChildPropertiesCount(componentProperty); Rect rect = position;
if (EcsGUI.DrawTypeMetaBlock(ref rect, rootProperty, meta))
Color panelColor = EcsGUI.SelectPanelColor(meta, positionCountr, -1).Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE);
Color alphaPanelColor = panelColor;
alphaPanelColor.a = EscEditorConsts.COMPONENT_DRAWER_ALPHA;
EditorGUI.BeginChangeCheck();
EditorGUI.DrawRect(position, alphaPanelColor);
Rect paddingPosition = RectUtility.AddPadding(position, Padding * 2f);
Rect optionButton = position;
optionButton.center -= new Vector2(0, optionButton.height);
optionButton.yMin = optionButton.yMax;
optionButton.yMax += HeadIconsRect.height;
optionButton.xMin = optionButton.xMax - 64;
optionButton.center += Vector2.up * Padding * 1f;
//Canceling isExpanded
if (EcsGUI.ClickTest(optionButton))
{ {
componentProperty.isExpanded = !componentProperty.isExpanded;
}
#region Draw Component Block
//Close button
optionButton.xMin = optionButton.xMax - HeadIconsRect.width;
if (EcsGUI.CloseButton(optionButton))
{
componentRefProp.managedReferenceValue = null;
return; return;
} }
//Edit script button
if (ScriptsCache.TryGetScriptAsset(meta.FindRootTypeMeta(), out MonoScript script))
{
optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width));
EcsGUI.ScriptAssetButton(optionButton, script);
}
//Description icon
if (string.IsNullOrEmpty(description) == false)
{
optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width));
EcsGUI.DescriptionIcon(optionButton, description);
}
label.text = meta.Name;
if (propCount <= 0) if (componentProp.propertyType == SerializedPropertyType.Generic)
{ {
EcsGUI.DrawEmptyComponentProperty(paddingPosition, componentRefProp, label, false); EditorGUI.PropertyField(rect, componentProp, label, true);
} }
else else
{ {
if (componentProperty.propertyType == SerializedPropertyType.Generic) EditorGUI.PropertyField(rect.AddPadding(0, 20f, 0, 0), componentProp, label, true);
{
EditorGUI.PropertyField(paddingPosition, componentProperty, label, true);
}
else
{
Rect r = RectUtility.AddPadding(paddingPosition, 0, 20f, 0, 0);
EditorGUI.PropertyField(r, componentProperty, label, true);
}
}
if (string.IsNullOrEmpty(label.text))
{
EditorGUI.indentLevel++;
EditorGUI.PrefixLabel(position.AddPadding(0, 0, 0, position.height - SingleLineWithPadding), UnityEditorUtility.GetLabel(name));
EditorGUI.indentLevel--;
}
else
{
GUI.Label(position.AddPadding(EditorGUIUtility.labelWidth, 0, 0, position.height - SingleLineWithPadding), name);
}
#endregion
if (EditorGUI.EndChangeCheck())
{
componentProperty.serializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(componentProperty.serializedObject.targetObject);
} }
} }
private void DrawSelectionPopup(Rect position, SerializedProperty componentRefProp, GUIContent label) private void DrawSelectionPopup(Rect position, SerializedProperty property, GUIContent label)
{ {
EditorGUI.LabelField(position, label); EditorGUI.LabelField(position, label);
Rect buttonRect = RectUtility.AddPadding(position, EditorGUIUtility.labelWidth, 0f, 0f, 0f); Rect buttonRect = RectUtility.AddPadding(position, EditorGUIUtility.labelWidth, 0f, 0f, 0f);
if (GUI.Button(buttonRect, "Select")) if (GUI.Button(buttonRect, "Select"))
{ {
currentProperty = componentRefProp; currentProperty = property;
_componentDropDown.Show(buttonRect); _componentDropDown.Show(buttonRect);
} }
} }