Net.Like.Xue.Tokyo/Assets/Plugins/Animancer/Internal/Editor/Animancer Tools/ModifySpritesTool.cs

251 lines
8.5 KiB
C#

// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2023 Kybernetik //
#if UNITY_EDITOR
#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value.
using System;
using UnityEditor;
using UnityEngine;
namespace Animancer.Editor.Tools
{
/// <summary>[Editor-Only] [Pro-Only]
/// A <see cref="SpriteModifierTool"/> for modifying <see cref="Sprite"/> detauls.
/// </summary>
/// <remarks>
/// Documentation: <see href="https://kybernetik.com.au/animancer/docs/manual/tools/modify-sprites">Modify Sprites</see>
/// </remarks>
/// https://kybernetik.com.au/animancer/api/Animancer.Editor.Tools/ModifySpritesTool
///
[Serializable]
public class ModifySpritesTool : SpriteModifierTool
{
/************************************************************************************************************************/
[SerializeField] private OffsetRectMode _RectMode;
[SerializeField] private Rect _RectOffset;
[SerializeField] private bool _SetPivot;
[SerializeField] private Vector2 _Pivot;
[SerializeField] private bool _SetAlignment;
[SerializeField] private SpriteAlignment _Alignment;
[SerializeField] private bool _SetBorder;
[SerializeField] private RectOffset _Border;
[SerializeField] private bool _ShowDetails;
/************************************************************************************************************************/
private enum OffsetRectMode { None, Add, Subtract }
private static readonly string[] OffsetRectModes = { "None", "Add", "Subtract" };
private SerializedProperty _SerializedProperty;
/************************************************************************************************************************/
/// <inheritdoc/>
public override int DisplayOrder => 1;
/// <inheritdoc/>
public override string Name => "Modify Sprites";
/// <inheritdoc/>
public override string HelpURL => Strings.DocsURLs.ModifySprites;
/// <inheritdoc/>
public override string Instructions
{
get
{
if (Sprites.Count == 0)
return "Select the Sprites you want to modify.";
if (!IsValidModification())
return "The current Rect Offset would move some Sprites outside the texture bounds.";
return "Enter the desired modifications and click Apply.";
}
}
/************************************************************************************************************************/
/// <inheritdoc/>
public override void OnEnable(int index)
{
base.OnEnable(index);
_SerializedProperty = AnimancerToolsWindow.Instance.FindSerializedPropertyForTool(this);
_SerializedProperty = _SerializedProperty.FindPropertyRelative(nameof(_RectMode));
}
/************************************************************************************************************************/
/// <inheritdoc/>
public override void DoBodyGUI()
{
base.DoBodyGUI();
var area = AnimancerGUI.LayoutSingleLineRect();
area.xMin += 4;
using (ObjectPool.Disposable.AcquireContent(out var label, "Offset Rects", null, false))
area = EditorGUI.PrefixLabel(area, label);
AnimancerToolsWindow.BeginChangeCheck();
var selected = (OffsetRectMode)GUI.Toolbar(area, (int)_RectMode, OffsetRectModes);
AnimancerToolsWindow.EndChangeCheck(ref _RectMode, selected);
using (var property = _SerializedProperty.Copy())
{
property.serializedObject.Update();
var depth = property.depth;
while (property.Next(false) && property.depth >= depth)
{
EditorGUILayout.PropertyField(property, true);
}
property.serializedObject.ApplyModifiedProperties();
}
GUI.enabled = false;
for (int i = 0; i < Sprites.Count; i++)
{
if (_ShowDetails)
GUILayout.BeginVertical(GUI.skin.box);
var sprite = Sprites[i] = (Sprite)EditorGUILayout.ObjectField(Sprites[i], typeof(Sprite), false);
if (_ShowDetails)
{
if (_RectMode != OffsetRectMode.None)
EditorGUILayout.RectField("Rect", sprite.rect);
if (_SetPivot)
EditorGUILayout.Vector2Field("Pivot", sprite.pivot);
if (_SetBorder)
EditorGUILayout.Vector4Field("Border", sprite.border);
GUILayout.EndVertical();
}
}
GUILayout.BeginHorizontal();
{
GUILayout.FlexibleSpace();
GUI.enabled = Sprites.Count > 0 && IsValidModification();
if (GUILayout.Button("Apply"))
{
AnimancerGUI.Deselect();
AskAndApply();
}
}
GUILayout.EndHorizontal();
}
/************************************************************************************************************************/
private bool IsValidModification()
{
switch (_RectMode)
{
default:
case OffsetRectMode.None:
return true;
case OffsetRectMode.Add:
case OffsetRectMode.Subtract:
break;
}
var offset = GetOffset();
var sprites = Sprites;
for (int i = 0; i < sprites.Count; i++)
{
var sprite = sprites[i];
var rect = Add(sprite.rect, offset);
if (rect.xMin < 0 ||
rect.yMin < 0 ||
rect.xMax >= sprite.texture.width ||
rect.xMax >= sprite.texture.height)
{
return false;
}
}
return true;
}
/************************************************************************************************************************/
private Rect GetOffset()
{
switch (_RectMode)
{
default:
case OffsetRectMode.None:
throw new InvalidOperationException($"Can't {nameof(GetOffset)} when the mode is {_RectMode}.");
case OffsetRectMode.Add:
return _RectOffset;
case OffsetRectMode.Subtract:
return new Rect(-_RectOffset.x, -_RectOffset.y, -_RectOffset.width, -_RectOffset.height);
}
}
private static Rect Add(Rect a, Rect b)
{
a.x += b.x;
a.y += b.y;
a.width += b.width;
a.height += b.height;
return a;
}
/************************************************************************************************************************/
/// <inheritdoc/>
protected override string AreYouSure => "Are you sure you want to modify the borders of these Sprites?";
/************************************************************************************************************************/
/// <inheritdoc/>
protected override void Modify(SpriteDataEditor data, int index, Sprite sprite)
{
switch (_RectMode)
{
default:
case OffsetRectMode.None:
break;
case OffsetRectMode.Add:
case OffsetRectMode.Subtract:
var rect = data.GetRect(index);
rect = Add(rect, GetOffset());
data.SetRect(index, rect);
break;
}
if (_SetPivot)
data.SetPivot(index, _Pivot);
if (_SetAlignment)
data.SetAlignment(index, _Alignment);
if (_SetBorder)
data.SetBorder(index, new Vector4(_Border.left, _Border.bottom, _Border.right, _Border.top));
}
/************************************************************************************************************************/
}
}
#endif