暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

SpriteShapeControllerEditor.cs 28KB

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