mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-05-14 14:29:52 -05:00
459 lines
22 KiB
C#
459 lines
22 KiB
C#
using System;
|
|
using System.Linq;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace MToon
|
|
{
|
|
public class MToonInspector : ShaderGUI
|
|
{
|
|
private const float RoundsToDegree = 360f;
|
|
private const float RoundsToRadian = (float) Math.PI * 2f;
|
|
|
|
private static bool isAdvancedLightingPanelFoldout = false;
|
|
private static EditorRotationUnit editorRotationUnit = EditorRotationUnit.Rounds;
|
|
|
|
private MaterialProperty _version;
|
|
private MaterialProperty _blendMode;
|
|
private MaterialProperty _bumpMap;
|
|
private MaterialProperty _bumpScale;
|
|
private MaterialProperty _color;
|
|
private MaterialProperty _cullMode;
|
|
// private MaterialProperty _outlineCullMode;
|
|
private MaterialProperty _cutoff;
|
|
|
|
private MaterialProperty _debugMode;
|
|
private MaterialProperty _emissionColor;
|
|
private MaterialProperty _emissionMap;
|
|
private MaterialProperty _lightColorAttenuation;
|
|
private MaterialProperty _indirectLightIntensity;
|
|
private MaterialProperty _mainTex;
|
|
private MaterialProperty _outlineColor;
|
|
private MaterialProperty _outlineColorMode;
|
|
private MaterialProperty _outlineLightingMix;
|
|
private MaterialProperty _outlineWidth;
|
|
private MaterialProperty _outlineScaledMaxDistance;
|
|
private MaterialProperty _outlineWidthMode;
|
|
private MaterialProperty _outlineWidthTexture;
|
|
private MaterialProperty _receiveShadowRate;
|
|
private MaterialProperty _receiveShadowTexture;
|
|
private MaterialProperty _shadingGradeRate;
|
|
private MaterialProperty _shadingGradeTexture;
|
|
private MaterialProperty _shadeColor;
|
|
private MaterialProperty _shadeShift;
|
|
private MaterialProperty _shadeTexture;
|
|
private MaterialProperty _shadeToony;
|
|
private MaterialProperty _sphereAdd;
|
|
private MaterialProperty _rimColor;
|
|
private MaterialProperty _rimTexture;
|
|
private MaterialProperty _rimLightingMix;
|
|
private MaterialProperty _rimFresnelPower;
|
|
private MaterialProperty _rimLift;
|
|
private MaterialProperty _uvAnimMaskTexture;
|
|
private MaterialProperty _uvAnimScrollX;
|
|
private MaterialProperty _uvAnimScrollY;
|
|
private MaterialProperty _uvAnimRotation;
|
|
|
|
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
|
|
{
|
|
_version = FindProperty(Utils.PropVersion, properties);
|
|
_debugMode = FindProperty(Utils.PropDebugMode, properties);
|
|
_outlineWidthMode = FindProperty(Utils.PropOutlineWidthMode, properties);
|
|
_outlineColorMode = FindProperty(Utils.PropOutlineColorMode, properties);
|
|
_blendMode = FindProperty(Utils.PropBlendMode, properties);
|
|
_cullMode = FindProperty(Utils.PropCullMode, properties);
|
|
// _outlineCullMode = FindProperty(Utils.PropOutlineCullMode, properties);
|
|
_cutoff = FindProperty(Utils.PropCutoff, properties);
|
|
_color = FindProperty(Utils.PropColor, properties);
|
|
_shadeColor = FindProperty(Utils.PropShadeColor, properties);
|
|
_mainTex = FindProperty(Utils.PropMainTex, properties);
|
|
_shadeTexture = FindProperty(Utils.PropShadeTexture, properties);
|
|
_bumpScale = FindProperty(Utils.PropBumpScale, properties);
|
|
_bumpMap = FindProperty(Utils.PropBumpMap, properties);
|
|
_receiveShadowRate = FindProperty(Utils.PropReceiveShadowRate, properties);
|
|
_receiveShadowTexture = FindProperty(Utils.PropReceiveShadowTexture, properties);
|
|
_shadingGradeRate = FindProperty(Utils.PropShadingGradeRate, properties);
|
|
_shadingGradeTexture = FindProperty(Utils.PropShadingGradeTexture, properties);
|
|
_shadeShift = FindProperty(Utils.PropShadeShift, properties);
|
|
_shadeToony = FindProperty(Utils.PropShadeToony, properties);
|
|
_lightColorAttenuation = FindProperty(Utils.PropLightColorAttenuation, properties);
|
|
_indirectLightIntensity = FindProperty(Utils.PropIndirectLightIntensity, properties);
|
|
_rimColor = FindProperty(Utils.PropRimColor, properties);
|
|
_rimTexture = FindProperty(Utils.PropRimTexture, properties);
|
|
_rimLightingMix = FindProperty(Utils.PropRimLightingMix, properties);
|
|
_rimFresnelPower = FindProperty(Utils.PropRimFresnelPower, properties);
|
|
_rimLift = FindProperty(Utils.PropRimLift, properties);
|
|
_sphereAdd = FindProperty(Utils.PropSphereAdd, properties);
|
|
_emissionColor = FindProperty(Utils.PropEmissionColor, properties);
|
|
_emissionMap = FindProperty(Utils.PropEmissionMap, properties);
|
|
_outlineWidthTexture = FindProperty(Utils.PropOutlineWidthTexture, properties);
|
|
_outlineWidth = FindProperty(Utils.PropOutlineWidth, properties);
|
|
_outlineScaledMaxDistance = FindProperty(Utils.PropOutlineScaledMaxDistance, properties);
|
|
_outlineColor = FindProperty(Utils.PropOutlineColor, properties);
|
|
_outlineLightingMix = FindProperty(Utils.PropOutlineLightingMix, properties);
|
|
_uvAnimMaskTexture = FindProperty(Utils.PropUvAnimMaskTexture, properties);
|
|
_uvAnimScrollX = FindProperty(Utils.PropUvAnimScrollX, properties);
|
|
_uvAnimScrollY = FindProperty(Utils.PropUvAnimScrollY, properties);
|
|
_uvAnimRotation = FindProperty(Utils.PropUvAnimRotation, properties);
|
|
var materials = materialEditor.targets.Select(x => x as Material).ToArray();
|
|
Draw(materialEditor, materials);
|
|
}
|
|
|
|
private void Draw(MaterialEditor materialEditor, Material[] materials)
|
|
{
|
|
EditorGUI.BeginChangeCheck();
|
|
{
|
|
_version.floatValue = Utils.VersionNumber;
|
|
|
|
EditorGUILayout.LabelField("Rendering", EditorStyles.boldLabel);
|
|
EditorGUILayout.BeginVertical(GUI.skin.box);
|
|
{
|
|
EditorGUILayout.LabelField("Mode", EditorStyles.boldLabel);
|
|
if (PopupEnum<RenderMode>("Rendering Type", _blendMode, materialEditor))
|
|
{
|
|
ModeChanged(materials, isBlendModeChangedByUser: true);
|
|
}
|
|
|
|
if ((RenderMode) _blendMode.floatValue == RenderMode.TransparentWithZWrite)
|
|
{
|
|
EditorGUILayout.HelpBox("TransparentWithZWrite mode can cause problems with rendering.", MessageType.Warning);
|
|
}
|
|
|
|
if (PopupEnum<CullMode>("Cull Mode", _cullMode, materialEditor))
|
|
{
|
|
ModeChanged(materials);
|
|
}
|
|
}
|
|
EditorGUILayout.EndVertical();
|
|
EditorGUILayout.Space();
|
|
|
|
EditorGUILayout.LabelField("Color", EditorStyles.boldLabel);
|
|
EditorGUILayout.BeginVertical(GUI.skin.box);
|
|
{
|
|
EditorGUILayout.LabelField("Texture", EditorStyles.boldLabel);
|
|
{
|
|
materialEditor.TexturePropertySingleLine(new GUIContent("Lit Color, Alpha", "Lit (RGB), Alpha (A)"),
|
|
_mainTex, _color);
|
|
|
|
materialEditor.TexturePropertySingleLine(new GUIContent("Shade Color", "Shade (RGB)"), _shadeTexture,
|
|
_shadeColor);
|
|
}
|
|
var bm = (RenderMode) _blendMode.floatValue;
|
|
if (bm == RenderMode.Cutout)
|
|
{
|
|
EditorGUILayout.Space();
|
|
EditorGUILayout.LabelField("Alpha", EditorStyles.boldLabel);
|
|
{
|
|
materialEditor.ShaderProperty(_cutoff, "Cutoff");
|
|
}
|
|
}
|
|
}
|
|
EditorGUILayout.EndVertical();
|
|
EditorGUILayout.Space();
|
|
|
|
EditorGUILayout.LabelField("Lighting", EditorStyles.boldLabel);
|
|
EditorGUILayout.BeginVertical(GUI.skin.box);
|
|
{
|
|
{
|
|
materialEditor.ShaderProperty(_shadeToony,
|
|
new GUIContent("Shading Toony",
|
|
"0.0 is Lambert. Higher value get toony shading."));
|
|
|
|
// Normal
|
|
EditorGUI.BeginChangeCheck();
|
|
materialEditor.TexturePropertySingleLine(new GUIContent("Normal Map [Normal]", "Normal Map (RGB)"),
|
|
_bumpMap,
|
|
_bumpScale);
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
materialEditor.RegisterPropertyChangeUndo("BumpEnabledDisabled");
|
|
ModeChanged(materials);
|
|
}
|
|
}
|
|
EditorGUILayout.Space();
|
|
|
|
EditorGUI.indentLevel++;
|
|
{
|
|
isAdvancedLightingPanelFoldout = EditorGUILayout.Foldout(isAdvancedLightingPanelFoldout, "Advanced Settings", EditorStyles.boldFont);
|
|
|
|
if (isAdvancedLightingPanelFoldout)
|
|
{
|
|
EditorGUILayout.BeginHorizontal();
|
|
EditorGUILayout.HelpBox(
|
|
"The default settings are suitable for Advanced Settings if you want to toony result.",
|
|
MessageType.Info);
|
|
if (GUILayout.Button("Use Default"))
|
|
{
|
|
_shadeShift.floatValue = 0;
|
|
_receiveShadowTexture.textureValue = null;
|
|
_receiveShadowRate.floatValue = 1;
|
|
_shadingGradeTexture.textureValue = null;
|
|
_shadingGradeRate.floatValue = 1;
|
|
_lightColorAttenuation.floatValue = 0;
|
|
_indirectLightIntensity.floatValue = 0.1f;
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
materialEditor.ShaderProperty(_shadeShift,
|
|
new GUIContent("Shading Shift",
|
|
"Zero is Default. Negative value increase lit area. Positive value increase shade area."));
|
|
materialEditor.TexturePropertySingleLine(
|
|
new GUIContent("Shadow Receive Multiplier",
|
|
"Texture (R) * Rate. White is Default. Black attenuates shadows."),
|
|
_receiveShadowTexture,
|
|
_receiveShadowRate);
|
|
materialEditor.TexturePropertySingleLine(
|
|
new GUIContent("Lit & Shade Mixing Multiplier",
|
|
"Texture (R) * Rate. Compatible with UTS2 ShadingGradeMap. White is Default. Black amplifies shade."),
|
|
_shadingGradeTexture,
|
|
_shadingGradeRate);
|
|
materialEditor.ShaderProperty(_lightColorAttenuation, "LightColor Attenuation");
|
|
materialEditor.ShaderProperty(_indirectLightIntensity, "GI Intensity");
|
|
}
|
|
}
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
EditorGUILayout.EndVertical();
|
|
EditorGUILayout.Space();
|
|
|
|
EditorGUILayout.LabelField("Emission", EditorStyles.boldLabel);
|
|
EditorGUILayout.BeginVertical(GUI.skin.box);
|
|
{
|
|
TextureWithHdrColor(materialEditor, "Emission", "Emission (RGB)",
|
|
_emissionMap, _emissionColor);
|
|
|
|
materialEditor.TexturePropertySingleLine(new GUIContent("MatCap", "MatCap Texture (RGB)"),
|
|
_sphereAdd);
|
|
}
|
|
EditorGUILayout.EndVertical();
|
|
EditorGUILayout.Space();
|
|
|
|
EditorGUILayout.LabelField("Rim", EditorStyles.boldLabel);
|
|
EditorGUILayout.BeginVertical(GUI.skin.box);
|
|
{
|
|
TextureWithHdrColor(materialEditor, "Color", "Rim Color (RGB)",
|
|
_rimTexture, _rimColor);
|
|
|
|
materialEditor.DefaultShaderProperty(_rimLightingMix, "Lighting Mix");
|
|
|
|
materialEditor.ShaderProperty(_rimFresnelPower,
|
|
new GUIContent("Fresnel Power",
|
|
"If you increase this value, you get sharpness rim light."));
|
|
|
|
materialEditor.ShaderProperty(_rimLift,
|
|
new GUIContent("Lift",
|
|
"If you increase this value, you can lift rim light."));
|
|
}
|
|
EditorGUILayout.EndVertical();
|
|
EditorGUILayout.Space();
|
|
|
|
|
|
EditorGUILayout.LabelField("Outline", EditorStyles.boldLabel);
|
|
EditorGUILayout.BeginVertical(GUI.skin.box);
|
|
{
|
|
// Outline
|
|
EditorGUILayout.LabelField("Width", EditorStyles.boldLabel);
|
|
{
|
|
if (PopupEnum<OutlineWidthMode>("Mode", _outlineWidthMode, materialEditor))
|
|
{
|
|
ModeChanged(materials);
|
|
}
|
|
|
|
if ((RenderMode) _blendMode.floatValue == RenderMode.Transparent &&
|
|
(OutlineWidthMode) _outlineWidthMode.floatValue != OutlineWidthMode.None)
|
|
{
|
|
EditorGUILayout.HelpBox("Outline with Transparent material cause problem with rendering.", MessageType.Warning);
|
|
}
|
|
|
|
var widthMode = (OutlineWidthMode) _outlineWidthMode.floatValue;
|
|
if (widthMode != OutlineWidthMode.None)
|
|
{
|
|
materialEditor.TexturePropertySingleLine(
|
|
new GUIContent("Width", "Outline Width Texture (RGB)"),
|
|
_outlineWidthTexture, _outlineWidth);
|
|
}
|
|
|
|
if (widthMode == OutlineWidthMode.ScreenCoordinates)
|
|
{
|
|
materialEditor.ShaderProperty(_outlineScaledMaxDistance, "Width Scaled Max Distance");
|
|
}
|
|
}
|
|
EditorGUILayout.Space();
|
|
|
|
EditorGUILayout.LabelField("Color", EditorStyles.boldLabel);
|
|
{
|
|
var widthMode = (OutlineWidthMode) _outlineWidthMode.floatValue;
|
|
if (widthMode != OutlineWidthMode.None)
|
|
{
|
|
EditorGUI.BeginChangeCheck();
|
|
|
|
if (PopupEnum<OutlineColorMode>("Mode", _outlineColorMode, materialEditor))
|
|
{
|
|
ModeChanged(materials);
|
|
}
|
|
|
|
var colorMode = (OutlineColorMode) _outlineColorMode.floatValue;
|
|
|
|
materialEditor.ShaderProperty(_outlineColor, "Color");
|
|
if (colorMode == OutlineColorMode.MixedLighting)
|
|
materialEditor.DefaultShaderProperty(_outlineLightingMix, "Lighting Mix");
|
|
}
|
|
}
|
|
}
|
|
EditorGUILayout.EndVertical();
|
|
EditorGUILayout.Space();
|
|
|
|
|
|
EditorGUILayout.LabelField("UV Coordinates", EditorStyles.boldLabel);
|
|
EditorGUILayout.BeginVertical(GUI.skin.box);
|
|
{
|
|
// UV
|
|
EditorGUILayout.LabelField("Scale & Offset", EditorStyles.boldLabel);
|
|
{
|
|
materialEditor.TextureScaleOffsetProperty(_mainTex);
|
|
}
|
|
EditorGUILayout.Space();
|
|
|
|
EditorGUILayout.LabelField("Auto Animation", EditorStyles.boldLabel);
|
|
{
|
|
materialEditor.TexturePropertySingleLine(new GUIContent("Mask", "Auto Animation Mask Texture (R)"), _uvAnimMaskTexture);
|
|
materialEditor.ShaderProperty(_uvAnimScrollX, "Scroll X (per second)");
|
|
materialEditor.ShaderProperty(_uvAnimScrollY, "Scroll Y (per second)");
|
|
|
|
{
|
|
var control = EditorGUILayout.GetControlRect(hasLabel: true);
|
|
const int popupMargin = 5;
|
|
const int popupWidth = 80;
|
|
|
|
var floatControl = new Rect(control);
|
|
floatControl.width -= popupMargin + popupWidth;
|
|
var popupControl = new Rect(control);
|
|
popupControl.x = floatControl.x + floatControl.width + popupMargin;
|
|
popupControl.width = popupWidth;
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
var inspectorRotationValue = GetInspectorRotationValue(editorRotationUnit, _uvAnimRotation.floatValue);
|
|
inspectorRotationValue = EditorGUI.FloatField(floatControl, "Rotation value (per second)", inspectorRotationValue);
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
materialEditor.RegisterPropertyChangeUndo("UvAnimRotationValueChanged");
|
|
_uvAnimRotation.floatValue = GetRawRotationValue(editorRotationUnit, inspectorRotationValue);
|
|
}
|
|
editorRotationUnit = (EditorRotationUnit) EditorGUI.EnumPopup(popupControl, editorRotationUnit);
|
|
}
|
|
}
|
|
}
|
|
EditorGUILayout.EndVertical();
|
|
EditorGUILayout.Space();
|
|
|
|
|
|
EditorGUILayout.LabelField("Options", EditorStyles.boldLabel);
|
|
EditorGUILayout.BeginVertical(GUI.skin.box);
|
|
{
|
|
EditorGUILayout.LabelField("Debugging Options", EditorStyles.boldLabel);
|
|
{
|
|
if (PopupEnum<DebugMode>("Visualize", _debugMode, materialEditor))
|
|
{
|
|
ModeChanged(materials);
|
|
}
|
|
}
|
|
EditorGUILayout.Space();
|
|
|
|
EditorGUILayout.LabelField("Advanced Options", EditorStyles.boldLabel);
|
|
{
|
|
#if UNITY_5_6_OR_NEWER
|
|
// materialEditor.EnableInstancingField();
|
|
materialEditor.DoubleSidedGIField();
|
|
#endif
|
|
EditorGUI.BeginChangeCheck();
|
|
materialEditor.RenderQueueField();
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
ModeChanged(materials);
|
|
}
|
|
}
|
|
}
|
|
EditorGUILayout.EndVertical();
|
|
EditorGUILayout.Space();
|
|
}
|
|
EditorGUI.EndChangeCheck();
|
|
}
|
|
|
|
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
|
|
{
|
|
base.AssignNewShaderToMaterial(material, oldShader, newShader);
|
|
|
|
Utils.ValidateProperties(material, isBlendModeChangedByUser: true);
|
|
}
|
|
|
|
private static void ModeChanged(Material[] materials, bool isBlendModeChangedByUser = false)
|
|
{
|
|
foreach (var material in materials)
|
|
{
|
|
Utils.ValidateProperties(material, isBlendModeChangedByUser);
|
|
}
|
|
}
|
|
|
|
private static bool PopupEnum<T>(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("EnumPopUp");
|
|
property.floatValue = ret;
|
|
}
|
|
|
|
EditorGUI.showMixedValue = false;
|
|
return changed;
|
|
}
|
|
|
|
private static void TextureWithHdrColor(MaterialEditor materialEditor, string label, string description,
|
|
MaterialProperty texProp, MaterialProperty colorProp)
|
|
{
|
|
materialEditor.TexturePropertyWithHDRColor(new GUIContent(label, description),
|
|
texProp,
|
|
colorProp,
|
|
#if UNITY_2018_1_OR_NEWER
|
|
#else
|
|
new ColorPickerHDRConfig(minBrightness: 0, maxBrightness: 10, minExposureValue: -10,
|
|
maxExposureValue: 10),
|
|
#endif
|
|
showAlpha: false);
|
|
|
|
}
|
|
|
|
private static float GetRawRotationValue(EditorRotationUnit unit, float inspectorValue)
|
|
{
|
|
switch (unit)
|
|
{
|
|
case EditorRotationUnit.Rounds:
|
|
return inspectorValue;
|
|
case EditorRotationUnit.Degrees:
|
|
return inspectorValue / RoundsToDegree;
|
|
case EditorRotationUnit.Radians:
|
|
return inspectorValue / RoundsToRadian;
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
}
|
|
|
|
private static float GetInspectorRotationValue(EditorRotationUnit unit, float rawValue)
|
|
{
|
|
switch (unit)
|
|
{
|
|
case EditorRotationUnit.Rounds:
|
|
return rawValue;
|
|
case EditorRotationUnit.Degrees:
|
|
return rawValue * RoundsToDegree;
|
|
case EditorRotationUnit.Radians:
|
|
return rawValue * RoundsToRadian;
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
}
|
|
}
|
|
} |