Files
Cielonos/Assets/OtherPlugins/GraphicsCat/Modules/Common/Misc/InGameMaterialInspector.cs
SoulliesOfficial d15957c719 更新
2025-12-17 04:19:38 -05:00

310 lines
15 KiB
C#

using System.Collections.Generic;
using UnityEngine;
namespace GraphicsCat
{
public class InGameMaterialInspector : MonoBehaviour, IMGUIDockable
{
Renderer targetRenderer;
[Range(0.1f, 1.0f)] public float width = 0.3f;
[Range(0.1f, 1.0f)] public float height = 0.5f;
Material m_Material;
Vector2 m_ScrollPosition;
Dictionary<string, bool> m_ColorFoldoutStates = new Dictionary<string, bool>();
void OnEnable()
{
if (targetRenderer == null)
targetRenderer = GetComponent<Renderer>();
if (targetRenderer != null)
m_Material = targetRenderer.material;
IMGUIDock.topRight.DockGUI(this);
}
void OnDisable()
{
Destroy(m_Material);
}
public void OnDockGUI()
{
if (m_Material == null)
{
GUILayout.Label("No material found on the target renderer.");
return;
}
float inspectorWidth = width * Screen.width / IMGUIUtils.scaleWithScreenSize;
float inspectorHeight = height * Screen.height / IMGUIUtils.scaleWithScreenSize;
GUILayout.BeginVertical("box", GUILayout.Width(inspectorWidth));
m_ScrollPosition = GUILayout.BeginScrollView(m_ScrollPosition, false, true, GUILayout.Height(inspectorHeight));
for (int propIndex = 0; propIndex < m_Material.shader.GetPropertyCount(); propIndex++)
{
string propName = m_Material.shader.GetPropertyName(propIndex);
string propDesc = m_Material.shader.GetPropertyDescription(propIndex);
UnityEngine.Rendering.ShaderPropertyType propType = m_Material.shader.GetPropertyType(propIndex);
string[] attributes = m_Material.shader.GetPropertyAttributes(propIndex);
foreach (var attr in attributes)
{
if (attr.StartsWith("BeginFoldout"))
{
string foldoutLabel = "# " + GetAttributeValue(attr, "BeginFoldout");
GUILayout.Label(foldoutLabel, new GUIStyle(GUI.skin.label) { fontStyle = FontStyle.Bold });
}
else if (attr.StartsWith("EndFoldout"))
{
GUILayout.Space(10);
}
else if (attr.StartsWith("Heade("))
{
string headerName = GetAttributeValue(attr, "Header");
if (!string.IsNullOrEmpty(headerName))
{
GUILayout.Space(10);
GUILayout.Label(headerName, new GUIStyle(GUI.skin.label) { fontStyle = FontStyle.Bold });
}
}
else if (attr.StartsWith("Space"))
{
string spaceValueStr = GetAttributeValue(attr, "Space");
if (float.TryParse(spaceValueStr, out float spaceValue))
{
GUILayout.Space(spaceValue);
}
}
}
var propFlags = m_Material.shader.GetPropertyFlags(propIndex);
var hideInInspector = (propFlags & UnityEngine.Rendering.ShaderPropertyFlags.HideInInspector) != 0;
if (hideInInspector)
continue;
string keywordName = GetKeywordFromToggleAttribute(m_Material.shader, propIndex, propName);
bool isToggle = !string.IsNullOrEmpty(keywordName);
if (isToggle)
{
GUILayout.BeginHorizontal();
float originalValue = m_Material.GetFloat(propName);
bool originalBool = originalValue > 0.5f;
bool newBool = GUILayout.Toggle(originalBool, propDesc);
if (newBool != originalBool)
{
m_Material.SetFloat(propName, newBool ? 1.0f : 0.0f);
if (newBool)
{
m_Material.EnableKeyword(keywordName);
}
else
{
m_Material.DisableKeyword(keywordName);
}
}
GUILayout.EndHorizontal();
}
else
{
switch (propType)
{
case UnityEngine.Rendering.ShaderPropertyType.Color:
{
if (!m_ColorFoldoutStates.ContainsKey(propName))
m_ColorFoldoutStates[propName] = false;
Color originalColor = m_Material.GetColor(propName);
GUILayout.BeginHorizontal();
{
var colorR = originalColor.r.ToString("0.00");
var colorG = originalColor.g.ToString("0.00");
var colorB = originalColor.b.ToString("0.00");
var colorA = originalColor.a.ToString("0.00");
var colorRGBA = $"({colorR}, {colorG}, {colorB}, {colorA})";
var colorLabel = propDesc + " " + colorRGBA;
GUILayout.Label(colorLabel, GUILayout.ExpandWidth(false));
// var previousColor = GUI.color;
// GUI.color = originalColor;
// if (GUILayout.Button(m_colorFoldoutStates[propertyName] ? "-" : "+"))
// m_colorFoldoutStates[propertyName] = !m_colorFoldoutStates[propertyName];
// GUI.color = previousColor;
if (GUILayout.Button(""))
m_ColorFoldoutStates[propName] = !m_ColorFoldoutStates[propName];
Rect buttonRect = GUILayoutUtility.GetLastRect();
buttonRect.x += 1;
buttonRect.y += 1;
buttonRect.width -= 2;
buttonRect.height -= 2;
var image = IMGUIColorTextureGenerator.GetTexture(originalColor);
GUI.DrawTexture(buttonRect, image, ScaleMode.StretchToFill);
// public static void DrawTexture(Rect position, Texture image, ScaleMode scaleMode, bool alphaBlend, float imageAspect, Color color, float borderWidth, float borderRadius)
// GUI.DrawTexture(buttonRect, image, ScaleMode.StretchToFill, false, 1, Color.white, 1, 0);
if (GUILayout.Button(m_ColorFoldoutStates[propName] ? "-" : "+", GUILayout.Width(20)))
m_ColorFoldoutStates[propName] = !m_ColorFoldoutStates[propName];
}
GUILayout.EndHorizontal();
if (m_ColorFoldoutStates[propName])
{
GUILayout.BeginVertical();
{
const int indentSize = 15;
GUILayout.BeginHorizontal();
GUILayout.Space(indentSize);
GUILayout.Label("- R ", GUILayout.ExpandWidth(false));
originalColor.r = GUILayout.HorizontalSlider(originalColor.r, 0.0f, 1.0f);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Space(indentSize);
GUILayout.Label("- G ", GUILayout.ExpandWidth(false));
originalColor.g = GUILayout.HorizontalSlider(originalColor.g, 0.0f, 1.0f);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Space(indentSize);
GUILayout.Label("- B ", GUILayout.ExpandWidth(false));
originalColor.b = GUILayout.HorizontalSlider(originalColor.b, 0.0f, 1.0f);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Space(indentSize);
GUILayout.Label("- A ", GUILayout.ExpandWidth(false));
originalColor.a = GUILayout.HorizontalSlider(originalColor.a, 0.0f, 1.0f);
GUILayout.EndHorizontal();
m_Material.SetColor(propName, originalColor);
}
GUILayout.EndVertical();
}
break;
}
case UnityEngine.Rendering.ShaderPropertyType.Float:
{
GUILayout.BeginHorizontal();
GUILayout.Label(propDesc);
float originalValue = m_Material.GetFloat(propName);
float newValue = GetFloatField(originalValue);
if (Mathf.Abs(newValue - originalValue) > 0.001f)
{
m_Material.SetFloat(propName, newValue);
}
GUILayout.EndHorizontal();
break;
}
case UnityEngine.Rendering.ShaderPropertyType.Range:
{
GUILayout.BeginHorizontal();
GUILayout.Label(propDesc, GUILayout.ExpandWidth(false));
float originalValue = m_Material.GetFloat(propName);
Vector2 limits = m_Material.shader.GetPropertyRangeLimits(propIndex);
GUILayout.Label(originalValue.ToString("0.00"), GUILayout.ExpandWidth(false));
float newValue = GUILayout.HorizontalSlider(originalValue, limits.x, limits.y);
if (Mathf.Abs(newValue - originalValue) > 0.01f)
m_Material.SetFloat(propName, newValue);
GUILayout.EndHorizontal();
break;
}
case UnityEngine.Rendering.ShaderPropertyType.Vector:
{
GUILayout.BeginHorizontal();
GUILayout.Label(propDesc);
Vector4 originalVector = m_Material.GetVector(propName);
GUILayout.BeginVertical();
GUILayout.BeginHorizontal();
GUILayout.Label("X", GUILayout.Width(20)); originalVector.x = GetFloatField(originalVector.x);
GUILayout.Label("Y", GUILayout.Width(20)); originalVector.y = GetFloatField(originalVector.y);
GUILayout.Label("Z", GUILayout.Width(20)); originalVector.z = GetFloatField(originalVector.z);
GUILayout.Label("W", GUILayout.Width(20)); originalVector.w = GetFloatField(originalVector.w);
GUILayout.EndHorizontal();
m_Material.SetVector(propName, originalVector);
GUILayout.EndVertical();
GUILayout.EndHorizontal();
break;
}
case UnityEngine.Rendering.ShaderPropertyType.Texture:
{
GUILayout.BeginHorizontal();
GUILayout.Label(propDesc, GUILayout.ExpandWidth(true));
Texture tex = m_Material.GetTexture(propName);
if (tex != null)
{
GUILayout.Box(tex, GUILayout.Width(16), GUILayout.Height(16));
}
else
{
GUILayout.Label("None (Texture)");
}
GUILayout.EndHorizontal();
break;
}
default:
{
GUILayout.BeginHorizontal();
GUILayout.Label(propDesc, GUILayout.Width(150));
GUILayout.Label("Unsupported Type");
GUILayout.EndHorizontal();
break;
}
}
}
}
GUILayout.EndScrollView();
GUILayout.EndVertical();
}
private string GetKeywordFromToggleAttribute(Shader shader, int propertyIndex, string propertyName)
{
string[] attributes = shader.GetPropertyAttributes(propertyIndex);
foreach (var attr in attributes)
{
if (attr.StartsWith("Toggle(") || attr.StartsWith("MaterialToggle("))
{
string keywordName = GetAttributeValue(attr, "Toggle") ?? GetAttributeValue(attr, "MaterialToggle");
return keywordName;
}
else if (attr.Equals("Toggle") || attr.Equals("MaterialToggle"))
{
return propertyName.ToUpperInvariant() + "_ON";
}
}
return null;
}
private string GetAttributeValue(string attributeString, string attributeName)
{
int start = attributeString.IndexOf(attributeName + "(") + attributeName.Length + 1;
int end = attributeString.LastIndexOf(')');
if (end > start)
{
string value = attributeString.Substring(start, end - start).Trim();
if (value.StartsWith("\"") && value.EndsWith("\""))
return value.Substring(1, value.Length - 2);
return value;
}
return null;
}
float GetFloatField(float value)
{
string strValue = GUILayout.TextField(value.ToString("0.00"), GUILayout.Width(50));
if (float.TryParse(strValue, out float result))
return result;
return value;
}
}
}