No Description
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 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  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. internal 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. var labelWidth = EditorGUIUtility.labelWidth;
  286. EditorGUIUtility.labelWidth = EditorGUIUtility.labelWidth + 20f;
  287. for (int i = 0; i < m_CornerSpritesProp.arraySize; ++i)
  288. {
  289. var m_CornerProp = m_CornerSpritesProp.GetArrayElementAtIndex(i);
  290. var m_CornerType = m_CornerProp.FindPropertyRelative("m_CornerType");
  291. var m_CornerSprite = m_CornerProp.FindPropertyRelative("m_Sprites").GetArrayElementAtIndex(0);
  292. m_CornerSprite.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(m_CornerType.enumDisplayNames[m_CornerType.intValue]), m_CornerSprite.objectReferenceValue, typeof(Sprite), false, GUILayout.Height(18.0f) );
  293. var sprite = m_CornerSprite.objectReferenceValue as Sprite;
  294. if (sprite != null)
  295. {
  296. string assetPath = AssetDatabase.GetAssetPath(sprite);
  297. TextureImporter importer = AssetImporter.GetAtPath(assetPath) as TextureImporter;
  298. if (importer != null)
  299. {
  300. TextureImporterSettings textureSettings = new TextureImporterSettings();
  301. importer.ReadTextureSettings(textureSettings);
  302. if (textureSettings.spriteMeshType == SpriteMeshType.Tight)
  303. tightMeshSprites.Add(sprite);
  304. }
  305. }
  306. }
  307. EditorGUIUtility.labelWidth = 0;
  308. serializedObject.ApplyModifiedProperties();
  309. if (tightMeshSprites.Count > 0)
  310. {
  311. int i = 0;
  312. string tightSpriteWarning = "The following sprites ( ";
  313. foreach (var sprite in tightMeshSprites)
  314. {
  315. string appendString = (i < tightMeshSprites.Count - 1) ? ", " : " ) ";
  316. tightSpriteWarning += (sprite.name + appendString);
  317. ++i;
  318. }
  319. tightSpriteWarning += "are imported as Sprites using Tight mesh. This can lead to Rendering Artifacts. Please use Full Rect.";
  320. EditorGUILayout.HelpBox(tightSpriteWarning, MessageType.Warning);
  321. }
  322. controller.view.DoCreateRangeTooltip();
  323. EditorGUIUtility.labelWidth = labelWidth;
  324. }
  325. private void DoRangeInspector()
  326. {
  327. var start = 0f;
  328. var end = 0f;
  329. var order = 0;
  330. if (m_CurrentAngleRange != null)
  331. {
  332. start = m_CurrentAngleRange.start;
  333. end = m_CurrentAngleRange.end;
  334. order = m_CurrentAngleRange.order;
  335. }
  336. var arSize = m_AngleRangesProp.arraySize;
  337. using (new EditorGUI.DisabledGroupScope(m_CurrentAngleRange == null))
  338. {
  339. DrawHeader(new GUIContent(string.Format(Contents.angleRangeLabel.text, (end - start))));
  340. EditorGUIUtility.labelWidth = 0f;
  341. EditorGUI.BeginChangeCheck();
  342. RangeField(ref start, ref end, ref order);
  343. if (EditorGUI.EndChangeCheck() && m_CurrentAngleRange != null)
  344. {
  345. RegisterUndo("Set Range");
  346. m_CurrentAngleRange.order = order;
  347. controller.SetRange(m_CurrentAngleRange, start, end);
  348. if (start >= end)
  349. controller.RemoveInvalidRanges();
  350. }
  351. EditorGUILayout.Space();
  352. if (m_AngleRangeSpriteList != null && arSize > 0)
  353. m_AngleRangeSpriteList.DoLayoutList();
  354. else
  355. m_EmptySpriteList.DoLayoutList();
  356. }
  357. }
  358. private void DoCreateRangeButton()
  359. {
  360. if (selectedIndex != kInvalidMinimum && angleRanges.Count != 0)
  361. return;
  362. EditorGUILayout.BeginHorizontal();
  363. GUILayout.FlexibleSpace();
  364. if (GUILayout.Button(Contents.createRangeButtonLabel, GUILayout.MaxWidth(100f)))
  365. {
  366. RegisterUndo("Create Range");
  367. controller.CreateRange();
  368. }
  369. GUILayout.FlexibleSpace();
  370. EditorGUILayout.EndHorizontal();
  371. }
  372. private void RangeField(ref float start, ref float end, ref int order)
  373. {
  374. var values = new int[] { Mathf.RoundToInt(-start), Mathf.RoundToInt(-end), order };
  375. var labels = new GUIContent[] { new GUIContent("Start"), new GUIContent("End"), new GUIContent("Order") };
  376. var position = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight);
  377. EditorGUI.BeginChangeCheck();
  378. SpriteShapeEditorGUI.MultiDelayedIntField(position, labels, values, 40f);
  379. if (EditorGUI.EndChangeCheck())
  380. {
  381. start = -1f * values[0];
  382. end = -1f * values[1];
  383. order = values[2];
  384. }
  385. }
  386. private void HandleAngleSpriteListGUI(Rect rect)
  387. {
  388. if (m_CurrentAngleRange == null || !isSelectedIndexValid)
  389. return;
  390. var currentEvent = Event.current;
  391. var usedEvent = false;
  392. var sprites = m_AngleRangesProp.GetArrayElementAtIndex(selectedIndex).FindPropertyRelative("m_Sprites");
  393. switch (currentEvent.type)
  394. {
  395. case EventType.DragExited:
  396. if (GUI.enabled)
  397. HandleUtility.Repaint();
  398. break;
  399. case EventType.DragUpdated:
  400. case EventType.DragPerform:
  401. if (rect.Contains(currentEvent.mousePosition) && GUI.enabled)
  402. {
  403. // Check each single object, so we can add multiple objects in a single drag.
  404. var didAcceptDrag = false;
  405. var references = DragAndDrop.objectReferences;
  406. foreach (var obj in references)
  407. {
  408. if (obj is Sprite)
  409. {
  410. Sprite spr = obj as Sprite;
  411. if (spr.texture != null)
  412. {
  413. DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
  414. if (currentEvent.type == EventType.DragPerform && sprites.arraySize < 64)
  415. {
  416. sprites.InsertArrayElementAtIndex(sprites.arraySize);
  417. var spriteProp = sprites.GetArrayElementAtIndex(sprites.arraySize - 1);
  418. spriteProp.objectReferenceValue = obj;
  419. didAcceptDrag = true;
  420. DragAndDrop.activeControlID = 0;
  421. }
  422. }
  423. }
  424. }
  425. serializedObject.ApplyModifiedProperties();
  426. if (didAcceptDrag)
  427. {
  428. GUI.changed = true;
  429. DragAndDrop.AcceptDrag();
  430. usedEvent = true;
  431. }
  432. }
  433. break;
  434. }
  435. if (usedEvent)
  436. currentEvent.Use();
  437. }
  438. private void DoRangesGUI()
  439. {
  440. var radius = controller.radius;
  441. EditorGUILayout.Space();
  442. EditorGUILayout.Space();
  443. var rect = EditorGUILayout.GetControlRect(false, radius * 2f);
  444. if (Event.current.type == EventType.Repaint)
  445. m_AngleRangeRect = rect;
  446. { //Draw background
  447. var backgroundColor = Contents.proBackgroundColor;
  448. var backgroundRangeColor = Contents.proBackgroundRangeColor;
  449. if (!EditorGUIUtility.isProSkin)
  450. {
  451. backgroundColor = Contents.defaultBackgroundColor;
  452. backgroundRangeColor.a = 0.1f;
  453. }
  454. var c = Handles.color;
  455. Handles.color = backgroundRangeColor;
  456. SpriteShapeHandleUtility.DrawSolidArc(rect.center, Vector3.forward, Vector3.right, 360f, radius, AngleRangeGUI.kRangeWidth);
  457. Handles.color = backgroundColor;
  458. Handles.DrawSolidDisc(rect.center, Vector3.forward, radius - AngleRangeGUI.kRangeWidth + 1f);
  459. Handles.color = c;
  460. }
  461. if (targets.Length == 1)
  462. {
  463. { //Draw fill texture and sprite preview
  464. SpriteShapeHandleUtility.DrawTextureArc(
  465. m_FillTextureProp.objectReferenceValue as Texture, 100.0f,
  466. rect.center, Vector3.forward, Quaternion.AngleAxis(m_PreviewAngle, Vector3.forward) * Vector3.right, 180f,
  467. radius - AngleRangeGUI.kRangeWidth);
  468. var rectSize = Vector2.one * (radius - AngleRangeGUI.kRangeWidth) * 2f;
  469. rectSize.y *= 0.33f;
  470. var spriteRect = new Rect(rect.center - rectSize * 0.5f, rectSize);
  471. DrawSpritePreview(spriteRect);
  472. HandleSpritePreviewCycle(spriteRect);
  473. }
  474. controller.rect = m_AngleRangeRect;
  475. controller.OnGUI();
  476. }
  477. EditorGUILayout.Space();
  478. EditorGUILayout.Space();
  479. }
  480. private void CreateReorderableSpriteList()
  481. {
  482. if (m_EmptySpriteList == null)
  483. {
  484. m_EmptySpriteList = new ReorderableList(new List<Sprite>(), typeof(Sprite), false, true, false, false)
  485. {
  486. drawHeaderCallback = (Rect rect) => { EditorGUI.LabelField(rect, Contents.spritesLabel); }
  487. };
  488. }
  489. m_AngleRangeSpriteList = null;
  490. serializedObject.UpdateIfRequiredOrScript();
  491. Debug.Assert(angleRanges.Count == m_AngleRangesProp.arraySize);
  492. Debug.Assert(selectedIndex < angleRanges.Count || selectedIndex == 0);
  493. if (targets.Length == 1 && isSelectedIndexValid)
  494. {
  495. var spritesProp = m_AngleRangesProp.GetArrayElementAtIndex(selectedIndex).FindPropertyRelative("m_Sprites");
  496. m_AngleRangeSpriteList = new ReorderableList(spritesProp.serializedObject, spritesProp)
  497. {
  498. drawElementCallback = DrawSpriteListElement,
  499. drawHeaderCallback = DrawSpriteListHeader,
  500. onSelectCallback = OnSelelectSpriteCallback,
  501. onRemoveCallback = OnRemoveSprite,
  502. onCanAddCallback = OnCanAddCallback,
  503. elementHeight = EditorGUIUtility.singleLineHeight + 6f
  504. };
  505. }
  506. }
  507. private void DrawSpritePreview(Rect rect)
  508. {
  509. if (Event.current.type != EventType.Repaint)
  510. return;
  511. if (!isSelectedIndexValid)
  512. return;
  513. var sprites = angleRanges[selectedIndex].sprites;
  514. if (sprites.Count == 0)
  515. return;
  516. var selectedSpriteIndex = GetPreviewSpriteIndex(selectedIndex);
  517. if (selectedSpriteIndex == kInvalidMinimum || selectedSpriteIndex >= sprites.Count)
  518. return;
  519. var sprite = sprites[selectedSpriteIndex];
  520. if (sprite == null)
  521. return;
  522. if (m_PreviewSprite != sprite)
  523. {
  524. m_PreviewSprite = sprite;
  525. EditorSpriteGUIUtility.DrawSpriteInRectPrepare(rect, sprite, EditorSpriteGUIUtility.FitMode.Tiled, true, true, previewSpriteMesh);
  526. }
  527. var material = EditorSpriteGUIUtility.spriteMaterial;
  528. material.mainTexture = EditorSpriteGUIUtility.GetOriginalSpriteTexture(sprite);
  529. EditorSpriteGUIUtility.DrawMesh(previewSpriteMesh, material, rect.center, Quaternion.AngleAxis(m_PreviewAngle, Vector3.forward), new Vector3(1f, -1f, 1f));
  530. }
  531. private void HandleSpritePreviewCycle(Rect rect)
  532. {
  533. if (!isSelectedIndexValid)
  534. return;
  535. Debug.Assert(m_AngleRangeSpriteList != null);
  536. var spriteIndex = GetPreviewSpriteIndex(selectedIndex);
  537. var sprites = angleRanges[selectedIndex].sprites;
  538. var ev = Event.current;
  539. if (ev.type == EventType.MouseDown && ev.button == 0 && HandleUtility.nearestControl == 0 &&
  540. ContainsPosition(rect, ev.mousePosition, m_PreviewAngle) && spriteIndex != kInvalidMinimum && sprites.Count > 0)
  541. {
  542. spriteIndex = Mathf.RoundToInt(Mathf.Repeat(spriteIndex + 1f, sprites.Count));
  543. SetPreviewSpriteIndex(selectedIndex, spriteIndex);
  544. m_AngleRangeSpriteList.GrabKeyboardFocus();
  545. m_AngleRangeSpriteList.index = spriteIndex;
  546. ev.Use();
  547. }
  548. }
  549. private bool ContainsPosition(Rect rect, Vector2 position, float angle)
  550. {
  551. Vector2 delta = position - rect.center;
  552. position = (Vector2)(Quaternion.AngleAxis(-angle, Vector3.forward) * (Vector3)delta) + rect.center;
  553. return rect.Contains(position);
  554. }
  555. }
  556. }