2024-03-07 03:18:00 +08:00
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
|
using DCFApixels.DragonECS.Unity.Internal;
|
2024-03-03 03:51:49 +08:00
|
|
|
|
using System;
|
|
|
|
|
using System.Reflection;
|
2024-03-07 03:18:00 +08:00
|
|
|
|
using UnityEditor;
|
|
|
|
|
using UnityEngine;
|
2024-03-03 03:51:49 +08:00
|
|
|
|
|
|
|
|
|
namespace DCFApixels.DragonECS.Unity.Editors
|
|
|
|
|
{
|
2024-03-11 08:23:51 +08:00
|
|
|
|
internal abstract class EntityTemplateEditorBase : Editor
|
2024-03-03 03:51:49 +08:00
|
|
|
|
{
|
2024-05-16 19:03:03 +08:00
|
|
|
|
private static readonly Rect HeadIconsRect = new Rect(0f, 0f, 19f, 19f);
|
2024-03-03 03:51:49 +08:00
|
|
|
|
|
2024-03-07 21:22:48 +08:00
|
|
|
|
private GenericMenu _genericMenu;
|
2024-03-03 03:51:49 +08:00
|
|
|
|
private bool _isInit = false;
|
|
|
|
|
|
2024-05-15 00:49:28 +08:00
|
|
|
|
private static ComponentColorMode AutoColorMode
|
2024-05-15 00:36:56 +08:00
|
|
|
|
{
|
2024-05-15 00:49:28 +08:00
|
|
|
|
get { return SettingsPrefs.instance.ComponentColorMode; }
|
|
|
|
|
set { SettingsPrefs.instance.ComponentColorMode = value; }
|
2024-05-15 00:36:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-03 03:51:49 +08:00
|
|
|
|
#region Init
|
|
|
|
|
private void Init()
|
|
|
|
|
{
|
2024-03-07 21:22:48 +08:00
|
|
|
|
if (_genericMenu == null) { _isInit = false; }
|
2024-03-07 03:18:00 +08:00
|
|
|
|
if (_isInit) { return; }
|
2024-03-03 03:51:49 +08:00
|
|
|
|
|
2024-03-07 21:22:48 +08:00
|
|
|
|
_genericMenu = new GenericMenu();
|
2024-03-03 03:51:49 +08:00
|
|
|
|
|
2024-03-06 23:29:54 +08:00
|
|
|
|
var componentTemplateDummies = ComponentTemplateTypeCache.Dummies;
|
|
|
|
|
foreach (var dummy in componentTemplateDummies)
|
2024-03-03 03:51:49 +08:00
|
|
|
|
{
|
2024-05-15 00:36:56 +08:00
|
|
|
|
if (dummy.Type.GetCustomAttribute<SerializableAttribute>() == null)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogWarning($"Type {dummy.Type.Name} does not have the [Serializable] attribute");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2024-03-06 23:29:54 +08:00
|
|
|
|
ITypeMeta meta = dummy is ITypeMeta metaOverride ? metaOverride : dummy.Type.ToMeta();
|
|
|
|
|
string name = meta.Name;
|
2024-05-01 15:02:54 +08:00
|
|
|
|
string description = meta.Description.Text;
|
2024-03-06 23:29:54 +08:00
|
|
|
|
MetaGroup group = meta.Group;
|
|
|
|
|
|
2024-03-07 03:18:00 +08:00
|
|
|
|
if (group.Name.Length > 0)
|
2024-03-06 23:29:54 +08:00
|
|
|
|
{
|
|
|
|
|
name = group.Name + name;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-03 03:51:49 +08:00
|
|
|
|
if (string.IsNullOrEmpty(description) == false)
|
|
|
|
|
{
|
2024-03-10 23:34:00 +08:00
|
|
|
|
name = $"{name} [i]";
|
2024-03-03 03:51:49 +08:00
|
|
|
|
}
|
2024-03-07 21:22:48 +08:00
|
|
|
|
_genericMenu.AddItem(new GUIContent(name, description), false, OnAddComponent, dummy);
|
2024-03-03 03:51:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_isInit = true;
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Add/Remove
|
|
|
|
|
private void OnAddComponent(object obj)
|
|
|
|
|
{
|
|
|
|
|
Type componentType = obj.GetType();
|
|
|
|
|
if (this.target is ITemplateInternal target)
|
|
|
|
|
{
|
|
|
|
|
SerializedProperty componentsProp = serializedObject.FindProperty(target.ComponentsPropertyName);
|
|
|
|
|
for (int i = 0; i < componentsProp.arraySize; i++)
|
|
|
|
|
{
|
|
|
|
|
if (componentsProp.GetArrayElementAtIndex(i).managedReferenceValue.GetType() == componentType)
|
2024-03-06 21:37:21 +08:00
|
|
|
|
{
|
2024-03-03 03:51:49 +08:00
|
|
|
|
return;
|
2024-03-06 21:37:21 +08:00
|
|
|
|
}
|
2024-03-03 03:51:49 +08:00
|
|
|
|
}
|
2024-05-19 23:02:00 +08:00
|
|
|
|
int index = componentsProp.arraySize;
|
|
|
|
|
componentsProp.InsertArrayElementAtIndex(index);
|
|
|
|
|
componentsProp.GetArrayElementAtIndex(index).managedReferenceValue = ((IComponentTemplate)obj).Clone();
|
2024-03-03 03:51:49 +08:00
|
|
|
|
|
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
|
|
|
EditorUtility.SetDirty(this.target);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private void OnRemoveComponentAt(int index)
|
|
|
|
|
{
|
|
|
|
|
if (this.target is ITemplateInternal target)
|
|
|
|
|
{
|
|
|
|
|
SerializedProperty componentsProp = serializedObject.FindProperty(target.ComponentsPropertyName);
|
|
|
|
|
componentsProp.DeleteArrayElementAtIndex(index);
|
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
|
|
|
EditorUtility.SetDirty(this.target);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
protected void Draw(ITemplateInternal target)
|
|
|
|
|
{
|
|
|
|
|
Init();
|
|
|
|
|
SerializedProperty componentsProp = serializedObject.FindProperty(target.ComponentsPropertyName);
|
|
|
|
|
if (componentsProp == null)
|
2024-03-05 00:46:47 +08:00
|
|
|
|
{
|
2024-03-03 03:51:49 +08:00
|
|
|
|
return;
|
2024-03-05 00:46:47 +08:00
|
|
|
|
}
|
2024-03-03 03:51:49 +08:00
|
|
|
|
|
2024-03-07 03:18:00 +08:00
|
|
|
|
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f));
|
2024-03-09 03:35:01 +08:00
|
|
|
|
DrawTop(target);
|
2024-03-06 21:37:21 +08:00
|
|
|
|
GUILayout.Label("", GUILayout.Height(0), GUILayout.ExpandWidth(true));
|
2024-05-19 23:02:00 +08:00
|
|
|
|
for (int i = componentsProp.arraySize - 1; i >= 0; i--)
|
2024-03-03 03:51:49 +08:00
|
|
|
|
{
|
2024-05-15 00:36:56 +08:00
|
|
|
|
DrawComponentData(componentsProp.GetArrayElementAtIndex(i), componentsProp.arraySize, i);
|
2024-03-03 03:51:49 +08:00
|
|
|
|
}
|
2024-05-19 23:02:00 +08:00
|
|
|
|
|
2024-03-04 07:38:38 +08:00
|
|
|
|
GUILayout.EndVertical();
|
2024-03-03 03:51:49 +08:00
|
|
|
|
}
|
|
|
|
|
private void DrawTop(ITemplateInternal target)
|
|
|
|
|
{
|
2024-03-09 03:35:01 +08:00
|
|
|
|
switch (EcsGUI.Layout.AddClearComponentButtons())
|
2024-03-03 03:51:49 +08:00
|
|
|
|
{
|
2024-03-09 03:35:01 +08:00
|
|
|
|
case EcsGUI.AddClearComponentButton.AddComponent:
|
|
|
|
|
Init();
|
|
|
|
|
_genericMenu.ShowAsContext();
|
|
|
|
|
break;
|
|
|
|
|
case EcsGUI.AddClearComponentButton.Clear:
|
|
|
|
|
Init();
|
|
|
|
|
serializedObject.FindProperty(target.ComponentsPropertyName).ClearArray();
|
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
|
|
|
break;
|
2024-03-03 03:51:49 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-03-09 03:35:01 +08:00
|
|
|
|
|
2024-05-15 00:36:56 +08:00
|
|
|
|
private void DrawComponentData(SerializedProperty componentRefProp, int total, int index)
|
2024-03-03 03:51:49 +08:00
|
|
|
|
{
|
|
|
|
|
IComponentTemplate template = componentRefProp.managedReferenceValue as IComponentTemplate;
|
2024-03-09 03:35:01 +08:00
|
|
|
|
if (template == null || componentRefProp.managedReferenceValue == null)
|
2024-03-03 03:51:49 +08:00
|
|
|
|
{
|
2024-05-15 00:36:56 +08:00
|
|
|
|
DrawDamagedComponent_Replaced(componentRefProp, index);
|
2024-03-03 03:51:49 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Type componentType;
|
|
|
|
|
SerializedProperty componentProperty = componentRefProp;
|
2024-05-15 00:36:56 +08:00
|
|
|
|
try
|
2024-03-03 03:51:49 +08:00
|
|
|
|
{
|
2024-05-15 00:36:56 +08:00
|
|
|
|
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();
|
|
|
|
|
}
|
2024-03-03 03:51:49 +08:00
|
|
|
|
}
|
2024-05-15 00:36:56 +08:00
|
|
|
|
catch (Exception e)
|
2024-03-03 03:51:49 +08:00
|
|
|
|
{
|
2024-05-15 00:36:56 +08:00
|
|
|
|
Debug.LogException(e, serializedObject.targetObject);
|
|
|
|
|
DrawDamagedComponent(index, "Damaged component template.");
|
|
|
|
|
return;
|
2024-03-03 03:51:49 +08:00
|
|
|
|
}
|
2024-03-07 03:18:00 +08:00
|
|
|
|
|
2024-05-15 00:36:56 +08:00
|
|
|
|
|
|
|
|
|
//сюда попадают уже валидные компоненты
|
|
|
|
|
|
|
|
|
|
|
2024-03-06 23:29:54 +08:00
|
|
|
|
ITypeMeta meta = template is ITypeMeta metaOverride ? metaOverride : template.Type.ToMeta();
|
|
|
|
|
string name = meta.Name;
|
2024-05-01 15:02:54 +08:00
|
|
|
|
string description = meta.Description.Text;
|
2024-03-03 03:51:49 +08:00
|
|
|
|
|
2024-05-16 19:03:03 +08:00
|
|
|
|
int propCount = EcsGUI.GetChildPropertiesCount(componentProperty, componentType, out bool isEmpty);
|
|
|
|
|
|
2024-03-05 00:46:47 +08:00
|
|
|
|
float padding = EditorGUIUtility.standardVerticalSpacing;
|
2024-05-15 00:36:56 +08:00
|
|
|
|
|
2024-05-16 19:03:03 +08:00
|
|
|
|
Color panelColor = EcsGUI.SelectPanelColor(meta, index, total).Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE);
|
2024-05-15 00:36:56 +08:00
|
|
|
|
|
2024-03-05 00:46:47 +08:00
|
|
|
|
Color alphaPanelColor = panelColor;
|
|
|
|
|
alphaPanelColor.a = EscEditorConsts.COMPONENT_DRAWER_ALPHA;
|
|
|
|
|
|
2024-03-07 21:22:48 +08:00
|
|
|
|
Rect removeButtonRect = GUILayoutUtility.GetLastRect();
|
|
|
|
|
|
2024-03-06 21:37:21 +08:00
|
|
|
|
EditorGUI.BeginChangeCheck();
|
2024-03-07 03:18:00 +08:00
|
|
|
|
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(alphaPanelColor));
|
2024-03-05 00:46:47 +08:00
|
|
|
|
|
|
|
|
|
#region Draw Component Block
|
2024-03-06 21:37:21 +08:00
|
|
|
|
removeButtonRect.yMin = removeButtonRect.yMax;
|
2024-05-16 19:03:03 +08:00
|
|
|
|
removeButtonRect.yMax += HeadIconsRect.height;
|
|
|
|
|
removeButtonRect.xMin = removeButtonRect.xMax - HeadIconsRect.width;
|
2024-03-06 21:37:21 +08:00
|
|
|
|
removeButtonRect.center += Vector2.up * padding * 2f;
|
2024-03-09 09:42:04 +08:00
|
|
|
|
|
2024-05-15 00:36:56 +08:00
|
|
|
|
bool isRemoveComponent = EcsGUI.CloseButton(removeButtonRect);
|
2024-03-05 03:35:38 +08:00
|
|
|
|
|
2024-05-15 00:36:56 +08:00
|
|
|
|
if (propCount <= 0)
|
2024-03-03 03:51:49 +08:00
|
|
|
|
{
|
2024-05-16 23:27:45 +08:00
|
|
|
|
EcsGUI.Layout.DrawEmptyComponentProperty(componentRefProp, name, isEmpty);
|
2024-03-03 03:51:49 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-05-04 01:43:39 +08:00
|
|
|
|
GUIContent label = UnityEditorUtility.GetLabel(name);
|
2024-05-13 18:21:51 +08:00
|
|
|
|
if (componentProperty.propertyType == SerializedPropertyType.Generic)
|
2024-05-05 00:59:26 +08:00
|
|
|
|
{
|
|
|
|
|
EditorGUILayout.PropertyField(componentProperty, label, true);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Rect r = RectUtility.AddPadding(GUILayoutUtility.GetRect(label, EditorStyles.objectField), 0, 20f, 0, 0);
|
|
|
|
|
EditorGUI.PropertyField(r, componentProperty, label, true);
|
|
|
|
|
}
|
2024-03-03 03:51:49 +08:00
|
|
|
|
}
|
2024-03-05 03:35:38 +08:00
|
|
|
|
if (isRemoveComponent)
|
2024-03-03 19:59:39 +08:00
|
|
|
|
{
|
2024-03-03 03:51:49 +08:00
|
|
|
|
OnRemoveComponentAt(index);
|
2024-03-03 19:59:39 +08:00
|
|
|
|
}
|
2024-03-07 03:18:00 +08:00
|
|
|
|
if (string.IsNullOrEmpty(description) == false)
|
2024-03-03 03:51:49 +08:00
|
|
|
|
{
|
2024-05-16 19:03:03 +08:00
|
|
|
|
Rect tooltipIconRect = HeadIconsRect;
|
2024-03-06 21:37:21 +08:00
|
|
|
|
tooltipIconRect.center = removeButtonRect.center;
|
|
|
|
|
tooltipIconRect.center -= Vector2.right * tooltipIconRect.width;
|
2024-03-09 09:42:04 +08:00
|
|
|
|
EcsGUI.DescriptionIcon(tooltipIconRect, description);
|
2024-03-03 03:51:49 +08:00
|
|
|
|
}
|
2024-03-06 21:37:21 +08:00
|
|
|
|
#endregion
|
2024-03-05 00:46:47 +08:00
|
|
|
|
|
2024-03-06 21:37:21 +08:00
|
|
|
|
GUILayout.EndVertical();
|
2024-03-09 09:42:04 +08:00
|
|
|
|
|
2024-03-05 00:46:47 +08:00
|
|
|
|
if (EditorGUI.EndChangeCheck())
|
|
|
|
|
{
|
|
|
|
|
componentProperty.serializedObject.ApplyModifiedProperties();
|
2024-03-06 21:37:21 +08:00
|
|
|
|
EditorUtility.SetDirty(componentProperty.serializedObject.targetObject);
|
2024-03-05 00:46:47 +08:00
|
|
|
|
}
|
2024-03-03 03:51:49 +08:00
|
|
|
|
}
|
2024-05-15 00:36:56 +08:00
|
|
|
|
private void DrawDamagedComponent_Replaced(SerializedProperty componentRefProp, int index)
|
2024-03-03 03:51:49 +08:00
|
|
|
|
{
|
2024-05-15 00:36:56 +08:00
|
|
|
|
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();
|
|
|
|
|
|
2024-03-03 03:51:49 +08:00
|
|
|
|
GUILayout.BeginHorizontal();
|
|
|
|
|
|
2024-05-15 00:36:56 +08:00
|
|
|
|
float padding = EditorGUIUtility.standardVerticalSpacing;
|
|
|
|
|
|
|
|
|
|
removeButtonRect.yMin = removeButtonRect.yMax;
|
2024-05-16 19:03:03 +08:00
|
|
|
|
removeButtonRect.yMax += HeadIconsRect.height;
|
|
|
|
|
removeButtonRect.xMin = removeButtonRect.xMax - HeadIconsRect.width;
|
2024-05-15 00:36:56 +08:00
|
|
|
|
removeButtonRect.center += Vector2.up * padding * 2f;
|
|
|
|
|
|
|
|
|
|
bool isRemoveComponent = EcsGUI.CloseButton(removeButtonRect);
|
2024-03-03 03:51:49 +08:00
|
|
|
|
|
2024-05-15 00:36:56 +08:00
|
|
|
|
EditorGUILayout.HelpBox(message, MessageType.Warning);
|
2024-03-03 03:51:49 +08:00
|
|
|
|
|
2024-05-15 00:36:56 +08:00
|
|
|
|
if (isRemoveComponent)
|
2024-03-06 21:37:21 +08:00
|
|
|
|
{
|
2024-03-03 03:51:49 +08:00
|
|
|
|
OnRemoveComponentAt(index);
|
2024-03-06 21:37:21 +08:00
|
|
|
|
}
|
2024-03-03 03:51:49 +08:00
|
|
|
|
|
|
|
|
|
GUILayout.EndHorizontal();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[CustomEditor(typeof(ScriptableEntityTemplate), true)]
|
2024-03-11 08:23:51 +08:00
|
|
|
|
internal class EntityTemplatePresetEditor : EntityTemplateEditorBase
|
2024-03-03 03:51:49 +08:00
|
|
|
|
{
|
|
|
|
|
public override void OnInspectorGUI()
|
|
|
|
|
{
|
|
|
|
|
Draw((ITemplateInternal)target);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
[CustomEditor(typeof(MonoEntityTemplate), true)]
|
2024-03-11 08:23:51 +08:00
|
|
|
|
internal class EntityTemplateEditor : EntityTemplateEditorBase
|
2024-03-03 03:51:49 +08:00
|
|
|
|
{
|
|
|
|
|
public override void OnInspectorGUI()
|
|
|
|
|
{
|
|
|
|
|
Draw((ITemplateInternal)target);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|