diff --git a/src/EcsPipelineTemplate/EcsPipelineTemplateSO.cs b/src/EcsPipelineTemplate/EcsPipelineTemplateSO.cs index 7845f21..968dd4f 100644 --- a/src/EcsPipelineTemplate/EcsPipelineTemplateSO.cs +++ b/src/EcsPipelineTemplate/EcsPipelineTemplateSO.cs @@ -137,7 +137,8 @@ namespace DCFApixels.DragonECS { [SerializeReference] [ReferenceButton(true, typeof(IEcsModule), typeof(IEcsProcess))] - public object target; + [ArrayElement] + public object target;// нельзя менять поярдок полей, иначе это поломает отрисовку в инспекторе изза применения property.Next(bool); public AddParams parameters; public Record(object target, AddParams parameters) { diff --git a/src/EcsPipelineTemplate/EcsPipelineTemplateSOEditor.cs b/src/EcsPipelineTemplate/EcsPipelineTemplateSOEditor.cs index 28b67a9..4fd5896 100644 --- a/src/EcsPipelineTemplate/EcsPipelineTemplateSOEditor.cs +++ b/src/EcsPipelineTemplate/EcsPipelineTemplateSOEditor.cs @@ -8,7 +8,6 @@ using UnityEngine; namespace DCFApixels.DragonECS.Unity.Editors { [CustomPropertyDrawer(typeof(EcsPipelineTemplateSO.Record))] - //[CustomPropertyDrawer(typeof(EcsPipelineTemplate.Record))] internal class EcsPipelineTemplateSORecordDrawer : ExtendedPropertyDrawer { protected override void DrawCustom(Rect position, SerializedProperty property, GUIContent label) @@ -28,8 +27,9 @@ namespace DCFApixels.DragonECS.Unity.Editors { Rect subPosition = position; int depth = -1; - property.Next(true); float height = 0f; + + property.Next(true); do { subPosition.y += height; @@ -71,7 +71,7 @@ namespace DCFApixels.DragonECS.Unity.Editors private SerializedProperty _recordsProp; private ReorderableList _reorderableLayersList; private ReorderableList _reorderableRecordsList; - + private SystemsDropDown _systemsDropDown; protected override bool IsInit { @@ -94,14 +94,29 @@ namespace DCFApixels.DragonECS.Unity.Editors _reorderableLayersList.drawElementCallback += OnReorderableLayersListDrawElement; _reorderableLayersList.onReorderCallback += OnReorderableListReorder; - _reorderableRecordsList = new ReorderableList(serializedObject, _recordsProp, true, false, true, true); + _reorderableRecordsList = new ReorderableList(serializedObject, _recordsProp, true, false, false, false); _reorderableRecordsList.onAddCallback += OnReorderableRecordsListAdd; _reorderableRecordsList.onRemoveCallback += OnReorderableListRemove; - _reorderableRecordsList.drawElementCallback += OnReorderableRecordsListDrawElement; + _reorderableRecordsList.drawElementCallback += OnReorderableListDrawEmptyElement; + _reorderableRecordsList.drawElementBackgroundCallback += OnReorderableRecordsListDrawElement; + _reorderableRecordsList.drawNoneElementCallback += OnReorderableRecordsListDrawNoneElement; _reorderableRecordsList.elementHeightCallback += OnReorderableRecordsListElementHeight; _reorderableRecordsList.onReorderCallback += OnReorderableListReorder; + _reorderableRecordsList.showDefaultBackground = false; + _reorderableRecordsList.footerHeight = 0f; + _reorderableRecordsList.headerHeight = 0f; + _reorderableRecordsList.elementHeight = 0f; + + _systemsDropDown = new SystemsDropDown(); } + private void OnReorderableRecordsListDrawNoneElement(Rect rect) + { + + } + + private void OnReorderableListDrawEmptyElement(Rect rect, int index, bool isActive, bool isFocused) { } + private void OnReorderableListReorder(ReorderableList list) { EcsGUI.Changed = true; @@ -148,17 +163,22 @@ namespace DCFApixels.DragonECS.Unity.Editors #region _reorderableRecordsList private void OnReorderableRecordsListDrawElement(Rect rect, int index, bool isActive, bool isFocused) { + if (index < 0) { return; } + rect = rect.AddPadding(OneLineHeight + Spacing, Spacing * 2f, Spacing, Spacing); using (EcsGUI.CheckChanged()) { - var prop = _recordsProp.GetArrayElementAtIndex(index); - + if (Event.current.type == EventType.Used) + { + return; + } + //EcsDebug.PrintPass(index); + SerializedProperty prop = _recordsProp.GetArrayElementAtIndex(index); var targetProp = prop.FindPropertyRelative(nameof(EcsPipelineTemplateSO.Record.target)); - var paramsProp = prop.FindPropertyRelative(nameof(EcsPipelineTemplateSO.Record.parameters)); bool isNull = targetProp.managedReferenceValue == null; ITypeMeta meta = isNull ? null : targetProp.managedReferenceValue.GetMeta(); - if (EcsGUI.DrawTypeMetaBlock(ref rect, prop, meta)) + if (EcsGUI.DrawTypeMetaElementBlock(ref rect, _recordsProp, index, prop, meta)) { return; } @@ -169,7 +189,7 @@ namespace DCFApixels.DragonECS.Unity.Editors { float result; result = EditorGUI.GetPropertyHeight(_recordsProp.GetArrayElementAtIndex(index)); - return EcsGUI.GetTypeMetaBlockHeight(result); + return EcsGUI.GetTypeMetaBlockHeight(result) + Spacing * 2f; } private void OnReorderableRecordsListAdd(ReorderableList list) @@ -183,20 +203,16 @@ namespace DCFApixels.DragonECS.Unity.Editors protected override void DrawCustom() { - using (EcsGUI.CheckChanged()) + EcsGUI.Changed = GUILayout.Button("Validate"); + + DrawLayoutNameList(_layersProp); + DrawRecordList(_recordsProp); + + if (EcsGUI.Changed) { - EditorGUI.BeginChangeCheck(); - - DrawLayoutNameList(_layersProp); - DrawRecordList(_recordsProp); - - EcsGUI.Changed = GUILayout.Button("Validate"); - if (EcsGUI.Changed) - { - serializedObject.ApplyModifiedProperties(); - Validate(); - Repaint(); - } + serializedObject.ApplyModifiedProperties(); + Validate(); + Repaint(); } } @@ -220,9 +236,19 @@ namespace DCFApixels.DragonECS.Unity.Editors } private void DrawRecordList(SerializedProperty recordsProp) { - using (EcsGUI.Layout.BeginVertical()) + GUILayout.Label(UnityEditorUtility.GetLabel(recordsProp.displayName), EditorStyles.boldLabel); + using (EcsGUI.Layout.BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f))) { - GUILayout.Label(UnityEditorUtility.GetLabel(recordsProp.displayName), EditorStyles.boldLabel); + switch (EcsGUI.Layout.AddClearSystemButtons(out Rect dropDownRect)) + { + case EcsGUI.AddClearButton.Add: + _systemsDropDown.OpenForArray(dropDownRect, recordsProp); + break; + case EcsGUI.AddClearButton.Clear: + recordsProp.ClearArray(); + recordsProp.serializedObject.ApplyModifiedProperties(); + break; + } _reorderableRecordsList.DoLayoutList(); //EditorGUILayout.PropertyField(recordsProp, UnityEditorUtility.GetLabel(recordsProp.displayName)); } diff --git a/src/EcsPipelineTemplate/ReferenceButtonAttribute.cs b/src/Editor/ReferenceButtonAttribute.cs similarity index 63% rename from src/EcsPipelineTemplate/ReferenceButtonAttribute.cs rename to src/Editor/ReferenceButtonAttribute.cs index a8a414a..5890965 100644 --- a/src/EcsPipelineTemplate/ReferenceButtonAttribute.cs +++ b/src/Editor/ReferenceButtonAttribute.cs @@ -28,8 +28,34 @@ namespace DCFApixels.DragonECS.Unity.Editors [CustomPropertyDrawer(typeof(ReferenceButtonAttribute))] internal sealed class ReferenceButtonAttributeDrawer : ExtendedPropertyDrawer { + protected override void OnInit() + { + Type referenceBaseType = typeof(Reference<>); + Type fieldType = fieldInfo.FieldType; + if (fieldType.IsGenericType) + { + if (fieldType.IsGenericTypeDefinition == false) + { + fieldType = fieldType.GetGenericTypeDefinition(); + } + if (fieldType == referenceBaseType) + { + _isReferenceWrapper = true; + return; + } + } + _isReferenceWrapper = false; + } + + private bool _isReferenceWrapper = false; + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { + if (_isReferenceWrapper) + { + property.Next(true); + } + if (property.managedReferenceValue != null) { return EditorGUI.GetPropertyHeight(property, label, true); @@ -42,9 +68,19 @@ namespace DCFApixels.DragonECS.Unity.Editors protected override void DrawCustom(Rect position, SerializedProperty property, GUIContent label) { + if (_isReferenceWrapper) + { + property.Next(true); + label.text = property.displayName; + } + + if (IsArrayElement) + { + label = UnityEditorUtility.GetLabelTemp(); + } Rect selButtnoRect = position; selButtnoRect.height = OneLineHeight; - DrawSelectionPopup(selButtnoRect, property, label); + DrawSelectionPopupButton(selButtnoRect, property, label); if (property.managedReferenceValue != null) { @@ -58,9 +94,9 @@ namespace DCFApixels.DragonECS.Unity.Editors } } - private void DrawSelectionPopup(Rect position, SerializedProperty property, GUIContent label) + private void DrawSelectionPopupButton(Rect position, SerializedProperty property, GUIContent label) { - Rect buttonRect = position.AddPadding(EditorGUIUtility.labelWidth, 0f, 0f, 0f); + Rect buttonRect = IsArrayElement ? position : position.AddPadding(EditorGUIUtility.labelWidth, 0f, 0f, 0f); ; EcsGUI.DrawSelectReferenceButton(buttonRect, property, Attribute.PredicateTypes.Length == 0 ? new Type[1] { fieldInfo.FieldType } : Attribute.PredicateTypes, Attribute.IsHideButtonIfNotNull); } } diff --git a/src/EcsPipelineTemplate/ReferenceButtonAttribute.cs.meta b/src/Editor/ReferenceButtonAttribute.cs.meta similarity index 100% rename from src/EcsPipelineTemplate/ReferenceButtonAttribute.cs.meta rename to src/Editor/ReferenceButtonAttribute.cs.meta diff --git a/src/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs b/src/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs index 6603056..4657362 100644 --- a/src/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs +++ b/src/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs @@ -163,7 +163,7 @@ namespace DCFApixels.DragonECS.Unity.Editors optionButton.xMin = optionButton.xMax - 64; optionButton.center += Vector2.up * Padding * 1f; //Canceling isExpanded - if (EcsGUI.HitTest(optionButton) && Event.current.type == EventType.MouseUp) + if (EcsGUI.ClickTest(optionButton)) { componentProperty.isExpanded = !componentProperty.isExpanded; } diff --git a/src/EntityTemplate/Editor/EntityTemplateEditor.cs b/src/EntityTemplate/Editor/EntityTemplateEditor.cs index 16e9e87..773299c 100644 --- a/src/EntityTemplate/Editor/EntityTemplateEditor.cs +++ b/src/EntityTemplate/Editor/EntityTemplateEditor.cs @@ -24,37 +24,10 @@ namespace DCFApixels.DragonECS.Unity.Editors protected override void OnInit() { _componentDropDown = new ComponentDropDown(); - _componentDropDown.OnSelected += OnAddComponent; } #endregion #region Add/Remove - private void OnAddComponent(ComponentDropDown.Item item) - { - Type componentType = item.Obj.GetType(); - IComponentTemplate cmptmp = item.Obj; - if (this.target is ITemplateInternal target) - { - SerializedProperty componentsProp = serializedObject.FindProperty(target.ComponentsPropertyName); - if (cmptmp.IsUnique) - { - for (int i = 0, iMax = componentsProp.arraySize; i < iMax; i++) - { - if (componentsProp.GetArrayElementAtIndex(i).managedReferenceValue.GetType() == componentType) - { - return; - } - } - } - - int index = componentsProp.arraySize; - componentsProp.InsertArrayElementAtIndex(index); - componentsProp.GetArrayElementAtIndex(index).managedReferenceValue = cmptmp.Clone(); - - serializedObject.ApplyModifiedProperties(); - EditorUtility.SetDirty(this.target); - } - } private void OnRemoveComponentAt(int index) { if (this.target is ITemplateInternal target) @@ -76,24 +49,25 @@ namespace DCFApixels.DragonECS.Unity.Editors return; } - GUILayout.BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f)); - DrawTop(target); - GUILayout.Label("", GUILayout.Height(0), GUILayout.ExpandWidth(true)); - for (int i = componentsProp.arraySize - 1; i >= 0; i--) + using (EcsGUI.Layout.BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f))) { - DrawComponentData(componentsProp.GetArrayElementAtIndex(i), componentsProp.arraySize, i); + DrawTop(target, componentsProp); + GUILayout.Label("", GUILayout.Height(0), GUILayout.ExpandWidth(true)); + for (int i = componentsProp.arraySize - 1; i >= 0; i--) + { + DrawComponentData(componentsProp.GetArrayElementAtIndex(i), componentsProp.arraySize, i); + } } - GUILayout.EndVertical(); } - private void DrawTop(ITemplateInternal target) + private void DrawTop(ITemplateInternal target, SerializedProperty componentsProp) { switch (EcsGUI.Layout.AddClearComponentButtons(out Rect rect)) { - case EcsGUI.AddClearComponentButton.AddComponent: + case EcsGUI.AddClearButton.Add: Init(); - _componentDropDown.Show(rect); + _componentDropDown.OpenForArray(rect, componentsProp, true); break; - case EcsGUI.AddClearComponentButton.Clear: + case EcsGUI.AddClearButton.Clear: Init(); serializedObject.FindProperty(target.ComponentsPropertyName).ClearArray(); serializedObject.ApplyModifiedProperties(); @@ -159,15 +133,11 @@ namespace DCFApixels.DragonECS.Unity.Editors optionButton.yMax += HeadIconsRect.height; optionButton.xMin = optionButton.xMax - 64; optionButton.center += Vector2.up * padding * 2f; - bool cancelExpanded = EcsGUI.HitTest(optionButton) && Event.current.type == EventType.MouseUp; + bool cancelExpanded = EcsGUI.ClickTest(optionButton); - using (EcsGUI.CheckChanged()) + #region Draw Component Block + using (EcsGUI.CheckChanged()) using (EcsGUI.Layout.BeginVertical(UnityEditorUtility.GetStyle(alphaPanelColor))) { - //EditorGUI.BeginChangeCheck(); - - GUILayout.BeginVertical(UnityEditorUtility.GetStyle(alphaPanelColor)); - - #region Draw Component Block //Close button optionButton.xMin = optionButton.xMax - HeadIconsRect.width; if (EcsGUI.CloseButton(optionButton)) @@ -210,17 +180,14 @@ namespace DCFApixels.DragonECS.Unity.Editors EditorGUI.PropertyField(r, componentProperty, label, true); } } - #endregion - GUILayout.EndVertical(); - - //if (EditorGUI.EndChangeCheck()) if (EcsGUI.Changed) { componentProperty.serializedObject.ApplyModifiedProperties(); EditorUtility.SetDirty(componentProperty.serializedObject.targetObject); } } + #endregion } private void DrawDamagedComponent_Replaced(SerializedProperty componentRefProp, int index) { diff --git a/src/EntityTemplate/Editor/MetaObjectsDropDown.cs b/src/EntityTemplate/Editor/MetaObjectsDropDown.cs index d4f6c8c..e8a451e 100644 --- a/src/EntityTemplate/Editor/MetaObjectsDropDown.cs +++ b/src/EntityTemplate/Editor/MetaObjectsDropDown.cs @@ -1,4 +1,5 @@ #if UNITY_EDITOR +using DCFApixels.DragonECS.Unity.Internal; using System; using System.Collections.Generic; using System.Linq; @@ -8,6 +9,72 @@ using UnityEngine; namespace DCFApixels.DragonECS.Unity.Editors { + internal class SystemsDropDown : MetaObjectsDropDown + { + public SystemsDropDown() + { + Type[] predicateTypes = new Type[] { typeof(IEcsModule), typeof(IEcsProcess) }; + IEnumerable<(Type, ITypeMeta)> itemMetaPairs = UnityEditorUtility._serializableTypes.Where(o => + { + foreach (Type predicateTypes in predicateTypes) + { + if (predicateTypes.IsAssignableFrom(o)) + { + return true; + } + } + return false; + }).Select(o => (o, (ITypeMeta)o.ToMeta())); + Setup(itemMetaPairs); + } + + private SerializedProperty _arrayProperty; + private SerializedProperty _fieldProperty; + + public void OpenForArray(Rect position, SerializedProperty arrayProperty) + { + _arrayProperty = arrayProperty; + _fieldProperty = null; + Show(position); + } + public void OpenForField(Rect position, SerializedProperty fieldProperty) + { + _arrayProperty = null; + _fieldProperty = fieldProperty; + Show(position); + } + + protected override void ItemSelected(Item item) + { + base.ItemSelected(item); + + Type type = item.Obj; + + if (_arrayProperty != null) + { + int index = _arrayProperty.arraySize; + _arrayProperty.arraySize += 1; + _fieldProperty = _arrayProperty.GetArrayElementAtIndex(index); + _fieldProperty.Next(true);//Смещение чтобы перейти к полю Traget внутри рекорда + } + + if (_fieldProperty != null) + { + if (type == null) + { + _fieldProperty.managedReferenceValue = null; + } + else + { + _fieldProperty.managedReferenceValue = Activator.CreateInstance(type); + _fieldProperty.isExpanded = true; + } + + _fieldProperty.serializedObject.ApplyModifiedProperties(); + EcsGUI.DelayedChanged = true; + } + } + } internal class ComponentDropDown : MetaObjectsDropDown { public ComponentDropDown() @@ -27,6 +94,59 @@ namespace DCFApixels.DragonECS.Unity.Editors }); Setup(itemMetaPairs); } + + private bool _isCheckUnique; + private SerializedProperty _arrayProperty; + private SerializedProperty _fieldProperty; + + public void OpenForArray(Rect position, SerializedProperty arrayProperty, bool isCheckUnique) + { + _isCheckUnique = isCheckUnique; + _arrayProperty = arrayProperty; + _fieldProperty = null; + Show(position); + } + public void OpenForField(Rect position, SerializedProperty fieldProperty) + { + _isCheckUnique = false; + _arrayProperty = null; + _fieldProperty = fieldProperty; + Show(position); + } + + protected override void ItemSelected(Item item) + { + base.ItemSelected(item); + + Type componentType = item.Obj.GetType(); + IComponentTemplate cmptmp = item.Obj; + + if (_arrayProperty != null) + { + int index = _arrayProperty.arraySize; + if (_isCheckUnique) + { + if (cmptmp.IsUnique) + { + for (int i = 0, iMax = _arrayProperty.arraySize; i < iMax; i++) + { + if (_arrayProperty.GetArrayElementAtIndex(i).managedReferenceValue.GetType() == componentType) + { + return; + } + } + } + } + _arrayProperty.arraySize += 1; + _fieldProperty = _arrayProperty.GetArrayElementAtIndex(index); + } + + if (_fieldProperty != null) + { + _fieldProperty.managedReferenceValue = cmptmp.Clone(); + _fieldProperty.serializedObject.ApplyModifiedProperties(); + } + } } internal class RuntimeComponentDropDown : MetaObjectsDropDown { @@ -38,6 +158,31 @@ namespace DCFApixels.DragonECS.Unity.Editors }); Setup(itemMetaPairs); } + + private int _entityID; + + public void Open(Rect position, int entityID) + { + _entityID = entityID; + Show(position); + } + + protected override void ItemSelected(Item item) + { + IEcsPool pool = item.Obj; + if (pool.World.IsUsed(_entityID) == false) + { + return; + } + if (pool.Has(_entityID) == false) + { + pool.AddRaw(_entityID, Activator.CreateInstance(pool.ComponentType)); + } + else + { + Debug.LogWarning($"Entity({_entityID}) already has component {EcsDebugUtility.GetGenericTypeName(pool.ComponentType)}."); + } + } } internal class MetaObjectsDropDown : AdvancedDropdown { @@ -49,7 +194,7 @@ namespace DCFApixels.DragonECS.Unity.Editors minimumSize = new Vector2(minimumSize.x, EditorGUIUtility.singleLineHeight * 30); } - protected void Setup(IEnumerable<(T, ITypeMeta)> itemMetaPairs, string name = "Select Type", bool isContainsNull = true) + protected void Setup(IEnumerable<(T, ITypeMeta)> itemMetaPairs, string name = "Select Type...", bool isContainsNull = true) { _name = name; _isContainsNull = isContainsNull; @@ -103,8 +248,12 @@ namespace DCFApixels.DragonECS.Unity.Editors protected override void ItemSelected(AdvancedDropdownItem item) { base.ItemSelected(item); - OnSelected((Item)item); + var tType = (Item)item; + ItemSelected(tType); + OnSelected(tType); } + protected virtual void ItemSelected(Item item) { } + public event Action OnSelected = delegate { }; diff --git a/src/Internal/Editor/EcsGUI.cs b/src/Internal/Editor/EcsGUI.cs index 8c0d30e..74c4db0 100644 --- a/src/Internal/Editor/EcsGUI.cs +++ b/src/Internal/Editor/EcsGUI.cs @@ -2,7 +2,6 @@ using DCFApixels.DragonECS.Unity.Internal; using System; using System.Collections.Generic; -using System.Linq; using System.Reflection; using UnityEditor; using UnityEditor.IMGUI.Controls; @@ -265,28 +264,6 @@ namespace DCFApixels.DragonECS.Unity.Editors public static float EntityBarHeight => EditorGUIUtility.singleLineHeight + 3f; - private static Type[] _serializableTypes; - - - static EcsGUI() - { - InitSerializableTypes(); - } - private static void InitSerializableTypes() - { - List types = new List(); - foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) - { - var targetTypes = assembly.GetTypes().Where(type => - (type.IsGenericType || type.IsAbstract || type.IsInterface) == false && - type.IsSubclassOf(typeof(UnityObject)) == false && - type.GetCustomAttribute() != null); - - types.AddRange(targetTypes); - } - _serializableTypes = types.ToArray(); - } - #region Properties private static ComponentColorMode AutoColorMode { @@ -314,14 +291,14 @@ namespace DCFApixels.DragonECS.Unity.Editors #endregion #region enums - public enum AddClearComponentButton : byte + public enum AddClearButton : byte { None = 0, - AddComponent, - Clear, + Add = 1, + Clear = 2, } [Flags] - public enum EntityStatus + public enum EntityStatus : byte { NotAlive = 0, Alive = 1 << 0, @@ -329,7 +306,7 @@ namespace DCFApixels.DragonECS.Unity.Editors } #endregion - #region HitTest + #region HitTest/ClickTest internal static bool HitTest(Rect rect) { return HitTest(rect, Event.current.mousePosition); @@ -347,6 +324,15 @@ namespace DCFApixels.DragonECS.Unity.Editors { return point.x >= rect.xMin - (float)offset && point.x < rect.xMax + (float)offset && point.y >= rect.yMin - (float)offset && point.y < rect.yMax + (float)offset; } + internal static bool ClickTest(Rect rect) + { + Event evt = Event.current; + return ClickTest(rect, evt); + } + internal static bool ClickTest(Rect rect, Event evt) + { + return HitTest(rect, evt.mousePosition) && evt.type == EventType.MouseUp; + } #endregion #region small elems @@ -538,14 +524,42 @@ namespace DCFApixels.DragonECS.Unity.Editors { return DrawTypeMetaBlockPadding * 2 + contentHeight; } + public static bool DrawTypeMetaElementBlock(ref Rect position, SerializedProperty arrayProperty, int elementIndex, SerializedProperty elementProperty, ITypeMeta meta) + { + var result = DrawTypeMetaBlock_Internal(ref position, elementProperty, meta); + if (result.HasFlag(DrawTypeMetaBlockResult.CloseButtonClicked)) + { + arrayProperty.DeleteArrayElementAtIndex(elementIndex); + } + return result != DrawTypeMetaBlockResult.None; + } public static bool DrawTypeMetaBlock(ref Rect position, SerializedProperty property, ITypeMeta meta) { + var result = DrawTypeMetaBlock_Internal(ref position, property, meta); + if (result.HasFlag(DrawTypeMetaBlockResult.CloseButtonClicked)) + { + property.ResetValues(); + } + return result.HasFlag(DrawTypeMetaBlockResult.Drop); + } + + private enum DrawTypeMetaBlockResult + { + None = 0, + Drop = 1 << 0, + CloseButtonClicked = 1 << 1, + } + private static DrawTypeMetaBlockResult DrawTypeMetaBlock_Internal(ref Rect position, SerializedProperty property, ITypeMeta meta) + { + Color alphaPanelColor; if (meta == null) { - return false; + alphaPanelColor = Color.black; + alphaPanelColor.a = EscEditorConsts.COMPONENT_DRAWER_ALPHA; + EditorGUI.DrawRect(position, alphaPanelColor); + position = position.AddPadding(DrawTypeMetaBlockPadding * 2f); + return DrawTypeMetaBlockResult.None; } - GUIContent label = UnityEditorUtility.GetLabel(property.displayName); - var counter = property.Copy(); int positionCountr = int.MaxValue; @@ -555,45 +569,40 @@ namespace DCFApixels.DragonECS.Unity.Editors positionCountr--; } - //var counter = property.Copy(); - //int positionCountr = int.MaxValue; - //while (counter.NextVisible(false)) - //{ - // positionCountr--; - //} - string name = meta.Name; string description = meta.Description.Text; - Color panelColor = EcsGUI.SelectPanelColor(meta, positionCountr, -1).Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE); - - Color alphaPanelColor = panelColor; + alphaPanelColor = SelectPanelColor(meta, positionCountr, -1).Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE); alphaPanelColor.a = EscEditorConsts.COMPONENT_DRAWER_ALPHA; + DrawTypeMetaBlockResult result = DrawTypeMetaBlockResult.None; using (CheckChanged()) { EditorGUI.DrawRect(position, alphaPanelColor); - Rect paddingPosition = RectUtility.AddPadding(position, DrawTypeMetaBlockPadding * 2f); - Rect optionButton = position; + position = position.AddPadding(DrawTypeMetaBlockPadding * 2f); + optionButton.center -= new Vector2(0, optionButton.height); optionButton.yMin = optionButton.yMax; optionButton.yMax += HeadIconsRect.height; optionButton.xMin = optionButton.xMax - 64; optionButton.center += Vector2.up * DrawTypeMetaBlockPadding * 1f; + //Canceling isExpanded - if (HitTest(optionButton) && Event.current.type == EventType.MouseUp) + bool oldIsExpanded = property.isExpanded; + if (ClickTest(optionButton)) { - property.isExpanded = !property.isExpanded; + property.isExpanded = oldIsExpanded; + result |= DrawTypeMetaBlockResult.Drop; } //Close button optionButton.xMin = optionButton.xMax - HeadIconsRect.width; if (CloseButton(optionButton)) { - property.ResetValues(); - return true; + result |= DrawTypeMetaBlockResult.CloseButtonClicked; + return result; } //Edit script button if (UnityEditorUtility.TryGetScriptAsset(meta.Type, out MonoScript script)) @@ -607,21 +616,8 @@ namespace DCFApixels.DragonECS.Unity.Editors optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width)); DescriptionIcon(optionButton, description); } - - //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); - //} - - position = paddingPosition; } - return false; + return result; } #endregion @@ -699,22 +695,30 @@ namespace DCFApixels.DragonECS.Unity.Editors dropDownRect = RectUtility.AddPadding(position, 20f, 20f, 12f, 2f); return GUI.Button(dropDownRect, "Add Component"); } - public static AddClearComponentButton AddClearComponentButtons(Rect position, out Rect dropDownRect) + public static AddClearButton AddClearComponentButtons(Rect position, out Rect dropDownRect) + { + return AddClearButtons(position, "Add Component", "Clear", out dropDownRect); + } + public static AddClearButton AddClearSystemButtons(Rect position, out Rect dropDownRect) + { + return AddClearButtons(position, "Add Record", "Clear", out dropDownRect); + } + public static AddClearButton AddClearButtons(Rect position, string addText, string clearText, out Rect dropDownRect) { position = RectUtility.AddPadding(position, 20f, 20f, 12f, 2f); var (left, right) = RectUtility.HorizontalSliceLerp(position, 0.75f); dropDownRect = left; - if (GUI.Button(left, "Add Component")) + if (GUI.Button(left, addText)) { - return AddClearComponentButton.AddComponent; + return AddClearButton.Add; } - if (GUI.Button(right, "Clear")) + if (GUI.Button(right, clearText)) { - return AddClearComponentButton.Clear; + return AddClearButton.Clear; } - return AddClearComponentButton.None; + return AddClearButton.None; } public static void DrawEmptyComponentProperty(Rect position, SerializedProperty property, string name, bool isDisplayEmpty) @@ -822,7 +826,7 @@ namespace DCFApixels.DragonECS.Unity.Editors Dictionary dict = new Dictionary(); - foreach (var type in _serializableTypes) + foreach (var type in UnityEditorUtility._serializableTypes) { bool isAssignable = false; foreach (Type predicateTypes in PredicateTypes) @@ -937,20 +941,24 @@ namespace DCFApixels.DragonECS.Unity.Editors public static void DrawSelectReferenceButton(Rect position, SerializedProperty property, Type[] sortedPredicateTypes, bool isHideButtonIfNotNull) { object obj = property.hasMultipleDifferentValues ? null : property.managedReferenceValue; + string text = obj == null ? "Select..." : obj.GetMeta().Name; if (!isHideButtonIfNotNull || obj == null) { - if (GUI.Button(position, obj == null ? "Select..." : obj.GetMeta().Name, EditorStyles.layerMaskField)) + if (GUI.Button(position, text, EditorStyles.layerMaskField)) { - _currentProperty = property; - GetReferenceDropDown(sortedPredicateTypes).Show(position); + DrawSelectReferenceMenu(position, property, sortedPredicateTypes); } } else { - GUI.Label(position, obj == null ? "Select..." : obj.GetMeta().Name); + GUI.Label(position, text); } } - + public static void DrawSelectReferenceMenu(Rect position, SerializedProperty property, Type[] sortedPredicateTypes) + { + _currentProperty = property; + GetReferenceDropDown(sortedPredicateTypes).Show(position); + } #endregion @@ -1045,10 +1053,14 @@ namespace DCFApixels.DragonECS.Unity.Editors { return EcsGUI.AddComponentButton(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 36f), out dropDownRect); } - public static AddClearComponentButton AddClearComponentButtons(out Rect dropDownRect) + public static AddClearButton AddClearComponentButtons(out Rect dropDownRect) { return EcsGUI.AddClearComponentButtons(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 36f), out dropDownRect); } + public static AddClearButton AddClearSystemButtons(out Rect dropDownRect) + { + return EcsGUI.AddClearSystemButtons(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 36f), out dropDownRect); + } public static void DrawRuntimeComponents(entlong entity, bool isWithFoldout = true) { if (entity.TryUnpackForUnityEditor(out int entityID, out _, out _, out EcsWorld world)) @@ -1071,9 +1083,7 @@ namespace DCFApixels.DragonECS.Unity.Editors { if (AddComponentButtons(out Rect dropDownRect)) { - RuntimeComponentDropDown genericMenu = RuntimeComponentsUtility.GetAddComponentGenericMenu(world); - RuntimeComponentsUtility.CurrentEntityID = entityID; - genericMenu.Show(dropDownRect); + RuntimeComponentsUtility.GetAddComponentGenericMenu(world).Open(dropDownRect, entityID); } GUILayout.Box("", UnityEditorUtility.GetStyle(GUI.color, 0.16f), GUILayout.ExpandWidth(true)); @@ -1109,7 +1119,7 @@ namespace DCFApixels.DragonECS.Unity.Editors optionButton.xMin = optionButton.xMax - 64; optionButton.center += Vector2.up * padding * 2f; //Canceling isExpanded - if (HitTest(optionButton) && Event.current.type == EventType.MouseUp) + if (ClickTest(optionButton)) { ref bool isExpanded = ref expandMatrix.Down(); isExpanded = !isExpanded; diff --git a/src/Internal/Editor/ExtendedEditor.cs b/src/Internal/Editor/ExtendedEditor.cs index 3be3c1d..a560bd2 100644 --- a/src/Internal/Editor/ExtendedEditor.cs +++ b/src/Internal/Editor/ExtendedEditor.cs @@ -86,7 +86,6 @@ namespace DCFApixels.DragonECS.Unity.Editors } internal abstract class ExtendedEditor : ExtendedEditor { - public T Target { get @@ -124,7 +123,7 @@ namespace DCFApixels.DragonECS.Unity.Editors } } - private IEnumerable Attributes + protected IEnumerable Attributes { get { diff --git a/src/Internal/Editor/UnityEditorUtility.cs b/src/Internal/Editor/UnityEditorUtility.cs index 037c846..7697571 100644 --- a/src/Internal/Editor/UnityEditorUtility.cs +++ b/src/Internal/Editor/UnityEditorUtility.cs @@ -2,10 +2,12 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Runtime.InteropServices; using System.Text; using UnityEditor; using UnityEngine; +using UnityObject = UnityEngine.Object; namespace DCFApixels.DragonECS.Unity.Editors { @@ -108,7 +110,30 @@ namespace DCFApixels.DragonECS.Unity.Editors static UnityEditorUtility() { colorBoxeStyles = new SparseArray(); + + #region InitSerializableTypes + List types = new List(); + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + var targetTypes = assembly.GetTypes().Where(type => + (type.IsGenericType || type.IsAbstract || type.IsInterface) == false && + type.IsSubclassOf(typeof(UnityObject)) == false && + type.GetCustomAttribute() != null); + + types.AddRange(targetTypes); + } + _serializableTypes = types.ToArray(); + //Array.Sort(_serializableTypes, (a, b) => string.Compare(a.AssemblyQualifiedName, b.AssemblyQualifiedName, StringComparison.Ordinal)); + + //_noHiddenSerializableTypes = _serializableTypes.Where(o => { + // var atr = o.GetCustomAttribute(); + // return atr != null && atr.Tags.Contains(MetaTags.HIDDEN); + //}).ToArray(); + #endregion } + internal static readonly Type[] _serializableTypes; + //private static Type[] _noHiddenSerializableTypes; + private static SparseArray colorBoxeStyles = new SparseArray(); private static GUIContent _singletonIconContent = null; private static GUIContent _singletonContent = null; @@ -116,6 +141,7 @@ namespace DCFApixels.DragonECS.Unity.Editors private static Dictionary scriptsAssets = new Dictionary(256); + internal static void ResetValues(this SerializedProperty property, bool isExpand = false) { ResetValues_Internal(property.Copy(), isExpand, property.depth); @@ -156,7 +182,7 @@ namespace DCFApixels.DragonECS.Unity.Editors property.colorValue = default; break; case SerializedPropertyType.ObjectReference: - property.objectReferenceValue = null; + property.objectReferenceValue = default; break; case SerializedPropertyType.LayerMask: property.intValue = default; @@ -200,7 +226,7 @@ namespace DCFApixels.DragonECS.Unity.Editors property.quaternionValue = Quaternion.identity; break; case SerializedPropertyType.ExposedReference: - property.objectReferenceValue = null; + property.objectReferenceValue = default; break; case SerializedPropertyType.FixedBufferSize: for (int i = 0, iMax = property.fixedBufferSize; i < iMax; i++) @@ -423,41 +449,9 @@ namespace DCFApixels.DragonECS.Unity.Editors { IEnumerable pools = world.AllPools.ToArray().Where(o => o.IsNullOrDummy() == false); RuntimeComponentDropDown genericMenu = new RuntimeComponentDropDown(pools); - - //var pools = world.AllPools; - //for (int i = 0; i < pools.Length; i++) - //{ - // var pool = pools[i]; - // if (pool.IsNullOrDummy()) - // { - // continue; - // } - // var meta = pool.ComponentType.ToMeta(); - // string name = meta.Group.Name + meta.Name; - // genericMenu.AddItem(new GUIContent(name, meta.Description.Text), false, OnAddComponent, pool); - //} return new WorldData(genericMenu, world.PoolsCount); } - public static int CurrentEntityID = 0; - - private static void OnAddComponent(object userData) - { - IEcsPool pool = (IEcsPool)userData; - if (pool.World.IsUsed(CurrentEntityID) == false) - { - return; - } - if (pool.Has(CurrentEntityID) == false) - { - pool.AddRaw(CurrentEntityID, Activator.CreateInstance(pool.ComponentType)); - } - else - { - Debug.LogWarning($"Entity({CurrentEntityID}) already has component {EcsDebugUtility.GetGenericTypeName(pool.ComponentType)}."); - } - } - private class Listener : IEcsWorldEventListener { private EcsWorld _world;