暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SpriteShapeEditor.cs 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. using UnityEngine;
  2. using UnityEngine.U2D;
  3. using UnityEditor;
  4. using UnityEditor.AnimatedValues;
  5. using UnityEditorInternal;
  6. using UnityEditor.U2D.Common;
  7. using System.Collections.Generic;
  8. using UnityEditor.U2D.SpriteShape;
  9. namespace UnityEditor.U2D
  10. {
  11. [CustomEditor(typeof(UnityEngine.U2D.SpriteShape)), CanEditMultipleObjects]
  12. public class SpriteShapeEditor : Editor, IAngleRangeCache
  13. {
  14. private static class Contents
  15. {
  16. public static readonly GUIContent fillTextureLabel = new GUIContent("Texture", "Fill texture used for Shape Fill.");
  17. public static readonly GUIContent fillScaleLabel = new GUIContent("Offset", "Determines Border Offset for Shape.");
  18. public static readonly GUIContent useSpriteBorderLabel = new GUIContent("Use Sprite Borders", "Draw Sprite Borders on discontinuities");
  19. public static readonly GUIContent cornerTypeLabel = new GUIContent("Corner Type", "Corner type sprite used.");
  20. public static readonly GUIContent controlPointsLabel = new GUIContent("Control Points");
  21. public static readonly GUIContent fillLabel = new GUIContent("Fill");
  22. public static readonly GUIContent cornerLabel = new GUIContent("Corners");
  23. public static readonly GUIContent cornerListLabel = new GUIContent("Corner List");
  24. public static readonly GUIContent cornerSpriteTypeLabel = new GUIContent("Corner Sprite");
  25. public static readonly GUIContent angleRangesLabel = new GUIContent("Angle Ranges");
  26. public static readonly GUIContent spritesLabel = new GUIContent("Sprites");
  27. public static readonly GUIContent angleRangeLabel = new GUIContent("Angle Range ({0})");
  28. public static readonly GUIContent wrapModeErrorLabel = new GUIContent("Fill texture must have wrap modes set to Repeat. Please re-import.");
  29. public static readonly GUIContent createRangeButtonLabel = new GUIContent("Create Range");
  30. public static readonly Color proBackgroundColor = new Color32(49, 77, 121, 255);
  31. public static readonly Color proBackgroundRangeColor = new Color32(25, 25, 25, 128);
  32. public static readonly Color proColor1 = new Color32(10, 46, 42, 255);
  33. public static readonly Color proColor2 = new Color32(33, 151, 138, 255);
  34. public static readonly Color defaultColor1 = new Color32(25, 61, 57, 255);
  35. public static readonly Color defaultColor2 = new Color32(47, 166, 153, 255);
  36. public static readonly Color defaultBackgroundColor = new Color32(64, 92, 136, 255);
  37. }
  38. private SerializedProperty m_FillTextureProp;
  39. private SerializedProperty m_AngleRangesProp;
  40. private SerializedProperty m_CornerSpritesProp;
  41. private SerializedProperty m_FillOffsetProp;
  42. private SerializedProperty m_UseSpriteBordersProp;
  43. private ReorderableList m_AngleRangeSpriteList = null;
  44. private ReorderableList m_EmptySpriteList = null;
  45. [SerializeField]
  46. private float m_PreviewAngle = 0f;
  47. [SerializeField]
  48. private int m_SelectedIndex;
  49. private const int kInvalidMinimum = -1;
  50. private Rect m_AngleRangeRect;
  51. private AngleRangeController controller;
  52. private AngleRange m_CurrentAngleRange;
  53. private Dictionary<int, int> m_SpriteSelection = new Dictionary<int, int>();
  54. private Sprite m_PreviewSprite;
  55. private Mesh m_PreviewSpriteMesh;
  56. private Mesh previewSpriteMesh
  57. {
  58. get
  59. {
  60. if (m_PreviewSpriteMesh == null)
  61. {
  62. m_PreviewSpriteMesh = new Mesh();
  63. m_PreviewSpriteMesh.MarkDynamic();
  64. m_PreviewSpriteMesh.hideFlags = HideFlags.DontSave;
  65. }
  66. return m_PreviewSpriteMesh;
  67. }
  68. }
  69. public List<AngleRange> angleRanges
  70. {
  71. get
  72. {
  73. if (spriteShape == null)
  74. return new List<AngleRange>();
  75. Debug.Assert(spriteShape != null);
  76. return spriteShape.angleRanges;
  77. }
  78. }
  79. public int selectedIndex
  80. {
  81. get { return m_SelectedIndex; }
  82. set { m_SelectedIndex = value; }
  83. }
  84. bool isSelectedIndexValid
  85. {
  86. get { return (selectedIndex != kInvalidMinimum && selectedIndex < angleRanges.Count); }
  87. }
  88. public float previewAngle
  89. {
  90. get { return m_PreviewAngle; }
  91. set
  92. {
  93. m_PreviewAngle = value;
  94. SessionState.SetFloat("SpriteShape/PreviewAngle/" + target.GetInstanceID(), value);
  95. }
  96. }
  97. public UnityEngine.U2D.SpriteShape spriteShape
  98. {
  99. get
  100. {
  101. if (target == null)
  102. return null;
  103. return target as UnityEngine.U2D.SpriteShape;
  104. }
  105. }
  106. public void RegisterUndo(string name)
  107. {
  108. Undo.RegisterCompleteObjectUndo(spriteShape, name);
  109. Undo.RegisterCompleteObjectUndo(this, name);
  110. EditorUtility.SetDirty(spriteShape);
  111. }
  112. void OnReset(UnityEngine.U2D.SpriteShape obj)
  113. {
  114. InitCache();
  115. }
  116. void InitCache()
  117. {
  118. selectedIndex = SpriteShapeEditorUtility.GetRangeIndexFromAngle(angleRanges, m_PreviewAngle);
  119. SetupAngleRangeController();
  120. }
  121. public void OnEnable()
  122. {
  123. if (targets == null || targets.Length == 0)
  124. return;
  125. m_PreviewAngle = SessionState.GetFloat("SpriteShape/PreviewAngle/" + target.GetInstanceID(), m_PreviewAngle);
  126. m_FillTextureProp = this.serializedObject.FindProperty("m_FillTexture");
  127. m_UseSpriteBordersProp = serializedObject.FindProperty("m_UseSpriteBorders");
  128. m_AngleRangesProp = this.serializedObject.FindProperty("m_Angles");
  129. m_CornerSpritesProp = this.serializedObject.FindProperty("m_CornerSprites");
  130. m_FillOffsetProp = this.serializedObject.FindProperty("m_FillOffset");
  131. InitCache();
  132. Undo.undoRedoPerformed += UndoRedoPerformed;
  133. UnityEngine.U2D.SpriteShape.onReset += OnReset;
  134. }
  135. public void OnDisable()
  136. {
  137. UnityEngine.U2D.SpriteShape.onReset -= OnReset;
  138. }
  139. public override bool RequiresConstantRepaint()
  140. {
  141. return true;
  142. }
  143. private void SetupAngleRangeController()
  144. {
  145. var radius = 125f;
  146. var angleOffset = -90f;
  147. var color1 = Contents.defaultColor1;
  148. var color2 = Contents.defaultColor2;
  149. if (!EditorGUIUtility.isProSkin)
  150. {
  151. color1 = Contents.proColor1;
  152. color2 = Contents.proColor2;
  153. }
  154. controller = new AngleRangeController();
  155. controller.view = new AngleRangeView();
  156. controller.cache = this;
  157. controller.radius = radius;
  158. controller.angleOffset = angleOffset;
  159. controller.gradientMin = color1;
  160. controller.gradientMid = color2;
  161. controller.gradientMax = color1;
  162. controller.snap = true;
  163. controller.selectionChanged += OnSelectionChange;
  164. OnSelectionChange();
  165. }
  166. private void OnSelectionChange()
  167. {
  168. CreateReorderableSpriteList();
  169. EditorApplication.delayCall += () =>
  170. {
  171. m_CurrentAngleRange = controller.selectedAngleRange;
  172. };
  173. }
  174. private void OnDestroy()
  175. {
  176. if (m_PreviewSpriteMesh)
  177. UnityEngine.Object.DestroyImmediate(m_PreviewSpriteMesh);
  178. Undo.undoRedoPerformed -= UndoRedoPerformed;
  179. }
  180. private void UndoRedoPerformed()
  181. {
  182. InitCache();
  183. OnSelectionChange();
  184. }
  185. private void OnSelelectSpriteCallback(ReorderableList list)
  186. {
  187. if (selectedIndex >= 0)
  188. {
  189. SetPreviewSpriteIndex(selectedIndex, list.index);
  190. }
  191. }
  192. private bool OnCanAddCallback(ReorderableList list)
  193. {
  194. return (list.count < 64);
  195. }
  196. private void OnRemoveSprite(ReorderableList list)
  197. {
  198. var count = list.count;
  199. var index = list.index;
  200. ReorderableList.defaultBehaviours.DoRemoveButton(list);
  201. if (list.count < count && list.count > 0)
  202. {
  203. list.index = Mathf.Clamp(index, 0, list.count - 1);
  204. OnSelelectSpriteCallback(list);
  205. }
  206. }
  207. private void DrawSpriteListHeader(Rect rect)
  208. {
  209. EditorGUI.LabelField(rect, Contents.spritesLabel);
  210. HandleAngleSpriteListGUI(rect);
  211. }
  212. private void DrawSpriteListElement(Rect rect, int index, bool selected, bool focused)
  213. {
  214. rect.y += 2f;
  215. rect.height = EditorGUIUtility.singleLineHeight;
  216. var sprite = m_AngleRangesProp.GetArrayElementAtIndex(selectedIndex).FindPropertyRelative("m_Sprites").GetArrayElementAtIndex(index);
  217. EditorGUI.BeginChangeCheck();
  218. EditorGUI.PropertyField(rect, sprite, GUIContent.none);
  219. if (EditorGUI.EndChangeCheck())
  220. {
  221. m_AngleRangeSpriteList.index = index;
  222. OnSelelectSpriteCallback(m_AngleRangeSpriteList);
  223. }
  224. }
  225. public void DrawHeader(GUIContent content)
  226. {
  227. EditorGUILayout.LabelField(content, EditorStyles.boldLabel);
  228. }
  229. private void SetPreviewSpriteIndex(int rangeIndex, int index)
  230. {
  231. m_SpriteSelection[rangeIndex] = index;
  232. }
  233. private int GetPreviewSpriteIndex(int rangeIndex)
  234. {
  235. int index;
  236. m_SpriteSelection.TryGetValue(rangeIndex, out index);
  237. return index;
  238. }
  239. public override void OnInspectorGUI()
  240. {
  241. serializedObject.Update();
  242. EditorGUILayout.Space();
  243. DrawHeader(Contents.controlPointsLabel);
  244. EditorGUILayout.PropertyField(m_UseSpriteBordersProp, Contents.useSpriteBorderLabel);
  245. EditorGUILayout.Space();
  246. DrawHeader(Contents.fillLabel);
  247. EditorGUILayout.PropertyField(m_FillTextureProp, Contents.fillTextureLabel);
  248. EditorGUILayout.Slider(m_FillOffsetProp, -0.5f, 0.5f, Contents.fillScaleLabel);
  249. if (m_FillTextureProp.objectReferenceValue != null)
  250. {
  251. var fillTex = m_FillTextureProp.objectReferenceValue as Texture2D;
  252. if (fillTex.wrapModeU != TextureWrapMode.Repeat || fillTex.wrapModeV != TextureWrapMode.Repeat)
  253. EditorGUILayout.HelpBox(Contents.wrapModeErrorLabel.text, MessageType.Warning);
  254. }
  255. EditorGUILayout.Space();
  256. DrawHeader(Contents.angleRangesLabel);
  257. DoRangesGUI();
  258. if (targets.Length == 1)
  259. {
  260. DoRangeInspector();
  261. DoCreateRangeButton();
  262. }
  263. EditorGUILayout.Space();
  264. DrawHeader(Contents.cornerLabel);
  265. HashSet<Sprite> tightMeshSprites = new HashSet<Sprite>();
  266. for (int i = 0; i < angleRanges.Count; ++i)
  267. {
  268. AngleRange angleRange = angleRanges[i];
  269. foreach (Sprite sprite in angleRange.sprites)
  270. {
  271. if (sprite != null)
  272. {
  273. string assetPath = AssetDatabase.GetAssetPath(sprite);
  274. TextureImporter importer = AssetImporter.GetAtPath(assetPath) as TextureImporter;
  275. if (importer != null)
  276. {
  277. TextureImporterSettings textureSettings = new TextureImporterSettings();
  278. importer.ReadTextureSettings(textureSettings);
  279. if (textureSettings.spriteMeshType == SpriteMeshType.Tight)
  280. tightMeshSprites.Add(sprite);
  281. }
  282. }
  283. }
  284. }
  285. EditorGUIUtility.labelWidth = EditorGUIUtility.labelWidth + 20f;
  286. for (int i = 0; i < m_CornerSpritesProp.arraySize; ++i)
  287. {
  288. var m_CornerProp = m_CornerSpritesProp.GetArrayElementAtIndex(i);
  289. var m_CornerType = m_CornerProp.FindPropertyRelative("m_CornerType");
  290. var m_CornerSprite = m_CornerProp.FindPropertyRelative("m_Sprites").GetArrayElementAtIndex(0);
  291. EditorGUILayout.PropertyField(m_CornerSprite, new GUIContent(m_CornerType.enumDisplayNames[m_CornerType.intValue]));
  292. var sprite = m_CornerSprite.objectReferenceValue as Sprite;
  293. if (sprite != null)
  294. {
  295. string assetPath = AssetDatabase.GetAssetPath(sprite);
  296. TextureImporter importer = AssetImporter.GetAtPath(assetPath) as TextureImporter;
  297. if (importer != null)
  298. {
  299. TextureImporterSettings textureSettings = new TextureImporterSettings();
  300. importer.ReadTextureSettings(textureSettings);
  301. if (textureSettings.spriteMeshType == SpriteMeshType.Tight)
  302. tightMeshSprites.Add(sprite);
  303. }
  304. }
  305. }
  306. EditorGUIUtility.labelWidth = 0;
  307. serializedObject.ApplyModifiedProperties();
  308. if (tightMeshSprites.Count > 0)
  309. {
  310. int i = 0;
  311. string tightSpriteWarning = "The following sprites ( ";
  312. foreach (var sprite in tightMeshSprites)
  313. {
  314. string appendString = (i < tightMeshSprites.Count - 1) ? ", " : " ) ";
  315. tightSpriteWarning += (sprite.name + appendString);
  316. ++i;
  317. }
  318. tightSpriteWarning += "are imported as Sprites using Tight mesh. This can lead to Rendering Artifacts. Please use Full Rect.";
  319. EditorGUILayout.HelpBox(tightSpriteWarning, MessageType.Warning);
  320. }
  321. controller.view.DoCreateRangeTooltip();
  322. }
  323. private void DoRangeInspector()
  324. {
  325. var start = 0f;
  326. var end = 0f;
  327. var order = 0;
  328. if (m_CurrentAngleRange != null)
  329. {
  330. start = m_CurrentAngleRange.start;
  331. end = m_CurrentAngleRange.end;
  332. order = m_CurrentAngleRange.order;
  333. }
  334. var arSize = m_AngleRangesProp.arraySize;
  335. using (new EditorGUI.DisabledGroupScope(m_CurrentAngleRange == null))
  336. {
  337. DrawHeader(new GUIContent(string.Format(Contents.angleRangeLabel.text, (end - start))));
  338. EditorGUIUtility.labelWidth = 0f;
  339. EditorGUI.BeginChangeCheck();
  340. RangeField(ref start, ref end, ref order);
  341. if (EditorGUI.EndChangeCheck() && m_CurrentAngleRange != null)
  342. {
  343. RegisterUndo("Set Range");
  344. m_CurrentAngleRange.order = order;
  345. controller.SetRange(m_CurrentAngleRange, start, end);
  346. if (start >= end)
  347. controller.RemoveInvalidRanges();
  348. }
  349. EditorGUILayout.Space();
  350. if (m_AngleRangeSpriteList != null && arSize > 0)
  351. m_AngleRangeSpriteList.DoLayoutList();
  352. else
  353. m_EmptySpriteList.DoLayoutList();
  354. }
  355. }
  356. private void DoCreateRangeButton()
  357. {
  358. if (selectedIndex != kInvalidMinimum && angleRanges.Count != 0)
  359. return;
  360. EditorGUILayout.BeginHorizontal();
  361. GUILayout.FlexibleSpace();
  362. if (GUILayout.Button(Contents.createRangeButtonLabel, GUILayout.MaxWidth(100f)))
  363. {
  364. RegisterUndo("Create Range");
  365. controller.CreateRange();
  366. }
  367. GUILayout.FlexibleSpace();
  368. EditorGUILayout.EndHorizontal();
  369. }
  370. private void RangeField(ref float start, ref float end, ref int order)
  371. {
  372. var values = new int[] { Mathf.RoundToInt(-start), Mathf.RoundToInt(-end), order };
  373. var labels = new GUIContent[] { new GUIContent("Start"), new GUIContent("End"), new GUIContent("Order") };
  374. var position = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight);
  375. EditorGUI.BeginChangeCheck();
  376. SpriteShapeEditorGUI.MultiDelayedIntField(position, labels, values, 40f);
  377. if (EditorGUI.EndChangeCheck())
  378. {
  379. start = -1f * values[0];
  380. end = -1f * values[1];
  381. order = values[2];
  382. }
  383. }
  384. private void HandleAngleSpriteListGUI(Rect rect)
  385. {
  386. if (m_CurrentAngleRange == null || !isSelectedIndexValid)
  387. return;
  388. var currentEvent = Event.current;
  389. var usedEvent = false;
  390. var sprites = m_AngleRangesProp.GetArrayElementAtIndex(selectedIndex).FindPropertyRelative("m_Sprites");
  391. switch (currentEvent.type)
  392. {
  393. case EventType.DragExited:
  394. if (GUI.enabled)
  395. HandleUtility.Repaint();
  396. break;
  397. case EventType.DragUpdated:
  398. case EventType.DragPerform:
  399. if (rect.Contains(currentEvent.mousePosition) && GUI.enabled)
  400. {
  401. // Check each single object, so we can add multiple objects in a single drag.
  402. var didAcceptDrag = false;
  403. var references = DragAndDrop.objectReferences;
  404. foreach (var obj in references)
  405. {
  406. if (obj is Sprite)
  407. {
  408. Sprite spr = obj as Sprite;
  409. if (spr.texture != null)
  410. {
  411. DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
  412. if (currentEvent.type == EventType.DragPerform && sprites.arraySize < 64)
  413. {
  414. sprites.InsertArrayElementAtIndex(sprites.arraySize);
  415. var spriteProp = sprites.GetArrayElementAtIndex(sprites.arraySize - 1);
  416. spriteProp.objectReferenceValue = obj;
  417. didAcceptDrag = true;
  418. DragAndDrop.activeControlID = 0;
  419. }
  420. }
  421. }
  422. }
  423. serializedObject.ApplyModifiedProperties();
  424. if (didAcceptDrag)
  425. {
  426. GUI.changed = true;
  427. DragAndDrop.AcceptDrag();
  428. usedEvent = true;
  429. }
  430. }
  431. break;
  432. }
  433. if (usedEvent)
  434. currentEvent.Use();
  435. }
  436. private void DoRangesGUI()
  437. {
  438. var radius = controller.radius;
  439. EditorGUILayout.Space();
  440. EditorGUILayout.Space();
  441. var rect = EditorGUILayout.GetControlRect(false, radius * 2f);
  442. if (Event.current.type == EventType.Repaint)
  443. m_AngleRangeRect = rect;
  444. { //Draw background
  445. var backgroundColor = Contents.proBackgroundColor;
  446. var backgroundRangeColor = Contents.proBackgroundRangeColor;
  447. if (!EditorGUIUtility.isProSkin)
  448. {
  449. backgroundColor = Contents.defaultBackgroundColor;
  450. backgroundRangeColor.a = 0.1f;
  451. }
  452. var c = Handles.color;
  453. Handles.color = backgroundRangeColor;
  454. SpriteShapeHandleUtility.DrawSolidArc(rect.center, Vector3.forward, Vector3.right, 360f, radius, AngleRangeGUI.kRangeWidth);
  455. Handles.color = backgroundColor;
  456. Handles.DrawSolidDisc(rect.center, Vector3.forward, radius - AngleRangeGUI.kRangeWidth + 1f);
  457. Handles.color = c;
  458. }
  459. if (targets.Length == 1)
  460. {
  461. { //Draw fill texture and sprite preview
  462. SpriteShapeHandleUtility.DrawTextureArc(
  463. m_FillTextureProp.objectReferenceValue as Texture, 100.0f,
  464. rect.center, Vector3.forward, Quaternion.AngleAxis(m_PreviewAngle, Vector3.forward) * Vector3.right, 180f,
  465. radius - AngleRangeGUI.kRangeWidth);
  466. var rectSize = Vector2.one * (radius - AngleRangeGUI.kRangeWidth) * 2f;
  467. rectSize.y *= 0.33f;
  468. var spriteRect = new Rect(rect.center - rectSize * 0.5f, rectSize);
  469. DrawSpritePreview(spriteRect);
  470. HandleSpritePreviewCycle(spriteRect);
  471. }
  472. controller.rect = m_AngleRangeRect;
  473. controller.OnGUI();
  474. }
  475. EditorGUILayout.Space();
  476. EditorGUILayout.Space();
  477. }
  478. private void CreateReorderableSpriteList()
  479. {
  480. if (m_EmptySpriteList == null)
  481. {
  482. m_EmptySpriteList = new ReorderableList(new List<Sprite>(), typeof(Sprite), false, true, false, false)
  483. {
  484. drawHeaderCallback = (Rect rect) => { EditorGUI.LabelField(rect, Contents.spritesLabel); }
  485. };
  486. }
  487. m_AngleRangeSpriteList = null;
  488. serializedObject.UpdateIfRequiredOrScript();
  489. Debug.Assert(angleRanges.Count == m_AngleRangesProp.arraySize);
  490. Debug.Assert(selectedIndex < angleRanges.Count || selectedIndex == 0);
  491. if (targets.Length == 1 && isSelectedIndexValid)
  492. {
  493. var spritesProp = m_AngleRangesProp.GetArrayElementAtIndex(selectedIndex).FindPropertyRelative("m_Sprites");
  494. m_AngleRangeSpriteList = new ReorderableList(spritesProp.serializedObject, spritesProp)
  495. {
  496. drawElementCallback = DrawSpriteListElement,
  497. drawHeaderCallback = DrawSpriteListHeader,
  498. onSelectCallback = OnSelelectSpriteCallback,
  499. onRemoveCallback = OnRemoveSprite,
  500. onCanAddCallback = OnCanAddCallback,
  501. elementHeight = EditorGUIUtility.singleLineHeight + 6f
  502. };
  503. }
  504. }
  505. private void DrawSpritePreview(Rect rect)
  506. {
  507. if (Event.current.type != EventType.Repaint)
  508. return;
  509. if (!isSelectedIndexValid)
  510. return;
  511. var sprites = angleRanges[selectedIndex].sprites;
  512. if (sprites.Count == 0)
  513. return;
  514. var selectedSpriteIndex = GetPreviewSpriteIndex(selectedIndex);
  515. if (selectedSpriteIndex == kInvalidMinimum || selectedSpriteIndex >= sprites.Count)
  516. return;
  517. var sprite = sprites[selectedSpriteIndex];
  518. if (sprite == null)
  519. return;
  520. if (m_PreviewSprite != sprite)
  521. {
  522. m_PreviewSprite = sprite;
  523. EditorSpriteGUIUtility.DrawSpriteInRectPrepare(rect, sprite, EditorSpriteGUIUtility.FitMode.Tiled, true, true, previewSpriteMesh);
  524. }
  525. var material = EditorSpriteGUIUtility.spriteMaterial;
  526. material.mainTexture = EditorSpriteGUIUtility.GetOriginalSpriteTexture(sprite);
  527. EditorSpriteGUIUtility.DrawMesh(previewSpriteMesh, material, rect.center, Quaternion.AngleAxis(m_PreviewAngle, Vector3.forward), new Vector3(1f, -1f, 1f));
  528. }
  529. private void HandleSpritePreviewCycle(Rect rect)
  530. {
  531. if (!isSelectedIndexValid)
  532. return;
  533. Debug.Assert(m_AngleRangeSpriteList != null);
  534. var spriteIndex = GetPreviewSpriteIndex(selectedIndex);
  535. var sprites = angleRanges[selectedIndex].sprites;
  536. var ev = Event.current;
  537. if (ev.type == EventType.MouseDown && ev.button == 0 && HandleUtility.nearestControl == 0 &&
  538. ContainsPosition(rect, ev.mousePosition, m_PreviewAngle) && spriteIndex != kInvalidMinimum && sprites.Count > 0)
  539. {
  540. spriteIndex = Mathf.RoundToInt(Mathf.Repeat(spriteIndex + 1f, sprites.Count));
  541. SetPreviewSpriteIndex(selectedIndex, spriteIndex);
  542. m_AngleRangeSpriteList.GrabKeyboardFocus();
  543. m_AngleRangeSpriteList.index = spriteIndex;
  544. ev.Use();
  545. }
  546. }
  547. private bool ContainsPosition(Rect rect, Vector2 position, float angle)
  548. {
  549. Vector2 delta = position - rect.center;
  550. position = (Vector2)(Quaternion.AngleAxis(-angle, Vector3.forward) * (Vector3)delta) + rect.center;
  551. return rect.Contains(position);
  552. }
  553. }
  554. }