SpriteShapeControllerEditor.cs 27 KB

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