Skip to content

Instantly share code, notes, and snippets.

@Myrkie
Last active January 20, 2025 23:37
Show Gist options
  • Save Myrkie/2b3664a05293d1bb0e118f05a3357cd2 to your computer and use it in GitHub Desktop.
Save Myrkie/2b3664a05293d1bb0e118f05a3357cd2 to your computer and use it in GitHub Desktop.
Shows hidden shaders in material shader selection
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using HarmonyLib;
[InitializeOnLoad]
public class ShowHiddenShaders : Editor
{
private static readonly Harmony _harmonyInstance = new("com.Myrkur.MaterialEditor.ShowHiddenShaders");
private static Dictionary<int, Shader> s_HiddenShadersById = new();
private static int s_NextCustomId = -1;
static ShowHiddenShaders()
{
try
{
var materialEditorType =
typeof(Editor).Assembly.GetType("UnityEditor.MaterialEditor+ShaderSelectionDropdown");
var shaderDropdownType =
materialEditorType.GetNestedType("ShaderDropdownDataSource", BindingFlags.NonPublic);
var fetchDataMethod = shaderDropdownType.GetMethod(
"FetchData", BindingFlags.NonPublic | BindingFlags.Instance);
if (fetchDataMethod == null)
{
Debug.LogError("Could not find FetchData method.");
return;
}
var fetchPostfix = new HarmonyMethod(typeof(ShowHiddenShaders).GetMethod(nameof(FetchDataPostfix),
BindingFlags.NonPublic | BindingFlags.Static));
_harmonyInstance.Patch(fetchDataMethod, postfix: fetchPostfix);
var itemSelectedMethod = materialEditorType.GetMethod("ItemSelected",
BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(AdvancedDropdownItem) }, null);
var itemSelectedPrefix = new HarmonyMethod(
typeof(ShowHiddenShaders).GetMethod(nameof(ShaderDropdownItemSelectedPrefix),
BindingFlags.NonPublic | BindingFlags.Static));
_harmonyInstance.Patch(itemSelectedMethod, prefix: itemSelectedPrefix);
}
catch (Exception ex)
{
Debug.LogError(ex);
}
}
private static void FetchDataPostfix(ref AdvancedDropdownItem __result, object __instance)
{
if (__result == null)
{
return;
}
var hiddenRoot = new AdvancedDropdownItem("Hidden Shaders");
__result.AddChild(hiddenRoot);
s_HiddenShadersById.Clear();
s_NextCustomId = -1;
ShaderInfo[] allShaderInfos;
try
{
allShaderInfos = ShaderUtil.GetAllShaderInfo();
if (allShaderInfos == null || allShaderInfos.Length == 0)
{
return;
}
}
catch (Exception)
{
return;
}
var hiddenShadersByCategory = new Dictionary<string, List<AdvancedDropdownItem>>();
foreach (var info in allShaderInfos)
{
if (info.name.StartsWith("Hidden/"))
{
string shaderName = info.name.Substring("Hidden/".Length);
string[] parts = info.name.Split('/');
if (parts.Length >= 2)
{
string category = parts[1];
if (!hiddenShadersByCategory.ContainsKey(category))
{
hiddenShadersByCategory[category] = new List<AdvancedDropdownItem>();
}
var customId = s_NextCustomId--;
s_HiddenShadersById[customId] = Shader.Find(info.name);
hiddenShadersByCategory[category].Add(new AdvancedDropdownItem(shaderName) { id = customId });
}
}
}
foreach (var category in hiddenShadersByCategory)
{
if (category.Value.Count > 1)
{
var subcategory = new AdvancedDropdownItem(category.Key);
hiddenRoot.AddChild(subcategory);
foreach (var shaderItem in category.Value)
{
subcategory.AddChild(shaderItem);
}
}
else
{
foreach (var shaderItem in category.Value)
{
hiddenRoot.AddChild(shaderItem);
}
}
}
}
private static bool ShaderDropdownItemSelectedPrefix(AdvancedDropdownItem item, object __instance)
{
if (!s_HiddenShadersById.TryGetValue(item.id, out Shader chosenHiddenShader))
{
return true;
}
AssignSelectedShader(chosenHiddenShader);
return false;
}
private static void AssignSelectedShader(Shader hiddenShader)
{
var selectedMaterials = Selection.objects.OfType<Material>().ToArray();
if (selectedMaterials.Length == 0)
{
var selectedGOs = Selection.gameObjects;
var collected = new List<Material>();
foreach (var go in selectedGOs)
{
var renderer = go.GetComponent<Renderer>();
if (renderer != null)
{
collected.AddRange(renderer.sharedMaterials.Where(m => m != null));
}
}
selectedMaterials = collected.ToArray();
}
if (selectedMaterials.Length == 0)
{
Debug.LogWarning("No selected Materials or Renderers to assign the hidden shader.");
return;
}
foreach (var material in selectedMaterials)
{
if (material != null && material.shader != hiddenShader)
{
Undo.RecordObject(material, "Change Shader");
material.shader = hiddenShader;
EditorUtility.SetDirty(material);
}
}
}
}
@Myrkie
Copy link
Author

Myrkie commented Jan 20, 2025

Unity_6ki8h7sgYq.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment