using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEngine; using UnityEngine.Rendering; using VRMShaders.VRM10.MToon10.Runtime; namespace VRMShaders.VRM10.MToon10.Editor { public sealed class MToonInspector : ShaderGUI { public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) { var props = MToon10Properties.UnityShaderLabNames .ToDictionary(x => x.Key, x => FindProperty(x.Value, properties)); var materials = materialEditor.targets.Select(x => x as Material).ToArray(); EditorGUI.BeginChangeCheck(); EditorGUILayout.HelpBox("This shader is for VRM 1.0.", MessageType.Info); using (new LabelScope("Editor Settings")) { PopupEnum("Edit Mode", props[MToon10Prop.EditorEditMode], materialEditor); } var editMode = (MToon10EditorEditMode)(int)props[MToon10Prop.EditorEditMode].floatValue; var isAdvancedEditMode = editMode == MToon10EditorEditMode.Advanced; using (new LabelScope("Rendering")) { PopupEnum("Alpha Mode", props[MToon10Prop.AlphaMode], materialEditor); var alphaMode = (MToon10AlphaMode)(int)props[MToon10Prop.AlphaMode].floatValue; if (isAdvancedEditMode && alphaMode == MToon10AlphaMode.Transparent) { PopupEnum( "Transparent With ZWrite Mode", props[MToon10Prop.TransparentWithZWrite], materialEditor ); } if (alphaMode == MToon10AlphaMode.Cutout) { materialEditor.ShaderProperty(props[MToon10Prop.AlphaCutoff], "Cutoff"); } PopupEnum("Double Sided", props[MToon10Prop.DoubleSided], materialEditor); if (isAdvancedEditMode) { materialEditor.ShaderProperty(props[MToon10Prop.RenderQueueOffsetNumber], "RenderQueue Offset"); } } using (new LabelScope("Lighting")) { materialEditor.TexturePropertySingleLine( new GUIContent("Lit Color, Alpha", "Lit (RGB), Alpha (A)"), props[MToon10Prop.BaseColorTexture], props[MToon10Prop.BaseColorFactor] ); materialEditor.TexturePropertySingleLine( new GUIContent("Shade Color", "Shade (RGB)"), props[MToon10Prop.ShadeColorTexture], props[MToon10Prop.ShadeColorFactor] ); if (isAdvancedEditMode) { materialEditor.TexturePropertySingleLine( new GUIContent("Normal Map", "Normal Map (RGB)"), props[MToon10Prop.NormalTexture], props[MToon10Prop.NormalTextureScale] ); } EditorGUILayout.Space(); if (isAdvancedEditMode) { materialEditor.ShaderProperty(props[MToon10Prop.ShadingToonyFactor], "Shading Toony"); materialEditor.ShaderProperty(props[MToon10Prop.ShadingShiftFactor], "Shading Shift"); materialEditor.TexturePropertySingleLine( new GUIContent("Additive Shading Shift", "Shading Shift (R)"), props[MToon10Prop.ShadingShiftTexture], props[MToon10Prop.ShadingShiftTextureScale] ); } else { EditorGUILayout.BeginHorizontal(); GUILayout.Label("Presets"); if (GUILayout.Button("Default")) { props[MToon10Prop.ShadingToonyFactor].floatValue = 0.95f; props[MToon10Prop.ShadingShiftFactor].floatValue = -0.05f; props[MToon10Prop.ShadingShiftTexture].textureValue = null; } if (GUILayout.Button("Lambert")) { props[MToon10Prop.ShadingToonyFactor].floatValue = 0.5f; props[MToon10Prop.ShadingShiftFactor].floatValue = -0.5f; props[MToon10Prop.ShadingShiftTexture].textureValue = null; } if (GUILayout.Button("Cartoon")) { props[MToon10Prop.ShadingToonyFactor].floatValue = 1.0f; props[MToon10Prop.ShadingShiftFactor].floatValue = 0.0f; props[MToon10Prop.ShadingShiftTexture].textureValue = null; } EditorGUILayout.EndHorizontal(); GUILayout.BeginVertical(GUI.skin.box); materialEditor.ShaderProperty(props[MToon10Prop.ShadingToonyFactor], "Shading Toony"); materialEditor.ShaderProperty(props[MToon10Prop.ShadingShiftFactor], "Shading Shift"); GUILayout.EndVertical(); } if (props[MToon10Prop.ShadingShiftTexture].textureValue == null) { var toony = props[MToon10Prop.ShadingToonyFactor].floatValue; var shift = props[MToon10Prop.ShadingShiftFactor].floatValue; if (toony - shift < 1.0f - 0.001f) { EditorGUILayout.HelpBox("The lit area includes non-lit area.", MessageType.Warning); } } } if (isAdvancedEditMode) { using (new LabelScope("Global Illumination")) { materialEditor.ShaderProperty(props[MToon10Prop.GiEqualizationFactor], "GI Equalization"); } } using (new LabelScope("Emission")) { materialEditor.TexturePropertySingleLine( new GUIContent("Emission", "Emission (RGB)"), props[MToon10Prop.EmissiveTexture], props[MToon10Prop.EmissiveFactor] ); } using (new LabelScope("Rim Lighting")) { if (isAdvancedEditMode) { materialEditor.TexturePropertySingleLine( new GUIContent("Mask", "Rim Lighting Mask (RGB)"), props[MToon10Prop.RimMultiplyTexture] ); materialEditor.ShaderProperty( props[MToon10Prop.RimLightingMixFactor], new GUIContent("LightingMix") ); EditorGUILayout.Space(); } using (new LabelScope("Matcap")) { materialEditor.TexturePropertySingleLine( new GUIContent("Matcap", "Matcap (RGB)"), props[MToon10Prop.MatcapTexture], props[MToon10Prop.MatcapColorFactor] ); EditorGUILayout.Space(); } using (new LabelScope("Parametric Rim")) { materialEditor.ShaderProperty( props[MToon10Prop.ParametricRimColorFactor], new GUIContent("Color") ); materialEditor.ShaderProperty( props[MToon10Prop.ParametricRimFresnelPowerFactor], new GUIContent("Fresnel Power") ); materialEditor.ShaderProperty( props[MToon10Prop.ParametricRimLiftFactor], new GUIContent("Lift") ); } } using (new LabelScope("Outline")) { PopupEnum("Outline Mode", props[MToon10Prop.OutlineWidthMode], materialEditor); var hasOutline = (MToon10OutlineMode)(int)props[MToon10Prop.OutlineWidthMode].floatValue != MToon10OutlineMode.None; if (hasOutline) { materialEditor.TexturePropertySingleLine( new GUIContent("Outline Width", "Outline Width (G) [meter]"), props[MToon10Prop.OutlineWidthMultiplyTexture], props[MToon10Prop.OutlineWidthFactor] ); materialEditor.ShaderProperty( props[MToon10Prop.OutlineColorFactor], new GUIContent("Outline Color") ); if (isAdvancedEditMode) { materialEditor.ShaderProperty( props[MToon10Prop.OutlineLightingMixFactor], new GUIContent("Outline LightingMix") ); } } } if (isAdvancedEditMode) { using (new LabelScope("UV Animation")) { materialEditor.TexturePropertySingleLine( new GUIContent("Mask", "Mask (B)"), props[MToon10Prop.UvAnimationMaskTexture] ); materialEditor.ShaderProperty( props[MToon10Prop.UvAnimationScrollXSpeedFactor], new GUIContent("Translate X") ); materialEditor.ShaderProperty( props[MToon10Prop.UvAnimationScrollYSpeedFactor], new GUIContent("Translate Y") ); materialEditor.ShaderProperty( props[MToon10Prop.UvAnimationRotationSpeedFactor], new GUIContent("Rotation") ); } } if (EditorGUI.EndChangeCheck()) { Validate(materials); } if (isAdvancedEditMode && materials.Length == 1) { var mat = materials[0]; using (new LabelScope("Debug")) { EditorGUILayout.LabelField("RenderQueue", mat.renderQueue.ToString()); EditorGUILayout.LabelField("Cull", ((CullMode)props[MToon10Prop.UnityCullMode].floatValue).ToString()); EditorGUILayout.LabelField("SrcBlend", ((BlendMode)props[MToon10Prop.UnitySrcBlend].floatValue).ToString()); EditorGUILayout.LabelField("DstBlend", ((BlendMode)props[MToon10Prop.UnityDstBlend].floatValue).ToString()); EditorGUILayout.LabelField("ZWrite", ((UnityZWriteMode)props[MToon10Prop.UnityZWrite].floatValue).ToString()); EditorGUILayout.LabelField("AlphaToMask", ((UnityAlphaToMaskMode)props[MToon10Prop.UnityAlphaToMask].floatValue).ToString()); EditorGUILayout.LabelField("Enabled Keywords", string.Join("\n", mat.shaderKeywords), EditorStyles.textArea); } } // base.OnGUI(materialEditor, properties); } private static void Validate(Material[] materials) { foreach (var material in materials) { new MToonValidator(material).Validate(); } } private static bool PopupEnum(string name, MaterialProperty property, MaterialEditor editor) where T : struct { EditorGUI.showMixedValue = property.hasMixedValue; EditorGUI.BeginChangeCheck(); var ret = EditorGUILayout.Popup(name, (int)property.floatValue, Enum.GetNames(typeof(T))); var changed = EditorGUI.EndChangeCheck(); if (changed) { editor.RegisterPropertyChangeUndo($"Change {name}"); property.floatValue = ret; } EditorGUI.showMixedValue = false; return changed; } } }