ModifySpritesTool.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
  2. #if UNITY_EDITOR
  3. #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value.
  4. using System;
  5. using UnityEditor;
  6. using UnityEngine;
  7. namespace Animancer.Editor.Tools
  8. {
  9. /// <summary>[Editor-Only] [Pro-Only]
  10. /// A <see cref="SpriteModifierTool"/> for modifying <see cref="Sprite"/> detauls.
  11. /// </summary>
  12. /// <remarks>
  13. /// <strong>Documentation:</strong>
  14. /// <see href="https://kybernetik.com.au/animancer/docs/manual/tools/modify-sprites">
  15. /// Modify Sprites</see>
  16. /// </remarks>
  17. /// https://kybernetik.com.au/animancer/api/Animancer.Editor.Tools/ModifySpritesTool
  18. ///
  19. [Serializable]
  20. public class ModifySpritesTool : SpriteModifierTool
  21. {
  22. /************************************************************************************************************************/
  23. [SerializeField] private OffsetRectMode _RectMode;
  24. [SerializeField] private Rect _RectOffset;
  25. [SerializeField] private bool _SetPivot;
  26. [SerializeField] private Vector2 _Pivot;
  27. [SerializeField] private bool _SetAlignment;
  28. [SerializeField] private SpriteAlignment _Alignment;
  29. [SerializeField] private bool _SetBorder;
  30. [SerializeField] private RectOffset _Border;
  31. [SerializeField] private bool _ShowDetails;
  32. /************************************************************************************************************************/
  33. private enum OffsetRectMode { None, Add, Subtract }
  34. private static readonly string[] OffsetRectModes = { "None", "Add", "Subtract" };
  35. private SerializedProperty _SerializedProperty;
  36. /************************************************************************************************************************/
  37. /// <inheritdoc/>
  38. public override int DisplayOrder => 1;
  39. /// <inheritdoc/>
  40. public override string Name => "Modify Sprites";
  41. /// <inheritdoc/>
  42. public override string HelpURL => Strings.DocsURLs.ModifySprites;
  43. /// <inheritdoc/>
  44. public override string Instructions
  45. {
  46. get
  47. {
  48. if (Sprites.Count == 0)
  49. return "Select the Sprites you want to modify.";
  50. if (!IsValidModification())
  51. return "The current Rect Offset would move some Sprites outside the texture bounds.";
  52. return "Enter the desired modifications and click Apply.";
  53. }
  54. }
  55. /************************************************************************************************************************/
  56. /// <inheritdoc/>
  57. public override void OnEnable(int index)
  58. {
  59. base.OnEnable(index);
  60. _SerializedProperty = AnimancerToolsWindow.Instance.FindSerializedPropertyForTool(this);
  61. _SerializedProperty = _SerializedProperty.FindPropertyRelative(nameof(_RectMode));
  62. }
  63. /************************************************************************************************************************/
  64. /// <inheritdoc/>
  65. public override void DoBodyGUI()
  66. {
  67. base.DoBodyGUI();
  68. var area = AnimancerGUI.LayoutSingleLineRect();
  69. area.xMin += 4;
  70. using (var label = PooledGUIContent.Acquire("Offset Rects", null))
  71. area = EditorGUI.PrefixLabel(area, label);
  72. AnimancerToolsWindow.BeginChangeCheck();
  73. var selected = (OffsetRectMode)GUI.Toolbar(area, (int)_RectMode, OffsetRectModes);
  74. AnimancerToolsWindow.EndChangeCheck(ref _RectMode, selected);
  75. using (var property = _SerializedProperty.Copy())
  76. {
  77. property.serializedObject.Update();
  78. var depth = property.depth;
  79. while (property.Next(false) && property.depth >= depth)
  80. {
  81. EditorGUILayout.PropertyField(property, true);
  82. }
  83. property.serializedObject.ApplyModifiedProperties();
  84. }
  85. GUI.enabled = false;
  86. for (int i = 0; i < Sprites.Count; i++)
  87. {
  88. if (_ShowDetails)
  89. GUILayout.BeginVertical(GUI.skin.box);
  90. var sprite = Sprites[i] = AnimancerGUI.DoObjectFieldGUI("", Sprites[i], false);
  91. if (_ShowDetails)
  92. {
  93. if (_RectMode != OffsetRectMode.None)
  94. EditorGUILayout.RectField("Rect", sprite.rect);
  95. if (_SetPivot)
  96. EditorGUILayout.Vector2Field("Pivot", sprite.pivot);
  97. if (_SetBorder)
  98. EditorGUILayout.Vector4Field("Border", sprite.border);
  99. GUILayout.EndVertical();
  100. }
  101. }
  102. GUILayout.BeginHorizontal();
  103. {
  104. GUILayout.FlexibleSpace();
  105. GUI.enabled = Sprites.Count > 0 && IsValidModification();
  106. if (GUILayout.Button("Apply"))
  107. {
  108. AnimancerGUI.Deselect();
  109. AskAndApply();
  110. }
  111. }
  112. GUILayout.EndHorizontal();
  113. }
  114. /************************************************************************************************************************/
  115. private bool IsValidModification()
  116. {
  117. switch (_RectMode)
  118. {
  119. default:
  120. case OffsetRectMode.None:
  121. return true;
  122. case OffsetRectMode.Add:
  123. case OffsetRectMode.Subtract:
  124. break;
  125. }
  126. var offset = GetOffset();
  127. var sprites = Sprites;
  128. for (int i = 0; i < sprites.Count; i++)
  129. {
  130. var sprite = sprites[i];
  131. var rect = Add(sprite.rect, offset);
  132. if (rect.xMin < 0 ||
  133. rect.yMin < 0 ||
  134. rect.xMax >= sprite.texture.width ||
  135. rect.xMax >= sprite.texture.height)
  136. {
  137. return false;
  138. }
  139. }
  140. return true;
  141. }
  142. /************************************************************************************************************************/
  143. private Rect GetOffset()
  144. {
  145. return _RectMode switch
  146. {
  147. OffsetRectMode.Add
  148. => _RectOffset,
  149. OffsetRectMode.Subtract
  150. => new(-_RectOffset.x, -_RectOffset.y, -_RectOffset.width, -_RectOffset.height),
  151. _
  152. => throw new InvalidOperationException($"Can't {nameof(GetOffset)} when the mode is {_RectMode}."),
  153. };
  154. }
  155. private static Rect Add(Rect a, Rect b)
  156. {
  157. a.x += b.x;
  158. a.y += b.y;
  159. a.width += b.width;
  160. a.height += b.height;
  161. return a;
  162. }
  163. /************************************************************************************************************************/
  164. /// <inheritdoc/>
  165. protected override string AreYouSure => "Are you sure you want to modify the borders of these Sprites?";
  166. /************************************************************************************************************************/
  167. /// <inheritdoc/>
  168. protected override void Modify(SpriteDataEditor data, int index, Sprite sprite)
  169. {
  170. switch (_RectMode)
  171. {
  172. default:
  173. case OffsetRectMode.None:
  174. break;
  175. case OffsetRectMode.Add:
  176. case OffsetRectMode.Subtract:
  177. var rect = data.GetRect(index);
  178. rect = Add(rect, GetOffset());
  179. data.SetRect(index, rect);
  180. break;
  181. }
  182. if (_SetPivot)
  183. data.SetPivot(index, _Pivot);
  184. if (_SetAlignment)
  185. data.SetAlignment(index, _Alignment);
  186. if (_SetBorder)
  187. data.SetBorder(index, new(_Border.left, _Border.bottom, _Border.right, _Border.top));
  188. }
  189. /************************************************************************************************************************/
  190. }
  191. }
  192. #endif