diff --git a/src/DebugUtils/UnityDebugService.cs b/src/DebugUtils/UnityDebugService.cs
index acca69e..fad1d26 100644
--- a/src/DebugUtils/UnityDebugService.cs
+++ b/src/DebugUtils/UnityDebugService.cs
@@ -11,6 +11,7 @@ namespace DCFApixels.DragonECS
public class UnityDebugService : DebugService
{
private ProfilerMarker[] _profilerMarkers = new ProfilerMarker[64];
+
static UnityDebugService()
{
Activate();
@@ -28,22 +29,30 @@ namespace DCFApixels.DragonECS
return;
}
+ string msg = AutoConvertObjectToString(v);
bool hasTag = string.IsNullOrEmpty(tag) == false;
if (hasTag)
{
- log = $"[{tag}] {v}";
string taglower = tag.ToLower();
- if (taglower.Contains("warning"))
+ switch (taglower)
{
- Debug.LogWarning(log);
- return;
+ case "pass":
+ log = $"[{tag}] {msg}";
+ Debug.Log(log);
+ break;
+ case "warning":
+ log = $"[{tag}] {msg}";
+ Debug.LogWarning(log);
+ break;
+ case "error":
+ log = $"[{tag}] {msg}";
+ Debug.LogError(log);
+ break;
+ default:
+ log = $"[{tag}] {msg}";
+ Debug.Log(log);
+ break;
}
- if (taglower.Contains("error"))
- {
- Debug.LogError(log);
- return;
- }
- Debug.Log(log);
return;
}
Debug.Log(v);
diff --git a/src/EcsPipelineTemplate/EcsPipelineTemplateSO.cs b/src/EcsPipelineTemplate/EcsPipelineTemplateSO.cs
index b713dbc..e9e5091 100644
--- a/src/EcsPipelineTemplate/EcsPipelineTemplateSO.cs
+++ b/src/EcsPipelineTemplate/EcsPipelineTemplateSO.cs
@@ -19,15 +19,26 @@ namespace DCFApixels.DragonECS
};
[SerializeField]
+ [ArrayElement]
private string[] _layers = _defaultLayers.ToArray();
[SerializeField]
- private Record[] _systems;
+ [ArrayElement]
+ private Record[] _records;
+
+ public ReadOnlySpan Layers
+ {
+ get { return _layers; }
+ }
+ public ReadOnlySpan Records
+ {
+ get { return _records; }
+ }
void IEcsModule.Import(EcsPipeline.Builder b)
{
b.Layers.MergeWith(_layers);
- foreach (var s in _systems)
+ foreach (var s in _records)
{
if (s.target == null) { continue; }
@@ -40,10 +51,10 @@ namespace DCFApixels.DragonECS
EcsPipelineTemplate result = new EcsPipelineTemplate();
result.layers = new string[_layers.Length];
Array.Copy(_layers, result.layers, _layers.Length);
- result.systems = new EcsPipelineTemplate.AddCommand[_systems.Length];
+ result.systems = new EcsPipelineTemplate.AddCommand[_records.Length];
for (int i = 0; i < result.systems.Length; i++)
{
- ref var s = ref _systems[i];
+ ref var s = ref _records[i];
result.systems[i] = new EcsPipelineTemplate.AddCommand(s.target, s.parameters);
}
return result;
@@ -53,21 +64,23 @@ namespace DCFApixels.DragonECS
{
_layers = new string[template.layers.Length];
Array.Copy(template.layers, _layers, template.layers.Length);
- _systems = new Record[template.systems.Length];
- for (int i = 0; i < _systems.Length; i++)
+ _records = new Record[template.systems.Length];
+ for (int i = 0; i < _records.Length; i++)
{
ref var s = ref template.systems[i];
- _systems[i] = new Record(s.target, s.parameters);
+ _records[i] = new Record(s.target, s.parameters);
}
}
- public void Validate()
+ public bool Validate()
{
- ValidateLayers();
- ValidateSystems();
+ bool resutl = ValidateLayers();
+ resutl |= ValidateSystems();
+ return resutl;
}
- private void ValidateLayers()
+ private bool ValidateLayers()
{
+ bool result = false;
Dictionary builtinLayerIndexes = new Dictionary();
foreach (var item in _defaultLayers)
{
@@ -102,16 +115,21 @@ namespace DCFApixels.DragonECS
int i = 0;
foreach (var pair in builtinLayerIndexes.OrderBy(o => o.Value))
{
- newLayers[pair.Value] = _defaultLayers[i];
+ if (newLayers[pair.Value] != _defaultLayers[i])
+ {
+ newLayers[pair.Value] = _defaultLayers[i];
+ result = true;
+ }
i++;
}
}
_layers = newLayers.ToArray();
+ return result;
}
- private void ValidateSystems()
+ private bool ValidateSystems()
{
-
+ return false;
}
[Serializable]
@@ -128,4 +146,4 @@ namespace DCFApixels.DragonECS
}
}
}
-}
+}
\ No newline at end of file
diff --git a/src/EcsPipelineTemplate/EcsPipelineTemplateSOEditor.cs b/src/EcsPipelineTemplate/EcsPipelineTemplateSOEditor.cs
index 663a042..0fcc518 100644
--- a/src/EcsPipelineTemplate/EcsPipelineTemplateSOEditor.cs
+++ b/src/EcsPipelineTemplate/EcsPipelineTemplateSOEditor.cs
@@ -1,31 +1,220 @@
#if UNITY_EDITOR
+using DCFApixels.DragonECS.Unity.Internal;
+using System;
using UnityEditor;
+using UnityEditorInternal;
using UnityEngine;
namespace DCFApixels.DragonECS.Unity.Editors
{
- [CustomEditor(typeof(EcsPipelineTemplateSO))]
- internal class EcsPipelineTemplateSOEditor : Editor
+ [CustomPropertyDrawer(typeof(EcsPipelineTemplateSO.Record))]
+ internal class EcsPipelineTemplateSORecordDrawer : ExtendedPropertyDrawer
{
- public override void OnInspectorGUI()
+ protected override void DrawCustom(Rect position, SerializedProperty property, GUIContent label)
{
- EditorGUI.BeginChangeCheck();
- base.OnInspectorGUI();
- if (EditorGUI.EndChangeCheck())
+ if (IsArrayElement == false)
{
- Validate();
+ Rect foldoutRect;
+ (foldoutRect, position) = position.VerticalSliceTop(OneLineHeight + Spacing);
+ property.isExpanded = EditorGUI.Foldout(foldoutRect, property.isExpanded, label);
+ if (property.isExpanded == false)
+ {
+ return;
+ }
}
- if (GUILayout.Button("Validate"))
+
+ using (EcsGUI.SetIndentLevel(IsArrayElement ? EditorGUI.indentLevel : EditorGUI.indentLevel + 1))
{
- Validate();
+ Rect subPosition = position;
+ int depth = -1;
+ property.Next(true);
+ float height = 0f;
+ do
+ {
+ subPosition.y += height;
+ height = EditorGUI.GetPropertyHeight(property);
+ subPosition.height = height;
+
+ EditorGUI.PropertyField(subPosition, property, true);
+
+ } while (property.NextDepth(false, ref depth));
+ }
+ }
+
+ public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
+ {
+ float result = 0f;
+ if (IsArrayElement == false)
+ {
+ result += OneLineHeight;
+ if (property.isExpanded == false)
+ {
+ return result;
+ }
+ }
+
+
+ property.Next(true);
+ int depth = -1;
+ do
+ {
+ result += EditorGUI.GetPropertyHeight(property, true);
+ } while (property.NextDepth(false, ref depth));
+ return result;
+ }
+ }
+ [CustomEditor(typeof(EcsPipelineTemplateSO))]
+ internal class EcsPipelineTemplateSOEditor : ExtendedEditor
+ {
+ private SerializedProperty _layersProp;
+ private SerializedProperty _recordsProp;
+ private ReorderableList _reorderableLayersList;
+ private ReorderableList _reorderableRecordsList;
+
+
+ protected override bool IsInit
+ {
+ get => _reorderableLayersList != null && _reorderableRecordsList != null;
+ }
+
+ protected override void OnStaticInit() { }
+ protected override void OnInit()
+ {
+ _layersProp = FindProperty("_layers");
+ _recordsProp = FindProperty("_records");
+
+ CreateLists();
+ }
+
+ private void CreateLists()
+ {
+ _reorderableLayersList = new ReorderableList(serializedObject, _layersProp, true, false, true, true);
+ _reorderableLayersList.onAddCallback += OnReorderableLayersListAdd;
+ _reorderableLayersList.onRemoveCallback += OnReorderableListRemove;
+ _reorderableLayersList.drawElementCallback += OnReorderableLayersListDrawElement;
+ _reorderableLayersList.onReorderCallback += OnReorderableListReorder;
+
+ _reorderableRecordsList = new ReorderableList(serializedObject, _recordsProp, true, false, true, true);
+ _reorderableRecordsList.onAddCallback += OnReorderableRecordsListAdd;
+ _reorderableRecordsList.onRemoveCallback += OnReorderableListRemove;
+ _reorderableRecordsList.drawElementCallback += OnReorderableRecordsListDrawElement;
+ _reorderableRecordsList.elementHeightCallback += OnReorderableRecordsListElementHeight;
+ _reorderableRecordsList.onReorderCallback += OnReorderableListReorder;
+ }
+
+ private void OnReorderableListReorder(ReorderableList list)
+ {
+ EcsGUI.Changed = true;
+ }
+
+ #region _reorderableList
+ private void OnReorderableListRemove(ReorderableList list)
+ {
+ if (list.selectedIndices.Count <= 0)
+ {
+ if (list.serializedProperty.arraySize > 0)
+ {
+ list.serializedProperty.DeleteArrayElementAtIndex(list.serializedProperty.arraySize - 1);
+ }
+ return;
+ }
+ for (int i = list.selectedIndices.Count - 1; i >= 0; i--)
+ {
+ list.serializedProperty.DeleteArrayElementAtIndex(list.selectedIndices[i]);
+ }
+ EcsGUI.Changed = true;
+ }
+ #endregion
+
+ #region _reorderableLayersList
+ private void OnReorderableLayersListDrawElement(Rect rect, int index, bool isActive, bool isFocused)
+ {
+ using (EcsGUI.CheckChanged())
+ {
+ var elementProp = _layersProp.GetArrayElementAtIndex(index);
+ elementProp.stringValue = EditorGUI.TextField(rect, elementProp.stringValue);
+ }
+ }
+ private void OnReorderableLayersListAdd(ReorderableList list)
+ {
+ list.serializedProperty.InsertArrayElementAtIndex(list.serializedProperty.arraySize);
+ var added = list.serializedProperty.GetArrayElementAtIndex(list.serializedProperty.arraySize - 1);
+ added.stringValue = $"Layer-{DateTime.Now.Ticks}";
+ added.serializedObject.ApplyModifiedProperties();
+ EcsGUI.Changed = true;
+ }
+ #endregion
+
+ #region _reorderableRecordsList
+ private void OnReorderableRecordsListDrawElement(Rect rect, int index, bool isActive, bool isFocused)
+ {
+ using (EcsGUI.CheckChanged())
+ {
+ var prop = _recordsProp.GetArrayElementAtIndex(index);
+ var mrProp = prop.FindPropertyRelative(nameof(EcsPipelineTemplateSO.Record.target));
+ ITypeMeta meta = mrProp.managedReferenceValue == null ? null : mrProp.managedReferenceValue.GetMeta();
+ EcsGUI.DrawTypeMetaBlock(ref rect, prop, meta);
+ EditorGUI.PropertyField(rect, prop, true);
+ }
+ }
+ private float OnReorderableRecordsListElementHeight(int index)
+ {
+ return EcsGUI.GetTypeMetaBlockHeight(EditorGUI.GetPropertyHeight(_recordsProp.GetArrayElementAtIndex(index)));
+ }
+
+ private void OnReorderableRecordsListAdd(ReorderableList list)
+ {
+ list.serializedProperty.arraySize += 1;
+ list.serializedProperty.GetArrayElementAtIndex(list.serializedProperty.arraySize - 1).ResetValues();
+ EcsGUI.Changed = true;
+ }
+
+ #endregion
+
+ protected override void DrawCustom()
+ {
+ using (EcsGUI.CheckChanged())
+ {
+ EditorGUI.BeginChangeCheck();
+
+ DrawLayoutNameList(_layersProp);
+ DrawRecordList(_recordsProp);
+
+ EcsGUI.Changed = GUILayout.Button("Validate");
+ if (EcsGUI.Changed)
+ {
+ serializedObject.ApplyModifiedProperties();
+ Validate();
+ Repaint();
+ }
}
}
private void Validate()
{
- foreach (var target in targets)
+ foreach (var target in Targets)
{
- ((EcsPipelineTemplateSO)target).Validate();
+ target.Validate();
+ EditorUtility.SetDirty(target);
+ }
+ serializedObject.Update();
+ }
+
+ private void DrawLayoutNameList(SerializedProperty layersProp)
+ {
+ using (EcsGUI.SetVerticalLayout())
+ {
+ GUILayout.Label(UnityEditorUtility.GetLabel(layersProp.displayName), EditorStyles.boldLabel);
+ _reorderableLayersList.DoLayoutList();
+ }
+ }
+ private void DrawRecordList(SerializedProperty recordsProp)
+ {
+ using (EcsGUI.SetVerticalLayout())
+ {
+ GUILayout.Label(UnityEditorUtility.GetLabel(recordsProp.displayName), EditorStyles.boldLabel);
+ _reorderableRecordsList.DoLayoutList();
+ //EditorGUILayout.PropertyField(recordsProp, UnityEditorUtility.GetLabel(recordsProp.displayName));
}
}
}
diff --git a/src/EcsPipelineTemplate/ReferenceButtonAttribute.cs b/src/EcsPipelineTemplate/ReferenceButtonAttribute.cs
index a8822cc..ef35bf7 100644
--- a/src/EcsPipelineTemplate/ReferenceButtonAttribute.cs
+++ b/src/EcsPipelineTemplate/ReferenceButtonAttribute.cs
@@ -247,6 +247,8 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
currentProperty.serializedObject.ApplyModifiedProperties();
+
+ EcsGUI.Changed = true;
}
#endregion
diff --git a/src/Editor/AddParamsDrawer.cs b/src/Editor/AddParamsDrawer.cs
index 3239760..38eb2d6 100644
--- a/src/Editor/AddParamsDrawer.cs
+++ b/src/Editor/AddParamsDrawer.cs
@@ -1,89 +1,143 @@
#if UNITY_EDITOR
using DCFApixels.DragonECS.Unity.Internal;
+using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace DCFApixels.DragonECS.Unity.Editors
{
[CustomPropertyDrawer(typeof(AddParams))]
- internal class AddParamsDrawer : PropertyDrawer
+ internal class AddParamsDrawer : ExtendedPropertyDrawer
{
- private float SingleLineHeight => EditorGUIUtility.singleLineHeight;
- private float Spacing => EditorGUIUtility.standardVerticalSpacing;
+ private static Dictionary _labelCache = new Dictionary()
+ {
+ { 0, "" },
+ { 1, "Layer" },
+ { 2, "Order" },
+ { 3, "Layer, Order" },
+ { 4, "IsUnique" },
+ { 5, "Layer, IsUnique" },
+ { 6, "Order, IsUnique" },
+ { 7, "Layer, Order, IsUnique" },
+ { (byte)AddParamsFlags.NoImport | 0, "NoImport" },
+ { (byte)AddParamsFlags.NoImport | 1, "NoImport, Layer" },
+ { (byte)AddParamsFlags.NoImport | 2, "NoImport, Order" },
+ { (byte)AddParamsFlags.NoImport | 3, "NoImport, Layer, Order" },
+ { (byte)AddParamsFlags.NoImport | 4, "NoImport, IsUnique" },
+ { (byte)AddParamsFlags.NoImport | 5, "NoImport, Layer, IsUnique" },
+ { (byte)AddParamsFlags.NoImport | 6, "NoImport, Order, IsUnique" },
+ { (byte)AddParamsFlags.NoImport | 7, "NoImport, Layer, Order, IsUnique" },
+ { byte.MaxValue, "NoImport, Layer, Order, IsUnique" },
+ };
+
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
- return !property.isExpanded ? EditorGUIUtility.singleLineHeight + Spacing : EditorGUIUtility.singleLineHeight * 4f + Spacing * 3f;
+ //return !property.isExpanded ?
+ // EditorGUIUtility.singleLineHeight + Spacing :
+ // EditorGUIUtility.singleLineHeight * 5f + Spacing * 4f;
+ return EditorGUI.GetPropertyHeight(property);
}
- public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
+ protected override void DrawCustom(Rect position, SerializedProperty property, GUIContent label)
{
+ Event e = Event.current;
+
var flagsProp = property.FindPropertyRelative("flags");
AddParamsFlags flags = (AddParamsFlags)flagsProp.enumValueFlag;
- var (foldoutRect, contentRect) = position.VerticalSliceTop(SingleLineHeight + Spacing);
+ var (foldoutRect, contentRect) = position.VerticalSliceTop(OneLineHeight + Spacing);
+ var (fieldsRects, checkboxRects) = contentRect.HorizontalSliceRight(OneLineHeight);
- var (fieldsRects, checkboxRects) = contentRect.HorizontalSliceRight(SingleLineHeight);
+ Rect labelField;
+ (foldoutRect, labelField) = foldoutRect.HorizontalSliceLeft(EditorGUIUtility.labelWidth);
- property.isExpanded = EditorGUI.Foldout(foldoutRect, property.isExpanded, label);
- //property.isExpanded = true;
- using (EcsGUI.UpIndentLevel())
+ using (EcsGUI.CheckChanged())
{
+ property.isExpanded = EditorGUI.Foldout(foldoutRect, property.isExpanded, label);
- EditorGUI.BeginChangeCheck();
-
- checkboxRects = checkboxRects.Move(EditorGUIUtility.standardVerticalSpacing, 0);
-
- Rect checkboxRect = checkboxRects;
- checkboxRect.height = SingleLineHeight;
- Rect fieldRect = fieldsRects;
- fieldRect.height = SingleLineHeight;
-
- //LayerName
- property.Next(true);
- using (EcsGUI.SetIndentLevel(0))
+ using (EcsGUI.SetAlignment(EditorStyles.miniLabel, TextAnchor.MiddleRight))
{
- flags = flags.SetOverwriteLayerName(EditorGUI.Toggle(checkboxRect, flags.IsOverwriteLayerName()));
+ if (_labelCache.TryGetValue((byte)(flags.Normalize()), out string str) == false)
+ {
+ str = _labelCache[0];
+ }
+ GUI.Label(labelField, str, EditorStyles.miniLabel);
}
- using (EcsGUI.SetEnable(flags.IsOverwriteLayerName()))
+
+ if (property.isExpanded == false)
{
+ goto exti;
+ }
+
+ //property.isExpanded = true;
+ using (EcsGUI.UpIndentLevel())
+ {
+ checkboxRects = checkboxRects.Move(EditorGUIUtility.standardVerticalSpacing, 0);
+
+ Rect checkboxRect = checkboxRects;
+ checkboxRect.height = OneLineHeight;
+ Rect fieldRect = fieldsRects;
+ fieldRect.height = OneLineHeight;
+
+ //LayerName
+ property.Next(true);
+ using (EcsGUI.SetIndentLevel(0))
+ {
+ flags = flags.SetOverwriteLayerName(EditorGUI.Toggle(checkboxRect, flags.IsOverwriteLayerName()));
+ }
+ using (EcsGUI.SetEnable(flags.IsOverwriteLayerName()))
+ {
+ EditorGUI.PropertyField(fieldRect, property, UnityEditorUtility.GetLabel(property.displayName), true);
+ }
+
+ checkboxRect = checkboxRect.Move(0, OneLineHeight + Spacing);
+ fieldRect = fieldRect.Move(0, OneLineHeight + Spacing);
+
+ //SortOrder
+ property.Next(false);
+ using (EcsGUI.SetIndentLevel(0))
+ {
+ flags = flags.SetOverwriteSortOrder(EditorGUI.Toggle(checkboxRect, flags.IsOverwriteSortOrder()));
+ }
+ using (EcsGUI.SetEnable(flags.IsOverwriteSortOrder()))
+ {
+ EditorGUI.PropertyField(fieldRect, property, UnityEditorUtility.GetLabel(property.displayName), true);
+ }
+
+ checkboxRect = checkboxRect.Move(0, OneLineHeight + Spacing);
+ fieldRect = fieldRect.Move(0, OneLineHeight + Spacing);
+
+ //IsUnique
+ property.Next(false);
+ using (EcsGUI.SetIndentLevel(0))
+ {
+ flags = flags.SetOverwriteIsUnique(EditorGUI.Toggle(checkboxRect, flags.IsOverwriteIsUnique()));
+ }
+ using (EcsGUI.SetEnable(flags.IsOverwriteIsUnique()))
+ {
+ EditorGUI.PropertyField(fieldRect, property, UnityEditorUtility.GetLabel(property.displayName), true);
+ }
+
+ if (EcsGUI.Changed)
+ {
+ flagsProp.enumValueFlag = (int)flags;
+ }
+
+ checkboxRect = checkboxRect.Move(0, OneLineHeight + Spacing);
+ fieldRect = fieldRect.Move(0, OneLineHeight + Spacing);
+ fieldRect.xMax += OneLineHeight + Spacing;
+ property.Next(false);
EditorGUI.PropertyField(fieldRect, property, UnityEditorUtility.GetLabel(property.displayName), true);
}
- checkboxRect = checkboxRect.Move(0, SingleLineHeight + Spacing);
- fieldRect = fieldRect.Move(0, SingleLineHeight + Spacing);
+ exti:;
- //SortOrder
- property.Next(false);
- using (EcsGUI.SetIndentLevel(0))
+ //EcsGUI.Changed = Event.current.type == EventType.MouseUp;
+ if (EcsGUI.Changed)
{
- flags = flags.SetOverwriteSortOrder(EditorGUI.Toggle(checkboxRect, flags.IsOverwriteSortOrder()));
- }
- using (EcsGUI.SetEnable(flags.IsOverwriteSortOrder()))
- {
- EditorGUI.PropertyField(fieldRect, property, UnityEditorUtility.GetLabel(property.displayName), true);
- }
-
- checkboxRect = checkboxRect.Move(0, SingleLineHeight + Spacing);
- fieldRect = fieldRect.Move(0, SingleLineHeight + Spacing);
-
- //IsUnique
- property.Next(false);
- using (EcsGUI.SetIndentLevel(0))
- {
- flags = flags.SetOverwriteIsUnique(EditorGUI.Toggle(checkboxRect, flags.IsOverwriteIsUnique()));
- }
- using (EcsGUI.SetEnable(flags.IsOverwriteIsUnique()))
- {
- EditorGUI.PropertyField(fieldRect, property, UnityEditorUtility.GetLabel(property.displayName), true);
- }
-
- if (EditorGUI.EndChangeCheck())
- {
- flagsProp.enumValueFlag = (int)flags;
property.serializedObject.ApplyModifiedProperties();
}
-
}
}
}
diff --git a/src/EntityTemplate/Templates/ComponentTemplateBase.cs b/src/EntityTemplate/Templates/ComponentTemplateBase.cs
index 4b03d40..76f92c9 100644
--- a/src/EntityTemplate/Templates/ComponentTemplateBase.cs
+++ b/src/EntityTemplate/Templates/ComponentTemplateBase.cs
@@ -35,6 +35,7 @@ namespace DCFApixels.DragonECS
{
#region Properties
public abstract Type Type { get; }
+ public virtual ITypeMeta BaseMeta { get { return null; } }
public virtual string Name { get { return string.Empty; } }
public virtual MetaColor Color { get { return new MetaColor(MetaColor.Black); } }
public virtual MetaGroup Group { get { return MetaGroup.Empty; } }
@@ -63,6 +64,7 @@ namespace DCFApixels.DragonECS
private byte _offset; // Fucking Unity drove me crazy with the error "Cannot get managed reference index with out bounds offset". This workaround helps avoid that error.
#region Properties
+ public sealed override ITypeMeta BaseMeta { get { return Meta; } }
public sealed override Type Type { get { return typeof(T); } }
public override string Name { get { return Meta.Name; } }
public override MetaColor Color { get { return Meta.Color; } }
diff --git a/src/Internal/Editor/EcsGUI.cs b/src/Internal/Editor/EcsGUI.cs
index 8320956..a86b560 100644
--- a/src/Internal/Editor/EcsGUI.cs
+++ b/src/Internal/Editor/EcsGUI.cs
@@ -12,10 +12,65 @@ namespace DCFApixels.DragonECS.Unity.Editors
internal static class EcsGUI
{
#region Scores
- public struct LabelWidthScore : IDisposable
+ private static int _changedCounter = 0;
+ private static bool _changed = false;
+
+ public static int ChangedCounter => _changedCounter;
+ public static bool Changed
+ {
+ get
+ {
+ _changed = _changed || GUI.changed;
+ return _changed;
+ }
+ set
+ {
+ _changed = _changed || GUI.changed || value;
+ GUI.changed = _changed;
+ }
+ }
+ public readonly struct CheckChangedScope : IDisposable
+ {
+ private readonly bool _value;
+ public CheckChangedScope(bool value)
+ {
+ _value = value;
+ _changedCounter++;
+ _changed = false;
+ }
+ public static CheckChangedScope New() { return new CheckChangedScope(Changed); }
+ public void Dispose()
+ {
+ Changed = Changed || _value;
+ _changedCounter--;
+ //if(_changedCounter <= 0 && Event.current.type == EventType.Repaint)
+ if (_changedCounter <= 0)
+ {
+ _changedCounter = 0;
+ _changed = false;
+ }
+ }
+ }
+
+ public struct VerticalLayoutScope : IDisposable
+ {
+ public static VerticalLayoutScope New() { GUILayout.BeginVertical(); return new VerticalLayoutScope(); }
+ public void Dispose() { GUILayout.EndVertical(); }
+ }
+ public struct HorizontalLayoutScope : IDisposable
+ {
+ public static HorizontalLayoutScope New() { GUILayout.BeginVertical(); return new HorizontalLayoutScope(); }
+ public void Dispose() { GUILayout.EndVertical(); }
+ }
+ public struct ScrollViewLayoutScope : IDisposable
+ {
+ public ScrollViewLayoutScope(ref Vector2 pos) { pos = GUILayout.BeginScrollView(pos); }
+ public void Dispose() { GUILayout.EndScrollView(); }
+ }
+ public readonly struct LabelWidthScope : IDisposable
{
private readonly float _value;
- public LabelWidthScore(float value)
+ public LabelWidthScope(float value)
{
_value = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = value;
@@ -116,13 +171,18 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
public void Dispose() { Target.fontStyle = _value; }
}
- #endregion
+ public static CheckChangedScope CheckChanged() => CheckChangedScope.New();
+ public static ScrollViewLayoutScope SetScrollViewLayout(ref Vector2 pos) => new ScrollViewLayoutScope(ref pos);
+ public static HorizontalLayoutScope SetHorizontalLayout() => HorizontalLayoutScope.New();
+ public static VerticalLayoutScope SetVerticalLayout() => VerticalLayoutScope.New();
public static FontStyleScope SetFontStyle(GUIStyle target, FontStyle value) => new FontStyleScope(target, value);
+ public static FontStyleScope SetFontStyle(FontStyle value) => new FontStyleScope(GUI.skin.label, value);
public static FontStyleScope SetFontStyle(GUIStyle target) => new FontStyleScope(target);
public static FontSizeScope SetFontSize(GUIStyle target, int value) => new FontSizeScope(target, value);
public static FontSizeScope SetFontSize(GUIStyle target) => new FontSizeScope(target);
public static AlignmentScope SetAlignment(GUIStyle target, TextAnchor value) => new AlignmentScope(target, value);
+ public static AlignmentScope SetAlignment(TextAnchor value) => new AlignmentScope(GUI.skin.label, value);
public static AlignmentScope SetAlignment(GUIStyle target) => new AlignmentScope(target);
public static IndentLevelScope SetIndentLevel(int level) => new IndentLevelScope(level);
public static IndentLevelScope UpIndentLevel() => new IndentLevelScope(EditorGUI.indentLevel + 1);
@@ -136,8 +196,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
public static EditorGUI.DisabledScope Enable => new EditorGUI.DisabledScope(false);
public static EditorGUI.DisabledScope Disable => new EditorGUI.DisabledScope(true);
public static EditorGUI.DisabledScope SetEnable(bool value) => new EditorGUI.DisabledScope(!value);
-
-
+ #endregion
private static readonly BindingFlags fieldFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
@@ -320,7 +379,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
public static void EntityBar(Rect position, bool isPlaceholder, EntityStatus status, int id = 0, short gen = 0, short world = 0)
{
- using (new LabelWidthScore(0f))
+ using (new LabelWidthScope(0f))
{
var (entityInfoRect, statusRect) = RectUtility.VerticalSliceBottom(position, 3f);
@@ -346,7 +405,7 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
private static void EntityBar_Internal(Rect position, bool isPlaceHolder, int id = 0, short gen = 0, short world = 0)
{
- using (new LabelWidthScore(0f))
+ using (new LabelWidthScope(0f))
{
Color w = Color.gray;
w.a = 0.6f;
@@ -385,13 +444,122 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
#endregion
- internal static int GetChildPropertiesCount(SerializedProperty property, Type type, out bool isEmpty)
+ #region DrawTypeMetaBlock
+ private static float DrawTypeMetaBlockPadding => EditorGUIUtility.standardVerticalSpacing;
+ private static float SingleLineWithPadding => EditorGUIUtility.singleLineHeight + DrawTypeMetaBlockPadding * 4f;
+ public static float GetTypeMetaBlockHeight(float contentHeight)
+ {
+ return DrawTypeMetaBlockPadding * 2 + contentHeight;
+ }
+ public static void DrawTypeMetaBlock(ref Rect position, SerializedProperty property, ITypeMeta meta)
+ {
+ if (meta == null)
+ {
+ return;
+ }
+ GUIContent label = UnityEditorUtility.GetLabel(property.displayName);
+
+
+ var counter = property.Copy();
+ int positionCountr = int.MaxValue;
+ int depth = -1;
+ while (counter.NextVisibleDepth(false, ref depth))
+ {
+ 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.a = EscEditorConsts.COMPONENT_DRAWER_ALPHA;
+
+
+ EditorGUI.BeginChangeCheck();
+ EditorGUI.DrawRect(position, alphaPanelColor);
+
+ Rect paddingPosition = RectUtility.AddPadding(position, DrawTypeMetaBlockPadding * 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 * DrawTypeMetaBlockPadding * 1f;
+ //Canceling isExpanded
+ if (HitTest(optionButton) && Event.current.type == EventType.MouseUp)
+ {
+ property.isExpanded = !property.isExpanded;
+ }
+
+ //Close button
+ optionButton.xMin = optionButton.xMax - HeadIconsRect.width;
+ if (CloseButton(optionButton))
+ {
+ property.ResetValues();
+ return;
+ }
+ //Edit script button
+ if (UnityEditorUtility.TryGetScriptAsset(meta.Type, out MonoScript script))
+ {
+ optionButton = HeadIconsRect.MoveTo(optionButton.center - (Vector2.right * optionButton.width));
+ ScriptAssetButton(optionButton, script);
+ }
+ //Description icon
+ if (string.IsNullOrEmpty(description) == false)
+ {
+ 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;
+ }
+ #endregion
+
+ #region NextDepth/GetChildPropertiesCount
+ internal static bool NextVisibleDepth(this SerializedProperty property, bool child, ref int depth)
+ {
+ if (depth < 0)
+ {
+ depth = property.depth;
+ }
+ return property.NextVisible(child) && property.depth >= depth;
+ }
+ internal static bool NextDepth(this SerializedProperty property, bool child, ref int depth)
+ {
+ if (depth < 0)
+ {
+ depth = property.depth;
+ }
+ return property.Next(child) && property.depth >= depth;
+ }
+ internal static int GetChildPropertiesCount(this SerializedProperty property, Type type, out bool isEmpty)
{
int result = GetChildPropertiesCount(property);
isEmpty = result <= 0 && type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Length <= 0;
return result;
}
- internal static int GetChildPropertiesCount(SerializedProperty property)
+ internal static int GetChildPropertiesCount(this SerializedProperty property)
{
var propsCounter = property.Copy();
int lastDepth = propsCounter.depth;
@@ -404,6 +572,9 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
return result;
}
+ #endregion
+
+ #region SelectPanelColor
public static Color SelectPanelColor(ITypeMeta meta, int index, int total)
{
var trueMeta = meta.Type.ToMeta();
@@ -431,6 +602,9 @@ namespace DCFApixels.DragonECS.Unity.Editors
}
}
}
+ #endregion
+
+ #region Other Elements
public static bool AddComponentButton(Rect position, out Rect dropDownRect)
{
dropDownRect = RectUtility.AddPadding(position, 20f, 20f, 12f, 2f);
@@ -471,7 +645,11 @@ namespace DCFApixels.DragonECS.Unity.Editors
EditorGUI.BeginProperty(position, label, property);
EditorGUI.EndProperty();
}
+ #endregion
+ #region SerializeReferenceFixer
+
+ #endregion
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/Internal/Editor/ExtendedEditor.cs b/src/Internal/Editor/ExtendedEditor.cs
new file mode 100644
index 0000000..1a5e434
--- /dev/null
+++ b/src/Internal/Editor/ExtendedEditor.cs
@@ -0,0 +1,176 @@
+namespace DCFApixels.DragonECS.Unity.Internal
+{
+ using System;
+
+ [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = true)]
+ internal sealed class ArrayElementAttribute : Attribute { }
+}
+
+#if UNITY_EDITOR
+namespace DCFApixels.DragonECS.Unity.Editors
+{
+ using DCFApixels.DragonECS.Unity.Internal;
+ using global::Unity.Collections.LowLevel.Unsafe;
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Reflection;
+ using UnityEditor;
+ using UnityEngine;
+ using UnityObject = UnityEngine.Object;
+
+
+ internal abstract class ExtendedEditor : Editor
+ {
+ private bool _isStaticInit = false;
+ private bool _isInit = false;
+
+ protected float SingleLineHeight
+ {
+ get => EditorGUIUtility.singleLineHeight;
+ }
+ protected float Spacing
+ {
+ get => EditorGUIUtility.standardVerticalSpacing;
+ }
+
+ protected virtual bool IsStaticInit { get { return _isStaticInit; } }
+ protected virtual bool IsInit { get { return _isInit; } }
+ protected void StaticInit()
+ {
+ if (IsStaticInit) { return; }
+ _isStaticInit = true;
+ OnStaticInit();
+ }
+ protected void Init()
+ {
+ if (IsInit) { return; }
+ _isInit = true;
+ OnInit();
+ }
+ protected virtual void OnStaticInit() { }
+ protected virtual void OnInit() { }
+
+ public sealed override void OnInspectorGUI()
+ {
+ using (EcsGUI.CheckChanged())
+ {
+ StaticInit();
+ Init();
+ DrawCustom();
+ }
+ }
+
+ protected abstract void DrawCustom();
+ protected void DrawDefault()
+ {
+ base.OnInspectorGUI();
+ }
+
+
+ protected SerializedProperty FindProperty(string name)
+ {
+ return serializedObject.FindProperty(name);
+ }
+ }
+ internal abstract class ExtendedEditor : ExtendedEditor where T : UnityObject
+ {
+
+ public T Target
+ {
+ get
+ {
+ var obj = target;
+ return UnsafeUtility.As(ref obj);
+ }
+ }
+ public T[] Targets
+ {
+ get
+ {
+ var obj = targets;
+ return UnsafeUtility.As(ref obj);
+ }
+ }
+ }
+ internal abstract class ExtendedPropertyDrawer : PropertyDrawer
+ {
+ private bool _isStaticInit = false;
+ private bool _isInit = false;
+
+ private IEnumerable _attributes = null;
+
+ private bool? _isArrayElement = null;
+ protected bool IsArrayElement
+ {
+ get
+ {
+ if (_isArrayElement == null)
+ {
+ _isArrayElement = Attributes.Any(o => o is ArrayElementAttribute);
+ }
+ return _isArrayElement.Value;
+ }
+ }
+
+ private IEnumerable Attributes
+ {
+ get
+ {
+ if (_attributes == null)
+ {
+ _attributes = fieldInfo.GetCustomAttributes();
+ }
+ return _attributes;
+ }
+ }
+ protected float OneLineHeight
+ {
+ get => EditorGUIUtility.singleLineHeight;
+ }
+ protected float Spacing
+ {
+ get => EditorGUIUtility.standardVerticalSpacing;
+ }
+
+ protected virtual bool IsStaticInit { get { return _isStaticInit; } }
+ protected virtual bool IsInit { get { return _isInit; } }
+ protected void StaticInit()
+ {
+ if (IsStaticInit) { return; }
+ _isStaticInit = true;
+ OnStaticInit();
+ }
+ protected void Init()
+ {
+ if (IsInit) { return; }
+ _isInit = true;
+ OnInit();
+ }
+ protected virtual void OnStaticInit() { }
+ protected virtual void OnInit() { }
+
+ public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
+ {
+ using (EcsGUI.CheckChanged())
+ {
+ StaticInit();
+ Init();
+ DrawCustom(position, property, label);
+ }
+ }
+ protected abstract void DrawCustom(Rect position, SerializedProperty property, GUIContent label);
+ }
+ internal abstract class ExtendedPropertyDrawer : ExtendedPropertyDrawer
+ {
+ protected TAttribute Attribute
+ {
+ get
+ {
+ var obj = attribute;
+ return UnsafeUtility.As(ref obj);
+ }
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/src/Internal/Editor/ExtendedEditor.cs.meta b/src/Internal/Editor/ExtendedEditor.cs.meta
new file mode 100644
index 0000000..bd24c24
--- /dev/null
+++ b/src/Internal/Editor/ExtendedEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e9a6ec3374a23a441bc22494aca34430
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/src/Internal/Editor/UnityEditorUtility.cs b/src/Internal/Editor/UnityEditorUtility.cs
index d4f916b..0a5c91f 100644
--- a/src/Internal/Editor/UnityEditorUtility.cs
+++ b/src/Internal/Editor/UnityEditorUtility.cs
@@ -116,6 +116,115 @@ namespace DCFApixels.DragonECS.Unity.Editors
private static Dictionary scriptsAssets = new Dictionary(256);
+ internal static void ResetValues(this SerializedProperty property, bool isExpand = false)
+ {
+ property.isExpanded = isExpand;
+ switch (property.propertyType)
+ {
+ case SerializedPropertyType.Generic:
+ try
+ //TODO хз как с этим работать, но это говно постоянно кидает
+ //InvalidOperationException: The operation is not possible when moved past all properties (Next returned false)
+ //и не дает инструментов и шансов этого избежать
+ {
+ while (property.Next(true))
+ {
+ property.ResetValues(isExpand);
+ }
+ }
+ catch (Exception) { }
+ break;
+ case SerializedPropertyType.Integer:
+ property.intValue = default;
+ break;
+ case SerializedPropertyType.Boolean:
+ property.boolValue = default;
+ break;
+ case SerializedPropertyType.Float:
+ property.floatValue = default;
+ break;
+ case SerializedPropertyType.String:
+ property.stringValue = string.Empty;
+ break;
+ case SerializedPropertyType.Color:
+ property.colorValue = default;
+ break;
+ case SerializedPropertyType.ObjectReference:
+ property.objectReferenceValue = null;
+ break;
+ case SerializedPropertyType.LayerMask:
+ property.intValue = default;
+ break;
+ case SerializedPropertyType.Enum:
+ property.enumValueIndex = default;
+ break;
+ case SerializedPropertyType.Vector2:
+ property.vector2Value = default;
+ break;
+ case SerializedPropertyType.Vector3:
+ property.vector3Value = default;
+ break;
+ case SerializedPropertyType.Vector4:
+ property.vector4Value = default;
+ break;
+ case SerializedPropertyType.Rect:
+ property.rectValue = default;
+ break;
+ case SerializedPropertyType.ArraySize:
+ property.ClearArray();
+ break;
+ case SerializedPropertyType.Character:
+ property.intValue = default;
+ break;
+ case SerializedPropertyType.AnimationCurve:
+ property.animationCurveValue = new AnimationCurve();
+ break;
+ case SerializedPropertyType.Bounds:
+ property.boundsValue = default;
+ break;
+ case SerializedPropertyType.Gradient:
+#if UNITY_2022_1_OR_NEWER
+ property.gradientValue = new Gradient();;
+
+#else
+ Debug.LogWarning($"Unsupported SerializedPropertyType: {property.propertyType}");
+#endif
+ break;
+ case SerializedPropertyType.Quaternion:
+ property.quaternionValue = Quaternion.identity;
+ break;
+ case SerializedPropertyType.ExposedReference:
+ property.objectReferenceValue = null;
+ break;
+ case SerializedPropertyType.FixedBufferSize:
+ for (int i = 0, iMax = property.fixedBufferSize; i < iMax; i++)
+ {
+ property.GetFixedBufferElementAtIndex(i).intValue = default;
+ }
+ break;
+ case SerializedPropertyType.Vector2Int:
+ property.vector2IntValue = default;
+ break;
+ case SerializedPropertyType.Vector3Int:
+ property.vector3IntValue = default;
+ break;
+ case SerializedPropertyType.RectInt:
+ property.rectIntValue = default;
+ break;
+ case SerializedPropertyType.BoundsInt:
+ property.boundsIntValue = default;
+ break;
+ case SerializedPropertyType.ManagedReference:
+ property.managedReferenceValue = default;
+ break;
+ case SerializedPropertyType.Hash128:
+ property.hash128Value = default;
+ break;
+ default:
+ Debug.LogWarning($"Unsupported SerializedPropertyType: {property.propertyType}");
+ break;
+ }
+ }
internal static bool TryGetScriptAsset(Type type, out MonoScript script)
{
if (scriptsAssets.TryGetValue(type, out script) == false)