diff --git a/package.json b/package.json index 8d731f3..ff23ab7 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "displayName": "DragonECS-Unity", "description": "Integration with Unity for DragonECS", "unity": "2021.2", - "version": "0.3.16", + "version": "0.3.19", "repository": { "type": "git", "url": "https://github.com/DCFApixels/DragonECS-Unity.git" diff --git a/src/Buildin/UnityComponents.cs b/src/Buildin/UnityComponents.cs index e6a17f3..c0cd18f 100644 --- a/src/Buildin/UnityComponents.cs +++ b/src/Buildin/UnityComponents.cs @@ -1,23 +1,27 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.CompilerServices; using UnityEngine; namespace DCFApixels.DragonECS { internal static class UnityComponentConsts { - private const string UNITY_COMPONENT_NAME = "UnityComponent"; + internal const string UNITY_COMPONENT_NAME = "UnityComponent"; public static readonly MetaGroup BaseGroup = new MetaGroup(UNITY_COMPONENT_NAME); public static readonly MetaGroup ColliderGroup = new MetaGroup($"{UNITY_COMPONENT_NAME}/Collider/"); public static readonly MetaGroup JointGroup = new MetaGroup($"{UNITY_COMPONENT_NAME}/Joint/"); } [Serializable] [MetaColor(255 / 3, 255, 0)] + [MetaDescription(EcsConsts.AUTHOR, "Component-reference to Unity object for EcsPool")] + [MetaGroup(UnityComponentConsts.UNITY_COMPONENT_NAME)] public struct UnityComponent : IEcsComponent, IEnumerable//IntelliSense hack where T : Component { public T obj; + [MethodImpl(MethodImplOptions.AggressiveInlining)] public UnityComponent(T obj) { this.obj = obj; @@ -30,6 +34,10 @@ namespace DCFApixels.DragonECS { throw new NotImplementedException(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator T(UnityComponent a) { return a.obj; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator UnityComponent(T a) { return new UnityComponent(a); } } #region Unity Component Templates diff --git a/src/Connectors/EcsEntityConnect.cs b/src/Connectors/EcsEntityConnect.cs index 78db7ff..0f6a22b 100644 --- a/src/Connectors/EcsEntityConnect.cs +++ b/src/Connectors/EcsEntityConnect.cs @@ -1,8 +1,10 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; -using UnityEditor; using UnityEngine; +#region UNITY_EDITOR +using UnityEditor; +#endregion namespace DCFApixels.DragonECS { @@ -172,6 +174,7 @@ namespace DCFApixels.DragonECS internal void Autoset_Editor() { Autoset(this); + } [ContextMenu("Autoset Cascade")] internal void AutosetCascade_Editor() diff --git a/src/Debug/Editor/SettingsEditor.cs b/src/Debug/Editor/SettingsEditor.cs index 377cfaf..be5310a 100644 --- a/src/Debug/Editor/SettingsEditor.cs +++ b/src/Debug/Editor/SettingsEditor.cs @@ -29,7 +29,6 @@ namespace DCFApixels.DragonECS.Unity.Editors nameof(EcsConsts.DISABLE_DEBUG), nameof(EcsConsts.ENABLE_DUMMY_SPAN), nameof(EcsConsts.DISABLE_CATH_EXCEPTIONS), - "DEBUG", }; for (int i = 0; i < _defineSymbols.Count; i++) { @@ -61,24 +60,27 @@ namespace DCFApixels.DragonECS.Unity.Editors GUILayout.BeginHorizontal(); settings.IsShowHidden = EditorGUILayout.Toggle(SettingsPrefs.instance.IsShowHidden, GUILayout.Width(checkBoxWidth)); - GUILayout.Label(nameof(SettingsPrefs.IsShowHidden), GUILayout.ExpandWidth(false)); + GUILayout.Label(UnityEditorUtility.TransformFieldName(nameof(SettingsPrefs.IsShowHidden)), GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); settings.IsShowInterfaces = EditorGUILayout.Toggle(SettingsPrefs.instance.IsShowInterfaces, GUILayout.Width(checkBoxWidth)); - GUILayout.Label(nameof(SettingsPrefs.IsShowInterfaces), GUILayout.ExpandWidth(false)); + GUILayout.Label(UnityEditorUtility.TransformFieldName(nameof(SettingsPrefs.IsShowInterfaces)), GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); settings.IsShowRuntimeComponents = EditorGUILayout.Toggle(SettingsPrefs.instance.IsShowRuntimeComponents, GUILayout.Width(checkBoxWidth)); - GUILayout.Label(nameof(SettingsPrefs.IsShowRuntimeComponents), GUILayout.ExpandWidth(false)); + GUILayout.Label(UnityEditorUtility.TransformFieldName(nameof(SettingsPrefs.IsShowRuntimeComponents)), GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); + settings.AutoColorMode = (ComponentColorMode)EditorGUILayout.EnumPopup(UnityEditorUtility.TransformFieldName(nameof(SettingsPrefs.ComponentColorMode)), SettingsPrefs.instance.ComponentColorMode); + if (EditorGUI.EndChangeCheck()) { SettingsPrefs.instance.IsShowHidden = settings.IsShowHidden; SettingsPrefs.instance.IsShowInterfaces = settings.IsShowInterfaces; SettingsPrefs.instance.IsShowRuntimeComponents = settings.IsShowRuntimeComponents; + SettingsPrefs.instance.ComponentColorMode = settings.AutoColorMode; } GUILayout.EndVertical(); @@ -144,6 +146,7 @@ namespace DCFApixels.DragonECS.Unity.Editors public bool IsShowHidden; public bool IsShowInterfaces; public bool IsShowRuntimeComponents; + public ComponentColorMode AutoColorMode; } } } diff --git a/src/Debug/Editor/SettingsPrefs.cs b/src/Debug/Editor/SettingsPrefs.cs index 072e06b..a193e42 100644 --- a/src/Debug/Editor/SettingsPrefs.cs +++ b/src/Debug/Editor/SettingsPrefs.cs @@ -4,8 +4,14 @@ using UnityEngine; namespace DCFApixels.DragonECS.Unity.Editors { - [FilePath(EcsConsts.FRAMEWORK_NAME + "/" + nameof(SettingsPrefs) + ".prefs", FilePathAttribute.Location.ProjectFolder)] - public class SettingsPrefs : ScriptableSingleton + internal enum ComponentColorMode + { + Generic = 0, + Auto = 1, + Rainbow = 2, + } + [FilePath(EcsConsts.AUTHOR + "/" + EcsConsts.FRAMEWORK_NAME + "/" + nameof(SettingsPrefs) + ".prefs", FilePathAttribute.Location.ProjectFolder)] + internal class SettingsPrefs : ScriptableSingleton { [SerializeField] private bool _isShowInterfaces = false; @@ -52,6 +58,19 @@ namespace DCFApixels.DragonECS.Unity.Editors Save(false); } } + + + [SerializeField] + private ComponentColorMode _componentColorMode = ComponentColorMode.Auto; + public ComponentColorMode ComponentColorMode + { + get => _componentColorMode; + set + { + _componentColorMode = value; + Save(false); + } + } } } #endif \ No newline at end of file diff --git a/src/Debug/Monitors/Editor/EntityMonitorEditor.cs b/src/Debug/Monitors/Editor/EntityMonitorEditor.cs index b3f505e..0581d9c 100644 --- a/src/Debug/Monitors/Editor/EntityMonitorEditor.cs +++ b/src/Debug/Monitors/Editor/EntityMonitorEditor.cs @@ -15,7 +15,7 @@ namespace DCFApixels.DragonECS.Unity.Editors bool isAlive = Target.Entity.TryUnpackForUnityEditor(out int id, out short gen, out short worldID, out EcsWorld world); using (new EditorGUI.DisabledScope(!isAlive)) { - if (GUILayout.Button("Delete Entity")) + if (GUILayout.Button("Delete Entity", GUILayout.Height(36f))) { world.DelEntity(id); } diff --git a/src/EntityTemplate/ComponentTemplateProperty.cs b/src/EntityTemplate/ComponentTemplateProperty.cs new file mode 100644 index 0000000..0a382fb --- /dev/null +++ b/src/EntityTemplate/ComponentTemplateProperty.cs @@ -0,0 +1,65 @@ +using System; +using System.Runtime.CompilerServices; +using UnityEngine; + +namespace DCFApixels.DragonECS +{ + [Serializable] + public struct ComponentTemplateProperty : IEquatable + { + [SerializeReference] + private IComponentTemplate _template; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ComponentTemplateProperty(IComponentTemplate template) + { + _template = template; + } + public IComponentTemplate Template + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return _template; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + set { _template = value; } + } + public Type Type + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return _template.Type; } + } + public bool IsNull + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return _template == null; } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Apply(short worldID, int entityID) { _template.Apply(worldID, entityID); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public object GetRaw() { return _template.GetRaw(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void OnGizmos(Transform transform, IComponentTemplate.GizmosMode mode) { _template.OnGizmos(transform, mode); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void OnValidate(UnityEngine.Object obj) { _template.OnValidate(obj); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void SetRaw(object raw) { _template.SetRaw(raw); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(ComponentTemplateProperty other) { return _template == other._template; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override int GetHashCode() { return _template.GetHashCode(); } + public override bool Equals(object obj) { return obj is ComponentTemplateProperty other && Equals(other); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator ==(ComponentTemplateProperty a, ComponentTemplateProperty b) { return a._template == b._template; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator !=(ComponentTemplateProperty a, ComponentTemplateProperty b) { return a._template != b._template; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator ==(ComponentTemplateProperty a, Null? b) { return a.IsNull; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator ==(Null? a, ComponentTemplateProperty b) { return b.IsNull; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator !=(ComponentTemplateProperty a, Null? b) { return !a.IsNull; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator !=(Null? a, ComponentTemplateProperty b) { return !b.IsNull; } + public readonly struct Null { } + } + + public sealed class ComponentTemplateReferenceAttribute : PropertyAttribute { } +} \ No newline at end of file diff --git a/src/EntityTemplate/ComponentTemplateProperty.cs.meta b/src/EntityTemplate/ComponentTemplateProperty.cs.meta new file mode 100644 index 0000000..92c9ce3 --- /dev/null +++ b/src/EntityTemplate/ComponentTemplateProperty.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6231d6781930a694696d09c3d55fc2fb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs b/src/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs new file mode 100644 index 0000000..3546089 --- /dev/null +++ b/src/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs @@ -0,0 +1,253 @@ +#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 + { + private ComponentTemplateReferenceDrawer _drawer = new ComponentTemplateReferenceDrawer(); + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + property.Next(true); + return _drawer.GetPropertyHeight(property, label); + } + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + property.Next(true); + _drawer.OnGUI(position, property, label); + } + } + [CustomPropertyDrawer(typeof(ComponentTemplateReferenceAttribute), true)] + internal class ComponentTemplateReferenceDrawer : PropertyDrawer + { + private static readonly Rect HeadIconsRect = new Rect(0f, 0f, 19f, 19f); + + private float Padding => EditorGUIUtility.standardVerticalSpacing; + private float SingleLineWithPadding => EditorGUIUtility.singleLineHeight + Padding * 4f; + + private const float DamagedComponentHeight = 18f * 2f; + + private static bool _isInit; + private static GenericMenu _genericMenu; + + #region Init + private static void Init() + { + if (_genericMenu == null) { _isInit = false; } + if (_isInit) { return; } + + _genericMenu = new GenericMenu(); + + var componentTemplateDummies = ComponentTemplateTypeCache.Dummies; + foreach (var dummy in componentTemplateDummies) + { + if (dummy.Type.GetCustomAttribute() == null) + { + Debug.LogWarning($"Type {dummy.Type.Name} does not have the [Serializable] attribute"); + continue; + } + ITypeMeta meta = dummy is ITypeMeta metaOverride ? metaOverride : dummy.Type.ToMeta(); + string name = meta.Name; + string description = meta.Description.Text; + MetaGroup group = meta.Group; + + if (group.Name.Length > 0) + { + name = group.Name + name; + } + + if (string.IsNullOrEmpty(description) == false) + { + name = $"{name} [i]"; + } + _genericMenu.AddItem(new GUIContent(name, description), false, SelectComponent, dummy); + } + + _isInit = true; + } + [ThreadStatic] + private static SerializedProperty currentProperty; + private static void SelectComponent(object dummy) + { + currentProperty.managedReferenceValue = ((IComponentTemplate)dummy).Clone(); + currentProperty.isExpanded = false; + currentProperty.serializedObject.ApplyModifiedProperties(); + } + #endregion + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + IComponentTemplate template = property.managedReferenceValue as IComponentTemplate; + if (template == null || property.managedReferenceValue == null) + { + return EditorGUIUtility.singleLineHeight + Padding * 2f; + } + + try + { + ComponentTemplateBase customTemplate = property.managedReferenceValue as ComponentTemplateBase; + if (customTemplate != null) + { + property = property.FindPropertyRelative("component"); + } + } + catch (Exception) + { + property = null; + } + if (property == null) + { + return DamagedComponentHeight; + } + + int propCount = EcsGUI.GetChildPropertiesCount(property); + + return (propCount <= 0 ? EditorGUIUtility.singleLineHeight : EditorGUI.GetPropertyHeight(property, label)) + Padding * 4f; + } + + + + public override void OnGUI(Rect position, SerializedProperty componentRefProp, GUIContent label) + { + Init(); + var counter = componentRefProp.Copy(); + + int positionCountr = int.MaxValue; + while (counter.NextVisible(false)) + { + positionCountr--; + } + + IComponentTemplate template = componentRefProp.managedReferenceValue as IComponentTemplate; + if (template == null || componentRefProp.managedReferenceValue == null) + { + DrawSelectionPopup(position, componentRefProp, label); + return; + } + + Type componentType; + SerializedProperty componentProperty = componentRefProp; + try + { + ComponentTemplateBase customTemplate = componentProperty.managedReferenceValue as ComponentTemplateBase; + if (customTemplate != null) + { + componentProperty = componentRefProp.FindPropertyRelative("component"); + componentType = customTemplate.GetType().GetField("component", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FieldType; + } + else + { + componentType = componentProperty.managedReferenceValue.GetType(); + } + + if (componentType == null || componentProperty == null) + { + throw new NullReferenceException(); + } + } + catch (Exception e) + { + Debug.LogException(e, componentRefProp.serializedObject.targetObject); + DrawDamagedComponent(position, "Damaged component template."); + 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); + + #region Draw Component Block + Rect removeButtonRect = position; + removeButtonRect.center -= new Vector2(0, removeButtonRect.height); + removeButtonRect.yMin = removeButtonRect.yMax; + removeButtonRect.yMax += HeadIconsRect.height; + removeButtonRect.xMin = removeButtonRect.xMax - HeadIconsRect.width; + removeButtonRect.center += Vector2.up * Padding * 1f; + + bool isRemoveComponent = EcsGUI.CloseButton(removeButtonRect); + + if (propCount <= 0) + { + EcsGUI.DrawEmptyComponentProperty(paddingPosition, componentRefProp, label, false); + } + 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); + } + + + if (isRemoveComponent) + { + componentRefProp.managedReferenceValue = null; + } + if (string.IsNullOrEmpty(description) == false) + { + Rect tooltipIconRect = HeadIconsRect; + tooltipIconRect.center = removeButtonRect.center; + tooltipIconRect.center -= Vector2.right * tooltipIconRect.width; + EcsGUI.DescriptionIcon(tooltipIconRect, description); + } + #endregion + + if (EditorGUI.EndChangeCheck()) + { + componentProperty.serializedObject.ApplyModifiedProperties(); + EditorUtility.SetDirty(componentProperty.serializedObject.targetObject); + } + } + + private void DrawSelectionPopup(Rect position, SerializedProperty componentRefProp, GUIContent label) + { + EditorGUI.LabelField(position, label); + Rect buttonRect = RectUtility.AddPadding(position, EditorGUIUtility.labelWidth, 0f, 0f, 0f); + if (GUI.Button(buttonRect, "Select")) + { + currentProperty = componentRefProp; + _genericMenu.ShowAsContext(); + } + } + private void DrawDamagedComponent(Rect position, string message) + { + EditorGUI.HelpBox(position, message, MessageType.Warning); + } + } +} +#endif \ No newline at end of file diff --git a/src/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs.meta b/src/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs.meta new file mode 100644 index 0000000..03dce75 --- /dev/null +++ b/src/EntityTemplate/Editor/ComponentTemplatePropertyDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dbf91ec8124942340b7f095474db92b1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/EntityTemplate/Editor/EntityTemplateEditor.cs b/src/EntityTemplate/Editor/EntityTemplateEditor.cs index 833b7fc..5b5ac16 100644 --- a/src/EntityTemplate/Editor/EntityTemplateEditor.cs +++ b/src/EntityTemplate/Editor/EntityTemplateEditor.cs @@ -9,39 +9,33 @@ namespace DCFApixels.DragonECS.Unity.Editors { internal abstract class EntityTemplateEditorBase : Editor { - private static readonly Rect RemoveButtonRect = new Rect(0f, 0f, 19f, 19f); - private static readonly Rect TooltipIconRect = new Rect(0f, 0f, 19f, 19f); + private static readonly Rect HeadIconsRect = new Rect(0f, 0f, 19f, 19f); - private GUIStyle _removeButtonStyle; private GenericMenu _genericMenu; private bool _isInit = false; + private static ComponentColorMode AutoColorMode + { + get { return SettingsPrefs.instance.ComponentColorMode; } + set { SettingsPrefs.instance.ComponentColorMode = value; } + } + #region Init private void Init() { if (_genericMenu == null) { _isInit = false; } if (_isInit) { return; } - var tmpstylebase = UnityEditorUtility.GetStyle(new Color(0.9f, 0f, 0.22f), 0.5f); - var tmpStyle = UnityEditorUtility.GetStyle(new Color(1f, 0.5f, 0.7f), 0.5f); - - _removeButtonStyle = new GUIStyle(EditorStyles.linkLabel); - _removeButtonStyle.alignment = TextAnchor.MiddleCenter; - - _removeButtonStyle.normal = tmpstylebase.normal; - _removeButtonStyle.hover = tmpStyle.normal; - _removeButtonStyle.active = tmpStyle.normal; - _removeButtonStyle.focused = tmpStyle.normal; - - _removeButtonStyle.padding = new RectOffset(0, 0, 0, 0); - _removeButtonStyle.margin = new RectOffset(0, 0, 0, 0); - _removeButtonStyle.border = new RectOffset(0, 0, 0, 0); - _genericMenu = new GenericMenu(); var componentTemplateDummies = ComponentTemplateTypeCache.Dummies; foreach (var dummy in componentTemplateDummies) { + if (dummy.Type.GetCustomAttribute() == null) + { + Debug.LogWarning($"Type {dummy.Type.Name} does not have the [Serializable] attribute"); + continue; + } ITypeMeta meta = dummy is ITypeMeta metaOverride ? metaOverride : dummy.Type.ToMeta(); string name = meta.Name; string description = meta.Description.Text; @@ -112,7 +106,7 @@ namespace DCFApixels.DragonECS.Unity.Editors GUILayout.Label("", GUILayout.Height(0), GUILayout.ExpandWidth(true)); for (int i = 0; i < componentsProp.arraySize; i++) { - DrawComponentData(componentsProp.GetArrayElementAtIndex(i), i); + DrawComponentData(componentsProp.GetArrayElementAtIndex(i), componentsProp.arraySize, i); } GUILayout.EndVertical(); } @@ -132,37 +126,56 @@ namespace DCFApixels.DragonECS.Unity.Editors } } - private void DrawComponentData(SerializedProperty componentRefProp, int index) + private void DrawComponentData(SerializedProperty componentRefProp, int total, int index) { IComponentTemplate template = componentRefProp.managedReferenceValue as IComponentTemplate; if (template == null || componentRefProp.managedReferenceValue == null) { - DrawDamagedComponent(componentRefProp, index); + DrawDamagedComponent_Replaced(componentRefProp, index); + 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, serializedObject.targetObject); + DrawDamagedComponent(index, "Damaged component template."); return; } - Type componentType; - SerializedProperty componentProperty = componentRefProp; - ComponentTemplateBase customInitializer = componentProperty.managedReferenceValue as ComponentTemplateBase; - if (customInitializer != null) - { - componentProperty = componentRefProp.FindPropertyRelative("component"); - componentType = customInitializer.GetType().GetField("component", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FieldType; - } - else - { - componentType = componentProperty.managedReferenceValue.GetType(); ; - } + //сюда попадают уже валидные компоненты + ITypeMeta meta = template is ITypeMeta metaOverride ? metaOverride : template.Type.ToMeta(); string name = meta.Name; string description = meta.Description.Text; - Color panelColor = meta.Color.ToUnityColor().Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE); - //GUIContent label = new GUIContent(name); - bool isEmpty = componentType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Length <= 0; + int propCount = EcsGUI.GetChildPropertiesCount(componentProperty, componentType, out bool isEmpty); + float padding = EditorGUIUtility.standardVerticalSpacing; + + Color panelColor = EcsGUI.SelectPanelColor(meta, index, total).Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE); + Color alphaPanelColor = panelColor; alphaPanelColor.a = EscEditorConsts.COMPONENT_DRAWER_ALPHA; @@ -171,26 +184,17 @@ namespace DCFApixels.DragonECS.Unity.Editors EditorGUI.BeginChangeCheck(); GUILayout.BeginVertical(UnityEditorUtility.GetStyle(alphaPanelColor)); - - #region Draw Component Block - bool isRemoveComponent = false; removeButtonRect.yMin = removeButtonRect.yMax; - removeButtonRect.yMax += RemoveButtonRect.height; - removeButtonRect.xMin = removeButtonRect.xMax - RemoveButtonRect.width; + removeButtonRect.yMax += HeadIconsRect.height; + removeButtonRect.xMin = removeButtonRect.xMax - HeadIconsRect.width; removeButtonRect.center += Vector2.up * padding * 2f; - if (EcsGUI.CloseButton(removeButtonRect)) - { - isRemoveComponent = true; - } + bool isRemoveComponent = EcsGUI.CloseButton(removeButtonRect); - if (isEmpty) + if (propCount <= 0) { - GUIContent label = UnityEditorUtility.GetLabel(name); - GUILayout.Label(label); - EditorGUI.BeginProperty(GUILayoutUtility.GetLastRect(), label, componentRefProp); - EditorGUI.EndProperty(); + EcsGUI.Layout.DrawEmptyComponentProperty(componentRefProp, name, isEmpty); } else { @@ -211,7 +215,7 @@ namespace DCFApixels.DragonECS.Unity.Editors } if (string.IsNullOrEmpty(description) == false) { - Rect tooltipIconRect = TooltipIconRect; + Rect tooltipIconRect = HeadIconsRect; tooltipIconRect.center = removeButtonRect.center; tooltipIconRect.center -= Vector2.right * tooltipIconRect.width; EcsGUI.DescriptionIcon(tooltipIconRect, description); @@ -226,19 +230,28 @@ namespace DCFApixels.DragonECS.Unity.Editors EditorUtility.SetDirty(componentProperty.serializedObject.targetObject); } } - - private void DrawDamagedComponent(SerializedProperty componentRefProp, int index) + private void DrawDamagedComponent_Replaced(SerializedProperty componentRefProp, int index) { + DrawDamagedComponent(index, $"Damaged component template. If the problem occurred after renaming a component or initializer. use MovedFromAttrubute"); + } + private void DrawDamagedComponent(int index, string message) + { + Rect removeButtonRect = GUILayoutUtility.GetLastRect(); + GUILayout.BeginHorizontal(); - EditorGUILayout.HelpBox($"Damaged component. If the problem occurred after renaming a component or initializer. use MovedFromAttrubute", MessageType.Warning); + float padding = EditorGUIUtility.standardVerticalSpacing; - Rect lastrect = GUILayoutUtility.GetLastRect(); - Rect removeButtonRect = RemoveButtonRect; - removeButtonRect.center = new Vector2(lastrect.xMax + removeButtonRect.width, lastrect.yMin + removeButtonRect.height / 2f); + removeButtonRect.yMin = removeButtonRect.yMax; + removeButtonRect.yMax += HeadIconsRect.height; + removeButtonRect.xMin = removeButtonRect.xMax - HeadIconsRect.width; + removeButtonRect.center += Vector2.up * padding * 2f; - GUILayout.Label("", GUILayout.Width(removeButtonRect.width)); - if (GUI.Button(removeButtonRect, "x", _removeButtonStyle)) + bool isRemoveComponent = EcsGUI.CloseButton(removeButtonRect); + + EditorGUILayout.HelpBox(message, MessageType.Warning); + + if (isRemoveComponent) { OnRemoveComponentAt(index); } diff --git a/src/EntityTemplate/Templates/ComponentTemplateBase.cs b/src/EntityTemplate/Templates/ComponentTemplateBase.cs index df4f541..a9b9364 100644 --- a/src/EntityTemplate/Templates/ComponentTemplateBase.cs +++ b/src/EntityTemplate/Templates/ComponentTemplateBase.cs @@ -57,12 +57,12 @@ namespace DCFApixels.DragonECS protected T component; #region Properties - public override Type Type { get { return typeof(T); } } + 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; } } public override MetaGroup Group { get { return Meta.Group; } } public override MetaDescription Description { get { return Meta.Description; } } public override IReadOnlyCollection Tags { get { return Meta.Tags; } } - public override MetaColor Color { get { return Meta.Color; } } #endregion #region Methods @@ -129,7 +129,7 @@ namespace DCFApixels.DragonECS.Unity.Editors Type interfaceType = typeof(IComponentTemplate); foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { - var targetTypes = assembly.GetTypes().Where(type => !type.IsGenericType && !(type.IsAbstract || type.IsInterface) && type.GetCustomAttribute() != null); + var targetTypes = assembly.GetTypes().Where(type => !type.IsGenericType && !(type.IsAbstract || type.IsInterface) /*&& type.GetCustomAttribute() != null*/); types.AddRange(targetTypes.Where(type => interfaceType.IsAssignableFrom(type))); diff --git a/src/Icons/AutosetCascadeIcon.png b/src/Icons/AutosetCascadeIcon.png new file mode 100644 index 0000000..2ad48f6 Binary files /dev/null and b/src/Icons/AutosetCascadeIcon.png differ diff --git a/src/Icons/d_winbtn_win_restore@2x.png.meta b/src/Icons/AutosetCascadeIcon.png.meta similarity index 83% rename from src/Icons/d_winbtn_win_restore@2x.png.meta rename to src/Icons/AutosetCascadeIcon.png.meta index 343fb69..641eceb 100644 --- a/src/Icons/d_winbtn_win_restore@2x.png.meta +++ b/src/Icons/AutosetCascadeIcon.png.meta @@ -3,10 +3,10 @@ guid: 8f9fb2a8877577940971d81a98aeaaaa TextureImporter: internalIDToNameTable: [] externalObjects: {} - serializedVersion: 13 + serializedVersion: 11 mipmaps: mipMapMode: 0 - enableMipMap: 1 + enableMipMap: 0 sRGBTexture: 1 linearTexture: 0 fadeOut: 0 @@ -20,12 +20,11 @@ TextureImporter: externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 - flipGreenChannel: 0 isReadable: 0 streamingMipmaps: 0 streamingMipmapsPriority: 0 vTOnly: 0 - ignoreMipmapLimit: 0 + ignoreMasterTextureLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -52,7 +51,7 @@ TextureImporter: spriteBorder: {x: 0, y: 0, z: 0, w: 0} spriteGenerateFallbackPhysicsShape: 1 alphaUsage: 1 - alphaIsTransparency: 0 + alphaIsTransparency: 1 spriteTessellationDetail: -1 textureType: 0 textureShape: 1 @@ -64,20 +63,17 @@ TextureImporter: textureFormatSet: 0 ignorePngGamma: 0 applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform maxTextureSize: 2048 - resizeAlgorithm: 0 + resizeAlgorithm: 1 textureFormat: -1 textureCompression: 1 compressionQuality: 50 crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 - ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 @@ -90,7 +86,18 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 - ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: @@ -107,8 +114,9 @@ TextureImporter: weights: [] secondaryTextures: [] nameFileIdTable: {} - mipmapLimitGroupName: + spritePackingTag: pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 userData: assetBundleName: assetBundleVariant: diff --git a/src/Icons/AutosetIcon.png b/src/Icons/AutosetIcon.png new file mode 100644 index 0000000..b1f790d Binary files /dev/null and b/src/Icons/AutosetIcon.png differ diff --git a/src/Icons/d_winbtn_win_max@2x.png.meta b/src/Icons/AutosetIcon.png.meta similarity index 81% rename from src/Icons/d_winbtn_win_max@2x.png.meta rename to src/Icons/AutosetIcon.png.meta index 7125548..c253200 100644 --- a/src/Icons/d_winbtn_win_max@2x.png.meta +++ b/src/Icons/AutosetIcon.png.meta @@ -3,10 +3,10 @@ guid: d01e651682f48b548b597714f47e14b9 TextureImporter: internalIDToNameTable: [] externalObjects: {} - serializedVersion: 13 + serializedVersion: 11 mipmaps: mipMapMode: 0 - enableMipMap: 1 + enableMipMap: 0 sRGBTexture: 1 linearTexture: 0 fadeOut: 0 @@ -20,12 +20,11 @@ TextureImporter: externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 - flipGreenChannel: 0 isReadable: 0 streamingMipmaps: 0 streamingMipmapsPriority: 0 vTOnly: 0 - ignoreMipmapLimit: 0 + ignoreMasterTextureLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -43,7 +42,7 @@ TextureImporter: nPOTScale: 0 lightmap: 0 compressionQuality: 50 - spriteMode: 2 + spriteMode: 1 spriteExtrude: 1 spriteMeshType: 1 alignment: 0 @@ -52,7 +51,7 @@ TextureImporter: spriteBorder: {x: 0, y: 0, z: 0, w: 0} spriteGenerateFallbackPhysicsShape: 1 alphaUsage: 1 - alphaIsTransparency: 0 + alphaIsTransparency: 1 spriteTessellationDetail: -1 textureType: 0 textureShape: 1 @@ -64,20 +63,17 @@ TextureImporter: textureFormatSet: 0 ignorePngGamma: 0 applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform maxTextureSize: 2048 - resizeAlgorithm: 0 + resizeAlgorithm: 1 textureFormat: -1 textureCompression: 1 compressionQuality: 50 crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 - ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 @@ -90,7 +86,18 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 - ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: @@ -99,7 +106,7 @@ TextureImporter: outline: [] physicsShape: [] bones: [] - spriteID: + spriteID: 5e97eb03825dee720800000000000000 internalID: 0 vertices: [] indices: @@ -107,8 +114,9 @@ TextureImporter: weights: [] secondaryTextures: [] nameFileIdTable: {} - mipmapLimitGroupName: + spritePackingTag: pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 userData: assetBundleName: assetBundleVariant: diff --git a/src/Icons/d_winbtn_win_close.png b/src/Icons/CloseIcon.png similarity index 100% rename from src/Icons/d_winbtn_win_close.png rename to src/Icons/CloseIcon.png diff --git a/src/Icons/d_winbtn_win_close.png.meta b/src/Icons/CloseIcon.png.meta similarity index 83% rename from src/Icons/d_winbtn_win_close.png.meta rename to src/Icons/CloseIcon.png.meta index 26a947b..8a67a2d 100644 --- a/src/Icons/d_winbtn_win_close.png.meta +++ b/src/Icons/CloseIcon.png.meta @@ -3,10 +3,10 @@ guid: 8a708e50662813d4a99c107e6431a60b TextureImporter: internalIDToNameTable: [] externalObjects: {} - serializedVersion: 13 + serializedVersion: 11 mipmaps: mipMapMode: 0 - enableMipMap: 1 + enableMipMap: 0 sRGBTexture: 1 linearTexture: 0 fadeOut: 0 @@ -20,12 +20,11 @@ TextureImporter: externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 - flipGreenChannel: 0 isReadable: 0 streamingMipmaps: 0 streamingMipmapsPriority: 0 vTOnly: 0 - ignoreMipmapLimit: 0 + ignoreMasterTextureLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -52,7 +51,7 @@ TextureImporter: spriteBorder: {x: 0, y: 0, z: 0, w: 0} spriteGenerateFallbackPhysicsShape: 1 alphaUsage: 1 - alphaIsTransparency: 0 + alphaIsTransparency: 1 spriteTessellationDetail: -1 textureType: 0 textureShape: 1 @@ -64,20 +63,17 @@ TextureImporter: textureFormatSet: 0 ignorePngGamma: 0 applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform maxTextureSize: 2048 - resizeAlgorithm: 0 + resizeAlgorithm: 1 textureFormat: -1 textureCompression: 1 compressionQuality: 50 crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 - ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 @@ -90,7 +86,18 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 - ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: @@ -107,8 +114,9 @@ TextureImporter: weights: [] secondaryTextures: [] nameFileIdTable: {} - mipmapLimitGroupName: + spritePackingTag: pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 userData: assetBundleName: assetBundleVariant: diff --git a/src/Icons/d_P4_DeletedLocal.png b/src/Icons/CloseIconOn.png similarity index 100% rename from src/Icons/d_P4_DeletedLocal.png rename to src/Icons/CloseIconOn.png diff --git a/src/Icons/d_P4_DeletedLocal.png.meta b/src/Icons/CloseIconOn.png.meta similarity index 83% rename from src/Icons/d_P4_DeletedLocal.png.meta rename to src/Icons/CloseIconOn.png.meta index 046fdf1..7904d9f 100644 --- a/src/Icons/d_P4_DeletedLocal.png.meta +++ b/src/Icons/CloseIconOn.png.meta @@ -3,10 +3,10 @@ guid: 6a1d402595b00c24db2ba647fed93a5c TextureImporter: internalIDToNameTable: [] externalObjects: {} - serializedVersion: 13 + serializedVersion: 11 mipmaps: mipMapMode: 0 - enableMipMap: 1 + enableMipMap: 0 sRGBTexture: 1 linearTexture: 0 fadeOut: 0 @@ -20,12 +20,11 @@ TextureImporter: externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 - flipGreenChannel: 0 isReadable: 0 streamingMipmaps: 0 streamingMipmapsPriority: 0 vTOnly: 0 - ignoreMipmapLimit: 0 + ignoreMasterTextureLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -52,7 +51,7 @@ TextureImporter: spriteBorder: {x: 0, y: 0, z: 0, w: 0} spriteGenerateFallbackPhysicsShape: 1 alphaUsage: 1 - alphaIsTransparency: 0 + alphaIsTransparency: 1 spriteTessellationDetail: -1 textureType: 0 textureShape: 1 @@ -64,20 +63,17 @@ TextureImporter: textureFormatSet: 0 ignorePngGamma: 0 applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform maxTextureSize: 2048 - resizeAlgorithm: 0 + resizeAlgorithm: 1 textureFormat: -1 textureCompression: 1 compressionQuality: 50 crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 - ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 @@ -90,7 +86,18 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 - ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: @@ -107,8 +114,9 @@ TextureImporter: weights: [] secondaryTextures: [] nameFileIdTable: {} - mipmapLimitGroupName: + spritePackingTag: pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 userData: assetBundleName: assetBundleVariant: diff --git a/src/Icons/d__Help.png b/src/Icons/HelpIcon.png similarity index 100% rename from src/Icons/d__Help.png rename to src/Icons/HelpIcon.png diff --git a/src/Icons/d__Help.png.meta b/src/Icons/HelpIcon.png.meta similarity index 83% rename from src/Icons/d__Help.png.meta rename to src/Icons/HelpIcon.png.meta index 439d0b0..fdee6d6 100644 --- a/src/Icons/d__Help.png.meta +++ b/src/Icons/HelpIcon.png.meta @@ -3,10 +3,10 @@ guid: e135cf23a5d53ce48a75e163b41e39d5 TextureImporter: internalIDToNameTable: [] externalObjects: {} - serializedVersion: 13 + serializedVersion: 11 mipmaps: mipMapMode: 0 - enableMipMap: 1 + enableMipMap: 0 sRGBTexture: 1 linearTexture: 0 fadeOut: 0 @@ -20,12 +20,11 @@ TextureImporter: externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 - flipGreenChannel: 0 isReadable: 0 streamingMipmaps: 0 streamingMipmapsPriority: 0 vTOnly: 0 - ignoreMipmapLimit: 0 + ignoreMasterTextureLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -52,7 +51,7 @@ TextureImporter: spriteBorder: {x: 0, y: 0, z: 0, w: 0} spriteGenerateFallbackPhysicsShape: 1 alphaUsage: 1 - alphaIsTransparency: 0 + alphaIsTransparency: 1 spriteTessellationDetail: -1 textureType: 0 textureShape: 1 @@ -64,20 +63,17 @@ TextureImporter: textureFormatSet: 0 ignorePngGamma: 0 applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform maxTextureSize: 2048 - resizeAlgorithm: 0 + resizeAlgorithm: 1 textureFormat: -1 textureCompression: 1 compressionQuality: 50 crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 - ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 @@ -90,7 +86,18 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 - ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: @@ -107,8 +114,9 @@ TextureImporter: weights: [] secondaryTextures: [] nameFileIdTable: {} - mipmapLimitGroupName: + spritePackingTag: pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 userData: assetBundleName: assetBundleVariant: diff --git a/src/Icons/UnlinkIcon.png b/src/Icons/UnlinkIcon.png new file mode 100644 index 0000000..f6f1004 Binary files /dev/null and b/src/Icons/UnlinkIcon.png differ diff --git a/src/Icons/d_Unlinked.png.meta b/src/Icons/UnlinkIcon.png.meta similarity index 83% rename from src/Icons/d_Unlinked.png.meta rename to src/Icons/UnlinkIcon.png.meta index f93621e..4689347 100644 --- a/src/Icons/d_Unlinked.png.meta +++ b/src/Icons/UnlinkIcon.png.meta @@ -3,10 +3,10 @@ guid: 5baead89a941e034e9f44d63617d3246 TextureImporter: internalIDToNameTable: [] externalObjects: {} - serializedVersion: 13 + serializedVersion: 11 mipmaps: mipMapMode: 0 - enableMipMap: 1 + enableMipMap: 0 sRGBTexture: 1 linearTexture: 0 fadeOut: 0 @@ -20,12 +20,11 @@ TextureImporter: externalNormalMap: 0 heightScale: 0.25 normalMapFilter: 0 - flipGreenChannel: 0 isReadable: 0 streamingMipmaps: 0 streamingMipmapsPriority: 0 vTOnly: 0 - ignoreMipmapLimit: 0 + ignoreMasterTextureLimit: 0 grayScaleToAlpha: 0 generateCubemap: 6 cubemapConvolution: 0 @@ -52,7 +51,7 @@ TextureImporter: spriteBorder: {x: 0, y: 0, z: 0, w: 0} spriteGenerateFallbackPhysicsShape: 1 alphaUsage: 1 - alphaIsTransparency: 0 + alphaIsTransparency: 1 spriteTessellationDetail: -1 textureType: 0 textureShape: 1 @@ -64,20 +63,17 @@ TextureImporter: textureFormatSet: 0 ignorePngGamma: 0 applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform maxTextureSize: 2048 - resizeAlgorithm: 0 + resizeAlgorithm: 1 textureFormat: -1 textureCompression: 1 compressionQuality: 50 crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 - ignorePlatformSupport: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 @@ -90,7 +86,18 @@ TextureImporter: crunchedCompression: 0 allowsAlphaSplitting: 0 overridden: 0 - ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 androidETC2FallbackOverride: 0 forceMaximumCompressionQuality_BC6H_BC7: 0 spriteSheet: @@ -107,8 +114,9 @@ TextureImporter: weights: [] secondaryTextures: [] nameFileIdTable: {} - mipmapLimitGroupName: + spritePackingTag: pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 userData: assetBundleName: assetBundleVariant: diff --git a/src/Icons/d_Unlinked.png b/src/Icons/d_Unlinked.png deleted file mode 100644 index 1482061..0000000 Binary files a/src/Icons/d_Unlinked.png and /dev/null differ diff --git a/src/Icons/d_winbtn_win_max@2x.png b/src/Icons/d_winbtn_win_max@2x.png deleted file mode 100644 index 66dd3d6..0000000 Binary files a/src/Icons/d_winbtn_win_max@2x.png and /dev/null differ diff --git a/src/Icons/d_winbtn_win_restore@2x.png b/src/Icons/d_winbtn_win_restore@2x.png deleted file mode 100644 index dc22a34..0000000 Binary files a/src/Icons/d_winbtn_win_restore@2x.png and /dev/null differ diff --git a/src/Internal/Editor/EcsGUI.cs b/src/Internal/Editor/EcsGUI.cs index c7e7ef4..9b900d6 100644 --- a/src/Internal/Editor/EcsGUI.cs +++ b/src/Internal/Editor/EcsGUI.cs @@ -4,6 +4,8 @@ using System; using System.Reflection; using UnityEditor; using UnityEngine; +using UnityObject = UnityEngine.Object; +using UnityComponent = UnityEngine.Component; namespace DCFApixels.DragonECS.Unity.Editors { @@ -26,6 +28,7 @@ namespace DCFApixels.DragonECS.Unity.Editors public struct ColorScope : IDisposable { private readonly Color _value; + public ColorScope(float r, float g, float b, float a = 1f) : this(new Color(r, g, b, a)) { } public ColorScope(Color value) { _value = GUI.color; @@ -39,6 +42,7 @@ namespace DCFApixels.DragonECS.Unity.Editors public struct ContentColorScope : IDisposable { private readonly Color _value; + public ContentColorScope(float r, float g, float b, float a = 1f) : this(new Color(r, g, b, a)) { } public ContentColorScope(Color value) { _value = GUI.contentColor; @@ -49,8 +53,17 @@ namespace DCFApixels.DragonECS.Unity.Editors GUI.contentColor = _value; } } + private static ContentColorScope SetContentColor(Color value) => new ContentColorScope(value); + private static ContentColorScope SetContentColor(float r, float g, float b, float a = 1f) => new ContentColorScope(r, g, b, a); + private static ColorScope SetColor(Color value) => new ColorScope(value); + private static ColorScope SetColor(float r, float g, float b, float a = 1f) => new ColorScope(r, g, b, a); + private static EditorGUI.DisabledScope Enable => new EditorGUI.DisabledScope(false); + private static EditorGUI.DisabledScope Disable => new EditorGUI.DisabledScope(true); + private static EditorGUI.DisabledScope SetEnable(bool value) => new EditorGUI.DisabledScope(!value); #endregion + private static readonly BindingFlags fieldFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; + 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); @@ -60,6 +73,12 @@ namespace DCFApixels.DragonECS.Unity.Editors public static float EntityBarHeight => EditorGUIUtility.singleLineHeight + 3f; + #region Properties + private static ComponentColorMode AutoColorMode + { + get { return SettingsPrefs.instance.ComponentColorMode; } + set { SettingsPrefs.instance.ComponentColorMode = value; } + } private static bool IsShowHidden { get { return SettingsPrefs.instance.IsShowHidden; } @@ -70,7 +89,9 @@ namespace DCFApixels.DragonECS.Unity.Editors get { return SettingsPrefs.instance.IsShowRuntimeComponents; } set { SettingsPrefs.instance.IsShowRuntimeComponents = value; } } + #endregion + #region enums public enum AddClearComponentButton : byte { None = 0, @@ -84,7 +105,9 @@ namespace DCFApixels.DragonECS.Unity.Editors Alive = 1 << 0, Undefined = 1 << 1, } + #endregion + #region HitTest internal static bool HitTest(Rect rect) { return HitTest(rect, Event.current.mousePosition); @@ -102,11 +125,16 @@ 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; } + #endregion + #region small elems public static void DrawIcon(Rect position, Texture icon, float iconPadding, string description) { - GUI.Label(position, UnityEditorUtility.GetLabel(string.Empty, description)); - GUI.DrawTexture(RectUtility.AddPadding(position, iconPadding), icon); + using (SetColor(GUI.enabled ? GUI.color : GUI.color * new Color(1f, 1f, 1f, 0.4f))) + { + GUI.Label(position, UnityEditorUtility.GetLabel(string.Empty, description)); + GUI.DrawTexture(RectUtility.AddPadding(position, iconPadding), icon); + } } public static (bool, bool) IconButtonGeneric(Rect position) { @@ -163,8 +191,9 @@ namespace DCFApixels.DragonECS.Unity.Editors { return IconButton(position, Icons.Instance.CloseIcon, 0f, "Delete Entity"); } + #endregion - + #region entity bar public static void EntityBarForAlive(Rect position, EntityStatus status, int id, short gen, short world) { EntityBar(position, status != EntityStatus.Alive, status, id, gen, world); @@ -242,7 +271,49 @@ namespace DCFApixels.DragonECS.Unity.Editors } } } + #endregion + internal static int GetChildPropertiesCount(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) + { + var propsCounter = property.Copy(); + int lastDepth = propsCounter.depth; + bool next = propsCounter.Next(true) && lastDepth < propsCounter.depth; + int result = next ? -1 : 0; + while (next) + { + result++; + next = propsCounter.Next(false); + } + return result; + } + public static Color SelectPanelColor(ITypeMeta meta, int index, int total) + { + var trueMeta = meta.Type.ToMeta(); + if (trueMeta.IsCustomColor || meta.Color != trueMeta.Color) + { + return meta.Color.ToUnityColor(); + } + else + { + switch (AutoColorMode) + { + case ComponentColorMode.Auto: + return meta.Color.ToUnityColor().Desaturate(0.48f) / 1.18f; //.Desaturate(0.48f) / 1.18f; + case ComponentColorMode.Rainbow: + int localTotal = Mathf.Max(total, EscEditorConsts.AUTO_COLOR_RAINBOW_MIN_RANGE); + Color hsv = Color.HSVToRGB(1f / localTotal * (index % localTotal), 1, 1); + return hsv.Desaturate(0.48f) / 1.18f; + default: + return index % 2 == 0 ? new Color(0.40f, 0.40f, 0.40f) : new Color(0.54f, 0.54f, 0.54f); + } + } + } public static bool AddComponentButtons(Rect position) { position = RectUtility.AddPadding(position, 20f, 20f, 12f, 2f); @@ -264,8 +335,34 @@ namespace DCFApixels.DragonECS.Unity.Editors return AddClearComponentButton.None; } + public static void DrawEmptyComponentProperty(Rect position, SerializedProperty property, string name, bool isDisplayEmpty) + { + DrawEmptyComponentProperty(position, property, UnityEditorUtility.GetLabel(name), isDisplayEmpty); + } + public static void DrawEmptyComponentProperty(Rect position, SerializedProperty property, GUIContent label, bool isDisplayEmpty) + { + EditorGUI.LabelField(position, label); + if (isDisplayEmpty) + { + using (SetContentColor(1f, 1f, 1f, 0.4f)) + { + GUI.Label(position.AddPadding(EditorGUIUtility.labelWidth, 0, 0, 0), "empty"); + } + } + EditorGUI.BeginProperty(position, label, property); + EditorGUI.EndProperty(); + } + public static class Layout { + public static void DrawEmptyComponentProperty(SerializedProperty property, string name, bool isDisplayEmpty) + { + EcsGUI.DrawEmptyComponentProperty(GUILayoutUtility.GetRect(UnityEditorUtility.GetLabel(name), EditorStyles.label), property, name, isDisplayEmpty); + } + public static void DrawEmptyComponentProperty(SerializedProperty property, GUIContent label, bool isDisplayEmpty) + { + EcsGUI.DrawEmptyComponentProperty(GUILayoutUtility.GetRect(label, EditorStyles.label), property, label, isDisplayEmpty); + } public static void DrawWorldBaseInfo(EcsWorld world) { bool isNull = world == null || world.IsDestroyed || world.id == 0; @@ -280,6 +377,8 @@ namespace DCFApixels.DragonECS.Unity.Editors EditorGUILayout.IntField("Leaked Entites", leakedEntitesCount, EditorStyles.boldLabel); } } + + #region entity bar public static void EntityBarForAlive(EntityStatus status, int id, short gen, short world) { float width = EditorGUIUtility.currentViewWidth; @@ -304,6 +403,7 @@ namespace DCFApixels.DragonECS.Unity.Editors float height = EntityBarHeight; EcsGUI.EntityBar(GUILayoutUtility.GetRect(width, height)); } + #endregion public static bool AddComponentButtons() { @@ -333,7 +433,7 @@ namespace DCFApixels.DragonECS.Unity.Editors } if (isWithFoldout == false || IsShowRuntimeComponents) { - if (EcsGUI.Layout.AddComponentButtons()) + if (AddComponentButtons()) { GenericMenu genericMenu = RuntimeComponentsUtility.GetAddComponentGenericMenu(world); RuntimeComponentsUtility.CurrentEntityID = entityID; @@ -343,24 +443,25 @@ namespace DCFApixels.DragonECS.Unity.Editors GUILayout.Box("", UnityEditorUtility.GetStyle(GUI.color, 0.16f), GUILayout.ExpandWidth(true)); IsShowHidden = EditorGUI.Toggle(GUILayoutUtility.GetLastRect(), "Show Hidden", IsShowHidden); + int i = 0; foreach (var componentTypeID in componentTypeIDs) { var pool = world.GetPoolInstance(componentTypeID); { - DrawRuntimeComponent(entityID, pool); + DrawRuntimeComponent(componentTypeIDs.Length, i++, entityID, pool); } } } GUILayout.EndVertical(); } - private static readonly BindingFlags fieldFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; - private static void DrawRuntimeComponent(int entityID, IEcsPool pool) + private static void DrawRuntimeComponent(int total, int index, int entityID, IEcsPool pool) { var meta = pool.ComponentType.ToMeta(); if (meta.IsHidden == false || IsShowHidden) { object data = pool.GetRaw(entityID); - Color panelColor = meta.Color.ToUnityColor().Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE); + + Color panelColor = SelectPanelColor(meta, index, total).Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE); float padding = EditorGUIUtility.standardVerticalSpacing; Rect removeButtonRect = GUILayoutUtility.GetLastRect(); @@ -373,7 +474,7 @@ namespace DCFApixels.DragonECS.Unity.Editors removeButtonRect.yMax += RemoveButtonRect.height; removeButtonRect.xMin = removeButtonRect.xMax - RemoveButtonRect.width; removeButtonRect.center += Vector2.up * padding * 2f; - if (EcsGUI.CloseButton(removeButtonRect)) + if (CloseButton(removeButtonRect)) { isRemoveComponent = true; } @@ -398,7 +499,7 @@ namespace DCFApixels.DragonECS.Unity.Editors Rect tooltipIconRect = TooltipIconRect; tooltipIconRect.center = removeButtonRect.center; tooltipIconRect.center -= Vector2.right * tooltipIconRect.width; - EcsGUI.DescriptionIcon(tooltipIconRect, meta.Description.Text); + DescriptionIcon(tooltipIconRect, meta.Description.Text); } GUILayout.EndVertical(); @@ -410,7 +511,7 @@ namespace DCFApixels.DragonECS.Unity.Editors outData = data; Type type = data == null ? typeof(void) : data.GetType(); - bool isUnityObject = typeof(UnityEngine.Object).IsAssignableFrom(fieldType); + bool isUnityObject = typeof(UnityObject).IsAssignableFrom(fieldType); if (isUnityObject == false && data == null) { @@ -447,12 +548,12 @@ namespace DCFApixels.DragonECS.Unity.Editors if (isUnityObject) { EditorGUI.BeginChangeCheck(); - var uobj = (UnityEngine.Object)data; + var uobj = (UnityObject)data; - bool isComponent = (typeof(UnityEngine.Component)).IsAssignableFrom(fieldType); + bool isComponent = typeof(UnityComponent).IsAssignableFrom(fieldType); if (isComponent) { - uobj = EditorGUILayout.ObjectField(label, uobj, typeof(UnityEngine.Object), true); + uobj = EditorGUILayout.ObjectField(label, uobj, typeof(UnityObject), true); } else { diff --git a/src/Internal/EscEditorConsts.cs b/src/Internal/EscEditorConsts.cs index 9307e9a..d3a7c88 100644 --- a/src/Internal/EscEditorConsts.cs +++ b/src/Internal/EscEditorConsts.cs @@ -4,5 +4,6 @@ { public const float COMPONENT_DRAWER_ALPHA = 0.26f; public const float COMPONENT_DRAWER_DESATURATE = 0.86f; + public const int AUTO_COLOR_RAINBOW_MIN_RANGE = 7; } } diff --git a/src/Internal/Utils/RectUtility.cs b/src/Internal/Utils/RectUtility.cs index e341fbf..82e033e 100644 --- a/src/Internal/Utils/RectUtility.cs +++ b/src/Internal/Utils/RectUtility.cs @@ -4,7 +4,7 @@ namespace DCFApixels.DragonECS.Unity.Internal { internal static class RectUtility { - public static (Rect, Rect) HorizontalSliceLerp(Rect rect, float t) + public static (Rect, Rect) HorizontalSliceLerp(in this Rect rect, float t) { Rect l = rect; Rect r = rect; @@ -12,7 +12,7 @@ namespace DCFApixels.DragonECS.Unity.Internal r.xMin += rect.width * t; return (l, r); } - public static (Rect, Rect) HorizontalSliceLeft(Rect rect, float with) + public static (Rect, Rect) HorizontalSliceLeft(in this Rect rect, float with) { Rect l = rect; Rect r = rect; @@ -20,7 +20,7 @@ namespace DCFApixels.DragonECS.Unity.Internal r.xMin += with; return (l, r); } - public static (Rect, Rect) HorizontalSliceRight(Rect rect, float with) + public static (Rect, Rect) HorizontalSliceRight(in this Rect rect, float with) { Rect l = rect; Rect r = rect; @@ -29,7 +29,7 @@ namespace DCFApixels.DragonECS.Unity.Internal return (l, r); } - public static (Rect, Rect) VerticalSliceTop(Rect rect, float height) + public static (Rect, Rect) VerticalSliceTop(in this Rect rect, float height) { Rect t = rect; Rect b = rect; @@ -37,7 +37,7 @@ namespace DCFApixels.DragonECS.Unity.Internal b.yMin += height; return (t, b); } - public static (Rect, Rect) VerticalSliceBottom(Rect rect, float height) + public static (Rect, Rect) VerticalSliceBottom(in this Rect rect, float height) { Rect t = rect; Rect b = rect; @@ -46,28 +46,30 @@ namespace DCFApixels.DragonECS.Unity.Internal return (t, b); } - public static Rect AddPadding(Rect rect, float verticalHorizontal) + public static Rect AddPadding(in this Rect rect, float verticalHorizontal) { return AddPadding(rect, verticalHorizontal, verticalHorizontal, verticalHorizontal, verticalHorizontal); } - public static Rect AddPadding(Rect rect, float horizontal, float vertical) + public static Rect AddPadding(in this Rect rect, float horizontal, float vertical) { return AddPadding(rect, horizontal, horizontal, vertical, vertical); } - public static Rect AddPadding(Rect rect, float left, float right, float top, float bottom) + public static Rect AddPadding(in this Rect rect, float left, float right, float top, float bottom) { - rect.xMin += left; - rect.xMax -= right; - rect.yMin += top; - rect.yMax -= bottom; + Rect result = rect; + result.xMin += left; + result.xMax -= right; + result.yMin += top; + result.yMax -= bottom; + return result; + } + public static Rect Move(in this Rect rect, Vector2 addVector) + { + Rect result = rect; + result.center += addVector; return rect; } - public static Rect Move(Rect rect, Vector2 addVector) - { - rect.center += addVector; - return rect; - } - public static Rect Move(Rect rect, float addX, float addY) + public static Rect Move(in this Rect rect, float addX, float addY) { return Move(rect, new Vector2(addX, addY)); }