Files
TheVVaS-Assets/RPGCoreCommon/Helpers/Runtime/VisualElementExtensions.cs
T
2026-04-25 23:37:10 +02:00

146 lines
6.1 KiB
C#

using System;
using System.Linq;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace RPGCoreCommon.Helpers
{
public static class VisualElementExtensions
{
public static void Click(this VisualElement visualElement)
{
using var clickEvent = ClickEvent.GetPooled();
clickEvent.target = visualElement;
visualElement.panel.visualTree.SendEvent(clickEvent);
if (visualElement is not Button button) return;
using var ev = new NavigationSubmitEvent();
ev.target = button;
button.SendEvent(ev);
}
public static void DisableDefaultAligning(this VisualElement visualElement)
{
const string class1 = "unity-base-field__inspector-field";
const string class2 = "unity-base-field__aligned";
visualElement.RegisterCallback<GeometryChangedEvent>(_ =>
{
visualElement.Query(className: class1).ForEach(el => el.RemoveFromClassList(class1));
visualElement.Query(className: class2).ForEach(el => el.RemoveFromClassList(class2));
}, TrickleDown.TrickleDown);
}
public static void SetContextAligningHere(this VisualElement visualElement)
{
visualElement.AddToClassList("unity-inspector-element");
visualElement.AddToClassList("unity-inspector-main-container");
}
/// <summary>
/// Only for <see cref="PropertyField"/> that has array element as <see cref="SerializedProperty"/>.
/// By default, those <see cref="PropertyField"/>s always draw inside <see cref="Foldout"/>.
/// When this function is called only content of foldout will be displayed (foldout will be hidden).
/// </summary>
/// <param name="propertyField">Property field that will draw array element</param>
public static void HideFoldoutAndLabel(this PropertyField propertyField)
{
propertyField.RegisterCallback<GeometryChangedEvent>(_ =>
{
propertyField.label = "";
if (propertyField.Q<Foldout>(name: "unity-foldout-" + propertyField.bindingPath) is {} foldout2)
{
foldout2.Q<Toggle>().style.display = DisplayStyle.None;
foldout2.Q<Toggle>().value = true;
foldout2.Q(name: "unity-content").style.marginLeft = 0;
}
else if (propertyField.Q<Label>(name: "unity-input-" + propertyField.bindingPath) is {} label)
{
label.style.display = DisplayStyle.None;
}
});
}
public static void RemoveFoldoutAndLabel(this PropertyField propertyField)
{
propertyField.RegisterCallback<GeometryChangedEvent>(_ =>
{
if (propertyField.Q<Foldout>(name: "unity-foldout-" + propertyField.bindingPath) is {} foldout)
{
var children = foldout.Q(name: "unity-content").Children().ToList();
children.ForEach(propertyField.Add);
foldout.RemoveFromHierarchy();
}
else if (propertyField.Q<Label>(name: "unity-input-" + propertyField.bindingPath) is {} label)
{
label.RemoveFromHierarchy();
}
});
}
public static void FadeOut(this VisualElement visualElement, float delay, float duration, bool remove)
{
if (visualElement.panel != null)
FadeOutPrivate(visualElement, delay, duration, remove);
else
visualElement.RegisterCallback<AttachToPanelEvent>(_ => FadeOutPrivate(visualElement, delay, duration, remove));
}
private static void FadeOutPrivate(VisualElement visualElement, float delayMs, float durationMs, bool remove)
{
const int waitMs = 50;
visualElement.style.opacity = 1f;
visualElement.schedule
.Execute(_ =>
{
visualElement.style.opacity = visualElement.style.opacity.value - waitMs / durationMs;
if (visualElement.style.opacity.value > 0f) return;
visualElement.style.opacity = 0f;
if (remove) visualElement.RemoveFromHierarchy();
})
.Every(waitMs)
.Until(() => visualElement.style.opacity.value <= 0f)
.ExecuteLater(Convert.ToInt64(delayMs));
}
public static void RemoveOnClick(this VisualElement visualElement, float delayMs = 0f, float durationMs = 250f)
{
visualElement.RegisterCallback<ClickEvent>(_ => FadeOutPrivate(visualElement, delayMs, durationMs, true));
}
public static void InsertBefore(this VisualElement thisElement, VisualElement otherElement)
{
var index = thisElement.parent.IndexOf(thisElement);
thisElement.parent.Insert(index, otherElement);
}
public static void InsertAfter(this VisualElement thisElement, VisualElement otherElement)
{
var index = thisElement.parent.IndexOf(thisElement);
if (index == thisElement.parent.childCount-1)
thisElement.parent.Add(otherElement);
else
thisElement.parent.Insert(index, otherElement);
}
public static bool IsAncestorOf(this VisualElement thisElement, VisualElement otherElement)
{
if (thisElement == null || otherElement == null) return false;
var ancestor = otherElement.parent;
while (ancestor != null)
{
if (ancestor == thisElement) return true;
ancestor = ancestor.parent;
}
return false;
}
public static bool IsDescendantOf(this VisualElement thisElement, VisualElement otherElement)
{
return otherElement.IsAncestorOf(thisElement);
}
}
}