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.

SpriteShapeControllerEditor.cs 30KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEngine;
  5. using UnityEngine.U2D;
  6. using UnityEditor;
  7. using UnityEditor.U2D.SpriteShapeInternal;
  8. using UnityEditor.U2D.Common;
  9. using UnityEditor.AnimatedValues;
  10. using UnityEditor.EditorTools;
  11. using UnityEditor.Overlays;
  12. using UnityEditor.U2D.Common.Path;
  13. using UnityEngine.SceneManagement;
  14. using Object = UnityEngine.Object;
  15. namespace UnityEditor.U2D
  16. {
  17. [CustomEditor(typeof(SpriteShapeController))]
  18. [CanEditMultipleObjects]
  19. internal class SpriteShapeControllerEditor : PathComponentEditor<CustomPath>
  20. {
  21. private static class Contents
  22. {
  23. public static readonly GUIContent splineLabel = new GUIContent("Spline");
  24. public static readonly string editSplineLabel = "Edit Spline";
  25. public static readonly GUIContent fillLabel = new GUIContent("Fill");
  26. public static readonly GUIContent colliderLabel = new GUIContent("Collider");
  27. public static readonly GUIContent fillPixelPerUnitLabel = new GUIContent("Pixel Per Unit", "Pixel Per Unit for fill texture.");
  28. public static readonly GUIContent spriteShapeProfile = new GUIContent("Profile", "The SpriteShape Profile to render");
  29. public static readonly GUIContent materialLabel = new GUIContent("Material", "Material to be used by SpriteRenderer");
  30. public static readonly GUIContent colorLabel = new GUIContent("Color", "Rendering color for the Sprite graphic");
  31. public static readonly GUIContent metaDataLabel = new GUIContent("Meta Data", "SpriteShape specific controlpoint data");
  32. public static readonly GUIContent showComponentsLabel = new GUIContent("Show Render Stuff", "Show Renderer Components.");
  33. public static readonly GUIContent[] splineDetailOptions = { new GUIContent("High Quality"), new GUIContent("Medium Quality"), new GUIContent("Low Quality") };
  34. public static readonly GUIContent splineDetail = new GUIContent("Detail", "Tessellation Quality for rendering.");
  35. public static readonly GUIContent openEndedLabel = new GUIContent("Open Ended", "Is the path open ended or closed.");
  36. public static readonly GUIContent adaptiveUVLabel = new GUIContent("Adaptive UV", "Allow Adaptive UV Generation");
  37. public static readonly GUIContent enableTangentsLabel = new GUIContent("Enable Tangents", "Enable Tangents for 2D Lighting.");
  38. public static readonly GUIContent worldUVLabel = new GUIContent("Worldspace UV", "Generate UV for world space.");
  39. public static readonly GUIContent stretchUVLabel = new GUIContent("Stretch UV", "Stretch the Fill UV to full Rect.");
  40. public static readonly GUIContent stretchTilingLabel = new GUIContent("Stretch Tiling", "Stretch Tiling Count.");
  41. public static readonly GUIContent colliderDetail = new GUIContent("Detail", "Tessellation Quality on the collider.");
  42. public static readonly GUIContent cornerThresholdDetail = new GUIContent("Corner Threshold", "Corner angle threshold below which corners wont be placed.");
  43. public static readonly GUIContent colliderOffset = new GUIContent("Offset", "Extrude collider distance.");
  44. public static readonly GUIContent updateColliderLabel = new GUIContent("Update Collider", "Update Collider as you edit SpriteShape");
  45. public static readonly GUIContent optimizeColliderLabel = new GUIContent("Optimize Collider", "Cleanup planar self-intersections and optimize collider points");
  46. public static readonly GUIContent optimizeGeometryLabel = new GUIContent("Optimize Geometry", "Simplify geometry");
  47. public static readonly GUIContent cacheGeometryLabel = new GUIContent("Cache Geometry", "Bake geometry data. This will save geometry data on editor and load it on runtime instead of generating.");
  48. public static readonly GUIContent uTess2DLabel = new GUIContent("Fill Tessellation (C# Job)", "Use C# Jobs to generate Fill Geometry. (Edge geometry always uses C# Jobs)");
  49. public static readonly GUIContent creatorLabel = new GUIContent("Custom Geometry Creator", "Allows over-riding default geometry calculations with a custom one.");
  50. public static readonly GUIContent modifiersLabel = new GUIContent("Custom Geometry Modifier", "Allows processing / modifying generated vertices geometry.");
  51. }
  52. private SerializedProperty m_SpriteShapeProp;
  53. private SerializedProperty m_SplineDetailProp;
  54. private SerializedProperty m_IsOpenEndedProp;
  55. private SerializedProperty m_AdaptiveUVProp;
  56. private SerializedProperty m_StretchUVProp;
  57. private SerializedProperty m_StretchTilingProp;
  58. private SerializedProperty m_WorldSpaceUVProp;
  59. private SerializedProperty m_FillPixelPerUnitProp;
  60. private SerializedProperty m_CornerAngleThresholdProp;
  61. private SerializedProperty m_ColliderAutoUpdate;
  62. private SerializedProperty m_ColliderDetailProp;
  63. private SerializedProperty m_ColliderOffsetProp;
  64. private SerializedProperty m_EnableTangentsProp;
  65. private SerializedProperty m_GeometryCachedProp;
  66. private SerializedProperty m_UTess2DGeometryProp;
  67. private SerializedProperty m_CreatorProp;
  68. private SerializedProperty m_ModifierListProp;
  69. public static SpriteShapeControllerEditor spriteshapeControllerEditor;
  70. private int m_CollidersCount = 0;
  71. private int[] m_QualityValues = new int[] { (int)QualityDetail.High, (int)QualityDetail.Mid, (int)QualityDetail.Low };
  72. readonly AnimBool m_ShowStretchOption = new AnimBool();
  73. readonly AnimBool m_ShowNonStretchOption = new AnimBool();
  74. private struct ShapeSegment
  75. {
  76. public int start;
  77. public int end;
  78. public int angleRange;
  79. };
  80. private struct ShapeAngleRange
  81. {
  82. public float start;
  83. public float end;
  84. public int order;
  85. public int index;
  86. };
  87. int m_ButtonSize = 4;
  88. int m_SelectedPoint = -1;
  89. int m_SelectedAngleRange = -1;
  90. int m_SpriteShapeHashCode = 0;
  91. int m_SplineHashCode = 0;
  92. List<ShapeSegment> m_ShapeSegments = new List<ShapeSegment>();
  93. SpriteSelector spriteSelector = new SpriteSelector();
  94. private SpriteShapeController m_SpriteShapeController
  95. {
  96. get { return target as SpriteShapeController; }
  97. }
  98. private void OnEnable()
  99. {
  100. if (target == null)
  101. return;
  102. m_SpriteShapeProp = serializedObject.FindProperty("m_SpriteShape");
  103. m_SplineDetailProp = serializedObject.FindProperty("m_SplineDetail");
  104. m_IsOpenEndedProp = serializedObject.FindProperty("m_Spline").FindPropertyRelative("m_IsOpenEnded");
  105. m_AdaptiveUVProp = serializedObject.FindProperty("m_AdaptiveUV");
  106. m_StretchUVProp = serializedObject.FindProperty("m_StretchUV");
  107. m_StretchTilingProp = serializedObject.FindProperty("m_StretchTiling");
  108. m_WorldSpaceUVProp = serializedObject.FindProperty("m_WorldSpaceUV");
  109. m_FillPixelPerUnitProp = serializedObject.FindProperty("m_FillPixelPerUnit");
  110. m_CornerAngleThresholdProp = serializedObject.FindProperty("m_CornerAngleThreshold");
  111. m_ColliderAutoUpdate = serializedObject.FindProperty("m_UpdateCollider");
  112. m_ColliderDetailProp = serializedObject.FindProperty("m_ColliderDetail");
  113. m_ColliderOffsetProp = serializedObject.FindProperty("m_ColliderOffset");
  114. m_EnableTangentsProp = serializedObject.FindProperty("m_EnableTangents");
  115. m_GeometryCachedProp = serializedObject.FindProperty("m_GeometryCached");
  116. m_UTess2DGeometryProp = serializedObject.FindProperty("m_UTess2D");
  117. m_CreatorProp = serializedObject.FindProperty("m_Creator");
  118. m_ModifierListProp = serializedObject.FindProperty("m_Modifiers");
  119. m_ShowStretchOption.valueChanged.AddListener(Repaint);
  120. m_ShowStretchOption.value = ShouldShowStretchOption();
  121. m_ShowNonStretchOption.valueChanged.AddListener(Repaint);
  122. m_ShowNonStretchOption.value = !ShouldShowStretchOption();
  123. m_CollidersCount += ((m_SpriteShapeController.edgeCollider != null) ? 1 : 0);
  124. m_CollidersCount += ((m_SpriteShapeController.polygonCollider != null) ? 1 : 0);
  125. spriteshapeControllerEditor = this;
  126. }
  127. private void OnDisable()
  128. {
  129. SpriteShapeUpdateCache.UpdateCache(targets);
  130. spriteshapeControllerEditor = null;
  131. }
  132. private bool OnCollidersAddedOrRemoved()
  133. {
  134. PolygonCollider2D polygonCollider = m_SpriteShapeController.polygonCollider;
  135. EdgeCollider2D edgeCollider = m_SpriteShapeController.edgeCollider;
  136. int collidersCount = 0;
  137. if (polygonCollider != null)
  138. collidersCount = collidersCount + 1;
  139. if (edgeCollider != null)
  140. collidersCount = collidersCount + 1;
  141. if (collidersCount != m_CollidersCount)
  142. {
  143. m_CollidersCount = collidersCount;
  144. return true;
  145. }
  146. return false;
  147. }
  148. public void DrawHeader(GUIContent content)
  149. {
  150. EditorGUILayout.LabelField(content, EditorStyles.boldLabel);
  151. }
  152. private bool ShouldShowStretchOption()
  153. {
  154. return m_StretchUVProp.boolValue;
  155. }
  156. static bool WithinRange(ShapeAngleRange angleRange, float inputAngle)
  157. {
  158. float range = angleRange.end - angleRange.start;
  159. float angle = Mathf.Repeat(inputAngle - angleRange.start, 360f);
  160. angle = (angle == 360.0f) ? 0 : angle;
  161. return (angle >= 0f && angle <= range);
  162. }
  163. static int RangeFromAngle(List<ShapeAngleRange> angleRanges, float angle)
  164. {
  165. foreach (var range in angleRanges)
  166. {
  167. if (WithinRange(range, angle))
  168. return range.index;
  169. }
  170. return -1;
  171. }
  172. private List<ShapeAngleRange> GetAngleRangeSorted(UnityEngine.U2D.SpriteShape ss)
  173. {
  174. List<ShapeAngleRange> angleRanges = new List<ShapeAngleRange>();
  175. int i = 0;
  176. foreach (var angleRange in ss.angleRanges)
  177. {
  178. ShapeAngleRange sar = new ShapeAngleRange() { start = angleRange.start, end = angleRange.end, order = angleRange.order, index = i };
  179. angleRanges.Add(sar);
  180. i++;
  181. }
  182. angleRanges.Sort((a, b) => a.order.CompareTo(b.order));
  183. return angleRanges;
  184. }
  185. private void GenerateSegments(SpriteShapeController sc, List<ShapeAngleRange> angleRanges)
  186. {
  187. var controlPointCount = sc.spline.GetPointCount();
  188. var angleRangeIndices = new int[controlPointCount];
  189. ShapeSegment activeSegment = new ShapeSegment() { start = -1, end = -1, angleRange = -1 };
  190. m_ShapeSegments.Clear();
  191. for (int i = 0; i < controlPointCount; ++i)
  192. {
  193. var actv = i;
  194. var next = SplineUtility.NextIndex(actv, controlPointCount);
  195. var pos1 = sc.spline.GetPosition(actv);
  196. var pos2 = sc.spline.GetPosition(next);
  197. bool continueStrip = (sc.spline.GetTangentMode(actv) == ShapeTangentMode.Continuous), edgeUpdated = false;
  198. float angle = 0;
  199. if (false == continueStrip || activeSegment.start == -1)
  200. angle = SplineUtility.SlopeAngle(pos1, pos2) + 90.0f;
  201. next = (!sc.spline.isOpenEnded && next == 0) ? (actv + 1) : next;
  202. int mn = (actv < next) ? actv : next;
  203. int mx = (actv > next) ? actv : next;
  204. var anglerange = RangeFromAngle(angleRanges, angle);
  205. angleRangeIndices[actv] = anglerange;
  206. if (anglerange == -1)
  207. {
  208. activeSegment = new ShapeSegment() { start = mn, end = mx, angleRange = anglerange };
  209. m_ShapeSegments.Add(activeSegment);
  210. continue;
  211. }
  212. // Check for Segments. Also check if the Segment Start has been resolved. Otherwise simply start with the next one
  213. if (activeSegment.start != -1)
  214. continueStrip = continueStrip && (angleRangeIndices[activeSegment.start] != -1);
  215. bool canContinue = (actv != (controlPointCount - 1)) || (!sc.spline.isOpenEnded && (actv == (controlPointCount - 1)));
  216. if (continueStrip && canContinue)
  217. {
  218. for (int s = 0; s < m_ShapeSegments.Count; ++s)
  219. {
  220. activeSegment = m_ShapeSegments[s];
  221. if (activeSegment.start - mn == 1)
  222. {
  223. edgeUpdated = true;
  224. activeSegment.start = mn;
  225. m_ShapeSegments[s] = activeSegment;
  226. break;
  227. }
  228. if (mx - activeSegment.end == 1)
  229. {
  230. edgeUpdated = true;
  231. activeSegment.end = mx;
  232. m_ShapeSegments[s] = activeSegment;
  233. break;
  234. }
  235. }
  236. }
  237. if (!edgeUpdated)
  238. {
  239. activeSegment.start = mn;
  240. activeSegment.end = mx;
  241. activeSegment.angleRange = anglerange;
  242. m_ShapeSegments.Add(activeSegment);
  243. }
  244. }
  245. }
  246. private int GetAngleRange(SpriteShapeController sc, int point, ref int startPoint)
  247. {
  248. int angleRange = -1;
  249. startPoint = point;
  250. for (int i = 0; i < m_ShapeSegments.Count; ++i)
  251. {
  252. if (point >= m_ShapeSegments[i].start && point < m_ShapeSegments[i].end)
  253. {
  254. angleRange = m_ShapeSegments[i].angleRange;
  255. startPoint = point; // m_ShapeSegments[i].start;
  256. if (angleRange >= sc.spriteShape.angleRanges.Count)
  257. angleRange = 0;
  258. break;
  259. }
  260. }
  261. return angleRange;
  262. }
  263. private void UpdateSegments()
  264. {
  265. var sc = target as SpriteShapeController;
  266. // Either SpriteShape Asset or SpriteShape Data has changed.
  267. if (m_SpriteShapeHashCode != sc.spriteShapeHashCode || m_SplineHashCode != sc.splineHashCode)
  268. {
  269. List<ShapeAngleRange> angleRanges = GetAngleRangeSorted(sc.spriteShape);
  270. GenerateSegments(sc, angleRanges);
  271. m_SpriteShapeHashCode = sc.spriteShapeHashCode;
  272. m_SplineHashCode = sc.splineHashCode;
  273. m_SelectedPoint = -1;
  274. }
  275. }
  276. private int ResolveSpriteIndex(List<int> spriteIndices, ISelection<int> selection, ref List<int> startPoints)
  277. {
  278. var spriteIndexValue = spriteIndices.FirstOrDefault();
  279. var sc = target as SpriteShapeController;
  280. var spline = sc.spline;
  281. if (sc == null || sc.spriteShape == null)
  282. return -1;
  283. UpdateSegments();
  284. if (sc.spriteShape != null)
  285. {
  286. if (selection.Count == 1)
  287. {
  288. m_SelectedAngleRange = GetAngleRange(sc, selection.elements[0], ref m_SelectedPoint);
  289. startPoints.Add(m_SelectedPoint);
  290. spriteIndexValue = spline.GetSpriteIndex(m_SelectedPoint);
  291. }
  292. else
  293. {
  294. m_SelectedAngleRange = -1;
  295. foreach (var index in selection.elements)
  296. {
  297. int startPoint = index;
  298. int angleRange = GetAngleRange(sc, index, ref startPoint);
  299. if (m_SelectedAngleRange != -1 && angleRange != m_SelectedAngleRange)
  300. {
  301. m_SelectedAngleRange = -1;
  302. break;
  303. }
  304. startPoints.Add(startPoint);
  305. m_SelectedAngleRange = angleRange;
  306. }
  307. }
  308. }
  309. if (m_SelectedAngleRange != -1)
  310. spriteSelector.UpdateSprites(sc.spriteShape.angleRanges[m_SelectedAngleRange].sprites.ToArray());
  311. else
  312. spriteIndexValue = -1;
  313. return spriteIndexValue;
  314. }
  315. public int GetAngleRange(int index)
  316. {
  317. int startPoint = 0;
  318. var sc = target as SpriteShapeController;
  319. UpdateSegments();
  320. return GetAngleRange(sc, index, ref startPoint);
  321. }
  322. public void OnOverlayGUI()
  323. {
  324. var pathTool = SpriteShapeEditorTool.activeSpriteShapeEditorTool;
  325. serializedObject.Update();
  326. DoPathInspector<SpriteShapeEditorTool>();
  327. if (Selection.gameObjects.Length == 1 && pathTool != null)
  328. {
  329. var sc = target as SpriteShapeController;
  330. var path = pathTool.GetPath(sc);
  331. if (path != null)
  332. {
  333. var selection = path.selection;
  334. if (selection.Count > 0)
  335. {
  336. var spline = sc.spline;
  337. var spriteIndices = new List<int>();
  338. List<int> startPoints = new List<int>();
  339. foreach (int index in selection.elements)
  340. spriteIndices.Add(spline.GetSpriteIndex(index));
  341. var spriteIndexValue = ResolveSpriteIndex(spriteIndices, selection, ref startPoints);
  342. if (spriteIndexValue != -1)
  343. {
  344. EditorGUI.BeginChangeCheck();
  345. spriteSelector.SetCustomSize(0, m_ButtonSize);
  346. bool shown = spriteSelector.ShowGUI(spriteIndexValue);
  347. spriteSelector.ResetSize();
  348. if (EditorGUI.EndChangeCheck())
  349. {
  350. foreach (var index in startPoints)
  351. {
  352. var data = path.GetData(index);
  353. data.spriteIndex = spriteSelector.selectedIndex;
  354. path.SetData(index, data);
  355. }
  356. pathTool.SetPath(target);
  357. }
  358. if (spriteSelector.hasSprites)
  359. m_ButtonSize = (int)GUI.HorizontalSlider(new Rect(InternalEditorBridge.GetEditorGUILayoutLastRect().width - 64, InternalEditorBridge.GetEditorGUILayoutLastRect().y + 100, 64, 100 ), m_ButtonSize, 1, 4);
  360. }
  361. EditorGUILayout.Space();
  362. }
  363. }
  364. }
  365. serializedObject.ApplyModifiedProperties();
  366. }
  367. public override void OnInspectorGUI()
  368. {
  369. var updateCollider = false;
  370. EditorGUI.BeginChangeCheck();
  371. serializedObject.Update();
  372. EditorGUILayout.PropertyField(m_SpriteShapeProp, Contents.spriteShapeProfile);
  373. DoEditButton<SpriteShapeEditorTool>(PathEditorToolContents.icon, Contents.editSplineLabel);
  374. EditorGUILayout.Space();
  375. DrawHeader(Contents.splineLabel);
  376. EditorGUILayout.IntPopup(m_SplineDetailProp, Contents.splineDetailOptions, m_QualityValues, Contents.splineDetail);
  377. serializedObject.ApplyModifiedProperties();
  378. DoOpenEndedInspector<SpriteShapeEditorTool>(m_IsOpenEndedProp);
  379. serializedObject.Update();
  380. EditorGUILayout.PropertyField(m_AdaptiveUVProp, Contents.adaptiveUVLabel);
  381. EditorGUILayout.PropertyField(m_EnableTangentsProp, Contents.enableTangentsLabel);
  382. if (UnityEditor.EditorTools.ToolManager.activeToolType == typeof(SpriteShapeEditorTool))
  383. {
  384. // Cache Geometry is only editable for Scene Objects or when in Prefab Isolation Mode.
  385. if (Selection.gameObjects.Length == 1 && Selection.transforms.Contains(Selection.gameObjects[0].transform))
  386. {
  387. EditorGUI.BeginChangeCheck();
  388. EditorGUILayout.PropertyField(m_GeometryCachedProp, Contents.cacheGeometryLabel);
  389. if (EditorGUI.EndChangeCheck())
  390. {
  391. if (m_GeometryCachedProp.boolValue)
  392. {
  393. var geometryCache = m_SpriteShapeController.spriteShapeGeometryCache;
  394. if (!geometryCache)
  395. geometryCache = m_SpriteShapeController.gameObject
  396. .AddComponent<SpriteShapeGeometryCache>();
  397. geometryCache.hideFlags = HideFlags.HideInInspector;
  398. }
  399. else
  400. {
  401. if (m_SpriteShapeController.spriteShapeGeometryCache)
  402. Object.DestroyImmediate(m_SpriteShapeController.spriteShapeGeometryCache);
  403. }
  404. m_SpriteShapeController.RefreshSpriteShape();
  405. }
  406. }
  407. SpriteShapeUpdateCache.s_cacheGeometrySet = true;
  408. }
  409. EditorGUI.BeginChangeCheck();
  410. var threshold = EditorGUILayout.Slider(Contents.cornerThresholdDetail, m_CornerAngleThresholdProp.floatValue, 0.0f, 90.0f);
  411. if (EditorGUI.EndChangeCheck())
  412. {
  413. m_CornerAngleThresholdProp.floatValue = threshold;
  414. updateCollider = true;
  415. }
  416. Debug.Assert(null != m_SpriteShapeController.spriteShapeCreator);
  417. EditorGUILayout.Space();
  418. DrawHeader(Contents.fillLabel);
  419. EditorGUILayout.PropertyField(m_UTess2DGeometryProp, Contents.uTess2DLabel);
  420. EditorGUILayout.PropertyField(m_StretchUVProp, Contents.stretchUVLabel);
  421. EditorGUILayout.PropertyField(m_CreatorProp, Contents.creatorLabel);
  422. EditorGUILayout.PropertyField(m_ModifierListProp, Contents.modifiersLabel);
  423. if (ShouldShowStretchOption())
  424. {
  425. EditorGUILayout.PropertyField(m_StretchTilingProp, Contents.stretchTilingLabel);
  426. }
  427. else
  428. {
  429. EditorGUILayout.PropertyField(m_FillPixelPerUnitProp, Contents.fillPixelPerUnitLabel);
  430. EditorGUILayout.PropertyField(m_WorldSpaceUVProp, Contents.worldUVLabel);
  431. }
  432. if (m_SpriteShapeController.gameObject.GetComponent<PolygonCollider2D>() != null || m_SpriteShapeController.gameObject.GetComponent<EdgeCollider2D>() != null)
  433. {
  434. EditorGUILayout.Space();
  435. DrawHeader(Contents.colliderLabel);
  436. EditorGUILayout.PropertyField(m_ColliderAutoUpdate, Contents.updateColliderLabel);
  437. if (m_ColliderAutoUpdate.boolValue)
  438. {
  439. EditorGUILayout.PropertyField(m_ColliderOffsetProp, Contents.colliderOffset);
  440. EditorGUILayout.IntPopup(m_ColliderDetailProp, Contents.splineDetailOptions, m_QualityValues, Contents.colliderDetail);
  441. }
  442. }
  443. if (EditorGUI.EndChangeCheck())
  444. {
  445. updateCollider = true;
  446. }
  447. serializedObject.ApplyModifiedProperties();
  448. if (updateCollider || OnCollidersAddedOrRemoved())
  449. BakeCollider();
  450. }
  451. void BakeCollider()
  452. {
  453. if (m_SpriteShapeController.autoUpdateCollider == false && !m_SpriteShapeController.forceColliderShapeUpdate)
  454. return;
  455. PolygonCollider2D polygonCollider = m_SpriteShapeController.polygonCollider;
  456. if (polygonCollider)
  457. {
  458. Undo.RegisterCompleteObjectUndo(polygonCollider, Undo.GetCurrentGroupName());
  459. EditorUtility.SetDirty(polygonCollider);
  460. m_SpriteShapeController.RefreshSpriteShape();
  461. }
  462. EdgeCollider2D edgeCollider = m_SpriteShapeController.edgeCollider;
  463. if (edgeCollider)
  464. {
  465. Undo.RegisterCompleteObjectUndo(edgeCollider, Undo.GetCurrentGroupName());
  466. EditorUtility.SetDirty(edgeCollider);
  467. m_SpriteShapeController.RefreshSpriteShape();
  468. }
  469. }
  470. void ShowMaterials(bool show)
  471. {
  472. HideFlags hideFlags = HideFlags.HideInInspector;
  473. if (show)
  474. hideFlags = HideFlags.None;
  475. Material[] materials = m_SpriteShapeController.spriteShapeRenderer.sharedMaterials;
  476. foreach (Material material in materials)
  477. {
  478. material.hideFlags = hideFlags;
  479. EditorUtility.SetDirty(material);
  480. }
  481. }
  482. [DrawGizmo(GizmoType.InSelectionHierarchy)]
  483. static void RenderSpline(SpriteShapeController m_SpriteShapeController, GizmoType gizmoType)
  484. {
  485. if (UnityEditor.EditorTools.ToolManager.activeToolType == typeof(SpriteShapeEditorTool))
  486. return;
  487. var m_Spline = m_SpriteShapeController.spline;
  488. var oldMatrix = Handles.matrix;
  489. var oldColor = Handles.color;
  490. Handles.matrix = m_SpriteShapeController.transform.localToWorldMatrix;
  491. Handles.color = Color.grey;
  492. var pointCount = m_Spline.GetPointCount();
  493. for (var i = 0; i < (m_Spline.isOpenEnded ? pointCount - 1 : pointCount); ++i)
  494. {
  495. Vector3 p1 = m_Spline.GetPosition(i);
  496. Vector3 p2 = m_Spline.GetPosition((i + 1) % pointCount);
  497. var t1 = p1 + m_Spline.GetRightTangent(i);
  498. var t2 = p2 + m_Spline.GetLeftTangent((i + 1) % pointCount);
  499. Vector3[] bezierPoints = Handles.MakeBezierPoints(p1, p2, t1, t2, m_SpriteShapeController.splineDetail);
  500. Handles.DrawAAPolyLine(bezierPoints);
  501. }
  502. Handles.matrix = oldMatrix;
  503. Handles.color = oldColor;
  504. }
  505. }
  506. [Overlay(typeof(SceneView), k_OverlayId, k_DisplayName)]
  507. class SceneViewPathOverlay : IMGUIOverlay, ITransientOverlay
  508. {
  509. const string k_OverlayId = "Scene View/Path";
  510. const string k_DisplayName = "Element Inspector";
  511. public bool visible
  512. {
  513. get
  514. {
  515. var pathTool = SpriteShapeEditorTool.activeSpriteShapeEditorTool;
  516. var valid= SpriteShapeControllerEditor.spriteshapeControllerEditor != null && pathTool != null;
  517. if (valid)
  518. {
  519. if (pathTool.targets != null)
  520. {
  521. foreach (var t in pathTool.targets)
  522. {
  523. var s = pathTool.GetPath(t);
  524. if (null != s && s.selection.Count != 0)
  525. return true;
  526. }
  527. }
  528. else if (pathTool.target != null)
  529. {
  530. var s1 = pathTool.GetPath(pathTool.target);
  531. if (null != s1 && s1.selection.Count != 0)
  532. return true;
  533. }
  534. }
  535. return false;
  536. }
  537. }
  538. public override void OnGUI()
  539. {
  540. if (SpriteShapeControllerEditor.spriteshapeControllerEditor == null)
  541. return;
  542. SpriteShapeControllerEditor.spriteshapeControllerEditor.OnOverlayGUI();
  543. }
  544. }
  545. [UnityEditor.InitializeOnLoad]
  546. internal static class SpriteShapeUpdateCache
  547. {
  548. internal static bool s_cacheGeometrySet = false;
  549. static SpriteShapeUpdateCache()
  550. {
  551. UnityEditor.EditorApplication.playModeStateChanged += change =>
  552. {
  553. if (change == UnityEditor.PlayModeStateChange.ExitingEditMode)
  554. UpdateSpriteShapeCacheInOpenScenes();
  555. };
  556. SceneManagement.EditorSceneManager.sceneSaving += (scene, removingScene) =>
  557. {
  558. SaveSpriteShapesInScene(scene);
  559. };
  560. UnityEditor.EditorTools.ToolManager.activeToolChanging += () =>
  561. {
  562. if (UnityEditor.EditorTools.ToolManager.activeToolType == typeof(SpriteShapeEditorTool))
  563. {
  564. if (null != SpriteShapeControllerEditor.spriteshapeControllerEditor)
  565. UpdateCache(SpriteShapeControllerEditor.spriteshapeControllerEditor.targets);
  566. }
  567. };
  568. }
  569. static void SaveSpriteShapesInScene(Scene scene)
  570. {
  571. var gos = scene.GetRootGameObjects();
  572. foreach (var go in gos)
  573. {
  574. if (!go.activeInHierarchy)
  575. continue;
  576. var scs = go.GetComponentsInChildren<SpriteShapeController>();
  577. foreach (var sc in scs)
  578. {
  579. var jh = sc.BakeMesh();
  580. jh.Complete();
  581. }
  582. }
  583. }
  584. static void UpdateSpriteShapeCacheInOpenScenes()
  585. {
  586. for (int i = 0; s_cacheGeometrySet && (i < SceneManager.sceneCount); ++i)
  587. {
  588. var scene = SceneManager.GetSceneAt(i);
  589. SaveSpriteShapesInScene(scene);
  590. }
  591. s_cacheGeometrySet = false;
  592. }
  593. internal static void UpdateCache(UnityEngine.Object[] targets)
  594. {
  595. foreach (var t in targets)
  596. {
  597. var s = t as SpriteShapeController;
  598. if (s)
  599. if (s.gameObject.activeInHierarchy && s.spriteShapeGeometryCache)
  600. s.spriteShapeGeometryCache.UpdateGeometryCache();
  601. }
  602. }
  603. }
  604. }