diff --git a/src/Connectors/AutoEntityCreator.cs b/src/Connectors/AutoEntityCreator.cs index 8953844..e2b31a7 100644 --- a/src/Connectors/AutoEntityCreator.cs +++ b/src/Connectors/AutoEntityCreator.cs @@ -30,6 +30,7 @@ namespace DCFApixels.DragonECS } #endregion + #region Methods private void AutoResolveWorldProviderDependensy() { _world = EcsDefaultWorldSingletonProvider.Instance; @@ -54,13 +55,14 @@ namespace DCFApixels.DragonECS } _created = true; } - private void InitConnect(EcsEntityConnect connect, EcsWorld world) { connect.ConnectWith(world.NewEntityLong()); connect.ApplyTemplates(); } + #endregion + #region Editor #if UNITY_EDITOR internal void Autoset_Editor() { @@ -68,5 +70,6 @@ namespace DCFApixels.DragonECS AutoResolveWorldProviderDependensy(); } #endif + #endregion } } \ No newline at end of file diff --git a/src/Connectors/EcsEntityConnect.cs b/src/Connectors/EcsEntityConnect.cs index f12313f..7ab7271 100644 --- a/src/Connectors/EcsEntityConnect.cs +++ b/src/Connectors/EcsEntityConnect.cs @@ -60,7 +60,7 @@ namespace DCFApixels.DragonECS if (_entity.TryGetID(out int oldEntityID) && _world != null) { var a = _world.GetAspect(); - a.unityGameObjects.Del(oldEntityID); + a.unityGameObjects.TryDel(oldEntityID); } _world = null; diff --git a/src/Connectors/Editor/EcsEntityConnectEditor.cs b/src/Connectors/Editor/EcsEntityConnectEditor.cs index 491f731..cfe896b 100644 --- a/src/Connectors/Editor/EcsEntityConnectEditor.cs +++ b/src/Connectors/Editor/EcsEntityConnectEditor.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEngine; -using static PlasticGui.LaunchDiffParameters; namespace DCFApixels.DragonECS.Unity.Editors { @@ -43,56 +42,29 @@ namespace DCFApixels.DragonECS.Unity.Editors private void DrawEntityInfo(EcsEntityConnect[] targets) { - //TODO Отрефакторить + bool isConnected = Target.Entity.TryUnpack(out int id, out short gen, out EcsWorld world); + EcsGUI.EntityStatus status = IsMultipleTargets ? EcsGUI.EntityStatus.Undefined : isConnected ? EcsGUI.EntityStatus.Alive : EcsGUI.EntityStatus.NotAlive; + float width = EditorGUIUtility.currentViewWidth; float height = EditorGUIUtility.singleLineHeight; - Rect entityRect = GUILayoutUtility.GetRect(width, height + 3f); - var (entityInfoRect, statusRect) = RectUtility.VerticalSliceBottom(entityRect, 3f); + Rect rect = GUILayoutUtility.GetRect(width, height + 3f); + var (left, delEntityButtonRect) = RectUtility.HorizontalSliceRight(rect, height + 3); + var (entityRect, unlinkButtonRect) = RectUtility.HorizontalSliceRight(left, height + 3); - Color w = Color.gray; - w.a = 0.6f; - Color b = Color.black; - b.a = 0.55f; - EditorGUI.DrawRect(entityInfoRect, w); - - var (idRect, genWorldRect) = RectUtility.HorizontalSliceLerp(entityInfoRect, 0.5f); - var (genRect, worldRect) = RectUtility.HorizontalSliceLerp(genWorldRect, 0.5f); - - idRect = RectUtility.AddPadding(idRect, 2, 1, 0, 0); - genRect = RectUtility.AddPadding(genRect, 1, 1, 0, 0); - worldRect = RectUtility.AddPadding(worldRect, 1, 2, 0, 0); - EditorGUI.DrawRect(idRect, b); - EditorGUI.DrawRect(genRect, b); - EditorGUI.DrawRect(worldRect, b); - - bool isConnected = Target.Entity.TryUnpack(out int id, out short gen, out short world); - - GUIStyle style = new GUIStyle(EditorStyles.numberField); - style.alignment = TextAnchor.MiddleCenter; - style.font = EditorStyles.boldFont; - if (IsMultipleTargets == false && isConnected) + using (new EditorGUI.DisabledScope(status != EcsGUI.EntityStatus.Alive)) { - Color statusColor = EcsGUI.GreenColor; - statusColor.a = 0.6f; - EditorGUI.DrawRect(statusRect, statusColor); - - EditorGUI.IntField(idRect, id, style); - EditorGUI.IntField(genRect, gen, style); - EditorGUI.IntField(worldRect, world, style); - } - else - { - Color statusColor = IsMultipleTargets ? new Color32(200, 200, 200, 255) : EcsGUI.RedColor; - statusColor.a = 0.6f; - EditorGUI.DrawRect(statusRect, statusColor); - - using (new EditorGUI.DisabledScope(true)) + if (EcsGUI.UnlinkButton(unlinkButtonRect)) { - GUI.Label(idRect, "Entity ID", style); - GUI.Label(genRect, "Generation", style); - GUI.Label(worldRect, "World ID", style); + Target.ConnectWith(entlong.NULL); + } + if (EcsGUI.DelEntityButton(delEntityButtonRect)) + { + world.DelEntity(id); + Target.ConnectWith(entlong.NULL); } } + + EcsGUI.DrawEntity(entityRect, status, id, gen, world.id); } private void DrawTemplates() diff --git a/src/EntityTemplate/Editor/EntityTemplateEditor.cs b/src/EntityTemplate/Editor/EntityTemplateEditor.cs index 6787868..2bba492 100644 --- a/src/EntityTemplate/Editor/EntityTemplateEditor.cs +++ b/src/EntityTemplate/Editor/EntityTemplateEditor.cs @@ -9,8 +9,8 @@ namespace DCFApixels.DragonECS.Unity.Editors { public abstract class EntityTemplateEditorBase : Editor { - private static readonly Rect RemoveButtonRect = new Rect(0f, 0f, 17f, 19f); - private static readonly Rect TooltipIconRect = new Rect(0f, 0f, 21f, 15f); + private static readonly Rect RemoveButtonRect = new Rect(0f, 0f, 19f, 19f); + private static readonly Rect TooltipIconRect = new Rect(0f, 0f, 19f, 19f); private GUIStyle _removeButtonStyle; private GenericMenu _genericMenu; @@ -141,6 +141,7 @@ namespace DCFApixels.DragonECS.Unity.Editors return; } + Type componentType; SerializedProperty componentProperty = componentRefProp; ComponentTemplateBase customInitializer = componentProperty.managedReferenceValue as ComponentTemplateBase; @@ -177,7 +178,8 @@ namespace DCFApixels.DragonECS.Unity.Editors removeButtonRect.yMax += RemoveButtonRect.height; removeButtonRect.xMin = removeButtonRect.xMax - RemoveButtonRect.width; removeButtonRect.center += Vector2.up * padding * 2f; - if (GUI.Button(removeButtonRect, "x")) + + if (EcsGUI.CloseButton(removeButtonRect)) { isRemoveComponent = true; } @@ -199,12 +201,12 @@ namespace DCFApixels.DragonECS.Unity.Editors Rect tooltipIconRect = TooltipIconRect; tooltipIconRect.center = removeButtonRect.center; tooltipIconRect.center -= Vector2.right * tooltipIconRect.width; - GUIContent descriptionLabel = UnityEditorUtility.GetLabel(EcsUnityConsts.INFO_MARK, description); - GUI.Label(tooltipIconRect, descriptionLabel, EditorStyles.boldLabel); + EcsGUI.DescriptionIcon(tooltipIconRect, description); } #endregion GUILayout.EndVertical(); + if (EditorGUI.EndChangeCheck()) { componentProperty.serializedObject.ApplyModifiedProperties(); diff --git a/src/Internal/Editor/EcsGUI.cs b/src/Internal/Editor/EcsGUI.cs index aa4ebb9..fbdfcc4 100644 --- a/src/Internal/Editor/EcsGUI.cs +++ b/src/Internal/Editor/EcsGUI.cs @@ -4,18 +4,31 @@ using System; using System.Reflection; using UnityEditor; using UnityEngine; -using static UnityEngine.GraphicsBuffer; namespace DCFApixels.DragonECS.Unity.Editors { internal static class EcsGUI { + public struct ColorScope : IDisposable + { + private readonly Color _oldColor; + public ColorScope(Color color) + { + _oldColor = GUI.color; + GUI.color = color; + } + public void Dispose() + { + GUI.color = _oldColor; + } + } + internal readonly static Color GrayColor = new Color32(100, 100, 100, 255); internal readonly static Color GreenColor = new Color32(75, 255, 0, 255); internal readonly static Color RedColor = new Color32(255, 0, 75, 255); - private static readonly Rect RemoveButtonRect = new Rect(0f, 0f, 17f, 19f); - private static readonly Rect TooltipIconRect = new Rect(0f, 0f, 21f, 15f); + private static readonly Rect RemoveButtonRect = new Rect(0f, 0f, 19f, 19f); + private static readonly Rect TooltipIconRect = new Rect(0f, 0f, 19f, 19f); private static bool IsShowHidden { @@ -34,6 +47,13 @@ namespace DCFApixels.DragonECS.Unity.Editors AddComponent, Clear, } + [Flags] + public enum EntityStatus + { + NotAlive = 0, + Alive = 1 << 0, + Undefined = 1 << 1, + } //private static GUILayoutOption[] _defaultParams; //private static bool _isInit = false; @@ -47,6 +67,178 @@ namespace DCFApixels.DragonECS.Unity.Editors // _isInit = true; //} + + internal static bool HitTest(Rect rect, Event evt) + { + return HitTest(rect, evt.mousePosition); + } + internal static bool HitTest(Rect rect, Vector2 point) + { + int offset = 0; + return HitTest(rect, point, offset); + } + internal static bool HitTest(Rect rect, Vector2 point, int offset) + { + 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; + } + + //public static bool IconButton(Rect position, Texture normal, Texture hover, GUIStyle normalStyle = null, GUIStyle hoverStyle = null) + //{ + // Color dc = GUI.color; + // GUI.color = Color.clear; //Хак чтобы сделать реакцию от курсора мыши без лага + // bool result = GUI.Button(position, "", EditorStyles.miniButtonMid); + // GUI.color = dc; + // + // var current = Event.current; + // { + // if (HitTest(position, current)) + // { + // if (hoverStyle != null && Event.current.type == EventType.Repaint) + // { + // hoverStyle.Draw(position, true, false, false, false); + // } + // GUI.DrawTexture(position, hover); + // } + // else + // { + // if (normalStyle != null && Event.current.type == EventType.Repaint) + // { + // normalStyle.Draw(position, false, false, false, false); + // } + // GUI.DrawTexture(position, normal); + // } + // } + // + // return result; + //} + public static (bool, bool) IconButton(Rect position) + { + Color dc = GUI.color; + GUI.color = Color.clear; //Хак чтобы сделать реакцию от курсора мыши без лага + bool result = GUI.Button(position, "", EditorStyles.miniButtonMid); + GUI.color = dc; + + var current = Event.current; + return (GUI.enabled && HitTest(position, current), result); + } + public static bool SingleIconButton(Rect position, Texture icon) + { + var (hover, click) = IconButton(position); + Color color = GUI.color; + float enableMultiplier = GUI.enabled ? 1f : 0.72f; + + if (hover) + { + if (Event.current.type == EventType.Repaint) + { + GUI.color = Color.white * 2.2f * enableMultiplier; + EditorStyles.helpBox.Draw(position, hover, false, false, false); + } + + Rect rect = RectUtility.AddPadding(position, -1f); + GUI.color = Color.white * enableMultiplier; + GUI.DrawTexture(rect, icon); + } + else + { + if (Event.current.type == EventType.Repaint) + { + GUI.color = Color.white * 1.7f * enableMultiplier; + EditorStyles.helpBox.Draw(position, hover, false, false, false); + } + GUI.color = Color.white * enableMultiplier; + GUI.DrawTexture(position, icon); + } + GUI.color = color; + return click; + } + public static void DescriptionIcon(Rect position, string description) + { + using (new ColorScope(new Color(1f, 1f, 1f, 0.8f))) + { + GUIContent descriptionLabel = UnityEditorUtility.GetLabel(EditorGUIUtility.IconContent("d__Help@2x").image, description); + GUI.Label(position, descriptionLabel, EditorStyles.boldLabel); + } + } + public static bool CloseButton(Rect position) + { + using (new ColorScope(new Color(1f, 1f, 1f, 0.8f))) + { + var (hover, click) = IconButton(position); + if (hover) + { + Rect rect = RectUtility.AddPadding(position, -4f); + GUI.DrawTexture(rect, EditorGUIUtility.IconContent("P4_DeletedLocal@2x").image); + } + else + { + GUI.DrawTexture(position, EditorGUIUtility.IconContent("d_winbtn_win_close@2x").image); + } + return click; + } + } + public static bool UnlinkButton(Rect position) + { + return SingleIconButton(position, EditorGUIUtility.IconContent("d_Unlinked@2x").image); + } + public static bool DelEntityButton(Rect position) + { + return SingleIconButton(position, EditorGUIUtility.IconContent("d_winbtn_win_close@2x").image); + } + public static void DrawEntity(Rect position, EntityStatus status, int id, short gen, short world) + { + var (entityInfoRect, statusRect) = RectUtility.VerticalSliceBottom(position, 3f); + + Color w = Color.gray; + w.a = 0.6f; + Color b = Color.black; + b.a = 0.55f; + EditorGUI.DrawRect(entityInfoRect, w); + + var (idRect, genWorldRect) = RectUtility.HorizontalSliceLerp(entityInfoRect, 0.4f); + var (genRect, worldRect) = RectUtility.HorizontalSliceLerp(genWorldRect, 0.5f); + + idRect = RectUtility.AddPadding(idRect, 2, 1, 0, 0); + genRect = RectUtility.AddPadding(genRect, 1, 1, 0, 0); + worldRect = RectUtility.AddPadding(worldRect, 1, 2, 0, 0); + EditorGUI.DrawRect(idRect, b); + EditorGUI.DrawRect(genRect, b); + EditorGUI.DrawRect(worldRect, b); + + + GUIStyle style = new GUIStyle(EditorStyles.numberField); + style.alignment = TextAnchor.MiddleCenter; + style.font = EditorStyles.boldFont; + if (status == EntityStatus.Alive) + { + Color statusColor = EcsGUI.GreenColor; + statusColor.a = 0.6f; + EditorGUI.DrawRect(statusRect, statusColor); + + EditorGUI.IntField(idRect, id, style); + EditorGUI.IntField(genRect, gen, style); + EditorGUI.IntField(worldRect, world, style); + } + else + { + Color statusColor = status == EntityStatus.Undefined ? new Color32(200, 200, 200, 255) : EcsGUI.RedColor; + statusColor.a = 0.6f; + EditorGUI.DrawRect(statusRect, statusColor); + + using (new EditorGUI.DisabledScope(true)) + { + GUI.Label(idRect, "Entity ID", style); + GUI.Label(genRect, "Generation", style); + GUI.Label(worldRect, "World ID", style); + } + } + } + + public static bool AddComponentButtons(Rect position) + { + position = RectUtility.AddPadding(position, 20f, 20f, 12f, 2f); + return GUI.Button(position, "Add Component"); + } public static AddClearComponentButton AddClearComponentButtons(Rect position) { //Rect rect = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 36f); @@ -66,7 +258,16 @@ namespace DCFApixels.DragonECS.Unity.Editors public static class Layout { - + public static void DrawEntity(EntityStatus status, int id, short gen, short world) + { + float width = EditorGUIUtility.currentViewWidth; + float height = EditorGUIUtility.singleLineHeight; + EcsGUI.DrawEntity(GUILayoutUtility.GetRect(width, height + 3f), status, id, gen, world); + } + public static bool AddComponentButtons() + { + return EcsGUI.AddComponentButtons(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 36f)); + } public static AddClearComponentButton AddClearComponentButtons() { return EcsGUI.AddClearComponentButtons(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 36f)); @@ -91,18 +292,13 @@ namespace DCFApixels.DragonECS.Unity.Editors } if (isWithFoldout == false || IsShowRuntimeComponents) { - switch (EcsGUI.Layout.AddClearComponentButtons()) + if (EcsGUI.Layout.AddComponentButtons()) { - case AddClearComponentButton.AddComponent: - GenericMenu genericMenu = RuntimeComponentsUtility.GetAddComponentGenericMenu(world); - RuntimeComponentsUtility.CurrentEntityID = entityID; - genericMenu.ShowAsContext(); - break; - case AddClearComponentButton.Clear: - break; + GenericMenu genericMenu = RuntimeComponentsUtility.GetAddComponentGenericMenu(world); + RuntimeComponentsUtility.CurrentEntityID = entityID; + genericMenu.ShowAsContext(); } - GUILayout.Box("", UnityEditorUtility.GetStyle(GUI.color, 0.16f), GUILayout.ExpandWidth(true)); IsShowHidden = EditorGUI.Toggle(GUILayoutUtility.GetLastRect(), "Show Hidden", IsShowHidden); @@ -136,7 +332,7 @@ namespace DCFApixels.DragonECS.Unity.Editors removeButtonRect.yMax += RemoveButtonRect.height; removeButtonRect.xMin = removeButtonRect.xMax - RemoveButtonRect.width; removeButtonRect.center += Vector2.up * padding * 2f; - if (GUI.Button(removeButtonRect, "x")) + if (EcsGUI.CloseButton(removeButtonRect)) { isRemoveComponent = true; } @@ -156,15 +352,23 @@ namespace DCFApixels.DragonECS.Unity.Editors } } + if (string.IsNullOrEmpty(meta.Description) == false) + { + Rect tooltipIconRect = TooltipIconRect; + tooltipIconRect.center = removeButtonRect.center; + tooltipIconRect.center -= Vector2.right * tooltipIconRect.width; + EcsGUI.DescriptionIcon(tooltipIconRect, meta.Description); + } + GUILayout.EndVertical(); } } private static bool DrawRuntimeData(Type fieldType, GUIContent label, ExpandMatrix expandMatrix, object data, out object outData) - { + { outData = data; Type type = data == null ? typeof(void) : data.GetType(); - + bool isUnityObject = typeof(UnityEngine.Object).IsAssignableFrom(fieldType); if (isUnityObject == false && data == null) diff --git a/src/Internal/Editor/UnityEditorUtility.cs b/src/Internal/Editor/UnityEditorUtility.cs index 5a4a43b..2be801c 100644 --- a/src/Internal/Editor/UnityEditorUtility.cs +++ b/src/Internal/Editor/UnityEditorUtility.cs @@ -75,6 +75,18 @@ namespace DCFApixels.DragonECS.Unity.Editors _singletonContent = new GUIContent(); } _singletonContent.text = name; + _singletonContent.image = null; + _singletonContent.tooltip = tooltip; + return _singletonContent; + } + public static GUIContent GetLabel(Texture image, string tooltip = null) + { + if (_singletonContent == null) + { + _singletonContent = new GUIContent(); + } + _singletonContent.text = string.Empty; + _singletonContent.image = image; _singletonContent.tooltip = tooltip; return _singletonContent; }