mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2025-01-06 14:45:06 +08:00
129 lines
4.1 KiB
C#
129 lines
4.1 KiB
C#
#region
|
|
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEditor;
|
|
using UnityEditor.UIElements;
|
|
using UnityEngine.UIElements;
|
|
|
|
#endregion
|
|
|
|
namespace nadena.dev.modular_avatar.core.editor
|
|
{
|
|
public class LogoElement : VisualElement
|
|
{
|
|
private const string LISTENER_REGISTERED = "ma--logo-listener-registered";
|
|
private static WeakHashSet<LogoElement> _activeLogos = new WeakHashSet<LogoElement>();
|
|
|
|
private static Dictionary<VisualElement, LogoElement> _logoDisplayNode
|
|
= null;
|
|
|
|
private VisualElement _inner;
|
|
|
|
public new class UxmlFactory : UxmlFactory<LogoElement, UxmlTraits>
|
|
{
|
|
}
|
|
|
|
public new class UxmlTraits : VisualElement.UxmlTraits
|
|
{
|
|
}
|
|
|
|
private static void RegisterNode(LogoElement target)
|
|
{
|
|
if (_logoDisplayNode == null)
|
|
{
|
|
_logoDisplayNode = new Dictionary<VisualElement, LogoElement>();
|
|
EditorApplication.delayCall += () => { _logoDisplayNode = null; };
|
|
}
|
|
|
|
// [editor list] -> EditorElement (private) -> InspectorElement -> MAVisualElement -> Logo
|
|
VisualElement container = target;
|
|
while (container.parent != null && !(container is InspectorElement))
|
|
{
|
|
container = container.parent;
|
|
}
|
|
|
|
container = container.parent ?? container; // EditorElement
|
|
container = container.parent ?? container; // editor list
|
|
|
|
if (container.ClassListContains(LISTENER_REGISTERED)) return;
|
|
container.RegisterCallback<GeometryChangedEvent>(geom => { UpdateLogoDisplayNode(container); });
|
|
}
|
|
|
|
private static void UpdateLogoDisplayNode(VisualElement root)
|
|
{
|
|
// Now walk down to find the LogoElements. We only walk one level past an InspectorElement (and once into
|
|
// its child MAVisualElement) to avoid descending too deep into madness.
|
|
List<LogoElement> elements = new List<LogoElement>();
|
|
|
|
WalkTree(root);
|
|
|
|
var target = elements.FirstOrDefault(e => e.resolvedStyle.visibility == Visibility.Visible);
|
|
foreach (var elem in elements)
|
|
{
|
|
elem.LogoShown = (elem == target);
|
|
}
|
|
|
|
void WalkTree(VisualElement visualElement)
|
|
{
|
|
if (visualElement.resolvedStyle.visibility == Visibility.Hidden ||
|
|
visualElement.resolvedStyle.height < 0.5) return;
|
|
|
|
var isInspector = visualElement.GetType() == typeof(InspectorElement);
|
|
|
|
foreach (var child in visualElement.Children())
|
|
{
|
|
if (child is MAVisualElement maChild)
|
|
{
|
|
foreach (var node in child.Children())
|
|
{
|
|
if (node is LogoElement logo)
|
|
{
|
|
elements.Add(logo);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
else if (!isInspector)
|
|
{
|
|
WalkTree(child);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public LogoElement()
|
|
{
|
|
_inner = new LogoImage();
|
|
_inner.style.display = DisplayStyle.None;
|
|
this.Add(_inner);
|
|
|
|
RegisterCallback<GeometryChangedEvent>(OnGeomChanged);
|
|
}
|
|
|
|
private void OnGeomChanged(GeometryChangedEvent evt)
|
|
{
|
|
// We should be in the visual tree now
|
|
if (parent == null) return;
|
|
|
|
RegisterNode(this);
|
|
|
|
UnregisterCallback<GeometryChangedEvent>(OnGeomChanged);
|
|
}
|
|
|
|
private bool _logoShown;
|
|
|
|
private bool LogoShown
|
|
{
|
|
get => _logoShown;
|
|
set
|
|
{
|
|
if (value == _logoShown) return;
|
|
_logoShown = value;
|
|
|
|
_inner.style.display = value ? DisplayStyle.Flex : DisplayStyle.None;
|
|
}
|
|
}
|
|
}
|
|
} |