Açıklama Yok
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.

SpriteShapeHandleUtility.cs 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. using UnityEditor;
  2. using UnityEngine;
  3. using UnityEditor.Sprites;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. namespace UnityEditor.U2D
  7. {
  8. internal class SpriteShapeHandleUtility
  9. {
  10. private class Styles
  11. {
  12. public Texture playheadTex;
  13. public Texture handRightTex;
  14. public Texture handLeftTex;
  15. }
  16. private static Styles s_Styles;
  17. private static Styles styles
  18. {
  19. get
  20. {
  21. if (s_Styles == null)
  22. s_Styles = new Styles();
  23. return s_Styles;
  24. }
  25. }
  26. static private Material s_HandleWireMaterial;
  27. private static Material handleWireMaterial
  28. {
  29. get
  30. {
  31. if (!s_HandleWireMaterial)
  32. s_HandleWireMaterial = (Material)EditorGUIUtility.LoadRequired("SceneView/2DHandleLines.mat");
  33. return s_HandleWireMaterial;
  34. }
  35. }
  36. private static Material s_FillTextureMaterial;
  37. private static Material fillTextureMaterial
  38. {
  39. get
  40. {
  41. if (s_FillTextureMaterial == null)
  42. {
  43. s_FillTextureMaterial = new Material(Shader.Find("Hidden/InternalSpritesInspector"));
  44. s_FillTextureMaterial.hideFlags = HideFlags.DontSave;
  45. }
  46. s_FillTextureMaterial.SetFloat("_AdjustLinearForGamma", PlayerSettings.colorSpace == ColorSpace.Linear ? 1.0f : 0.0f);
  47. return s_FillTextureMaterial;
  48. }
  49. }
  50. private static Mesh s_TextureCapMesh;
  51. private static Mesh textureCapMesh
  52. {
  53. get
  54. {
  55. if (s_TextureCapMesh == null)
  56. {
  57. s_TextureCapMesh = new Mesh();
  58. s_TextureCapMesh.hideFlags = HideFlags.DontSave;
  59. s_TextureCapMesh.vertices = new Vector3[] {
  60. new Vector2(-0.5f, -0.5f),
  61. new Vector2(-0.5f, 0.5f),
  62. new Vector2(0.5f, 0.5f),
  63. new Vector2(-0.5f, -0.5f),
  64. new Vector2(0.5f, 0.5f),
  65. new Vector2(0.5f, -0.5f)
  66. };
  67. s_TextureCapMesh.uv = new Vector2[] {
  68. Vector3.zero,
  69. Vector3.up,
  70. Vector3.up + Vector3.right,
  71. Vector3.zero,
  72. Vector3.up + Vector3.right,
  73. Vector3.right
  74. };
  75. s_TextureCapMesh.SetTriangles(new int[] { 0, 1, 2, 3, 4, 5 }, 0);
  76. }
  77. return s_TextureCapMesh;
  78. }
  79. }
  80. private static readonly Vector3[] s_WireArcPoints = new Vector3[60];
  81. public static float PosToAngle(Vector2 position, Vector2 center, float angleOffset)
  82. {
  83. Vector2 dir = (Quaternion.AngleAxis(angleOffset, Vector3.forward) * (position - center)).normalized;
  84. return Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
  85. }
  86. public static Vector2 Slider2D(int id, Vector2 position, Vector3 capOffset, Quaternion rotation, float size, Handles.CapFunction drawCapFunction)
  87. {
  88. return Handles.Slider2D(id, position, capOffset, Vector3.forward, rotation * Vector3.up, rotation * Vector3.right, size, drawCapFunction, Vector2.zero);
  89. }
  90. public static void DrawRangeOutline(float start, float end, float angleOffset, Vector2 center, float radius, float width)
  91. {
  92. Vector3 startVec = Quaternion.AngleAxis(start + angleOffset, Vector3.forward) * Vector3.right;
  93. Vector3 endVec = Quaternion.AngleAxis(end + angleOffset, Vector3.forward) * Vector3.right;
  94. Handles.DrawWireArc(center, Vector3.forward, startVec, end - start, radius - width);
  95. Handles.DrawWireArc(center, Vector3.forward, startVec, end - start, radius);
  96. Handles.DrawLine(startVec * (radius - width) + (Vector3)center, startVec * radius + (Vector3)center);
  97. Handles.DrawLine(endVec * (radius - width) + (Vector3)center, endVec * radius + (Vector3)center);
  98. }
  99. private static void ApplyWireMaterial()
  100. {
  101. UnityEngine.Rendering.CompareFunction zTest = UnityEngine.Rendering.CompareFunction.Always;
  102. ApplyWireMaterial(zTest);
  103. }
  104. private static void ApplyWireMaterial(UnityEngine.Rendering.CompareFunction zTest)
  105. {
  106. Material mat = handleWireMaterial;
  107. mat.SetInt("_HandleZTest", (int)zTest);
  108. mat.SetPass(0);
  109. }
  110. static void SetDiscSectionPoints(Vector3[] dest, Vector3 center, Vector3 normal, Vector3 from, float angle, float radius)
  111. {
  112. Vector3 fromn = from.normalized;
  113. Quaternion r = Quaternion.AngleAxis(angle / (float)(dest.Length - 1), normal);
  114. Vector3 tangent = fromn * radius;
  115. for (int i = 0; i < dest.Length; i++)
  116. {
  117. dest[i] = center + tangent;
  118. tangent = r * tangent;
  119. }
  120. }
  121. public static void DrawSolidArc(Vector3 center, Vector3 normal, Vector3 from, float angle, float radius, float width)
  122. {
  123. if (Event.current.type != EventType.Repaint)
  124. return;
  125. SetDiscSectionPoints(s_WireArcPoints, center, normal, from, angle, radius);
  126. Shader.SetGlobalColor("_HandleColor", Handles.color);
  127. Shader.SetGlobalFloat("_HandleSize", 1);
  128. ApplyWireMaterial(Handles.zTest);
  129. float widthPercentage = 1f - Mathf.Clamp01(width / radius);
  130. // Draw it twice to ensure backface culling doesn't hide any of the faces
  131. GL.PushMatrix();
  132. GL.MultMatrix(Handles.matrix);
  133. GL.Begin(GL.TRIANGLES);
  134. for (int i = 1, count = s_WireArcPoints.Length; i < count; ++i)
  135. {
  136. Vector3 d1 = s_WireArcPoints[i - 1] - center;
  137. Vector3 d2 = s_WireArcPoints[i] - center;
  138. GL.Color(Handles.color);
  139. GL.Vertex(d1 * widthPercentage + center);
  140. GL.Vertex(s_WireArcPoints[i - 1]);
  141. GL.Vertex(s_WireArcPoints[i]);
  142. GL.Vertex(d1 * widthPercentage + center);
  143. GL.Vertex(s_WireArcPoints[i]);
  144. GL.Vertex(d2 * widthPercentage + center);
  145. GL.Vertex(d1 * widthPercentage + center);
  146. GL.Vertex(s_WireArcPoints[i]);
  147. GL.Vertex(s_WireArcPoints[i - 1]);
  148. GL.Vertex(d1 * widthPercentage + center);
  149. GL.Vertex(d2 * widthPercentage + center);
  150. GL.Vertex(s_WireArcPoints[i]);
  151. }
  152. GL.End();
  153. GL.PopMatrix();
  154. }
  155. public static void DrawTextureArc(Texture texture, float pixelsPerRadius, Vector3 center, Vector3 normal, Vector3 from, float angle, float radius)
  156. {
  157. if (Event.current.type != EventType.Repaint || !texture)
  158. return;
  159. SetDiscSectionPoints(s_WireArcPoints, Vector3.zero, normal, from, angle, 0.5f);
  160. fillTextureMaterial.mainTexture = texture;
  161. fillTextureMaterial.mainTextureScale = new Vector2(1f, -1f);
  162. fillTextureMaterial.mainTextureOffset = Vector2.zero;
  163. fillTextureMaterial.SetPass(0);
  164. Matrix4x4 matrix = new Matrix4x4();
  165. matrix.SetTRS(center, Quaternion.identity, new Vector3(radius, radius, 1) * 2f);
  166. Vector3 texOffset = Vector2.one * 0.5f;
  167. float scale = pixelsPerRadius / radius;
  168. GL.PushMatrix();
  169. GL.LoadPixelMatrix();
  170. GL.MultMatrix(matrix);
  171. GL.Begin(GL.TRIANGLES);
  172. for (int i = 1, count = s_WireArcPoints.Length; i < count; ++i)
  173. {
  174. GL.Color(Handles.color);
  175. GL.TexCoord(texOffset);
  176. GL.Vertex(Vector3.zero);
  177. GL.TexCoord(s_WireArcPoints[i - 1] * scale + texOffset);
  178. GL.Vertex(s_WireArcPoints[i - 1]);
  179. GL.TexCoord(s_WireArcPoints[i] * scale + texOffset);
  180. GL.Vertex(s_WireArcPoints[i]);
  181. GL.TexCoord(texOffset);
  182. GL.Vertex(Vector3.zero);
  183. GL.TexCoord(s_WireArcPoints[i] * scale + texOffset);
  184. GL.Vertex(s_WireArcPoints[i]);
  185. GL.TexCoord(s_WireArcPoints[i - 1] * scale + texOffset);
  186. GL.Vertex(s_WireArcPoints[i - 1]);
  187. }
  188. GL.End();
  189. GL.PopMatrix();
  190. }
  191. public static void PlayHeadCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)
  192. {
  193. if (styles.playheadTex == null)
  194. styles.playheadTex = AssetDatabase.LoadAssetAtPath<Texture2D>("Packages/com.unity.2d.spriteshape/Editor/Handles/ss_playhead.png");
  195. GUITextureCap(controlID, styles.playheadTex, position, rotation, size, eventType);
  196. }
  197. public static void RangeLeftCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)
  198. {
  199. if (styles.handLeftTex == null)
  200. styles.handLeftTex = AssetDatabase.LoadAssetAtPath<Texture2D>("Packages/com.unity.2d.spriteshape/Editor/Handles/ss_leftrange.png");
  201. GUITextureCap(controlID, styles.handLeftTex, position, rotation, size, eventType);
  202. }
  203. public static void RangeRightCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType)
  204. {
  205. if (styles.handRightTex == null)
  206. styles.handRightTex = AssetDatabase.LoadAssetAtPath<Texture2D>("Packages/com.unity.2d.spriteshape/Editor/Handles/ss_rightrange.png");
  207. GUITextureCap(controlID, styles.handRightTex, position, rotation, size, eventType);
  208. }
  209. public static void GUITextureCap(int controlID, Texture texture, Vector3 position, Quaternion rotation, float size, EventType eventType)
  210. {
  211. switch (eventType)
  212. {
  213. case (EventType.Layout):
  214. HandleUtility.AddControl(controlID, DistanceToRectangle(position, rotation, Vector2.one * size * 0.5f));
  215. break;
  216. case (EventType.Repaint):
  217. FilterMode filterMode = texture.filterMode;
  218. texture.filterMode = FilterMode.Bilinear;
  219. EditorSpriteGUIUtility.spriteMaterial.mainTexture = texture;
  220. float w = (float)texture.width;
  221. float h = (float)texture.height;
  222. float max = Mathf.Max(w, h);
  223. Vector3 scale = new Vector2(w / max, h / max) * size;
  224. if (Camera.current == null)
  225. scale.y *= -1f;
  226. EditorSpriteGUIUtility.DrawMesh(textureCapMesh, EditorSpriteGUIUtility.spriteMaterial, position, rotation, scale);
  227. texture.filterMode = filterMode;
  228. break;
  229. }
  230. }
  231. public static float DistanceToArcWidth(Vector2 position, Vector2 center, float start, float end, float radius, float width, float angleOffet)
  232. {
  233. float innerRadius = radius - width;
  234. float angle = PosToAngle(position, center, -angleOffet);
  235. angle = Mathf.Repeat(angle - start, 360f);
  236. float range = end - start;
  237. if (angle >= 0f && angle <= range)
  238. {
  239. float distanceToCenter = (position - center).magnitude;
  240. if (distanceToCenter <= radius && distanceToCenter >= innerRadius)
  241. return 0f;
  242. else if (distanceToCenter > radius)
  243. return distanceToCenter - radius;
  244. else if (distanceToCenter < innerRadius)
  245. return innerRadius - distanceToCenter;
  246. }
  247. else if (angle < 0f)
  248. {
  249. Vector2 pos1 = (Vector2)(Quaternion.AngleAxis(start + angleOffet, Vector3.forward) * Vector3.right * radius) + center;
  250. Vector2 pos2 = (Vector2)(Quaternion.AngleAxis(start + angleOffet, Vector3.forward) * Vector3.right * innerRadius) + center;
  251. return Mathf.Min((position - pos1).magnitude, (position - pos2).magnitude);
  252. }
  253. else if (angle > range)
  254. {
  255. Vector2 pos1 = (Vector2)(Quaternion.AngleAxis(end + angleOffet, Vector3.forward) * Vector3.right * radius) + center;
  256. Vector2 pos2 = (Vector2)(Quaternion.AngleAxis(end + angleOffet, Vector3.forward) * Vector3.right * innerRadius) + center;
  257. return Mathf.Min((position - pos1).magnitude, (position - pos2).magnitude);
  258. }
  259. return float.MaxValue;
  260. }
  261. public static float DistanceToRectangle(Vector3 position, Quaternion rotation, Vector2 size)
  262. {
  263. Vector3[] points = { Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero };
  264. Vector3 sideways = rotation * new Vector3(size.x, 0, 0);
  265. Vector3 up = rotation * new Vector3(0, size.y, 0);
  266. points[0] = HandleUtility.WorldToGUIPoint(position + sideways + up);
  267. points[1] = HandleUtility.WorldToGUIPoint(position + sideways - up);
  268. points[2] = HandleUtility.WorldToGUIPoint(position - sideways - up);
  269. points[3] = HandleUtility.WorldToGUIPoint(position - sideways + up);
  270. points[4] = points[0];
  271. Vector2 pos = Event.current.mousePosition;
  272. bool oddNodes = false;
  273. int j = 4;
  274. for (int i = 0; i < 5; i++)
  275. {
  276. if ((points[i].y > pos.y) != (points[j].y > pos.y))
  277. {
  278. if (pos.x < (points[j].x - points[i].x) * (pos.y - points[i].y) / (points[j].y - points[i].y) + points[i].x)
  279. {
  280. oddNodes = !oddNodes;
  281. }
  282. }
  283. j = i;
  284. }
  285. if (!oddNodes)
  286. {
  287. // Distance to closest edge (not so fast)
  288. float dist, closestDist = -1f;
  289. j = 1;
  290. for (int i = 0; i < 4; i++)
  291. {
  292. dist = HandleUtility.DistancePointToLineSegment(pos, points[i], points[j++]);
  293. if (dist < closestDist || closestDist < 0)
  294. closestDist = dist;
  295. }
  296. return closestDist;
  297. }
  298. else
  299. return 0;
  300. }
  301. }
  302. }