Light2DEditor.cs 33 KB

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