Net-Game/Library/PackageCache/com.unity.2d.animation@494a3b4e73a9/Editor/SpriteLib/SpriteSwapOverlay/SpriteSwapOverlay.cs
2025-03-28 08:33:16 -04:00

353 lines
12 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.Overlays;
using UnityEngine;
using UnityEngine.U2D.Animation;
using UnityEngine.UIElements;
namespace UnityEditor.U2D.Animation.SceneOverlays
{
internal interface INavigableElement
{
public event Action<int> onSelectionChange;
int itemCount { get; }
int selectedIndex { get; }
public void Select(int index);
void SetItems(IList items);
object GetItem(int index);
VisualElement visualElement { get; }
}
internal enum PropertyAnimationState
{
NotAnimated,
Animated,
Candidate,
Recording
}
[Overlay(typeof(SceneView), overlayId, k_DefaultName,
defaultDisplay = k_DefaultVisibility,
defaultDockZone = DockZone.RightColumn,
defaultDockPosition = DockPosition.Bottom,
defaultLayout = Overlays.Layout.Panel,
defaultWidth = k_DefaultWidth + k_WidthPadding,
defaultHeight = k_DefaultHeight + k_HeightPadding)]
[Icon("Packages/com.unity.2d.animation/Editor/Assets/ComponentIcons/Animation.SpriteResolver.png")]
internal class SpriteSwapOverlay : Overlay
{
public static class Settings
{
public const float minThumbnailSize = 20.0f + k_ThumbnailPadding;
public const float maxThumbnailSize = 110.0f + k_ThumbnailPadding;
public const float defaultThumbnailSize = 50.0f + k_ThumbnailPadding;
const float k_ThumbnailPadding = 8.0f;
const string k_FilterKey = UserSettings.kSettingsUniqueKey + "SpriteSwapOverlay.filter";
const string k_LockKey = UserSettings.kSettingsUniqueKey + "SpriteSwapOverlay.lock";
const string k_ThumbnailSizeKey = UserSettings.kSettingsUniqueKey + "SpriteSwapOverlay.thumbnailSize";
const string k_PreferredWidthKey = UserSettings.kSettingsUniqueKey + "SpriteSwapOverlay.preferredWidth";
const string k_PreferredHeightKey = UserSettings.kSettingsUniqueKey + "SpriteSwapOverlay.preferredHeight";
public static bool filter
{
get => EditorPrefs.GetBool(k_FilterKey, false);
set => EditorPrefs.SetBool(k_FilterKey, value);
}
public static bool locked
{
get => EditorPrefs.GetBool(k_LockKey, false);
set => EditorPrefs.SetBool(k_LockKey, value);
}
public static float thumbnailSize
{
get => EditorPrefs.GetFloat(k_ThumbnailSizeKey, defaultThumbnailSize);
set => EditorPrefs.SetFloat(k_ThumbnailSizeKey, Mathf.Clamp(value, minThumbnailSize, maxThumbnailSize));
}
public static float preferredWidth
{
get => EditorPrefs.GetFloat(k_PreferredWidthKey, k_DefaultWidth);
set => EditorPrefs.SetFloat(k_PreferredWidthKey, value);
}
public static float preferredHeight
{
get => EditorPrefs.GetFloat(k_PreferredHeightKey, k_DefaultHeight);
set => EditorPrefs.SetFloat(k_PreferredHeightKey, value);
}
}
public const string overlayId = "Scene View/Sprite Swap";
public const string rootStyle = "sprite-swap-overlay";
const float k_DefaultWidth = 230.0f;
const float k_DefaultHeight = 133.0f;
const float k_WidthPadding = 6.0f;
const float k_HeightPadding = 19.0f;
const bool k_DefaultVisibility = false;
const string k_DefaultName = "Sprite Swap";
public SpriteSwapVisualElement mainVisualElement => m_MainVisualElement;
internal SpriteResolver[] selection => m_Selection;
bool isViewInitialized => m_MainVisualElement != null;
SpriteResolver[] m_Selection = Array.Empty<SpriteResolver>();
SpriteSwapVisualElement m_MainVisualElement;
public SpriteSwapOverlay()
{
minSize = new Vector2(k_DefaultWidth + k_WidthPadding, k_DefaultHeight + k_HeightPadding);
maxSize = new Vector2(k_DefaultWidth * 10.0f + k_WidthPadding, k_DefaultHeight * 10.0f + k_HeightPadding);
}
public override VisualElement CreatePanelContent()
{
var overlayElement = new SpriteSwapVisualElement { style = { width = Settings.preferredWidth, height = Settings.preferredHeight } };
var toolbar = overlayElement.Q<OverlayToolbar>();
toolbar.onFilterToggled += OnFilterToggled;
toolbar.onLockToggled += OnLockToggled;
toolbar.onResetSliderValue += OnResetThumbnailSize;
toolbar.onSliderValueChanged += OnChangeThumbnailSize;
overlayElement.RegisterCallback<AttachToPanelEvent>(OnAttachToPanel);
overlayElement.RegisterCallback<DetachFromPanelEvent>(OnDetachFromPanel);
overlayElement.styleSheets.Add(ResourceLoader.Load<StyleSheet>("SpriteSwap/SpriteSwapOverlay.uss"));
return overlayElement;
}
public override void OnCreated()
{
base.OnCreated();
EditorApplication.hierarchyChanged += OnHierarchyChanged;
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
Selection.selectionChanged += OnSelectionChanged;
SceneView.duringSceneGui += OnSceneGUI;
UpdateSelection(true);
}
public override void OnWillBeDestroyed()
{
EditorApplication.hierarchyChanged -= OnHierarchyChanged;
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
Selection.selectionChanged -= OnSelectionChanged;
SceneView.duringSceneGui -= OnSceneGUI;
base.OnWillBeDestroyed();
}
void OnSceneGUI(SceneView sceneView)
{
if (containerWindow != sceneView || m_MainVisualElement == null)
return;
m_MainVisualElement.OnSceneGUI();
}
internal void OnSelectionChanged()
{
UpdateSelection();
}
void OnHierarchyChanged()
{
var needUpdate = false;
foreach (var spriteResolver in m_Selection)
{
if (spriteResolver == null)
{
needUpdate = true;
break;
}
}
UpdateSelection(needUpdate);
}
void OnPlayModeStateChanged(PlayModeStateChange newState)
{
if (newState is PlayModeStateChange.EnteredEditMode)
UpdateSelection(true);
}
void OnAttachToPanel(AttachToPanelEvent evt)
{
var element = (SpriteSwapVisualElement)evt.target;
if (element != null)
{
m_MainVisualElement = element;
m_MainVisualElement.parent.RegisterCallback<GeometryChangedEvent>(OnParentGeometryChanged);
if (collapsed || isInToolbar)
{
m_MainVisualElement.style.width = m_MainVisualElement.style.maxWidth = Settings.preferredWidth;
m_MainVisualElement.style.height = m_MainVisualElement.style.maxHeight = Settings.preferredHeight;
}
UpdateResolverList();
}
}
void OnDetachFromPanel(DetachFromPanelEvent evt)
{
var element = (SpriteSwapVisualElement)evt.currentTarget;
if (element == m_MainVisualElement)
m_MainVisualElement = null;
}
void OnParentGeometryChanged(GeometryChangedEvent evt)
{
if (m_MainVisualElement == null)
return;
if (!isInToolbar && !collapsed)
{
Settings.preferredWidth = evt.newRect.width;
Settings.preferredHeight = evt.newRect.height;
}
m_MainVisualElement.style.width = evt.newRect.width;
}
void OnFilterToggled(bool filter)
{
if (Settings.filter == filter)
return;
Settings.filter = filter;
if (!isViewInitialized)
return;
UpdateResolverList();
}
void OnLockToggled(bool locked)
{
if (Settings.locked == locked)
return;
Settings.locked = locked;
if (!locked)
UpdateSelection();
}
void OnChangeThumbnailSize(float newSize)
{
if (Math.Abs(Settings.thumbnailSize - newSize) < 0.01f)
return;
Settings.thumbnailSize = newSize;
RefreshResolverList();
}
void OnResetThumbnailSize()
{
if (Math.Abs(Settings.thumbnailSize - Settings.defaultThumbnailSize) < 0.01f)
return;
Settings.thumbnailSize = Settings.defaultThumbnailSize;
RefreshResolverList();
}
void UpdateSelection(bool force = false)
{
if (Settings.locked && !force)
return;
var gameObjects = Selection.gameObjects.Where(go => go.activeInHierarchy).ToArray();
m_Selection = GetSelectedSpriteResolvers(gameObjects);
UpdateResolverList();
}
void UpdateResolverList()
{
if (!isViewInitialized)
return;
var filtered = false;
var filteredSelection = Settings.filter ? FilterSelection(out filtered) : selection;
m_MainVisualElement.SetSpriteResolvers(filteredSelection);
m_MainVisualElement.SetFiltered(filtered);
}
void RefreshResolverList()
{
if (!isViewInitialized)
return;
m_MainVisualElement.RefreshSpriteResolvers();
}
SpriteResolver[] FilterSelection(out bool filtered)
{
filtered = false;
var filteredSelection = new List<SpriteResolver>();
if (selection != null)
{
for (var i = 0; i < selection.Length; i++)
{
var spriteResolver = selection[i];
var spriteLibrary = spriteResolver.spriteLibrary;
if (spriteLibrary == null)
{
filtered = true;
continue;
}
var selectedCategory = spriteResolver.GetCategory();
if (string.IsNullOrEmpty(selectedCategory))
{
filtered = true;
continue;
}
var labelNames = spriteLibrary.GetEntryNames(selectedCategory);
if (labelNames != null && labelNames.Count() > 1)
filteredSelection.Add(spriteResolver);
else
filtered = true;
}
}
return filteredSelection.ToArray();
}
static SpriteResolver[] GetSelectedSpriteResolvers(GameObject[] selectedGameObjects)
{
var spriteResolvers = new HashSet<SpriteResolver>();
if (selectedGameObjects != null)
{
for (var o = 0; o < selectedGameObjects.Length; o++)
{
var gameObject = selectedGameObjects[o];
if (gameObject == null || !gameObject.activeSelf)
continue;
var children = gameObject.GetComponentsInChildren<SpriteResolver>();
for (var c = 0; c < children.Length; c++)
{
var spriteResolver = children[c];
spriteResolvers.Add(spriteResolver);
}
}
}
return spriteResolvers.ToArray();
}
}
}