WuhuIslandTesting/Library/PackageCache/com.unity.render-pipelines.universal@8148.0.7-4/Editor/ShaderGUI/ShaderGUIUtils.cs

289 lines
12 KiB
C#
Raw Normal View History

2025-01-07 02:06:59 +01:00
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System;
using UnityEditor;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using UnityEngine.UIElements;
using Unity.Collections;
using Unity.Mathematics;
using System.IO;
using Object = UnityEngine.Object;
namespace SLZ.SLZEditorTools
{
public static class ShaderGUIUtils
{
const string shaderGUIStylePath = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGUI/Styles/ShaderGUIStyles.uss";
static StyleSheet s_ShaderGUISheet;
public static StyleSheet shaderGUISheet
{
get
{
if (s_ShaderGUISheet == null)
{
s_ShaderGUISheet = AssetDatabase.LoadAssetAtPath<StyleSheet>(shaderGUIStylePath);
if (s_ShaderGUISheet == null)
{
Debug.LogError("Failed to find Shader GUI Style Sheet at " + shaderGUIStylePath);
}
}
return s_ShaderGUISheet;
}
}
static FieldInfo s_InaccessibleToggle;
/// <summary>
/// Makes a foldout look like a unity inspector header.
/// </summary>
/// <param name="f"></param>
/// <param name="title"></param>
/// <param name="iconTex"></param>
public static void SetHeaderStyle(Foldout f, string title, Texture iconTex = null, Toggle headerToggle = null)
{
f.AddToClassList("headerRoot");
if (s_InaccessibleToggle == null)
{
s_InaccessibleToggle = typeof(Foldout).GetField("m_Toggle", BindingFlags.NonPublic | BindingFlags.Instance);
}
Toggle actualFuckingToggle = (Toggle)s_InaccessibleToggle.GetValue(f);
actualFuckingToggle.AddToClassList("headerTogglebar");
actualFuckingToggle.style.paddingBottom = 3;
actualFuckingToggle.style.paddingTop = 2;
actualFuckingToggle.style.marginBottom = 1;
VisualElement container = actualFuckingToggle.ElementAt(0);
container.style.marginRight = 0;
container.style.alignItems = Align.Center;
VisualElement dropdown = container.ElementAt(0);
dropdown.style.marginLeft = 5;
Label titleLabel = new Label(title);
titleLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
titleLabel.style.marginLeft = 6;
titleLabel.style.unityTextAlign = TextAnchor.UpperLeft;
titleLabel.style.paddingTop = 0;
if (iconTex != null)
{
Image icon = new Image();
icon.image = iconTex;
icon.style.height = 16;
icon.style.width = 16;
icon.style.minWidth = 16;
icon.style.minHeight = 16;
icon.style.maxWidth = 16;
icon.style.maxHeight = 16;
icon.style.marginRight = 0;
icon.style.marginLeft = 0;
icon.style.marginTop = 0;
icon.style.marginBottom = 0;
// icon.style.ba
//icon.style.scale = new Vector2(1.1f, 1.1f);
container.Add(icon);
}
if (headerToggle == null)
{
headerToggle = new Toggle();
headerToggle.style.visibility = Visibility.Hidden;
}
headerToggle.style.marginLeft = 6;
headerToggle.style.marginRight = 0;
headerToggle.style.marginBottom = 1;
container.Add(headerToggle);
container.Add(titleLabel);
f.contentContainer.AddToClassList("headerContent");
}
// Gets the shader property index corresponding to each element of a material property array
public static int[] GetMaterialPropertyShaderIdx(MaterialProperty[] materialProperties, Shader shader)
{
int numMatProps = materialProperties.Length;
int[] propertyIdx = new int[numMatProps];
for (int i = 0; i < numMatProps; i++)
{
propertyIdx[i] = shader.FindPropertyIndex(materialProperties[i].name);
}
return propertyIdx;
}
public static int[] GetShaderIdxToMaterialProp(MaterialProperty[] materialProperties, Shader shader)
{
int numMatProps = materialProperties.Length;
int[] propertyIdx = new int[shader.GetPropertyCount()];
for (int i = 0; i < numMatProps; i++)
{
//propertyIdx[shader.FindPropertyIndex(materialProperties[i].name)] = i;
propertyIdx[i] = i;
}
return propertyIdx;
}
/// <summary>
/// Strip out unused texture references in materials to avoid unity bundling/loading them
/// </summary>
/// <param name="targets">target objects, assumed to all be materials</param>
/// <param name="materialProperties">Array of material properties retrieved from MaterialEditor.GetMaterialProperties</param>
/// <param name="propertyIdx">map from each element of materialProperties to the index of its shader property</param>
/// <param name="shader">Shader used by all the target materials</param>
public static void SanitizeMaterials(Object[] targets, MaterialProperty[] materialProperties, int[] propertyIdx, Shader shader)
{
int numMatProps = materialProperties.Length;
HashSet<string> validTextureNames = new HashSet<string>();
for (int i = 0; i < numMatProps; i++)
{
ShaderPropertyType type = shader.GetPropertyType(propertyIdx[i]);
switch (type)
{
case ShaderPropertyType.Texture:
validTextureNames.Add(materialProperties[i].name);
break;
}
}
int numMats = targets.Length;
for (int mat = 0; mat < numMats; mat++)
{
SerializedObject smat = new SerializedObject(targets[mat]);
SerializedProperty texEnv = smat.FindProperty("m_SavedProperties.m_TexEnvs");
bool removedProp = false;
string removedPropNames = "\n ";
if (texEnv != null)
{
int numTex = texEnv.arraySize;
for (int tIdx = numTex - 1; tIdx >= 0; tIdx--)
{
SerializedProperty nameProp = smat.FindProperty("m_SavedProperties.m_TexEnvs.Array.data[" + tIdx.ToString() + "].first");
string name = nameProp.stringValue;
if (!validTextureNames.Contains(name))
{
texEnv.DeleteArrayElementAtIndex(tIdx);
removedPropNames += name + "\n ";
removedProp = true;
}
}
}
if (removedProp)
{
Debug.LogWarning("LitMAS GUI: Removed the following unused texture properties from " + targets[mat].name + removedPropNames);
smat.ApplyModifiedProperties();
}
smat.Dispose();
}
}
static Dictionary<string, Texture2D> icon16px = new Dictionary<string, Texture2D>();
public static Texture2D GetClosestUnityIconMip(string textureName, int iconHeightInPts)
{
int closestPow2Res = (int)math.round(math.log2(iconHeightInPts * EditorGUIUtility.pixelsPerPoint));
int iconRes = 1 << closestPow2Res;
string key = textureName + "X" + iconRes.ToString();
if (icon16px.ContainsKey(key))
{
Texture2D storedIcon = icon16px[key];
if (storedIcon != null)
{
return icon16px[key];
}
else
{
icon16px.Remove(key);
}
}
GUIContent imguiIcon = EditorGUIUtility.IconContent(textureName);
if (imguiIcon == null)
{
return null;
}
Texture2D icon = imguiIcon.image as Texture2D;
if (icon == null)
{
return null;
}
if (icon.width < (iconRes + (iconRes / 2)))
{
return icon;
}
int numMips = icon.mipmapCount;
int desiredMip = numMips - (closestPow2Res + 1);
if (desiredMip < 1)
{
return icon;
}
Texture2D tex = new Texture2D(
Mathf.Max(icon.width >> desiredMip, 1),
Mathf.Max(icon.height >> desiredMip, 1),
icon.graphicsFormat,
TextureCreationFlags.MipChain);
tex.hideFlags = HideFlags.DontSaveInEditor | HideFlags.DontSaveInBuild;
tex.name = textureName;
int currentMip = 0;
NativeArray<byte> iconData = new NativeArray<byte>((int)GraphicsFormatUtility.ComputeMipmapSize(tex.width, tex.height, tex.graphicsFormat), Allocator.Persistent);
while (desiredMip < numMips && currentMip < tex.mipmapCount)
{
NativeArray<byte> texData = tex.GetPixelData<byte>(currentMip);
AsyncGPUReadbackRequest request = AsyncGPUReadback.RequestIntoNativeArray<byte>(ref iconData, icon, desiredMip);
request.WaitForCompletion();
NativeArray<byte>.Copy(iconData, texData, texData.Length);
currentMip++;
desiredMip++;
texData.Dispose();
}
iconData.Dispose();
tex.Apply(false, true);
icon16px.Add(key, tex);
return tex;
}
static Action<VisualElement, int> s_IncrementVersion;
public static void UpdateVisualElement(VisualElement v)
{
if (s_IncrementVersion == null)
{
MethodInfo mi = typeof(VisualElement).GetMethod("IncrementVersion", BindingFlags.NonPublic | BindingFlags.Instance);
s_IncrementVersion = (Action<VisualElement, int>) mi.CreateDelegate(typeof(Action<VisualElement, int>));
}
s_IncrementVersion.Invoke(v, 8 | 2048);
}
static MethodInfo getTracker;
static PropertyInfo s_PropertyViewer;
static void ReflectEditorTracker()
{
s_PropertyViewer = typeof(Editor).GetProperty("propertyViewer", BindingFlags.NonPublic | BindingFlags.Instance);
if (s_PropertyViewer == null) Debug.Log("NULL Property Viewer field");
Type viewerInterface = s_PropertyViewer.PropertyType;
if (viewerInterface == null) Debug.Log("NULL Property Viewer type");
getTracker = viewerInterface.GetProperty("tracker", BindingFlags.Public | BindingFlags.Instance).GetGetMethod();
}
public static void ForceRebuild(Editor e)
{
if (s_PropertyViewer == null)
{
ReflectEditorTracker();
}
object propertyViewer = s_PropertyViewer.GetValue(e);
if (propertyViewer != null)
{
var map = propertyViewer.GetType().GetInterfaceMap(getTracker.DeclaringType);
int index = Array.IndexOf(map.InterfaceMethods, getTracker);
if (index < 0) return;
object tracker = map.InterfaceMethods[index].Invoke(propertyViewer, null);
ActiveEditorTracker activeEditorTracker = (ActiveEditorTracker) tracker;
//activeEditorTracker.ForceRebuild();
}
}
}
}