using UnityEditor; using UnityEngine; using System.Collections; using System.Collections.Generic; using System.Linq; using System; using System.Reflection; public class XSFurInspector : ShaderGUI { BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; Material ThisMaterial = null; //Assign all properties as null at first to stop hundreds of warnings spamming the log when script gets compiled. //If they aren't we get warnings, because assigning with reflection seems to make Unity think that the properties never actually get used. // MaterialProperty _LightProbeMethod = null; MaterialProperty _TextureSampleMode = null; MaterialProperty _TriplanarFalloff = null; MaterialProperty _MainTex = null; MaterialProperty _Cutoff = null; MaterialProperty _Color = null; MaterialProperty _BottomColor = null; MaterialProperty _ColorFalloffMin = null; MaterialProperty _ColorFalloffMax = null; MaterialProperty _FurTexture = null; MaterialProperty _FurLengthMask = null; MaterialProperty _NoiseTexture = null; MaterialProperty _LayerCount = null; MaterialProperty _FurLength = null; MaterialProperty _FurWidth = null; MaterialProperty _Gravity = null; MaterialProperty _CombX = null; MaterialProperty _CombY = null; MaterialProperty _FurOcclusion = null; MaterialProperty _OcclusionFalloffMin = null; MaterialProperty _OcclusionFalloffMax = null; MaterialProperty _BumpMap = null; MaterialProperty _BumpScale = null; MaterialProperty _MetallicGlossMap = null; MaterialProperty _Metallic = null; MaterialProperty _Glossiness = null; MaterialProperty _Reflectance = null; MaterialProperty _Anisotropy = null; MaterialProperty _OcclusionMap = null; MaterialProperty _OcclusionColor = null; MaterialProperty _EmissionMap = null; MaterialProperty _EmissionColor = null; MaterialProperty _EmissionFalloffMin = null; MaterialProperty _EmissionFalloffMax = null; MaterialProperty _ClearcoatMap = null; MaterialProperty _Clearcoat = null; MaterialProperty _ClearcoatGlossiness = null; MaterialProperty _ClearcoatAnisotropy = null; MaterialProperty _SpecularLMOcclusion = null; MaterialProperty _SpecLMOcclusionAdjust = null; MaterialProperty _LMStrength = null; MaterialProperty _RTLMStrength = null; //-- static bool showMainSettings = true; static bool showNormalMapSettings = false; static bool showReflection = false; static bool showEmission = false; static bool showFurSettings = false; static bool showOcclusion = false; static bool showLightmap = false; public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props) { //Find all material properties listed in the script using reflection, and set them using a loop only if they're of type MaterialProperty. //This makes things a lot nicer to maintain and cleaner to look at. foreach (var property in GetType().GetFields(bindingFlags)) { if (property.FieldType == typeof(MaterialProperty)) { try { property.SetValue(this, FindProperty(property.Name, props)); } catch { /*Is it really a problem if it doesn't exist?*/ } } } EditorGUI.BeginChangeCheck(); { XSFurUIStyles.ShurikenHeaderCentered("XSFur v" + XSFurUIStyles.ver); ThisMaterial = materialEditor.target as Material; DrawMainSettings(materialEditor); DrawNormalSettings(materialEditor); DrawFurSettings(materialEditor); DrawOcclusionSettings(materialEditor); DrawReflectionsSettings(materialEditor); DrawEmissionSettings(materialEditor); DrawLightmappingSettings(materialEditor); XSFurUIStyles.DoFooter(); } } private void DrawMainSettings(MaterialEditor materialEditor) { materialEditor.ShaderProperty(_LightProbeMethod, new GUIContent("Lightprobe Sampling Method", "How light probes get sampled. Non Linear L1 may be better in some situations.")); materialEditor.ShaderProperty(_TextureSampleMode, new GUIContent("Texture Sample Space", "How to sample textures.")); if (ThisMaterial.GetInt("_TextureSampleMode") != 0) materialEditor.ShaderProperty(_TriplanarFalloff, new GUIContent("Triplanar Blend", "Triplanar blending amount.")); showMainSettings = XSFurUIStyles.ShurikenFoldout("Main Settings", showMainSettings); if (showMainSettings) { materialEditor.TexturePropertySingleLine(new GUIContent("Skin Albedo", "Albedo texture for the skin"), _MainTex); materialEditor.TextureScaleOffsetProperty(_MainTex); materialEditor.ShaderProperty(_Cutoff, new GUIContent("Cutoff", "Cutoff value")); XSFurUIStyles.SeparatorThin(); } } private void DrawFurSettings(MaterialEditor materialEditor) { showFurSettings = XSFurUIStyles.ShurikenFoldout("Fur Settings", showFurSettings); if (showFurSettings) { materialEditor.TexturePropertySingleLine(new GUIContent("Fur Albedo", "Albedo Texture for the fur coat"), _FurTexture); materialEditor.TextureScaleOffsetProperty(_FurTexture); XSFurUIStyles.SeparatorThin(); materialEditor.TexturePropertySingleLine(new GUIContent("Noise Texture", "Used to control the pattern of the fur strands."), _NoiseTexture); materialEditor.TextureScaleOffsetProperty(_NoiseTexture); XSFurUIStyles.SeparatorThin(); materialEditor.TexturePropertySingleLine(new GUIContent("Length Mask", "Used to control length of the fur."), _FurLengthMask); materialEditor.TextureScaleOffsetProperty(_FurLengthMask); XSFurUIStyles.SeparatorThin(); materialEditor.ShaderProperty(_Color, new GUIContent("Top Color", "")); materialEditor.ShaderProperty(_BottomColor, new GUIContent("Bottom Color", "")); materialEditor.ShaderProperty(_ColorFalloffMin, new GUIContent("Blend Min", "")); materialEditor.ShaderProperty(_ColorFalloffMax, new GUIContent("Blend Max", "")); XSFurUIStyles.SeparatorThin(); materialEditor.ShaderProperty(_LayerCount, new GUIContent("Layer Count", "")); materialEditor.ShaderProperty(_FurLength, new GUIContent("Length", "")); materialEditor.ShaderProperty(_FurWidth, new GUIContent("Strand Width", "")); XSFurUIStyles.SeparatorThin(); materialEditor.ShaderProperty(_Gravity, new GUIContent("Gravity Strength", "")); materialEditor.ShaderProperty(_CombX, new GUIContent("Comb X", "")); materialEditor.ShaderProperty(_CombY, new GUIContent("Comb Y", "")); XSFurUIStyles.SeparatorThin(); } } private void DrawNormalSettings(MaterialEditor materialEditor) { showNormalMapSettings = XSFurUIStyles.ShurikenFoldout("Normal Maps", showNormalMapSettings); if (showNormalMapSettings) { materialEditor.TexturePropertySingleLine(new GUIContent("Normal Map", ""), _BumpMap); materialEditor.TextureScaleOffsetProperty(_BumpMap); materialEditor.ShaderProperty(_BumpScale, new GUIContent("Normal Scale", "")); XSFurUIStyles.SeparatorThin(); } } private void DrawOcclusionSettings(MaterialEditor materialEditor) { showOcclusion = XSFurUIStyles.ShurikenFoldout("Occlusion", showOcclusion); if (showOcclusion) { materialEditor.TexturePropertySingleLine(new GUIContent("Occlusion Map", ""), _OcclusionMap); materialEditor.TextureScaleOffsetProperty(_OcclusionMap); materialEditor.ShaderProperty(_OcclusionColor, new GUIContent("Occlusion Color", "")); XSFurUIStyles.SeparatorThin(); materialEditor.ShaderProperty(_FurOcclusion, new GUIContent("Depth Occlusion", "")); materialEditor.ShaderProperty(_OcclusionFalloffMin, new GUIContent("Occlusion Blend Min", "")); materialEditor.ShaderProperty(_OcclusionFalloffMax, new GUIContent("Occlusion Blend Max", "")); XSFurUIStyles.SeparatorThin(); } } private void DrawReflectionsSettings(MaterialEditor materialEditor) { showReflection = XSFurUIStyles.ShurikenFoldout("Reflections", showReflection); if (showReflection) { XSFurUIStyles.doLabel("Main"); materialEditor.TexturePropertySingleLine(new GUIContent("Metallic Map", ""), _MetallicGlossMap); materialEditor.TextureScaleOffsetProperty(_MetallicGlossMap); XSFurUIStyles.SeparatorThin(); materialEditor.ShaderProperty(_Metallic, new GUIContent("Metallic", "")); materialEditor.ShaderProperty(_Glossiness, new GUIContent("Smoothness", "")); materialEditor.ShaderProperty(_Reflectance, new GUIContent("Reflectance", "")); materialEditor.ShaderProperty(_Anisotropy, new GUIContent("Anisotropy", "")); XSFurUIStyles.SeparatorThin(); XSFurUIStyles.doLabel("Clearcoat"); materialEditor.TexturePropertySingleLine(new GUIContent("Clearcoat Map", ""), _ClearcoatMap); materialEditor.TextureScaleOffsetProperty(_ClearcoatMap); XSFurUIStyles.SeparatorThin(); materialEditor.ShaderProperty(_Clearcoat, new GUIContent("Smoothness", "")); materialEditor.ShaderProperty(_ClearcoatGlossiness, new GUIContent("Reflectance", "")); materialEditor.ShaderProperty(_ClearcoatAnisotropy, new GUIContent("Anisotropy", "")); XSFurUIStyles.SeparatorThin(); } } private void DrawEmissionSettings(MaterialEditor materialEditor) { showEmission = XSFurUIStyles.ShurikenFoldout("Emission", showEmission); if (showEmission) { materialEditor.TexturePropertySingleLine(new GUIContent("Emission Map", ""), _EmissionMap); materialEditor.TextureScaleOffsetProperty(_EmissionMap); XSFurUIStyles.SeparatorThin(); materialEditor.ShaderProperty(_EmissionColor, new GUIContent("Emission Color", "")); materialEditor.ShaderProperty(_EmissionFalloffMin, new GUIContent("Emission Blend Min", "")); materialEditor.ShaderProperty(_EmissionFalloffMax, new GUIContent("Emission Blend Max", "")); XSFurUIStyles.SeparatorThin(); } } private void DrawLightmappingSettings(MaterialEditor materialEditor) { showLightmap = XSFurUIStyles.ShurikenFoldout("Lightmapping", showLightmap); if (showLightmap) { materialEditor.ShaderProperty(_SpecularLMOcclusion, new GUIContent("Specular Occlusion", "")); materialEditor.ShaderProperty(_SpecLMOcclusionAdjust, new GUIContent("Radius", ""), 2); materialEditor.ShaderProperty(_LMStrength, new GUIContent("Lightmap Strength", "")); materialEditor.ShaderProperty(_RTLMStrength, new GUIContent("Realtime Lightmap Strength", "")); XSFurUIStyles.SeparatorThin(); } } }