HighlightEffectEditor.cs 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. using System.Collections.Generic;
  2. using UnityEditor;
  3. using UnityEngine;
  4. using UnityEngine.Rendering;
  5. using UnityEngine.Rendering.Universal;
  6. namespace HighlightPlus {
  7. [CustomEditor(typeof(HighlightEffect))]
  8. [CanEditMultipleObjects]
  9. public class HighlightEffectEditor : Editor {
  10. #pragma warning disable 0618
  11. SerializedProperty profile, profileSync, camerasLayerMask, ignoreObjectVisibility, reflectionProbes, GPUInstancing, optimizeSkinnedMesh;
  12. SerializedProperty ignore, effectGroup, effectGroupLayer, effectNameFilter, combineMeshes, alphaCutOff, cullBackFaces, normalsOption;
  13. SerializedProperty highlighted, fadeInDuration, fadeOutDuration, flipY, constantWidth, subMeshMask;
  14. SerializedProperty overlay, overlayMode, overlayColor, overlayAnimationSpeed, overlayMinIntensity, overlayBlending, overlayTexture, overlayTextureUVSpace, overlayTextureScale, overlayVisibility;
  15. SerializedProperty outline, outlineColor, outlineColorStyle, outlineGradient, outlineGradientInLocalSpace, outlineBlurPasses, outlineWidth, outlineQuality, outlineEdgeMode, outlineEdgeThreshold, outlineDownsampling, outlineVisibility, outlineBlitDebug, outlineIndependent, outlineContourStyle;
  16. SerializedProperty glow, glowWidth, glowQuality, glowBlurMethod, glowDownsampling, glowHQColor, glowDithering, glowMagicNumber1, glowMagicNumber2, glowAnimationSpeed;
  17. SerializedProperty glowBlendPasses, glowPasses, glowVisibility, glowBlendMode, glowBlitDebug, glowIgnoreMask;
  18. SerializedProperty innerGlow, innerGlowWidth, innerGlowColor, innerGlowBlendMode, innerGlowVisibility;
  19. SerializedProperty seeThrough, seeThroughOccluderMask, seeThroughOccluderMaskAccurate, seeThroughOccluderThreshold, seeThroughOccluderCheckInterval, seeThroughOccluderCheckIndividualObjects, seeThroughDepthOffset, seeThroughMaxDepth;
  20. SerializedProperty seeThroughIntensity, seeThroughTintAlpha, seeThroughTintColor, seeThroughNoise, seeThroughBorder, seeThroughBorderWidth, seeThroughBorderColor, seeThroughOrdered, seeThroughBorderOnly, seeThroughTexture, seeThroughTextureUVSpace, seeThroughTextureScale, seeThroughChildrenSortingMode;
  21. SerializedProperty targetFX, targetFXTexture, targetFXColor, targetFXCenter, targetFXRotationSpeed, targetFXInitialScale, targetFXEndScale, targetFXScaleToRenderBounds;
  22. SerializedProperty targetFXAlignToGround, targetFXFadePower, targetFXGroundMaxDistance, targetFXGroundLayerMask, targetFXTransitionDuration, targetFXStayDuration, targetFXVisibility;
  23. SerializedProperty hitFxInitialIntensity, hitFxMode, hitFxFadeOutDuration, hitFxColor, hitFxRadius;
  24. SerializedProperty cameraDistanceFade, cameraDistanceFadeNear, cameraDistanceFadeFar;
  25. HighlightEffect thisEffect;
  26. bool profileChanged, enableProfileApply;
  27. UniversalRenderPipelineAsset pipe;
  28. bool expandGeneralSettings, expandHighlightOptions;
  29. bool showCurrentOccluders;
  30. const string HP_GENERAL_SETTINGS = "HPGeneralSettings";
  31. const string HP_HIGHLIGHT_OPTIONS = "HPHighlightOptions";
  32. GUIStyle foldoutBold;
  33. void OnEnable() {
  34. expandGeneralSettings = EditorPrefs.GetBool("HPGeneralSettings", true);
  35. expandHighlightOptions = EditorPrefs.GetBool("HPHighlightOptions", true);
  36. profile = serializedObject.FindProperty("profile");
  37. profileSync = serializedObject.FindProperty("profileSync");
  38. camerasLayerMask = serializedObject.FindProperty("camerasLayerMask");
  39. ignoreObjectVisibility = serializedObject.FindProperty("ignoreObjectVisibility");
  40. reflectionProbes = serializedObject.FindProperty("reflectionProbes");
  41. optimizeSkinnedMesh = serializedObject.FindProperty("optimizeSkinnedMesh");
  42. normalsOption = serializedObject.FindProperty("normalsOption");
  43. GPUInstancing = serializedObject.FindProperty("GPUInstancing");
  44. ignore = serializedObject.FindProperty("ignore");
  45. effectGroup = serializedObject.FindProperty("effectGroup");
  46. effectGroupLayer = serializedObject.FindProperty("effectGroupLayer");
  47. effectNameFilter = serializedObject.FindProperty("effectNameFilter");
  48. combineMeshes = serializedObject.FindProperty("combineMeshes");
  49. alphaCutOff = serializedObject.FindProperty("alphaCutOff");
  50. cullBackFaces = serializedObject.FindProperty("cullBackFaces");
  51. highlighted = serializedObject.FindProperty("_highlighted");
  52. fadeInDuration = serializedObject.FindProperty("fadeInDuration");
  53. fadeOutDuration = serializedObject.FindProperty("fadeOutDuration");
  54. flipY = serializedObject.FindProperty("flipY");
  55. constantWidth = serializedObject.FindProperty("constantWidth");
  56. subMeshMask = serializedObject.FindProperty("subMeshMask");
  57. overlay = serializedObject.FindProperty("overlay");
  58. overlayMode = serializedObject.FindProperty("overlayMode");
  59. overlayColor = serializedObject.FindProperty("overlayColor");
  60. overlayAnimationSpeed = serializedObject.FindProperty("overlayAnimationSpeed");
  61. overlayMinIntensity = serializedObject.FindProperty("overlayMinIntensity");
  62. overlayBlending = serializedObject.FindProperty("overlayBlending");
  63. overlayTexture = serializedObject.FindProperty("overlayTexture");
  64. overlayTextureUVSpace = serializedObject.FindProperty("overlayTextureUVSpace");
  65. overlayTextureScale = serializedObject.FindProperty("overlayTextureScale");
  66. overlayVisibility = serializedObject.FindProperty("overlayVisibility");
  67. outline = serializedObject.FindProperty("outline");
  68. outlineColor = serializedObject.FindProperty("outlineColor");
  69. outlineColorStyle = serializedObject.FindProperty("outlineColorStyle");
  70. outlineGradient = serializedObject.FindProperty("outlineGradient");
  71. outlineGradientInLocalSpace = serializedObject.FindProperty("outlineGradientInLocalSpace");
  72. outlineWidth = serializedObject.FindProperty("outlineWidth");
  73. outlineBlurPasses = serializedObject.FindProperty("outlineBlurPasses");
  74. outlineQuality = serializedObject.FindProperty("outlineQuality");
  75. outlineEdgeMode = serializedObject.FindProperty("outlineEdgeMode");
  76. outlineEdgeThreshold = serializedObject.FindProperty("outlineEdgeThreshold");
  77. outlineDownsampling = serializedObject.FindProperty("outlineDownsampling");
  78. outlineVisibility = serializedObject.FindProperty("outlineVisibility");
  79. outlineBlitDebug = serializedObject.FindProperty("outlineBlitDebug");
  80. outlineIndependent = serializedObject.FindProperty("outlineIndependent");
  81. outlineContourStyle = serializedObject.FindProperty("outlineContourStyle");
  82. glow = serializedObject.FindProperty("glow");
  83. glowWidth = serializedObject.FindProperty("glowWidth");
  84. glowQuality = serializedObject.FindProperty("glowQuality");
  85. glowBlurMethod = serializedObject.FindProperty("glowBlurMethod");
  86. glowHQColor = serializedObject.FindProperty("glowHQColor");
  87. glowAnimationSpeed = serializedObject.FindProperty("glowAnimationSpeed");
  88. glowBlendPasses = serializedObject.FindProperty("glowBlendPasses");
  89. glowDithering = serializedObject.FindProperty("glowDithering");
  90. glowMagicNumber1 = serializedObject.FindProperty("glowMagicNumber1");
  91. glowMagicNumber2 = serializedObject.FindProperty("glowMagicNumber2");
  92. glowAnimationSpeed = serializedObject.FindProperty("glowAnimationSpeed");
  93. glowPasses = serializedObject.FindProperty("glowPasses");
  94. glowVisibility = serializedObject.FindProperty("glowVisibility");
  95. glowBlendMode = serializedObject.FindProperty("glowBlendMode");
  96. glowBlitDebug = serializedObject.FindProperty("glowBlitDebug");
  97. glowIgnoreMask = serializedObject.FindProperty("glowIgnoreMask");
  98. glowDownsampling = serializedObject.FindProperty("glowDownsampling");
  99. innerGlow = serializedObject.FindProperty("innerGlow");
  100. innerGlowColor = serializedObject.FindProperty("innerGlowColor");
  101. innerGlowWidth = serializedObject.FindProperty("innerGlowWidth");
  102. innerGlowBlendMode = serializedObject.FindProperty("innerGlowBlendMode");
  103. innerGlowVisibility = serializedObject.FindProperty("innerGlowVisibility");
  104. seeThrough = serializedObject.FindProperty("seeThrough");
  105. seeThroughOccluderMask = serializedObject.FindProperty("seeThroughOccluderMask");
  106. seeThroughOccluderMaskAccurate = serializedObject.FindProperty("seeThroughOccluderMaskAccurate");
  107. seeThroughOccluderThreshold = serializedObject.FindProperty("seeThroughOccluderThreshold");
  108. seeThroughOccluderCheckInterval = serializedObject.FindProperty("seeThroughOccluderCheckInterval");
  109. seeThroughOccluderCheckIndividualObjects = serializedObject.FindProperty("seeThroughOccluderCheckIndividualObjects");
  110. seeThroughDepthOffset = serializedObject.FindProperty("seeThroughDepthOffset");
  111. seeThroughMaxDepth = serializedObject.FindProperty("seeThroughMaxDepth");
  112. seeThroughIntensity = serializedObject.FindProperty("seeThroughIntensity");
  113. seeThroughTintAlpha = serializedObject.FindProperty("seeThroughTintAlpha");
  114. seeThroughTintColor = serializedObject.FindProperty("seeThroughTintColor");
  115. seeThroughNoise = serializedObject.FindProperty("seeThroughNoise");
  116. seeThroughBorder = serializedObject.FindProperty("seeThroughBorder");
  117. seeThroughBorderWidth = serializedObject.FindProperty("seeThroughBorderWidth");
  118. seeThroughBorderColor = serializedObject.FindProperty("seeThroughBorderColor");
  119. seeThroughOrdered = serializedObject.FindProperty("seeThroughOrdered");
  120. seeThroughBorderOnly = serializedObject.FindProperty("seeThroughBorderOnly");
  121. seeThroughTexture = serializedObject.FindProperty("seeThroughTexture");
  122. seeThroughTextureScale = serializedObject.FindProperty("seeThroughTextureScale");
  123. seeThroughTextureUVSpace = serializedObject.FindProperty("seeThroughTextureUVSpace");
  124. seeThroughChildrenSortingMode = serializedObject.FindProperty("seeThroughChildrenSortingMode");
  125. targetFX = serializedObject.FindProperty("targetFX");
  126. targetFXTexture = serializedObject.FindProperty("targetFXTexture");
  127. targetFXRotationSpeed = serializedObject.FindProperty("targetFXRotationSpeed");
  128. targetFXInitialScale = serializedObject.FindProperty("targetFXInitialScale");
  129. targetFXEndScale = serializedObject.FindProperty("targetFXEndScale");
  130. targetFXScaleToRenderBounds = serializedObject.FindProperty("targetFXScaleToRenderBounds");
  131. targetFXAlignToGround = serializedObject.FindProperty("targetFXAlignToGround");
  132. targetFXFadePower = serializedObject.FindProperty("targetFXFadePower");
  133. targetFXGroundMaxDistance = serializedObject.FindProperty("targetFXGroundMaxDistance");
  134. targetFXGroundLayerMask = serializedObject.FindProperty("targetFXGroundLayerMask");
  135. targetFXColor = serializedObject.FindProperty("targetFXColor");
  136. targetFXCenter = serializedObject.FindProperty("targetFXCenter");
  137. targetFXTransitionDuration = serializedObject.FindProperty("targetFXTransitionDuration");
  138. targetFXStayDuration = serializedObject.FindProperty("targetFXStayDuration");
  139. targetFXVisibility = serializedObject.FindProperty("targetFXVisibility");
  140. hitFxInitialIntensity = serializedObject.FindProperty("hitFxInitialIntensity");
  141. hitFxMode = serializedObject.FindProperty("hitFxMode");
  142. hitFxFadeOutDuration = serializedObject.FindProperty("hitFxFadeOutDuration");
  143. hitFxColor = serializedObject.FindProperty("hitFxColor");
  144. hitFxRadius = serializedObject.FindProperty("hitFxRadius");
  145. cameraDistanceFade = serializedObject.FindProperty("cameraDistanceFade");
  146. cameraDistanceFadeNear = serializedObject.FindProperty("cameraDistanceFadeNear");
  147. cameraDistanceFadeFar = serializedObject.FindProperty("cameraDistanceFadeFar");
  148. thisEffect = (HighlightEffect)target;
  149. thisEffect.Refresh();
  150. }
  151. private void OnDisable() {
  152. EditorPrefs.SetBool(HP_GENERAL_SETTINGS, expandGeneralSettings);
  153. EditorPrefs.SetBool(HP_HIGHLIGHT_OPTIONS, expandHighlightOptions);
  154. }
  155. public override void OnInspectorGUI() {
  156. EditorGUILayout.Separator();
  157. // URP setup helpers
  158. pipe = GraphicsSettings.currentRenderPipeline as UniversalRenderPipelineAsset;
  159. if (pipe == null) {
  160. EditorGUILayout.HelpBox("You must assign the Universal Rendering Pipeline asset in Project Settings / Graphics. Then, add the Highlight Plus Scriptable Render Feature to the list of Renderer Features of the Forward Renderer.", MessageType.Error);
  161. if (GUILayout.Button("Watch Setup Video Tutorial")) {
  162. Application.OpenURL("https://youtu.be/EgyBs8v9aRI");
  163. }
  164. return;
  165. }
  166. if (!HighlightPlusRenderPassFeature.installed) {
  167. EditorGUILayout.HelpBox("Highlight Plus Render Feature must be added to the list of features of the Forward Renderer in the Universal Rendering Pipeline asset.", MessageType.Warning);
  168. if (GUILayout.Button("Watch Setup Video Tutorial")) {
  169. Application.OpenURL("https://youtu.be/EgyBs8v9aRI");
  170. }
  171. if (GUILayout.Button("Go to Universal Rendering Pipeline Asset")) {
  172. Selection.activeObject = pipe;
  173. }
  174. EditorGUILayout.Separator();
  175. }
  176. bool isManager = IsDefaultEffectUsedByManager();
  177. serializedObject.Update();
  178. bool isMeshObject = !thisEffect.spriteMode;
  179. if (foldoutBold == null) {
  180. foldoutBold = new GUIStyle(EditorStyles.foldout);
  181. foldoutBold.fontStyle = FontStyle.Bold;
  182. }
  183. EditorGUILayout.BeginHorizontal();
  184. HighlightProfile prevProfile = (HighlightProfile)profile.objectReferenceValue;
  185. EditorGUILayout.PropertyField(profile, new GUIContent("Profile", "Create or load stored presets."));
  186. if (profile.objectReferenceValue != null) {
  187. if (prevProfile != profile.objectReferenceValue) {
  188. profileChanged = true;
  189. }
  190. EditorGUILayout.EndHorizontal();
  191. EditorGUILayout.BeginHorizontal();
  192. GUILayout.Label("", GUILayout.Width(EditorGUIUtility.labelWidth));
  193. if (GUILayout.Button(new GUIContent("Create", "Creates a new profile which is a copy of the current settings."), GUILayout.Width(60))) {
  194. CreateProfile();
  195. profileChanged = false;
  196. enableProfileApply = false;
  197. GUIUtility.ExitGUI();
  198. return;
  199. }
  200. if (GUILayout.Button(new GUIContent("Load", "Updates settings with the profile configuration."), GUILayout.Width(60))) {
  201. profileChanged = true;
  202. }
  203. GUI.enabled = enableProfileApply;
  204. if (GUILayout.Button(new GUIContent("Save", "Updates profile configuration with changes in this inspector."), GUILayout.Width(60))) {
  205. enableProfileApply = false;
  206. profileChanged = false;
  207. thisEffect.profile.Save(thisEffect);
  208. EditorUtility.SetDirty(thisEffect.profile);
  209. GUIUtility.ExitGUI();
  210. return;
  211. }
  212. GUI.enabled = true;
  213. if (GUILayout.Button(new GUIContent("Locate", "Finds the profile in the project"), GUILayout.Width(60))) {
  214. if (thisEffect.profile != null) {
  215. Selection.activeObject = thisEffect.profile;
  216. EditorGUIUtility.PingObject(thisEffect.profile);
  217. }
  218. }
  219. EditorGUILayout.EndHorizontal();
  220. EditorGUILayout.PropertyField(profileSync, new GUIContent("Sync With Profile", "If disabled, profile settings will only be loaded when clicking 'Load' which allows you to customize settings after loading a profile and keep those changes."));
  221. EditorGUILayout.BeginHorizontal();
  222. } else {
  223. if (GUILayout.Button(new GUIContent("Create", "Creates a new profile which is a copy of the current settings."), GUILayout.Width(60))) {
  224. CreateProfile();
  225. GUIUtility.ExitGUI();
  226. return;
  227. }
  228. }
  229. EditorGUILayout.EndHorizontal();
  230. if (isManager) {
  231. EditorGUILayout.HelpBox("These are default settings for highlighted objects. If the highlighted object already has a Highlight Effect component, those properties will be used.", MessageType.Info);
  232. }
  233. expandGeneralSettings = EditorGUILayout.Foldout(expandGeneralSettings, "General Settings", true, foldoutBold);
  234. if (expandGeneralSettings) {
  235. EditorGUILayout.PropertyField(camerasLayerMask);
  236. EditorGUILayout.PropertyField(ignoreObjectVisibility);
  237. if (thisEffect.staticChildren) {
  238. EditorGUILayout.HelpBox("This GameObject or one of its children is marked as static. If highlight is not visible, add a MeshCollider to them (the MeshCollider can be disabled).", MessageType.Warning);
  239. }
  240. EditorGUILayout.PropertyField(reflectionProbes);
  241. if (isMeshObject) {
  242. EditorGUILayout.PropertyField(normalsOption);
  243. }
  244. EditorGUILayout.PropertyField(optimizeSkinnedMesh);
  245. if (isMeshObject || optimizeSkinnedMesh.boolValue) {
  246. EditorGUILayout.PropertyField(GPUInstancing);
  247. }
  248. EditorGUILayout.Separator();
  249. }
  250. if (!isManager) {
  251. EditorGUILayout.LabelField("State", EditorStyles.boldLabel);
  252. if (isManager) {
  253. EditorGUILayout.LabelField(new GUIContent("Highlighted", "Highlight state (controlled by Highlight Manager)."), new GUIContent(thisEffect.highlighted.ToString()));
  254. } else {
  255. EditorGUILayout.PropertyField(highlighted);
  256. }
  257. EditorGUILayout.LabelField(new GUIContent("Selected", "Selection state (used by Highlight Trigger or Manager) when using multi-selection option."), new GUIContent(thisEffect.isSelected.ToString()));
  258. EditorGUILayout.Separator();
  259. }
  260. EditorGUILayout.BeginHorizontal();
  261. expandHighlightOptions = EditorGUILayout.Foldout(expandHighlightOptions, "Highlight Options", true, foldoutBold);
  262. if (!isMeshObject) {
  263. GUILayout.Label(new GUIContent("SPRITE MODE", "Highlight Effect over sprites. Some effects are not available in sprite mode"), EditorStyles.centeredGreyMiniLabel);
  264. }
  265. if (GUILayout.Button("Help", GUILayout.Width(50))) {
  266. EditorUtility.DisplayDialog("Quick Help", "Move the mouse over a setting for a short description.\n\nVisit kronnect.com's forum for support, questions and more cool assets.\n\nIf you like Highlight Plus please rate it or leave a review on the Asset Store! Thanks.", "Ok");
  267. }
  268. EditorGUILayout.EndHorizontal();
  269. if (expandHighlightOptions) {
  270. EditorGUI.BeginChangeCheck();
  271. if (!isManager) {
  272. EditorGUILayout.PropertyField(ignore, new GUIContent("Ignore", "This object won't be highlighted."));
  273. }
  274. if (!ignore.boolValue) {
  275. EditorGUILayout.PropertyField(effectGroup, new GUIContent("Include", "Additional objects to highlight. Pro tip: when highlighting multiple objects at the same time include them in the same layer or under the same parent."));
  276. if (effectGroup.intValue == (int)TargetOptions.LayerInScene || effectGroup.intValue == (int)TargetOptions.LayerInChildren) {
  277. EditorGUI.indentLevel++;
  278. EditorGUILayout.PropertyField(effectGroupLayer, new GUIContent("Layer"));
  279. EditorGUI.indentLevel--;
  280. }
  281. if (effectGroup.intValue != (int)TargetOptions.OnlyThisObject && effectGroup.intValue != (int)TargetOptions.Scripting) {
  282. EditorGUI.indentLevel++;
  283. EditorGUILayout.PropertyField(effectNameFilter, new GUIContent("Object Name Filter"));
  284. if (isMeshObject) {
  285. EditorGUILayout.BeginHorizontal();
  286. EditorGUILayout.PropertyField(combineMeshes);
  287. if (combineMeshes.boolValue) {
  288. if (GUILayout.Button("Refresh", GUILayout.Width(70))) {
  289. thisEffect.Refresh(true);
  290. }
  291. }
  292. EditorGUILayout.EndHorizontal();
  293. }
  294. EditorGUI.indentLevel--;
  295. }
  296. EditorGUILayout.PropertyField(alphaCutOff, new GUIContent("Alpha Cut Off", "Only for semi-transparent objects. Leave this to zero for normal opaque objects."));
  297. if (isMeshObject) {
  298. EditorGUILayout.PropertyField(cullBackFaces);
  299. }
  300. EditorGUILayout.PropertyField(fadeInDuration);
  301. EditorGUILayout.PropertyField(fadeOutDuration);
  302. EditorGUILayout.PropertyField(cameraDistanceFade);
  303. if (cameraDistanceFade.boolValue) {
  304. EditorGUI.indentLevel++;
  305. EditorGUILayout.PropertyField(cameraDistanceFadeNear, new GUIContent("Near Distance"));
  306. EditorGUILayout.PropertyField(cameraDistanceFadeFar, new GUIContent("Far Distance"));
  307. EditorGUI.indentLevel--;
  308. }
  309. if ((outlineQuality.intValue == (int)QualityLevel.Highest && outline.floatValue > 0) || (glowQuality.intValue == (int)QualityLevel.Highest && glow.floatValue > 0)) {
  310. EditorGUILayout.PropertyField(flipY, new GUIContent("Flip Y Fix", "Flips outline/glow effect to fix bug introduced in Unity 2019.1.0 when VR is enabled."));
  311. }
  312. if (glowQuality.intValue != (int)QualityLevel.Highest || outlineQuality.intValue != (int)QualityLevel.Highest) {
  313. EditorGUILayout.PropertyField(constantWidth, new GUIContent("Constant Width", "Compensates outline/glow width with depth increase."));
  314. }
  315. if (isMeshObject) {
  316. EditorGUILayout.PropertyField(subMeshMask);
  317. EditorGUILayout.PropertyField(outlineIndependent, new GUIContent("Independent", "Do not combine outline or glow with other highlighted objects."));
  318. }
  319. }
  320. }
  321. if (!ignore.boolValue) {
  322. EditorGUILayout.Separator();
  323. EditorGUILayout.LabelField("Effects", EditorStyles.boldLabel);
  324. EditorGUILayout.BeginVertical(GUI.skin.box);
  325. DrawSectionField(outline, "Outline", outline.floatValue > 0);
  326. if (outline.floatValue > 0) {
  327. EditorGUI.indentLevel++;
  328. if (isMeshObject) {
  329. EditorGUILayout.BeginHorizontal();
  330. QualityPropertyField(outlineQuality);
  331. if (outlineQuality.intValue == (int)QualityLevel.Highest) {
  332. GUILayout.Label("(Screen-Space Effect)");
  333. } else {
  334. GUILayout.Label("(Mesh-based Effect)");
  335. }
  336. EditorGUILayout.EndHorizontal();
  337. }
  338. CheckVRSupport(outlineQuality.intValue);
  339. if (outlineQuality.intValue == (int)QualityLevel.Highest) {
  340. EditorGUILayout.PropertyField(outlineEdgeMode, new GUIContent("Edges"));
  341. if (outlineEdgeMode.intValue == (int)OutlineEdgeMode.Any) {
  342. EditorGUILayout.PropertyField(outlineEdgeThreshold, new GUIContent("Edge Detection Threshold"));
  343. }
  344. EditorGUILayout.PropertyField(outlineContourStyle, new GUIContent("Contour Style"));
  345. EditorGUILayout.PropertyField(outlineWidth, new GUIContent("Width"));
  346. EditorGUILayout.PropertyField(outlineColor, new GUIContent("Color"));
  347. EditorGUILayout.PropertyField(outlineBlurPasses, new GUIContent("Blur Passes"));
  348. } else {
  349. EditorGUILayout.PropertyField(outlineWidth, new GUIContent("Width"));
  350. EditorGUILayout.PropertyField(outlineColorStyle, new GUIContent("Color Style"));
  351. switch ((ColorStyle)outlineColorStyle.intValue) {
  352. case ColorStyle.SingleColor:
  353. EditorGUILayout.PropertyField(outlineColor, new GUIContent("Color"));
  354. break;
  355. case ColorStyle.Gradient:
  356. EditorGUI.indentLevel++;
  357. EditorGUILayout.PropertyField(outlineGradient, new GUIContent("Gradient"));
  358. EditorGUILayout.PropertyField(outlineGradientInLocalSpace, new GUIContent("In Local Space"));
  359. EditorGUI.indentLevel--;
  360. break;
  361. }
  362. }
  363. if (outlineQuality.intValue == (int)QualityLevel.Highest && outlineEdgeMode.intValue != (int)OutlineEdgeMode.Any) {
  364. CheckDepthTextureSupport("Highest Quality");
  365. EditorGUILayout.PropertyField(outlineDownsampling, new GUIContent("Downsampling"));
  366. }
  367. if (outlineQuality.intValue == (int)QualityLevel.Highest && (glow.floatValue > 0 && glowQuality.intValue == (int)QualityLevel.Highest)) {
  368. outlineVisibility.intValue = glowVisibility.intValue;
  369. }
  370. EditorGUILayout.PropertyField(outlineVisibility, new GUIContent("Visibility"));
  371. if (outlineQuality.intValue == (int)QualityLevel.Highest) {
  372. EditorGUILayout.PropertyField(outlineBlitDebug, new GUIContent("Debug View", "Shows the blitting rectangle on the screen."));
  373. if (!Application.isPlaying && outlineBlitDebug.boolValue && (!HighlightPlusRenderPassFeature.showingInEditMode || !highlighted.boolValue)) {
  374. EditorGUILayout.HelpBox("Enable \"Preview In Editor\" in the Highlight Render Feature and \"Highlighted\" to display the outline Debug View.", MessageType.Warning);
  375. }
  376. }
  377. EditorGUI.indentLevel--;
  378. }
  379. EditorGUILayout.EndVertical();
  380. EditorGUILayout.BeginVertical(GUI.skin.box);
  381. DrawSectionField(glow, "Outer Glow", glow.floatValue > 0);
  382. if (glow.floatValue > 0) {
  383. EditorGUI.indentLevel++;
  384. if (isMeshObject) {
  385. EditorGUILayout.BeginHorizontal();
  386. QualityPropertyField(glowQuality);
  387. if (glowQuality.intValue == (int)QualityLevel.Highest) {
  388. GUILayout.Label("(Screen-Space Effect)");
  389. } else {
  390. GUILayout.Label("(Mesh-based Effect)");
  391. }
  392. EditorGUILayout.EndHorizontal();
  393. }
  394. CheckVRSupport(glowQuality.intValue);
  395. if (glowQuality.intValue == (int)QualityLevel.Highest) {
  396. CheckDepthTextureSupport("Highest Quality");
  397. EditorGUILayout.PropertyField(outlineContourStyle, new GUIContent("Contour Style"));
  398. EditorGUILayout.PropertyField(glowWidth, new GUIContent("Width"));
  399. EditorGUILayout.PropertyField(glowHQColor, new GUIContent("Color"));
  400. EditorGUILayout.PropertyField(glowBlurMethod, new GUIContent("Blur Method", "Gaussian: better quality. Kawase: faster."));
  401. EditorGUILayout.PropertyField(glowDownsampling, new GUIContent("Downsampling"));
  402. } else {
  403. EditorGUILayout.PropertyField(glowWidth, new GUIContent("Width"));
  404. }
  405. if (glowQuality.intValue == (int)QualityLevel.Highest) {
  406. EditorGUILayout.PropertyField(glowVisibility, new GUIContent("Visibility"));
  407. EditorGUILayout.PropertyField(glowBlendMode, new GUIContent("Blend Mode"));
  408. } else {
  409. EditorGUILayout.PropertyField(glowVisibility, new GUIContent("Visibility"));
  410. EditorGUILayout.PropertyField(glowDithering, new GUIContent("Dithering"));
  411. if (glowDithering.boolValue) {
  412. EditorGUI.indentLevel++;
  413. EditorGUILayout.PropertyField(glowMagicNumber1, new GUIContent("Magic Number 1"));
  414. EditorGUILayout.PropertyField(glowMagicNumber2, new GUIContent("Magic Number 2"));
  415. EditorGUI.indentLevel--;
  416. }
  417. EditorGUILayout.PropertyField(glowBlendPasses, new GUIContent("Blend Passes"));
  418. if (!glowBlendPasses.boolValue) {
  419. HighlightEffect ef = (HighlightEffect)target;
  420. if (ef.glowPasses != null) {
  421. for (int k = 0; k < ef.glowPasses.Length - 1; k++) {
  422. if (ef.glowPasses[k].offset > ef.glowPasses[k + 1].offset) {
  423. EditorGUILayout.HelpBox("Glow pass " + k + " has a greater offset than the next one. Reduce it to ensure the next glow pass is visible.", MessageType.Warning);
  424. }
  425. }
  426. }
  427. }
  428. EditorGUILayout.PropertyField(glowPasses, true);
  429. }
  430. EditorGUILayout.PropertyField(glowAnimationSpeed, new GUIContent("Animation Speed"));
  431. EditorGUILayout.PropertyField(glowIgnoreMask, new GUIContent("Ignore Mask"));
  432. if (glowQuality.intValue == (int)QualityLevel.Highest) {
  433. EditorGUILayout.PropertyField(glowBlitDebug, new GUIContent("Debug View", "Shows the blitting rectangle on the screen."));
  434. if (!Application.isPlaying && glowBlitDebug.boolValue && (!HighlightPlusRenderPassFeature.showingInEditMode || !highlighted.boolValue)) {
  435. EditorGUILayout.HelpBox("Enable \"Preview In Editor\" in the Highlight Render Feature and \"Highlighted\" to display the glow Debug View.", MessageType.Warning);
  436. }
  437. }
  438. EditorGUI.indentLevel--;
  439. }
  440. EditorGUILayout.EndVertical();
  441. if (isMeshObject) {
  442. EditorGUILayout.BeginVertical(GUI.skin.box);
  443. DrawSectionField(innerGlow, "Inner Glow", innerGlow.floatValue > 0);
  444. if (innerGlow.floatValue > 0) {
  445. EditorGUI.indentLevel++;
  446. EditorGUILayout.PropertyField(innerGlowColor, new GUIContent("Color"));
  447. EditorGUILayout.PropertyField(innerGlowWidth, new GUIContent("Width"));
  448. EditorGUILayout.PropertyField(innerGlowBlendMode, new GUIContent("Blend Mode"));
  449. EditorGUILayout.PropertyField(innerGlowVisibility, new GUIContent("Visibility"));
  450. EditorGUI.indentLevel--;
  451. }
  452. EditorGUILayout.EndVertical();
  453. }
  454. EditorGUILayout.BeginVertical(GUI.skin.box);
  455. DrawSectionField(overlay, "Overlay", overlay.floatValue > 0);
  456. if (overlay.floatValue > 0) {
  457. EditorGUI.indentLevel++;
  458. EditorGUILayout.PropertyField(overlayMode, new GUIContent("Mode"));
  459. EditorGUILayout.PropertyField(overlayColor, new GUIContent("Color"));
  460. EditorGUILayout.PropertyField(overlayTexture, new GUIContent("Texture"));
  461. if (overlayTexture.objectReferenceValue != null) {
  462. EditorGUILayout.PropertyField(overlayTextureUVSpace, new GUIContent("UV Space"));
  463. EditorGUILayout.PropertyField(overlayTextureScale, new GUIContent("Texture Scale"));
  464. }
  465. EditorGUILayout.PropertyField(overlayBlending, new GUIContent("Blending"));
  466. EditorGUILayout.PropertyField(overlayMinIntensity, new GUIContent("Min Intensity"));
  467. EditorGUILayout.PropertyField(overlayAnimationSpeed, new GUIContent("Animation Speed"));
  468. EditorGUILayout.PropertyField(overlayVisibility, new GUIContent("Visibility"));
  469. EditorGUI.indentLevel--;
  470. }
  471. EditorGUILayout.EndVertical();
  472. EditorGUILayout.BeginVertical(GUI.skin.box);
  473. DrawSectionField(targetFX, "Target", targetFX.boolValue);
  474. if (targetFX.boolValue) {
  475. EditorGUI.indentLevel++;
  476. EditorGUILayout.PropertyField(targetFXTexture, new GUIContent("Texture", "The texture that contains the shape to be drawn over the highlighted object."));
  477. EditorGUILayout.PropertyField(targetFXColor, new GUIContent("Color"));
  478. EditorGUILayout.PropertyField(targetFXCenter, new GUIContent("Center", "Optionally assign a transform. Target will follow transform. If the object is skinned, you can also assign a bone to reflect currenct animation position."));
  479. EditorGUILayout.PropertyField(targetFXRotationSpeed, new GUIContent("Rotation Speed"));
  480. EditorGUILayout.PropertyField(targetFXInitialScale, new GUIContent("Initial Scale"));
  481. EditorGUILayout.PropertyField(targetFXEndScale, new GUIContent("End Scale"));
  482. EditorGUILayout.PropertyField(targetFXScaleToRenderBounds, new GUIContent("Scale To Object Bounds"));
  483. EditorGUILayout.PropertyField(targetFXAlignToGround, new GUIContent("Align To Ground"));
  484. if (targetFXAlignToGround.boolValue) {
  485. CheckDepthTextureSupport("Align To Ground option");
  486. EditorGUI.indentLevel++;
  487. if (thisEffect.includedObjectsCount > 1 && targetFXCenter.objectReferenceValue == null && effectGroup.intValue != (int)TargetOptions.OnlyThisObject) {
  488. EditorGUILayout.HelpBox("It's recommended to specify in the 'Center' property above, the specific object used to position the target fx image (will be rendered under that object on the ground).", MessageType.Info);
  489. }
  490. EditorGUILayout.PropertyField(targetFXGroundMaxDistance, new GUIContent("Ground Max Distance"));
  491. EditorGUILayout.PropertyField(targetFXGroundLayerMask, new GUIContent("Ground Layer Mask"));
  492. HighlightEffect he = (HighlightEffect)target;
  493. if ((targetFXGroundLayerMask.intValue & (1 << he.gameObject.layer)) != 0) {
  494. EditorGUILayout.HelpBox("Ground Layer Mask should not include this object layer.", MessageType.Warning);
  495. }
  496. EditorGUILayout.PropertyField(targetFXFadePower, new GUIContent("Fade Power"));
  497. EditorGUI.indentLevel--;
  498. }
  499. EditorGUILayout.PropertyField(targetFXTransitionDuration, new GUIContent("Transition Duration"));
  500. EditorGUILayout.PropertyField(targetFXStayDuration, new GUIContent("Stay Duration"));
  501. EditorGUILayout.PropertyField(targetFXVisibility, new GUIContent("Visibility"));
  502. EditorGUI.indentLevel--;
  503. }
  504. EditorGUILayout.EndVertical();
  505. }
  506. if (isMeshObject) {
  507. EditorGUILayout.BeginVertical(GUI.skin.box);
  508. EditorGUILayout.PropertyField(seeThrough);
  509. if (seeThrough.intValue != (int)SeeThroughMode.Never) {
  510. if (isManager && seeThrough.intValue == (int)SeeThroughMode.AlwaysWhenOccluded) {
  511. EditorGUILayout.HelpBox("This option is not valid in Manager.\nTo make an object always visible add a Highlight Effect component to the gameobject and enable this option on the component.", MessageType.Error);
  512. }
  513. EditorGUI.indentLevel++;
  514. EditorGUILayout.PropertyField(seeThroughOccluderMask, new GUIContent("Occluder Layer"));
  515. if (seeThroughOccluderMask.intValue > 0) {
  516. EditorGUI.indentLevel++;
  517. EditorGUILayout.PropertyField(seeThroughOccluderMaskAccurate, new GUIContent("Accurate"));
  518. EditorGUILayout.PropertyField(seeThroughOccluderThreshold, new GUIContent("Radius Threshold", "Multiplier to the object bounds. Making the bounds smaller prevents false occlusion tests."));
  519. EditorGUILayout.PropertyField(seeThroughOccluderCheckInterval, new GUIContent("Check Interval", "Interval in seconds between occlusion tests."));
  520. EditorGUILayout.PropertyField(seeThroughOccluderCheckIndividualObjects, new GUIContent("Check Individual Objects"));
  521. if (!showCurrentOccluders && Camera.main != null) {
  522. GUI.enabled = Application.isPlaying;
  523. EditorGUILayout.BeginHorizontal();
  524. GUILayout.Label("", GUILayout.Width(30));
  525. if (GUILayout.Button(" Show Current Occluders (only during Play Mode) ")) {
  526. showCurrentOccluders = true;
  527. }
  528. GUILayout.FlexibleSpace();
  529. EditorGUILayout.EndHorizontal();
  530. GUI.enabled = true;
  531. }
  532. if (showCurrentOccluders) {
  533. HighlightEffect h = (HighlightEffect)target;
  534. List<Renderer> occluders = h.GetOccluders(Camera.main);
  535. int count = occluders != null ? occluders.Count : 0;
  536. if (count == 0) {
  537. EditorGUILayout.LabelField("No occluders found (using main camera)");
  538. } else {
  539. EditorGUILayout.LabelField("Occluders found (using main camera):");
  540. for (int k = 0; k < count; k++) {
  541. if (occluders[k] == null) continue;
  542. EditorGUILayout.BeginHorizontal();
  543. EditorGUILayout.LabelField(occluders[k].name);
  544. if (GUILayout.Button("Select")) {
  545. Selection.activeGameObject = occluders[k].gameObject;
  546. GUIUtility.ExitGUI();
  547. }
  548. EditorGUILayout.EndHorizontal();
  549. }
  550. }
  551. }
  552. EditorGUI.indentLevel--;
  553. }
  554. EditorGUILayout.PropertyField(seeThroughDepthOffset, new GUIContent("Depth Offset" + ((seeThroughDepthOffset.floatValue > 0) ? " •" : "")));
  555. EditorGUILayout.PropertyField(seeThroughMaxDepth, new GUIContent("Max Depth" + ((seeThroughMaxDepth.floatValue > 0) ? " •" : "")));
  556. if (seeThroughDepthOffset.floatValue > 0 || seeThroughMaxDepth.floatValue > 0) {
  557. CheckDepthTextureSupport("See-Through Depth Options");
  558. }
  559. EditorGUILayout.PropertyField(seeThroughIntensity, new GUIContent("Intensity"));
  560. EditorGUILayout.PropertyField(seeThroughTintColor, new GUIContent("Color"));
  561. EditorGUILayout.PropertyField(seeThroughTintAlpha, new GUIContent("Color Blend"));
  562. EditorGUILayout.PropertyField(seeThroughNoise, new GUIContent("Noise"));
  563. EditorGUILayout.PropertyField(seeThroughTexture, new GUIContent("Texture"));
  564. if (seeThroughTexture.objectReferenceValue != null) {
  565. EditorGUI.indentLevel++;
  566. EditorGUILayout.PropertyField(seeThroughTextureUVSpace, new GUIContent("UV Space"));
  567. EditorGUILayout.PropertyField(seeThroughTextureScale, new GUIContent("Texture Scale"));
  568. EditorGUI.indentLevel--;
  569. }
  570. EditorGUILayout.PropertyField(seeThroughBorder, new GUIContent("Border When Hidden" + ((seeThroughBorder.floatValue > 0) ? " •" : "")));
  571. if (seeThroughBorder.floatValue > 0) {
  572. EditorGUI.indentLevel++;
  573. EditorGUILayout.PropertyField(seeThroughBorderWidth, new GUIContent("Width"));
  574. EditorGUILayout.PropertyField(seeThroughBorderColor, new GUIContent("Color"));
  575. EditorGUILayout.PropertyField(seeThroughBorderOnly, new GUIContent("Border Only"));
  576. EditorGUI.indentLevel--;
  577. }
  578. EditorGUILayout.PropertyField(seeThroughChildrenSortingMode, new GUIContent("Children Sorting Mode"));
  579. EditorGUILayout.PropertyField(seeThroughOrdered, new GUIContent("Ordered"));
  580. EditorGUI.indentLevel--;
  581. }
  582. EditorGUILayout.EndVertical();
  583. }
  584. EditorGUILayout.BeginVertical(GUI.skin.box);
  585. DrawSectionField(hitFxInitialIntensity, "Hit FX", hitFxInitialIntensity.floatValue > 0);
  586. if (hitFxInitialIntensity.floatValue > 0) {
  587. EditorGUI.indentLevel++;
  588. EditorGUILayout.PropertyField(hitFxMode, new GUIContent("Mode"));
  589. EditorGUILayout.PropertyField(hitFxFadeOutDuration, new GUIContent("Fade Out Duration"));
  590. EditorGUILayout.PropertyField(hitFxColor, new GUIContent("Color"));
  591. if ((HitFxMode)hitFxMode.intValue == HitFxMode.LocalHit) {
  592. EditorGUILayout.PropertyField(hitFxRadius, new GUIContent("Radius"));
  593. }
  594. EditorGUI.indentLevel--;
  595. }
  596. if (!Application.isPlaying) {
  597. EditorGUILayout.HelpBox("Enter Play Mode to test this feature. In your code, call effect.HitFX() method to execute this hit effect.", MessageType.Info);
  598. } else {
  599. EditorGUI.indentLevel++;
  600. if (GUILayout.Button("Execute Hit")) {
  601. thisEffect.HitFX();
  602. }
  603. EditorGUI.indentLevel--;
  604. }
  605. EditorGUILayout.EndVertical();
  606. if (serializedObject.ApplyModifiedProperties() || profileChanged || Event.current.commandName == "UndoRedoPerformed") {
  607. if (thisEffect.profile != null) {
  608. if (profileChanged) {
  609. thisEffect.profile.Load(thisEffect);
  610. profileChanged = false;
  611. enableProfileApply = false;
  612. } else {
  613. enableProfileApply = true;
  614. }
  615. }
  616. foreach (HighlightEffect effect in targets) {
  617. effect.Refresh();
  618. }
  619. }
  620. }
  621. void DrawSectionField(SerializedProperty property, string label, bool active) {
  622. EditorGUILayout.PropertyField(property, new GUIContent(active ? label + " •" : label));
  623. }
  624. void CheckVRSupport(int qualityLevel) {
  625. if (qualityLevel == (int)QualityLevel.Highest && PlayerSettings.virtualRealitySupported) {
  626. if (PlayerSettings.stereoRenderingPath != StereoRenderingPath.MultiPass) {
  627. EditorGUILayout.HelpBox("Highest Quality only supports VR Multi-Pass as CommandBuffers do not support this VR mode yet. Either switch to 'High Quality' or change VR Stereo mode to Multi-Pass.", MessageType.Error);
  628. }
  629. }
  630. }
  631. void CheckDepthTextureSupport(string feature) {
  632. if (pipe == null) return;
  633. if (!pipe.supportsCameraDepthTexture && !thisEffect.spriteMode) {
  634. EditorGUILayout.HelpBox(feature + " requires Depth Texture support and currently it's not enabled in the Rendering Pipeline asset.", MessageType.Error);
  635. if (pipe != null && GUILayout.Button("Go to Universal Rendering Pipeline Asset")) {
  636. Selection.activeObject = pipe;
  637. }
  638. EditorGUILayout.Separator();
  639. }
  640. }
  641. static readonly int[] qualityValues = { 0, 3, 1, 2 };
  642. static readonly GUIContent[] qualityTexts = { new GUIContent("Fastest"), new GUIContent("Medium"), new GUIContent("High"), new GUIContent("Highest") };
  643. public static void QualityPropertyField(SerializedProperty prop) {
  644. prop.intValue = EditorGUILayout.IntPopup(new GUIContent("Quality", "Default and High use a mesh displacement technique. Highest quality can provide best look and also performance depending on the complexity of mesh."), prop.intValue, qualityTexts, qualityValues);
  645. }
  646. bool IsDefaultEffectUsedByManager() {
  647. MonoBehaviour[] components = thisEffect.GetComponents<MonoBehaviour>();
  648. if (components != null) {
  649. for (int k = 0; k < components.Length; k++) {
  650. if (components[k] == null || !components[k].enabled)
  651. continue;
  652. string name = components[k].GetType().Name;
  653. if ("HighlightManager".Equals(name)) return true;
  654. }
  655. }
  656. return false;
  657. }
  658. #region Profile handling
  659. void CreateProfile() {
  660. HighlightProfile newProfile = CreateInstance<HighlightProfile>();
  661. newProfile.Save(thisEffect);
  662. AssetDatabase.CreateAsset(newProfile, "Assets/Highlight Plus Profile.asset");
  663. AssetDatabase.SaveAssets();
  664. EditorUtility.FocusProjectWindow();
  665. Selection.activeObject = newProfile;
  666. thisEffect.profile = newProfile;
  667. }
  668. #endregion
  669. #pragma warning restore 0618
  670. }
  671. }