Files
Hasebe/Library/PackageCache/com.annulusgames.alchemy@1402075f473d/Editor/Internal/GUIHelper.cs
T
2026-09-21 12:15:57 +03:00

196 lines
8.0 KiB
C#

using System;
using System.Reflection;
using Alchemy.Inspector;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.UIElements;
namespace Alchemy.Editor
{
internal static class GUIHelper
{
public static Color LineColor => EditorGUIUtility.isProSkin ? new(0.4f, 0.4f, 0.4f) : new(0.6f, 0.6f, 0.6f);
public static Color SubtitleColor => new(0.5f, 0.5f, 0.5f);
public static Color TextColor => EditorGUIUtility.isProSkin ? new(0.725f, 0.725f, 0.725f) : new(0.141f, 0.141f, 0.141f);
public static float CalculateFieldWidth(VisualElement element, VisualElement root)
{
var labelWidth = CalculateLabelWidth(element, root);
return root.resolvedStyle.width - labelWidth - 27f;
}
public static float CalculateLabelWidth(VisualElement element, VisualElement root)
{
// This code is a partial modification of the Label width calculation method actually used inside PropertyField.
var num = root.resolvedStyle.paddingLeft;
var num2 = 37f;
var num3 = 123f;
var num4 = element.GetFirstAncestorOfType<Foldout>() == null ? 0f : 15f;
var width = root.resolvedStyle.width;
var a = width * 0.45f - num2 - num - num4;
var b = Mathf.Max(num3 - num - num4, 0f);
return Mathf.Max(a, b) + 12f;
}
public static ListView CreateDefaultListView(string label)
{
return new ListView()
{
reorderable = true,
reorderMode = ListViewReorderMode.Animated,
showBorder = true,
showFoldoutHeader = true,
headerTitle = label,
showAddRemoveFooter = true,
fixedItemHeight = 20f,
virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight,
showAlternatingRowBackgrounds = AlternatingRowBackground.None,
};
}
public static ListView CreateListViewFromFieldInfo(object target, FieldInfo fieldInfo)
{
var settings = fieldInfo.GetCustomAttribute<ListViewSettingsAttribute>();
var listView = new ListView
{
reorderable = settings == null ? true : settings.Reorderable,
reorderMode = settings == null ? ListViewReorderMode.Animated : settings.ReorderMode,
showBorder = settings == null ? true : settings.ShowBorder,
showFoldoutHeader = settings == null ? true : settings.ShowFoldoutHeader,
showBoundCollectionSize = settings == null ? true : (settings.ShowFoldoutHeader && settings.ShowBoundCollectionSize),
selectionType = settings == null ? SelectionType.Multiple : settings.SelectionType,
showAddRemoveFooter = settings == null ? true : settings.ShowAddRemoveFooter,
fixedItemHeight = 20f,
virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight,
showAlternatingRowBackgrounds = settings == null ? AlternatingRowBackground.None : settings.ShowAlternatingRowBackgrounds,
};
var events = fieldInfo.GetCustomAttribute<OnListViewChangedAttribute>();
if (events != null)
{
listView.itemsAdded += indices =>
{
if (events.OnItemsAdded == null) return;
ReflectionHelper.Invoke(target, events.OnItemsAdded, new object[] { indices });
};
listView.itemsRemoved += indices =>
{
if (events.OnItemsRemoved == null) return;
ReflectionHelper.Invoke(target, events.OnItemsRemoved, new object[] { indices });
};
#if UNITY_2022_1_OR_NEWER
listView.itemsChosen += items =>
{
if (events.OnItemsChosen == null) return;
ReflectionHelper.Invoke(target, events.OnItemsChosen, new object[] { items });
};
#else
listView.onItemsChosen += items =>
{
if (events.OnItemsChosen == null) return;
ReflectionHelper.Invoke(target, events.OnItemsChosen, new object[] { items });
};
#endif
listView.itemIndexChanged += (before, after) =>
{
if (events.OnItemIndexChanged == null) return;
ReflectionHelper.Invoke(target, events.OnItemIndexChanged, new object[] { before, after });
};
#if UNITY_2022_1_OR_NEWER
listView.selectionChanged += items =>
{
if (events.OnSelectionChanged == null) return;
ReflectionHelper.Invoke(target, events.OnSelectionChanged, new object[] { items });
};
listView.selectedIndicesChanged += indices =>
{
if (events.OnSelectedIndicesChanged == null) return;
ReflectionHelper.Invoke(target, events.OnSelectedIndicesChanged, new object[] { indices });
};
#else
listView.onSelectionChange += items =>
{
if (events.OnSelectionChanged == null) return;
ReflectionHelper.Invoke(target, events.OnSelectionChanged, new object[] { items });
};
listView.onSelectedIndicesChange += indices =>
{
if (events.OnSelectedIndicesChanged== null) return;
ReflectionHelper.Invoke(target, events.OnSelectedIndicesChanged, new object[] { indices });
};
#endif
listView.itemsSourceChanged += () =>
{
if (events.OnItemsSourceChanged == null) return;
ReflectionHelper.Invoke(target, events.OnItemsSourceChanged, null);
};
}
return listView;
}
public static PropertyField CreateObjectPropertyField(SerializedProperty property, Type type)
{
Assert.IsTrue(property.propertyType == SerializedPropertyType.ObjectReference);
var fieldInfo = property.GetFieldInfo();
var isAssetsOnly = fieldInfo.HasCustomAttribute<AssetsOnlyAttribute>();
var propertyField = new PropertyField(property);
propertyField.RegisterValueChangeCallback(x =>
{
var objectField = propertyField.Q<ObjectField>();
if (objectField == null) return;
objectField.objectType = type;
objectField.allowSceneObjects = !isAssetsOnly;
});
return propertyField;
}
public static void ScheduleAdjustLabelWidth(VisualElement element)
{
void Adjust(VisualElement visualElement)
{
var label = element.Q<Label>();
if (label == null) return;
label.style.minWidth = 0f;
label.style.width = CalculateLabelWidth(element, visualElement);
}
// Adjust label width
element.schedule.Execute(() =>
{
var visualTree = element.panel.visualTree;
visualTree.RegisterCallback<GeometryChangedEvent>(x => Adjust(visualTree));
Adjust(visualTree);
});
}
public static IMGUIContainer CreateLine(Color color, float height)
{
return new IMGUIContainer(() =>
{
var rect = EditorGUILayout.GetControlRect(false, height);
rect.xMin += 3f;
rect.y += rect.height * 0.5f;
rect.height = 1f;
EditorGUI.DrawRect(rect, color);
});
}
public static void SetMinAndCurrentWidth(VisualElement visualElement, float value)
{
visualElement.style.minWidth = value;
visualElement.style.width = value;
}
}
}