diff --git a/src/Editor/ReferenceButtonAttribute.cs b/src/Editor/ReferenceButtonAttribute.cs index 84877c0..b8ea2a4 100644 --- a/src/Editor/ReferenceButtonAttribute.cs +++ b/src/Editor/ReferenceButtonAttribute.cs @@ -1,12 +1,15 @@ -using System; +using DCFApixels.DragonECS.Unity.Editors; +using System; 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 bool IsHideButtonIfNotNull; + Type[] IReferenceButtonAttribute.PredicateTypes { get { return PredicateTypes; } } + bool IReferenceButtonAttribute.IsHideButtonIfNotNull { get { return IsHideButtonIfNotNull; } } public ReferenceButtonAttribute(bool isHideButtonIfNotNull = false) : this(isHideButtonIfNotNull, Array.Empty()) { } public ReferenceButtonAttribute(params Type[] predicateTypes) : this(false, 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 namespace DCFApixels.DragonECS.Unity.Editors @@ -25,8 +36,9 @@ namespace DCFApixels.DragonECS.Unity.Editors using System; using UnityEditor; - [CustomPropertyDrawer(typeof(ReferenceButtonAttribute))] - internal sealed class ReferenceButtonAttributeDrawer : ExtendedPropertyDrawer + [CustomPropertyDrawer(typeof(ComponentTemplateReferenceAttribute), true)] + [CustomPropertyDrawer(typeof(ReferenceButtonAttribute), true)] + internal sealed class ReferenceButtonAttributeDrawer : ExtendedPropertyDrawer { protected override void OnInit() { diff --git a/src/Internal/Editor/EcsGUI.cs b/src/Internal/Editor/EcsGUI.cs index de5c042..53b114d 100644 --- a/src/Internal/Editor/EcsGUI.cs +++ b/src/Internal/Editor/EcsGUI.cs @@ -527,21 +527,21 @@ namespace DCFApixels.DragonECS.Unity.Editors { 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)) { arrayProperty.DeleteArrayElementAtIndex(elementIndex); } 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)) { - property.ResetValues(); + rootProperty.ResetValues(); } return result.HasFlag(DrawTypeMetaBlockResult.Drop); } @@ -552,7 +552,7 @@ namespace DCFApixels.DragonECS.Unity.Editors Drop = 1 << 0, 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; if (meta == null) @@ -567,24 +567,23 @@ namespace DCFApixels.DragonECS.Unity.Editors string name = meta.Name; string description = meta.Description.Text; - int positionCountr; + int positionIndex; if (index < 0) { - positionCountr = int.MaxValue; - var counter = property.Copy(); + positionIndex = int.MaxValue; + var counter = rootProperty.Copy(); int depth = -1; while (counter.NextVisibleDepth(false, ref depth)) { - positionCountr--; + positionIndex--; } } else { - positionCountr = index; + positionIndex = index; } - alphaPanelColor = SelectPanelColor(meta, positionCountr, total).Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE); - alphaPanelColor.a = EscEditorConsts.COMPONENT_DRAWER_ALPHA; + alphaPanelColor = SelectPanelColor(meta, positionIndex, total).Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE).SetAlpha(EscEditorConsts.COMPONENT_DRAWER_ALPHA); DrawTypeMetaBlockResult result = DrawTypeMetaBlockResult.None; using (CheckChanged()) @@ -601,10 +600,10 @@ namespace DCFApixels.DragonECS.Unity.Editors optionButton.center += Vector2.up * DrawTypeMetaBlockPadding * 1f; //Canceling isExpanded - bool oldIsExpanded = property.isExpanded; + bool oldIsExpanded = rootProperty.isExpanded; if (ClickTest(optionButton)) { - property.isExpanded = oldIsExpanded; + rootProperty.isExpanded = oldIsExpanded; result |= DrawTypeMetaBlockResult.Drop; } @@ -639,7 +638,8 @@ namespace DCFApixels.DragonECS.Unity.Editors { 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) { diff --git a/src/Internal/Editor/ExtendedEditor.cs b/src/Internal/Editor/ExtendedEditor.cs index f4abe62..9cc0fd0 100644 --- a/src/Internal/Editor/ExtendedEditor.cs +++ b/src/Internal/Editor/ExtendedEditor.cs @@ -53,13 +53,13 @@ namespace DCFApixels.DragonECS.Unity.Editors protected virtual bool IsStaticInit { get { return _isStaticInit; } } protected virtual bool IsInit { get { return _isInit; } } - protected void StaticInit() + public void StaticInit() { if (IsStaticInit) { return; } _isStaticInit = true; OnStaticInit(); } - protected void Init() + public void Init() { if (IsInit) { return; } _isInit = true; @@ -165,13 +165,13 @@ namespace DCFApixels.DragonECS.Unity.Editors } protected virtual bool IsStaticInit { get { return _isStaticInit; } } protected virtual bool IsInit { get { return _isInit; } } - protected void StaticInit() + public void StaticInit() { if (IsStaticInit) { return; } _isStaticInit = true; OnStaticInit(); } - protected void Init() + public void Init() { if (IsInit) { return; } _isInit = true; @@ -180,14 +180,20 @@ namespace DCFApixels.DragonECS.Unity.Editors protected virtual void OnStaticInit() { } protected virtual void OnInit() { } + //private Stopwatch _stopwatch = new Stopwatch(); + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { + //_stopwatch.Restart(); using (EcsGUI.CheckChanged(property.serializedObject)) { StaticInit(); Init(); 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); } diff --git a/src/Internal/Editor/MetaObjectsDropDown.cs b/src/Internal/Editor/MetaObjectsDropDown.cs index 681cf63..ac391d2 100644 --- a/src/Internal/Editor/MetaObjectsDropDown.cs +++ b/src/Internal/Editor/MetaObjectsDropDown.cs @@ -118,6 +118,13 @@ namespace DCFApixels.DragonECS.Unity.Editors { base.ItemSelected(item); + if (item.Obj == null) + { + _fieldProperty.managedReferenceValue = null; + _fieldProperty.serializedObject.ApplyModifiedProperties(); + return; + } + Type componentType = item.Obj.GetType(); IComponentTemplate cmptmp = item.Obj; diff --git a/src/Internal/Editor/UnityEditorUtility.cs b/src/Internal/Editor/UnityEditorUtility.cs index 848c40e..4ec3289 100644 --- a/src/Internal/Editor/UnityEditorUtility.cs +++ b/src/Internal/Editor/UnityEditorUtility.cs @@ -102,7 +102,6 @@ namespace DCFApixels.DragonECS.Unity.Editors #if UNITY_EDITOR namespace DCFApixels.DragonECS.Unity.Editors { - using System.Reflection; using UnityEditor; [InitializeOnLoad] diff --git a/src/Internal/Utils/ColorUtility.cs b/src/Internal/Utils/ColorUtility.cs index fe2b945..fd6eb62 100644 --- a/src/Internal/Utils/ColorUtility.cs +++ b/src/Internal/Utils/ColorUtility.cs @@ -16,5 +16,10 @@ namespace DCFApixels.DragonECS.Unity.Internal b = b + (gray - b) * (1 - t); return new Color(r, g, b, self.a); } + public static Color SetAlpha(this Color self, float a) + { + self.a = a; + return self; + } } } \ No newline at end of file diff --git a/src/Templates/EntityTemplate/ComponentTemplateProperty.cs b/src/Templates/EntityTemplate/ComponentTemplateProperty.cs index 0a382fb..4ef8f14 100644 --- a/src/Templates/EntityTemplate/ComponentTemplateProperty.cs +++ b/src/Templates/EntityTemplate/ComponentTemplateProperty.cs @@ -1,4 +1,5 @@ -using System; +using DCFApixels.DragonECS.Unity.Editors; +using System; using System.Runtime.CompilerServices; using UnityEngine; @@ -61,5 +62,16 @@ namespace DCFApixels.DragonECS 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; + } + } } \ No newline at end of file diff --git a/src/Templates/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs b/src/Templates/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs index 3aa0c1a..dcda40c 100644 --- a/src/Templates/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs +++ b/src/Templates/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs @@ -1,25 +1,29 @@ #if UNITY_EDITOR using DCFApixels.DragonECS.Unity.Internal; using System; -using System.Reflection; using UnityEditor; using UnityEngine; namespace DCFApixels.DragonECS.Unity.Editors { [CustomPropertyDrawer(typeof(ComponentTemplateProperty), true)] - internal class ComponentTemplatePropertyDrawer : PropertyDrawer + internal class ComponentTemplatePropertyDrawer : ExtendedPropertyDrawer { private ComponentTemplateReferenceDrawer _drawer = new ComponentTemplateReferenceDrawer(); public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { property.Next(true); + _drawer.StaticInit(); + _drawer.Init(); 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); - _drawer.OnGUI(position, property, label); + _drawer.StaticInit(); + _drawer.Init(); + _drawer.Draw(position, root, property, label); } } [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 ComponentDropDown _componentDropDown; + #region Properties private float SingleLineWithPadding => OneLineHeight + Padding * 4f; private float Padding => Spacing; - protected override bool IsInit => _componentDropDown != null; + protected override bool IsStaticInit => _componentDropDown != null; + #endregion #region Init protected override void OnStaticInit() @@ -53,25 +59,29 @@ namespace DCFApixels.DragonECS.Unity.Editors 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); } - IComponentTemplate template = property.managedReferenceValue as IComponentTemplate; - if (template == null || property.managedReferenceValue == null) + #endregion + + var instance = property.managedReferenceValue; + IComponentTemplate template = instance as IComponentTemplate; + + if (template == null || instance == null) { return EditorGUIUtility.singleLineHeight + Padding * 2f; } try { - ComponentTemplateBase customTemplate = property.managedReferenceValue as ComponentTemplateBase; - if (customTemplate != null) + if (instance is ComponentTemplateBase customTemplate) { property = property.FindPropertyRelative("component"); } } - catch (Exception) + catch { property = null; } @@ -85,155 +95,66 @@ namespace DCFApixels.DragonECS.Unity.Editors return (propCount <= 0 ? EditorGUIUtility.singleLineHeight : EditorGUI.GetPropertyHeight(property, label)) + Padding * 4f; } - - protected override void DrawCustom(Rect position, SerializedProperty componentRefProp, GUIContent label) + protected override void DrawCustom(Rect position, SerializedProperty property, GUIContent label) { - if (componentRefProp.propertyType == SerializedPropertyType.ManagedReference == false) + 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, componentRefProp, label, true); + EditorGUI.PropertyField(position, property, label, true); + return; + } + #endregion + + var instance = property.managedReferenceValue; + IComponentTemplate template = instance as IComponentTemplate; + + if (template == null || instance == null) + { + DrawSelectionPopup(position, property, label); return; } - Init(); - var counter = componentRefProp.Copy(); - - int positionCountr = int.MaxValue; - while (counter.NextVisible(false)) + SerializedProperty componentProp = property; + if (componentProp.managedReferenceValue is ComponentTemplateBase customTemplate) { - positionCountr--; + componentProp = property.FindPropertyRelative("component"); } - - IComponentTemplate template = componentRefProp.managedReferenceValue as IComponentTemplate; - if (template == null || componentRefProp.managedReferenceValue == null) + if (componentProp == 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."); return; } - //сюда попадают уже валидные компоненты - ITypeMeta meta = template is ITypeMeta metaOverride ? metaOverride : template.Type.ToMeta(); - string name = meta.Name; - string description = meta.Description.Text; - int propCount = EcsGUI.GetChildPropertiesCount(componentProperty); - - 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)) + Rect rect = position; + if (EcsGUI.DrawTypeMetaBlock(ref rect, rootProperty, meta)) { - componentProperty.isExpanded = !componentProperty.isExpanded; - } - - #region Draw Component Block - //Close button - optionButton.xMin = optionButton.xMax - HeadIconsRect.width; - if (EcsGUI.CloseButton(optionButton)) - { - componentRefProp.managedReferenceValue = null; 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); - } - - if (propCount <= 0) + label.text = meta.Name; + if (componentProp.propertyType == SerializedPropertyType.Generic) { - EcsGUI.DrawEmptyComponentProperty(paddingPosition, componentRefProp, label, false); + EditorGUI.PropertyField(rect, componentProp, label, true); } else { - if (componentProperty.propertyType == SerializedPropertyType.Generic) - { - 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); + EditorGUI.PropertyField(rect.AddPadding(0, 20f, 0, 0), componentProp, label, true); } } - private void DrawSelectionPopup(Rect position, SerializedProperty componentRefProp, GUIContent label) + private void DrawSelectionPopup(Rect position, SerializedProperty property, GUIContent label) { EditorGUI.LabelField(position, label); Rect buttonRect = RectUtility.AddPadding(position, EditorGUIUtility.labelWidth, 0f, 0f, 0f); if (GUI.Button(buttonRect, "Select")) { - currentProperty = componentRefProp; + currentProperty = property; _componentDropDown.Show(buttonRect); } }