You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
246 lines
9.1 KiB
246 lines
9.1 KiB
2 years ago
|
// Copyright (c) 2014 Marmoset LLC
|
||
|
//
|
||
|
using UnityEngine;
|
||
|
using UnityEditor;
|
||
|
|
||
|
using System;
|
||
|
using System.IO;
|
||
|
using System.Xml;
|
||
|
using System.Text;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Linq;
|
||
|
|
||
|
public class LayerInspector : MaterialEditor {
|
||
|
|
||
|
|
||
|
// draws a standard material property, optionally disabled, and either compact or full-sized.
|
||
|
// minimal flag on texture properties means hide UV tiling.
|
||
|
private void DrawProperty(MaterialProperty prop, string label, string subLabel, bool disabled) {
|
||
|
EditorGUI.BeginDisabledGroup(disabled);
|
||
|
if( prop.type == MaterialProperty.PropType.Color ) {
|
||
|
EditorGUIUtility.labelWidth = 134;
|
||
|
EditorGUIUtility.fieldWidth = 84;
|
||
|
}
|
||
|
else if( prop.type == MaterialProperty.PropType.Texture ) {
|
||
|
EditorGUIUtility.labelWidth = 220;
|
||
|
EditorGUIUtility.fieldWidth = 84;
|
||
|
}
|
||
|
else {
|
||
|
EditorGUIUtility.labelWidth = 134;
|
||
|
EditorGUIUtility.fieldWidth = 84;
|
||
|
}
|
||
|
|
||
|
if( prop.type == MaterialProperty.PropType.Color ) {
|
||
|
ShaderProperty(prop, label);
|
||
|
}
|
||
|
else if( prop.type == MaterialProperty.PropType.Texture ) {
|
||
|
TextureProperty(prop, label);
|
||
|
/*if( subLabel.Length > 0 ) {
|
||
|
Rect r = GUILayoutUtility.GetLastRect();
|
||
|
r.x = EditorGUIUtility.labelWidth - 21f;
|
||
|
EditorGUI.BeginDisabledGroup(true);
|
||
|
EditorGUI.LabelField(r, subLabel);
|
||
|
EditorGUI.EndDisabledGroup();
|
||
|
}*/
|
||
|
GUILayout.Space(6);
|
||
|
} else {
|
||
|
ShaderProperty(prop, label);
|
||
|
}
|
||
|
EditorGUI.EndDisabledGroup();
|
||
|
}
|
||
|
|
||
|
//Draws a property that's also a section header (usually a checkbox) along with a collapse/expand triangle. Returns true if block is expanded.
|
||
|
public void DrawPropertyHeader(PropertyBlock block, MaterialProperty prop, string label) {
|
||
|
float controlSize = 110;
|
||
|
EditorGUIUtility.fieldWidth = controlSize;
|
||
|
EditorGUIUtility.labelWidth = 0;
|
||
|
|
||
|
EditorGUILayout.BeginHorizontal();
|
||
|
|
||
|
//draw folding triangle and retrieve state
|
||
|
Rect r = EditorGUILayout.GetControlRect(GUILayout.Width(0), GUILayout.Height(16));
|
||
|
block.open = EditorGUI.Foldout(r, block.open, "", false);
|
||
|
|
||
|
if( !block.label ) {
|
||
|
//draw a 10-pixel checkbox or a control-sized whatever-else (combo box usually)
|
||
|
r = EditorGUILayout.GetControlRect(GUILayout.Width(block.checkbox ? 10 : controlSize), GUILayout.Height(16));
|
||
|
//draw property with label to the right
|
||
|
ShaderProperty(r, prop, "");
|
||
|
}
|
||
|
EditorGUILayout.LabelField(label);
|
||
|
|
||
|
EditorGUILayout.EndHorizontal();
|
||
|
}
|
||
|
|
||
|
//structure defining the header of a block of material properties. The header can be enabled/disabled by a series of keywords or
|
||
|
//collapsed/expanded with a GUI foldout.
|
||
|
public class PropertyBlock {
|
||
|
public bool open = true; //current folded state, collapsed or expanded
|
||
|
public bool enabled = true; //current state of keywords enabling/disabling this block of properties
|
||
|
public bool checkbox = false; //if true, this property header is drawn as a checkbox left of the label, otherwise it is drawn as a combo box
|
||
|
public bool label = false; //if true, no property gui is drawn for this element, it is just a section label
|
||
|
public string[] keywords = null; //list of keywords that will toggle this block as enabled and visible
|
||
|
|
||
|
public PropertyBlock(string[] keys, bool isCheckbox) {
|
||
|
this.keywords = keys;
|
||
|
this.checkbox = isCheckbox;
|
||
|
}
|
||
|
|
||
|
public void evalKeywords( string[] matKeywords ) {
|
||
|
this.enabled = false;
|
||
|
if( this.keywords == null ) {
|
||
|
enabled = true;
|
||
|
} else {
|
||
|
for(int i=0; i<this.keywords.Length && !this.enabled; ++i) {
|
||
|
this.enabled |= matKeywords.Contains(this.keywords[i]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
private Dictionary<string, PropertyBlock> blocks = null;
|
||
|
public LayerInspector() {
|
||
|
blocks = new Dictionary<string, PropertyBlock>();
|
||
|
blocks.Add( "Header_Layering", new PropertyBlock(null, true ) ); blocks["Header_Layering"].label = true;
|
||
|
//blocks.Add( "Marmo_Diffuse", new PropertyBlock(null, true ) ); blocks["Marmo_Diffuse"].label = true;
|
||
|
//blocks.Add( "Marmo_Specular", new PropertyBlock(new string[]{ "MARMO_SPECULAR_ON" }, true) );
|
||
|
//blocks.Add( "Marmo_Bump", new PropertyBlock(new string[]{ "MARMO_BUMP_ON", "MARMO_BUMP_ON" }, true) );
|
||
|
blocks.Add( "Header_Shared", new PropertyBlock(null, true ) ); blocks["Header_Shared"].label = true;
|
||
|
blocks.Add( "Header_Layer0", new PropertyBlock(null, true ) ); blocks["Header_Layer0"].label = true;
|
||
|
blocks.Add( "Header_Layer1", new PropertyBlock(null, true ) ); blocks["Header_Layer1"].label = true;
|
||
|
blocks.Add( "Header_Layer2", new PropertyBlock(null, true ) ); blocks["Header_Layer2"].label = true;
|
||
|
blocks.Add( "Header_Layer3", new PropertyBlock(null, true ) ); blocks["Header_Layer3"].label = true;
|
||
|
|
||
|
blocks.Add( "Header_Advanced", new PropertyBlock(null, true ) ); blocks["Header_Advanced"].label = true;
|
||
|
}
|
||
|
|
||
|
|
||
|
public override void OnInspectorGUI() {
|
||
|
|
||
|
|
||
|
Material targetMat = target as Material;
|
||
|
string[] keyWords = targetMat.shaderKeywords;
|
||
|
|
||
|
foreach( KeyValuePair<string, PropertyBlock> itr in blocks ) {
|
||
|
itr.Value.evalKeywords(keyWords);
|
||
|
}
|
||
|
|
||
|
//material checkboxes
|
||
|
bool twoLayerOn = keyWords.Contains("MARMO_LAYER_COUNT_2_LAYER");
|
||
|
bool fourLayerOn = keyWords.Contains("MARMO_LAYER_COUNT_4_LAYER");
|
||
|
bool specOn = keyWords.Contains("MARMO_SPECULAR_ON");
|
||
|
bool diffSpecOn = keyWords.Contains("MARMO_DIFFUSE_SPECULAR_COMBINED_ON");
|
||
|
bool bumpOn = keyWords.Contains("MARMO_BUMP_ON");
|
||
|
bool maskOn = keyWords.Contains("MARMO_LAYER_MASK_TEXTURE_UV0") || keyWords.Contains("MARMO_LAYER_MASK_TEXTURE_UV1");
|
||
|
|
||
|
serializedObject.Update();
|
||
|
SerializedProperty theShader = serializedObject.FindProperty("m_Shader");
|
||
|
if(isVisible && !theShader.hasMultipleDifferentValues && theShader.objectReferenceValue != null) {
|
||
|
|
||
|
EditorGUI.BeginChangeCheck();
|
||
|
MaterialProperty[] props = MaterialEditor.GetMaterialProperties(targets);
|
||
|
|
||
|
PropertyBlock headerBlock = null;
|
||
|
bool prevVisible = true;
|
||
|
for(int i = 0; i < props.Length; i++) {
|
||
|
if( (props[i].flags & MaterialProperty.PropFlags.HideInInspector) > 0 ) continue;
|
||
|
|
||
|
bool enabled = true;
|
||
|
bool visible = true;
|
||
|
string name = props[i].name;
|
||
|
string label = props[i].displayName;
|
||
|
string subLabel = "";
|
||
|
|
||
|
if( name == "Header_Layer1" || name == "Header_Layer2" || name == "Header_Layer3" ) {
|
||
|
visible = fourLayerOn;
|
||
|
}
|
||
|
|
||
|
if( name == "Header_Layer1" ) {
|
||
|
visible |= twoLayerOn;
|
||
|
}
|
||
|
|
||
|
//is this property a header to a new block?
|
||
|
bool header = blocks.ContainsKey(name);
|
||
|
|
||
|
//starting a new header
|
||
|
if( header && visible ) {
|
||
|
// if a previous block is still open, add a little space to the end (helps get a little GUI nudge when unrolling empty blocks).
|
||
|
if( headerBlock != null && headerBlock.open ) {
|
||
|
GUILayout.Space(2);
|
||
|
}
|
||
|
if( headerBlock != null ) {
|
||
|
Rect r = EditorGUILayout.GetControlRect();
|
||
|
Vector2 a = r.center; a.x = 0;
|
||
|
Vector2 b = r.center; b.x = Screen.width;
|
||
|
Drawing.DrawLine(a, b, Color.grey, 1f, false);
|
||
|
}
|
||
|
// new block started
|
||
|
headerBlock = blocks[name];
|
||
|
}
|
||
|
|
||
|
if(name == "_MainTex" || name == "_MainTex1" || name == "_MainTex2" || name == "_MainTex3" ) {
|
||
|
if( diffSpecOn ) label = "Diffuse(RGB) Specular(A)";
|
||
|
else label = "Diffuse(RGBA)";
|
||
|
}
|
||
|
|
||
|
if( name == "_LayerMask" ) {
|
||
|
visible = maskOn && (fourLayerOn || twoLayerOn);
|
||
|
}
|
||
|
|
||
|
if(name == ("_MainTex1") || name == ("_MainTex2") || name == ("_MainTex3") ||
|
||
|
name == ("_Color1") || name == ("_Color2") || name == ("_Color3") ||
|
||
|
name == ("_SpecTex1") || name == ("_SpecTex2") || name == ("_SpecTex3") ||
|
||
|
name == ("_Fresnel1") || name == ("_Fresnel2") || name == ("_Fresnel3") ||
|
||
|
name == ("_BumpMap1") || name == ("_BumpMap2") || name == ("_BumpMap3")) {
|
||
|
visible = fourLayerOn;
|
||
|
}
|
||
|
|
||
|
if(name == "_MainTex1" || name == "_Color1" || name == "_SpecTex1" || name == "_Fresnel1" || name == "_BumpMap1" ) {
|
||
|
visible |= twoLayerOn;
|
||
|
}
|
||
|
|
||
|
//unless diff-spec is enabled, bump3 and spec3 are disabled, not enough texture samplers for them
|
||
|
if( name == "_BumpMap3" || name == "_SpecTex3" || name == "_Fresnel3" ) {
|
||
|
visible &= diffSpecOn;
|
||
|
}
|
||
|
|
||
|
if(name.Contains("_SpecTex") || name.Contains("_Fresnel")) {
|
||
|
visible &= specOn;
|
||
|
}
|
||
|
if(name.Contains("_BumpMap")) {
|
||
|
visible &= bumpOn;
|
||
|
}
|
||
|
if(name == "_SpecTex" || name == "_SpecTex1" || name == "_SpecTex2" || name == "_SpecTex3") {
|
||
|
visible &= !diffSpecOn;
|
||
|
}
|
||
|
|
||
|
// texture tiling is copied from the texture scaleOffset fields
|
||
|
if( props[i].type == MaterialProperty.PropType.Texture ) {
|
||
|
targetMat.SetVector(name + "Tiling", props[i].textureScaleAndOffset);
|
||
|
}
|
||
|
|
||
|
// link tiling attributes of textures to the textures themselves
|
||
|
//NOTE: tiling settings must come immediately after texture slots
|
||
|
if( name.Contains("Tiling") ) { visible = prevVisible; }
|
||
|
|
||
|
if( headerBlock != null && !header ) {
|
||
|
visible &= headerBlock.enabled;
|
||
|
visible &= headerBlock.open;
|
||
|
}
|
||
|
|
||
|
// draw each header type and update the appropriate flags
|
||
|
if( visible ) {
|
||
|
if(header) DrawPropertyHeader(headerBlock, props[i], label);
|
||
|
else DrawProperty(props[i], label, subLabel, !enabled);
|
||
|
}
|
||
|
prevVisible = visible;
|
||
|
|
||
|
}
|
||
|
if(EditorGUI.EndChangeCheck()) PropertiesChanged();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|