Light2DEditor.cs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using UnityEditor.EditorTools;
  4. using UnityEditor.Experimental.Rendering.Universal.Path2D;
  5. using UnityEngine;
  6. using UnityEngine.Experimental.Rendering.Universal;
  7. using UnityEngine.Rendering.Universal;
  8. namespace UnityEditor.Experimental.Rendering.Universal
  9. {
  10. [CustomEditor(typeof(Light2D))]
  11. [CanEditMultipleObjects]
  12. internal class Light2DEditor : PathComponentEditor<ScriptablePath>
  13. {
  14. [EditorTool("Edit Freeform Shape", typeof(Light2D))]
  15. class FreeformShapeTool : PathEditorTool<ScriptablePath>
  16. {
  17. const string k_ShapePath = "m_ShapePath";
  18. public override bool IsAvailable()
  19. {
  20. var light = target as Light2D;
  21. if (light == null)
  22. return false;
  23. else
  24. return base.IsAvailable() && light.lightType == Light2D.LightType.Freeform;
  25. }
  26. protected override IShape GetShape(Object target)
  27. {
  28. return (target as Light2D).shapePath.ToPolygon(false);
  29. }
  30. protected override void SetShape(ScriptablePath shapeEditor, SerializedObject serializedObject)
  31. {
  32. serializedObject.Update();
  33. var pointsProperty = serializedObject.FindProperty(k_ShapePath);
  34. pointsProperty.arraySize = shapeEditor.pointCount;
  35. for (var i = 0; i < shapeEditor.pointCount; ++i)
  36. pointsProperty.GetArrayElementAtIndex(i).vector3Value = shapeEditor.GetPoint(i).position;
  37. ((Light2D)(serializedObject.targetObject)).UpdateMesh();
  38. // This is untracked right now...
  39. serializedObject.ApplyModifiedProperties();
  40. }
  41. }
  42. private static class Styles
  43. {
  44. public static Texture lightCapTopRight = Resources.Load<Texture>("LightCapTopRight");
  45. public static Texture lightCapTopLeft = Resources.Load<Texture>("LightCapTopLeft");
  46. public static Texture lightCapBottomLeft = Resources.Load<Texture>("LightCapBottomLeft");
  47. public static Texture lightCapBottomRight = Resources.Load<Texture>("LightCapBottomRight");
  48. public static Texture lightCapUp = Resources.Load<Texture>("LightCapUp");
  49. public static Texture lightCapDown = Resources.Load<Texture>("LightCapDown");
  50. public static GUIContent lightTypeParametric = new GUIContent("Parametric", Resources.Load("InspectorIcons/ParametricLight") as Texture);
  51. public static GUIContent lightTypeFreeform = new GUIContent("Freeform", Resources.Load("InspectorIcons/FreeformLight") as Texture);
  52. public static GUIContent lightTypeSprite = new GUIContent("Sprite", Resources.Load("InspectorIcons/SpriteLight") as Texture);
  53. public static GUIContent lightTypePoint = new GUIContent("Point", Resources.Load("InspectorIcons/PointLight") as Texture);
  54. public static GUIContent lightTypeGlobal = new GUIContent("Global", Resources.Load("InspectorIcons/GlobalLight") as Texture);
  55. public static GUIContent[] lightTypeOptions = new GUIContent[] { lightTypeParametric, lightTypeFreeform, lightTypeSprite, lightTypePoint, lightTypeGlobal };
  56. public static GUIContent generalLightType = EditorGUIUtility.TrTextContent("Light Type", "Specify the light type");
  57. public static GUIContent generalFalloffSize = EditorGUIUtility.TrTextContent("Falloff", "Specify the falloff of the light");
  58. public static GUIContent generalFalloffIntensity = EditorGUIUtility.TrTextContent("Falloff Intensity", "Adjusts the falloff curve");
  59. public static GUIContent generalLightColor = EditorGUIUtility.TrTextContent("Color", "Specify the light color");
  60. public static GUIContent generalLightIntensity = EditorGUIUtility.TrTextContent("Intensity", "Specify the light color's intensity");
  61. public static GUIContent generalUseNormalMap = EditorGUIUtility.TrTextContent("Use Normal Map", "Specify whether the light considers normal maps");
  62. public static GUIContent generalVolumeOpacity = EditorGUIUtility.TrTextContent("Volume Opacity", "Specify the light's volumetric light volume opacity");
  63. public static GUIContent generalBlendStyle = EditorGUIUtility.TrTextContent("Blend Style", "Specify the blend style");
  64. public static GUIContent generalLightOverlapMode = EditorGUIUtility.TrTextContent("Alpha Blend on Overlap", "Use alpha blending instead of additive blending when this light overlaps others");
  65. public static GUIContent generalLightOrder = EditorGUIUtility.TrTextContent("Light Order", "The relative order in which lights of the same blend style get rendered.");
  66. public static GUIContent generalShadowIntensity = EditorGUIUtility.TrTextContent("Shadow Intensity", "Controls the shadow's darkness.");
  67. public static GUIContent generalShadowVolumeIntensity = EditorGUIUtility.TrTextContent("Shadow Volume Intensity", "Controls the shadow volume's darkness.");
  68. public static GUIContent generalSortingLayerPrefixLabel = EditorGUIUtility.TrTextContent("Target Sorting Layers", "Apply this light to the specified sorting layers.");
  69. public static GUIContent generalLightNoLightEnabled = EditorGUIUtility.TrTextContentWithIcon("No valid blend styles are enabled.", MessageType.Error);
  70. public static GUIContent pointLightQuality = EditorGUIUtility.TrTextContent("Quality", "Use accurate if there are noticeable visual issues");
  71. public static GUIContent pointLightInnerAngle = EditorGUIUtility.TrTextContent("Inner Angle", "Specify the inner angle of the light");
  72. public static GUIContent pointLightOuterAngle = EditorGUIUtility.TrTextContent("Outer Angle", "Specify the outer angle of the light");
  73. public static GUIContent pointLightInnerRadius = EditorGUIUtility.TrTextContent("Inner Radius", "Specify the inner radius of the light");
  74. public static GUIContent pointLightOuterRadius = EditorGUIUtility.TrTextContent("Outer Radius", "Specify the outer radius of the light");
  75. public static GUIContent pointLightZDistance = EditorGUIUtility.TrTextContent("Distance", "Specify the Z Distance of the light");
  76. public static GUIContent pointLightCookie = EditorGUIUtility.TrTextContent("Cookie", "Specify a sprite as the cookie for the light");
  77. public static GUIContent shapeLightSprite = EditorGUIUtility.TrTextContent("Sprite", "Specify the sprite");
  78. public static GUIContent shapeLightParametricRadius = EditorGUIUtility.TrTextContent("Radius", "Adjust the size of the object");
  79. public static GUIContent shapeLightParametricSides = EditorGUIUtility.TrTextContent("Sides", "Adjust the shapes number of sides");
  80. public static GUIContent shapeLightFalloffOffset = EditorGUIUtility.TrTextContent("Falloff Offset", "Specify the shape's falloff offset");
  81. public static GUIContent shapeLightAngleOffset = EditorGUIUtility.TrTextContent("Angle Offset", "Adjust the rotation of the object");
  82. public static GUIContent renderPipelineUnassignedWarning = EditorGUIUtility.TrTextContentWithIcon("Universal scriptable renderpipeline asset must be assigned in Graphics Settings or Quality Settings.", MessageType.Warning);
  83. public static GUIContent asset2DUnassignedWarning = EditorGUIUtility.TrTextContentWithIcon("2D renderer data must be assigned to your universal render pipeline asset or camera.", MessageType.Warning);
  84. }
  85. const float k_GlobalLightGizmoSize = 1.2f;
  86. const float k_AngleCapSize = 0.16f * k_GlobalLightGizmoSize;
  87. const float k_AngleCapOffset = 0.08f * k_GlobalLightGizmoSize;
  88. const float k_AngleCapOffsetSecondary = -0.05f;
  89. const float k_RangeCapSize = 0.025f * k_GlobalLightGizmoSize;
  90. const float k_InnerRangeCapSize = 0.08f * k_GlobalLightGizmoSize;
  91. SerializedProperty m_LightType;
  92. SerializedProperty m_LightColor;
  93. SerializedProperty m_LightIntensity;
  94. SerializedProperty m_UseNormalMap;
  95. SerializedProperty m_ShadowIntensity;
  96. SerializedProperty m_ShadowVolumeIntensity;
  97. SerializedProperty m_ApplyToSortingLayers;
  98. SerializedProperty m_VolumetricAlpha;
  99. SerializedProperty m_BlendStyleIndex;
  100. SerializedProperty m_FalloffIntensity;
  101. SerializedProperty m_PointZDistance;
  102. SerializedProperty m_LightOrder;
  103. SerializedProperty m_AlphaBlendOnOverlap;
  104. // Point Light Properties
  105. SerializedProperty m_PointInnerAngle;
  106. SerializedProperty m_PointOuterAngle;
  107. SerializedProperty m_PointInnerRadius;
  108. SerializedProperty m_PointOuterRadius;
  109. SerializedProperty m_PointLightCookie;
  110. SerializedProperty m_PointLightQuality;
  111. // Shape Light Properties
  112. SerializedProperty m_ShapeLightParametricRadius;
  113. SerializedProperty m_ShapeLightFalloffSize;
  114. SerializedProperty m_ShapeLightParametricSides;
  115. SerializedProperty m_ShapeLightParametricAngleOffset;
  116. SerializedProperty m_ShapeLightFalloffOffset;
  117. SerializedProperty m_ShapeLightSprite;
  118. int[] m_BlendStyleIndices;
  119. GUIContent[] m_BlendStyleNames;
  120. bool m_AnyBlendStyleEnabled = false;
  121. SortingLayerDropDown m_SortingLayerDropDown;
  122. Light2D lightObject => target as Light2D;
  123. Analytics.Renderer2DAnalytics m_Analytics;
  124. HashSet<Light2D> m_ModifiedLights;
  125. private void AnalyticsTrackChanges(SerializedObject serializedObject)
  126. {
  127. if (serializedObject.hasModifiedProperties)
  128. {
  129. foreach (Object targetObj in serializedObject.targetObjects)
  130. {
  131. Light2D light2d = (Light2D)targetObj;
  132. if(!m_ModifiedLights.Contains(light2d))
  133. m_ModifiedLights.Add(light2d);
  134. }
  135. }
  136. }
  137. void OnEnable()
  138. {
  139. m_Analytics = Analytics.Renderer2DAnalytics.instance;
  140. m_ModifiedLights = new HashSet<Light2D>();
  141. m_SortingLayerDropDown = new SortingLayerDropDown();
  142. m_LightType = serializedObject.FindProperty("m_LightType");
  143. m_LightColor = serializedObject.FindProperty("m_Color");
  144. m_LightIntensity = serializedObject.FindProperty("m_Intensity");
  145. m_UseNormalMap = serializedObject.FindProperty("m_UseNormalMap");
  146. m_ShadowIntensity = serializedObject.FindProperty("m_ShadowIntensity");
  147. m_ShadowVolumeIntensity = serializedObject.FindProperty("m_ShadowVolumeIntensity");
  148. m_ApplyToSortingLayers = serializedObject.FindProperty("m_ApplyToSortingLayers");
  149. m_VolumetricAlpha = serializedObject.FindProperty("m_LightVolumeOpacity");
  150. m_BlendStyleIndex = serializedObject.FindProperty("m_BlendStyleIndex");
  151. m_FalloffIntensity = serializedObject.FindProperty("m_FalloffIntensity");
  152. m_PointZDistance = serializedObject.FindProperty("m_PointLightDistance");
  153. m_LightOrder = serializedObject.FindProperty("m_LightOrder");
  154. m_AlphaBlendOnOverlap = serializedObject.FindProperty("m_AlphaBlendOnOverlap");
  155. // Point Light
  156. m_PointInnerAngle = serializedObject.FindProperty("m_PointLightInnerAngle");
  157. m_PointOuterAngle = serializedObject.FindProperty("m_PointLightOuterAngle");
  158. m_PointInnerRadius = serializedObject.FindProperty("m_PointLightInnerRadius");
  159. m_PointOuterRadius = serializedObject.FindProperty("m_PointLightOuterRadius");
  160. m_PointLightCookie = serializedObject.FindProperty("m_LightCookieSprite");
  161. m_PointLightQuality = serializedObject.FindProperty("m_PointLightQuality");
  162. // Shape Light
  163. m_ShapeLightParametricRadius = serializedObject.FindProperty("m_ShapeLightParametricRadius");
  164. m_ShapeLightFalloffSize = serializedObject.FindProperty("m_ShapeLightFalloffSize");
  165. m_ShapeLightParametricSides = serializedObject.FindProperty("m_ShapeLightParametricSides");
  166. m_ShapeLightParametricAngleOffset = serializedObject.FindProperty("m_ShapeLightParametricAngleOffset");
  167. m_ShapeLightFalloffOffset = serializedObject.FindProperty("m_ShapeLightFalloffOffset");
  168. m_ShapeLightSprite = serializedObject.FindProperty("m_LightCookieSprite");
  169. m_AnyBlendStyleEnabled = false;
  170. var blendStyleIndices = new List<int>();
  171. var blendStyleNames = new List<string>();
  172. var rendererData = Light2DEditorUtility.GetRenderer2DData();
  173. if (rendererData != null)
  174. {
  175. for (int i = 0; i < rendererData.lightBlendStyles.Length; ++i)
  176. {
  177. blendStyleIndices.Add(i);
  178. ref var blendStyle = ref rendererData.lightBlendStyles[i];
  179. blendStyleNames.Add(blendStyle.name);
  180. m_AnyBlendStyleEnabled = true;
  181. }
  182. }
  183. else
  184. {
  185. for (int i = 0; i < 4; ++i)
  186. {
  187. blendStyleIndices.Add(i);
  188. blendStyleNames.Add("Operation" + i);
  189. }
  190. }
  191. m_BlendStyleIndices = blendStyleIndices.ToArray();
  192. m_BlendStyleNames = blendStyleNames.Select(x => new GUIContent(x)).ToArray();
  193. m_SortingLayerDropDown.OnEnable(serializedObject, "m_ApplyToSortingLayers");
  194. }
  195. internal void SendModifiedAnalytics(Analytics.Renderer2DAnalytics analytics, Light2D light)
  196. {
  197. Analytics.Light2DData lightData = new Analytics.Light2DData();
  198. lightData.was_create_event = false;
  199. lightData.instance_id = light.GetInstanceID();
  200. lightData.light_type = light.lightType;
  201. Analytics.Renderer2DAnalytics.instance.SendData(Analytics.AnalyticsDataTypes.k_LightDataString, lightData);
  202. }
  203. void OnDestroy()
  204. {
  205. if(m_ModifiedLights != null && m_ModifiedLights.Count > 0)
  206. {
  207. foreach (Light2D light in m_ModifiedLights)
  208. {
  209. SendModifiedAnalytics(m_Analytics, light);
  210. }
  211. }
  212. }
  213. void OnPointLight(SerializedObject serializedObject)
  214. {
  215. EditorGUI.BeginChangeCheck();
  216. EditorGUILayout.Slider(m_PointInnerAngle, 0, 360, Styles.pointLightInnerAngle);
  217. if (EditorGUI.EndChangeCheck())
  218. m_PointInnerAngle.floatValue = Mathf.Min(m_PointInnerAngle.floatValue, m_PointOuterAngle.floatValue);
  219. EditorGUI.BeginChangeCheck();
  220. EditorGUILayout.Slider(m_PointOuterAngle, 0, 360, Styles.pointLightOuterAngle);
  221. if (EditorGUI.EndChangeCheck())
  222. m_PointOuterAngle.floatValue = Mathf.Max(m_PointInnerAngle.floatValue, m_PointOuterAngle.floatValue);
  223. EditorGUI.BeginChangeCheck();
  224. EditorGUILayout.PropertyField(m_PointInnerRadius, Styles.pointLightInnerRadius);
  225. if (EditorGUI.EndChangeCheck())
  226. m_PointInnerRadius.floatValue = Mathf.Max(0.0f, Mathf.Min(m_PointInnerRadius.floatValue, m_PointOuterRadius.floatValue));
  227. EditorGUI.BeginChangeCheck();
  228. EditorGUILayout.PropertyField(m_PointOuterRadius, Styles.pointLightOuterRadius);
  229. if (EditorGUI.EndChangeCheck())
  230. m_PointOuterRadius.floatValue = Mathf.Max(m_PointInnerRadius.floatValue, m_PointOuterRadius.floatValue);
  231. EditorGUILayout.Slider(m_FalloffIntensity, 0, 1, Styles.generalFalloffIntensity);
  232. EditorGUILayout.PropertyField(m_PointLightCookie, Styles.pointLightCookie);
  233. }
  234. void OnShapeLight(Light2D.LightType lightType, SerializedObject serializedObject)
  235. {
  236. if (lightType == Light2D.LightType.Sprite)
  237. {
  238. EditorGUILayout.PropertyField(m_ShapeLightSprite, Styles.shapeLightSprite);
  239. }
  240. else if (lightType == Light2D.LightType.Parametric || lightType == Light2D.LightType.Freeform)
  241. {
  242. if (lightType == Light2D.LightType.Parametric)
  243. {
  244. EditorGUILayout.PropertyField(m_ShapeLightParametricRadius, Styles.shapeLightParametricRadius);
  245. if (m_ShapeLightParametricRadius.floatValue < 0)
  246. m_ShapeLightParametricRadius.floatValue = 0;
  247. EditorGUILayout.IntSlider(m_ShapeLightParametricSides, 3, 48, Styles.shapeLightParametricSides);
  248. EditorGUILayout.Slider(m_ShapeLightParametricAngleOffset, 0, 359, Styles.shapeLightAngleOffset);
  249. }
  250. EditorGUILayout.PropertyField(m_ShapeLightFalloffSize, Styles.generalFalloffSize);
  251. if (m_ShapeLightFalloffSize.floatValue < 0)
  252. m_ShapeLightFalloffSize.floatValue = 0;
  253. EditorGUILayout.Slider(m_FalloffIntensity, 0, 1, Styles.generalFalloffIntensity);
  254. if (lightType == Light2D.LightType.Parametric || lightType == Light2D.LightType.Freeform)
  255. {
  256. bool oldWideMode = EditorGUIUtility.wideMode;
  257. EditorGUIUtility.wideMode = true;
  258. EditorGUILayout.PropertyField(m_ShapeLightFalloffOffset, Styles.shapeLightFalloffOffset);
  259. EditorGUIUtility.wideMode = oldWideMode;
  260. }
  261. }
  262. }
  263. Vector3 DrawAngleSlider2D(Transform transform, Quaternion rotation, float radius, float offset, Handles.CapFunction capFunc, float capSize, bool leftAngle, bool drawLine, bool useCapOffset, ref float angle)
  264. {
  265. float oldAngle = angle;
  266. float angleBy2 = (angle / 2) * (leftAngle ? -1.0f : 1.0f);
  267. Vector3 trcwPos = Quaternion.AngleAxis(angleBy2, -transform.forward) * (transform.up);
  268. Vector3 cwPos = transform.position + trcwPos * (radius + offset);
  269. float direction = leftAngle ? 1 : -1;
  270. // Offset the handle
  271. float size = .25f * capSize;
  272. Vector3 handleOffset = useCapOffset ? rotation * new Vector3(direction * size, 0, 0) : Vector3.zero;
  273. EditorGUI.BeginChangeCheck();
  274. var id = GUIUtility.GetControlID("AngleSlider".GetHashCode(), FocusType.Passive);
  275. Vector3 cwHandle = Handles.Slider2D(id, cwPos, handleOffset, Vector3.forward, rotation * Vector3.up, rotation * Vector3.right, capSize, capFunc, Vector3.zero);
  276. if (EditorGUI.EndChangeCheck())
  277. {
  278. Vector3 toCwHandle = (transform.position - cwHandle).normalized;
  279. angle = 360 - 2 * Quaternion.Angle(Quaternion.FromToRotation(transform.up, toCwHandle), Quaternion.identity);
  280. angle = Mathf.Round(angle * 100) / 100f;
  281. float side = Vector3.Dot(direction * transform.right, toCwHandle);
  282. if (side < 0)
  283. {
  284. if (oldAngle < 180)
  285. angle = 0;
  286. else
  287. angle = 360;
  288. }
  289. }
  290. if (drawLine)
  291. Handles.DrawLine(transform.position, cwHandle);
  292. return cwHandle;
  293. }
  294. private float DrawAngleHandle(Transform transform, float radius, float offset, Handles.CapFunction capLeft, Handles.CapFunction capRight, ref float angle)
  295. {
  296. float old = angle;
  297. float handleOffset = HandleUtility.GetHandleSize(transform.position) * offset;
  298. float handleSize = HandleUtility.GetHandleSize(transform.position) * k_AngleCapSize;
  299. Quaternion rotLt = Quaternion.AngleAxis(-angle / 2, -transform.forward) * transform.rotation;
  300. DrawAngleSlider2D(transform, rotLt, radius, handleOffset, capLeft, handleSize, true, true, true, ref angle);
  301. Quaternion rotRt = Quaternion.AngleAxis(angle / 2, -transform.forward) * transform.rotation;
  302. DrawAngleSlider2D(transform, rotRt, radius, handleOffset, capRight, handleSize, false, true, true, ref angle);
  303. return angle - old;
  304. }
  305. private void DrawRadiusArc(Transform transform, float radius, float angle, int steps, Handles.CapFunction capFunc, float capSize, bool even)
  306. {
  307. Handles.DrawWireArc(transform.position, transform.forward, Quaternion.AngleAxis(180 - angle / 2, transform.forward) * -transform.up, angle, radius);
  308. }
  309. Handles.CapFunction GetCapFunc(Texture texture, bool isAngleHandle)
  310. {
  311. return (controlID, position, rotation, size, eventType) => Light2DEditorUtility.GUITextureCap(controlID, texture, position, rotation, size, eventType, isAngleHandle);
  312. }
  313. private void DrawAngleHandles(Light2D light)
  314. {
  315. var oldColor = Handles.color;
  316. Handles.color = Color.yellow;
  317. float outerAngle = light.pointLightOuterAngle;
  318. float diff = DrawAngleHandle(light.transform, light.pointLightOuterRadius, k_AngleCapOffset, GetCapFunc(Styles.lightCapTopRight, true), GetCapFunc(Styles.lightCapBottomRight, true), ref outerAngle);
  319. light.pointLightOuterAngle = outerAngle;
  320. if (diff != 0.0f)
  321. light.pointLightInnerAngle = Mathf.Max(0.0f, light.pointLightInnerAngle + diff);
  322. float innerAngle = light.pointLightInnerAngle;
  323. diff = DrawAngleHandle(light.transform, light.pointLightOuterRadius, -k_AngleCapOffset, GetCapFunc(Styles.lightCapTopLeft, true), GetCapFunc(Styles.lightCapBottomLeft, true), ref innerAngle);
  324. light.pointLightInnerAngle = innerAngle;
  325. if (diff != 0.0f)
  326. light.pointLightInnerAngle = light.pointLightInnerAngle < light.pointLightOuterAngle ? light.pointLightInnerAngle : light.pointLightOuterAngle;
  327. light.pointLightInnerAngle = Mathf.Min(light.pointLightInnerAngle, light.pointLightOuterAngle);
  328. Handles.color = oldColor;
  329. }
  330. private void DrawRangeHandles(Light2D light)
  331. {
  332. var dummy = 0.0f;
  333. bool radiusChanged = false;
  334. Vector3 handlePos = Vector3.zero;
  335. Quaternion rotLeft = Quaternion.AngleAxis(0, -light.transform.forward) * light.transform.rotation;
  336. float handleOffset = HandleUtility.GetHandleSize(light.transform.position) * k_AngleCapOffsetSecondary;
  337. float handleSize = HandleUtility.GetHandleSize(light.transform.position) * k_AngleCapSize;
  338. var oldColor = Handles.color;
  339. Handles.color = Color.yellow;
  340. float outerRadius = light.pointLightOuterRadius;
  341. EditorGUI.BeginChangeCheck();
  342. Vector3 returnPos = DrawAngleSlider2D(light.transform, rotLeft, outerRadius, -handleOffset, GetCapFunc(Styles.lightCapUp, false), handleSize, false, false, false, ref dummy);
  343. if (EditorGUI.EndChangeCheck())
  344. {
  345. var vec = (returnPos - light.transform.position).normalized;
  346. light.transform.up = new Vector3(vec.x, vec.y, 0);
  347. outerRadius = (returnPos - light.transform.position).magnitude;
  348. outerRadius = outerRadius + handleOffset;
  349. radiusChanged = true;
  350. }
  351. DrawRadiusArc(light.transform, light.pointLightOuterRadius, light.pointLightOuterAngle, 0, Handles.DotHandleCap, k_RangeCapSize, false);
  352. Handles.color = Color.gray;
  353. float innerRadius = light.pointLightInnerRadius;
  354. EditorGUI.BeginChangeCheck();
  355. returnPos = DrawAngleSlider2D(light.transform, rotLeft, innerRadius, handleOffset, GetCapFunc(Styles.lightCapDown, false), handleSize, true, false, false, ref dummy);
  356. if (EditorGUI.EndChangeCheck())
  357. {
  358. innerRadius = (returnPos - light.transform.position).magnitude;
  359. innerRadius = innerRadius - handleOffset;
  360. radiusChanged = true;
  361. }
  362. DrawRadiusArc(light.transform, light.pointLightInnerRadius, light.pointLightOuterAngle, 0, Handles.SphereHandleCap, k_InnerRangeCapSize, false);
  363. Handles.color = oldColor;
  364. if (radiusChanged)
  365. {
  366. light.pointLightInnerRadius = (outerRadius < innerRadius) ? outerRadius : innerRadius;
  367. light.pointLightOuterRadius = (innerRadius > outerRadius) ? innerRadius : outerRadius;
  368. }
  369. }
  370. void OnSceneGUI()
  371. {
  372. var light = target as Light2D;
  373. if (light == null)
  374. return;
  375. Transform t = light.transform;
  376. switch (light.lightType)
  377. {
  378. case Light2D.LightType.Point:
  379. {
  380. Undo.RecordObject(light.transform, "Edit Point Light Transform");
  381. Undo.RecordObject(light, "Edit Point Light");
  382. DrawRangeHandles(light);
  383. DrawAngleHandles(light);
  384. if (GUI.changed)
  385. EditorUtility.SetDirty(light);
  386. }
  387. break;
  388. case Light2D.LightType.Sprite:
  389. {
  390. var cookieSprite = light.lightCookieSprite;
  391. if (cookieSprite != null)
  392. {
  393. Vector3 min = cookieSprite.bounds.min;
  394. Vector3 max = cookieSprite.bounds.max;
  395. Vector3 v0 = t.TransformPoint(new Vector3(min.x, min.y));
  396. Vector3 v1 = t.TransformPoint(new Vector3(max.x, min.y));
  397. Vector3 v2 = t.TransformPoint(new Vector3(max.x, max.y));
  398. Vector3 v3 = t.TransformPoint(new Vector3(min.x, max.y));
  399. Handles.DrawLine(v0, v1);
  400. Handles.DrawLine(v1, v2);
  401. Handles.DrawLine(v2, v3);
  402. Handles.DrawLine(v3, v0);
  403. }
  404. }
  405. break;
  406. case Light2D.LightType.Parametric:
  407. {
  408. float radius = light.shapeLightParametricRadius;
  409. float sides = light.shapeLightParametricSides;
  410. float angleOffset = Mathf.PI / 2.0f + Mathf.Deg2Rad * light.shapeLightParametricAngleOffset;
  411. if (sides < 3)
  412. sides = 3;
  413. if (sides == 4)
  414. angleOffset = Mathf.PI / 4.0f + Mathf.Deg2Rad * light.shapeLightParametricAngleOffset;
  415. Vector3 direction = new Vector3(Mathf.Cos(angleOffset), Mathf.Sin(angleOffset), 0);
  416. Vector3 startPoint = radius * direction;
  417. Vector3 featherStartPoint = startPoint + light.shapeLightFalloffSize * direction;
  418. float radiansPerSide = 2 * Mathf.PI / sides;
  419. Vector3 falloffOffset = light.shapeLightFalloffOffset;
  420. for (int i = 0; i < sides; ++i)
  421. {
  422. float endAngle = (i + 1) * radiansPerSide;
  423. direction = new Vector3(Mathf.Cos(endAngle + angleOffset), Mathf.Sin(endAngle + angleOffset), 0);
  424. Vector3 endPoint = radius * direction;
  425. Vector3 featherEndPoint = endPoint + light.shapeLightFalloffSize * direction;
  426. Handles.DrawLine(t.TransformPoint(startPoint), t.TransformPoint(endPoint));
  427. Handles.DrawLine(t.TransformPoint(featherStartPoint + falloffOffset), t.TransformPoint(featherEndPoint + falloffOffset));
  428. startPoint = endPoint;
  429. featherStartPoint = featherEndPoint;
  430. }
  431. }
  432. break;
  433. case Light2D.LightType.Freeform:
  434. {
  435. // Draw the falloff shape's outline
  436. List<Vector2> falloffShape = light.GetFalloffShape();
  437. Handles.color = Color.white;
  438. Vector3 falloffOffset = m_ShapeLightFalloffOffset.vector2Value;
  439. for (int i = 0; i < falloffShape.Count - 1; ++i)
  440. {
  441. Handles.DrawLine(t.TransformPoint(falloffShape[i]) + falloffOffset, t.TransformPoint(falloffShape[i + 1]) + falloffOffset);
  442. Handles.DrawLine(t.TransformPoint(light.shapePath[i]), t.TransformPoint(light.shapePath[i + 1]));
  443. }
  444. Handles.DrawLine(t.TransformPoint(falloffShape[falloffShape.Count - 1]) + falloffOffset, t.TransformPoint(falloffShape[0]) + falloffOffset);
  445. Handles.DrawLine(t.TransformPoint(light.shapePath[falloffShape.Count - 1]), t.TransformPoint(light.shapePath[0]));
  446. }
  447. break;
  448. }
  449. }
  450. public override void OnInspectorGUI()
  451. {
  452. UniversalRenderPipelineAsset asset = UniversalRenderPipeline.asset;
  453. if (asset != null)
  454. {
  455. if (!Light2DEditorUtility.IsUsing2DRenderer())
  456. {
  457. EditorGUILayout.HelpBox(Styles.asset2DUnassignedWarning);
  458. return;
  459. }
  460. }
  461. else
  462. {
  463. EditorGUILayout.HelpBox(Styles.renderPipelineUnassignedWarning);
  464. return;
  465. }
  466. EditorGUILayout.Space();
  467. serializedObject.Update();
  468. var meshChanged = false;
  469. Rect lightTypeRect = EditorGUILayout.GetControlRect();
  470. EditorGUI.BeginProperty(lightTypeRect, GUIContent.none, m_LightType);
  471. EditorGUI.BeginChangeCheck();
  472. int newLightType = EditorGUI.Popup(lightTypeRect, Styles.generalLightType, m_LightType.intValue, Styles.lightTypeOptions);
  473. if (EditorGUI.EndChangeCheck())
  474. {
  475. m_LightType.intValue = newLightType;
  476. meshChanged = true;
  477. }
  478. EditorGUI.EndProperty();
  479. switch (m_LightType.intValue)
  480. {
  481. case (int)Light2D.LightType.Point:
  482. {
  483. OnPointLight(serializedObject);
  484. }
  485. break;
  486. case (int)Light2D.LightType.Parametric:
  487. case (int)Light2D.LightType.Freeform:
  488. case (int)Light2D.LightType.Sprite:
  489. {
  490. OnShapeLight((Light2D.LightType)m_LightType.intValue, serializedObject);
  491. }
  492. break;
  493. }
  494. if(m_LightType.intValue != (int)Light2D.LightType.Global)
  495. EditorGUILayout.PropertyField(m_AlphaBlendOnOverlap, Styles.generalLightOverlapMode);
  496. EditorGUILayout.PropertyField(m_LightOrder, Styles.generalLightOrder);
  497. if (!m_AnyBlendStyleEnabled)
  498. EditorGUILayout.HelpBox(Styles.generalLightNoLightEnabled);
  499. else
  500. EditorGUILayout.IntPopup(m_BlendStyleIndex, m_BlendStyleNames, m_BlendStyleIndices, Styles.generalBlendStyle);
  501. EditorGUILayout.PropertyField(m_LightColor, Styles.generalLightColor);
  502. EditorGUI.BeginChangeCheck();
  503. EditorGUILayout.PropertyField(m_LightIntensity, Styles.generalLightIntensity);
  504. if (EditorGUI.EndChangeCheck())
  505. m_LightIntensity.floatValue = Mathf.Max(m_LightIntensity.floatValue, 0);
  506. if (m_LightType.intValue != (int)Light2D.LightType.Global)
  507. {
  508. EditorGUILayout.PropertyField(m_UseNormalMap, Styles.generalUseNormalMap);
  509. if (m_UseNormalMap.boolValue)
  510. {
  511. EditorGUI.BeginChangeCheck();
  512. EditorGUILayout.PropertyField(m_PointZDistance, Styles.pointLightZDistance);
  513. if (EditorGUI.EndChangeCheck())
  514. m_PointZDistance.floatValue = Mathf.Max(0.0f, m_PointZDistance.floatValue);
  515. EditorGUILayout.PropertyField(m_PointLightQuality, Styles.pointLightQuality);
  516. }
  517. EditorGUILayout.Slider(m_VolumetricAlpha, 0, 1, Styles.generalVolumeOpacity);
  518. EditorGUILayout.Slider(m_ShadowIntensity, 0, 1, Styles.generalShadowIntensity);
  519. if(m_VolumetricAlpha.floatValue > 0)
  520. EditorGUILayout.Slider(m_ShadowVolumeIntensity, 0, 1, Styles.generalShadowVolumeIntensity);
  521. }
  522. m_SortingLayerDropDown.OnTargetSortingLayers(serializedObject, targets, Styles.generalSortingLayerPrefixLabel, AnalyticsTrackChanges);
  523. if (m_LightType.intValue == (int)Light2D.LightType.Freeform)
  524. {
  525. DoEditButton<FreeformShapeTool>(PathEditorToolContents.icon, "Edit Shape");
  526. DoPathInspector<FreeformShapeTool>();
  527. DoSnappingInspector<FreeformShapeTool>();
  528. }
  529. AnalyticsTrackChanges(serializedObject);
  530. if (serializedObject.ApplyModifiedProperties())
  531. {
  532. if(meshChanged)
  533. lightObject.UpdateMesh();
  534. }
  535. }
  536. }
  537. }