Skip to content

Commit 58ff43d

Browse files
committed
Add macOS shader builder tool
1 parent 3517837 commit 58ff43d

File tree

11 files changed

+388
-9
lines changed

11 files changed

+388
-9
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,7 @@ crashlytics-build.properties
7373
# Temporary auto-generated Android Assets
7474
/[Aa]ssets/[Ss]treamingAssets/aa.meta
7575
/[Aa]ssets/[Ss]treamingAssets/aa/*
76+
77+
# Shader bundle related files
78+
SerializedMaterials/
79+
SerializedMaterials.meta

Assets/Editor/BackgroundEditor.cs

Lines changed: 124 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,91 @@
11
using System.Collections.Generic;
22
using System.IO;
3+
using System.Linq;
34
using UnityEditor;
45
using UnityEngine;
56
using UnityEngine.Video;
67
using TrombLoader.Data;
78

8-
namespace TrombLoader
9+
namespace TrombLoader
910
{
1011
[CustomEditor(typeof(Camera))]
1112
public class BackgroundEditor : Editor
1213
{
1314
Camera tromboneBackground;
1415

16+
// yoinked from https://github.com/tc-mods/TrombLoader/blob/9469e0593896eafb7a927847aa1bd8899ad781d5/Helpers/ShaderHelper.cs#L36
17+
public List<string> BaseGameShaderNames = new List<string>
18+
{
19+
"Custom/WavySpriteLit", "Custom/WavySpriteUnlit", "FX/Flare", "FX/Gem", "GUI/Text Shader",
20+
"Hidden/BlitCopy", "Hidden/BlitCopyDepth", "Hidden/BlitCopyWithDepth", "Hidden/BlitToDepth",
21+
"Hidden/BlitToDepth/MSAA", "Hidden/Compositing", "Hidden/ConvertTexture", "Hidden/CubeBlend",
22+
"Hidden/CubeBlur", "Hidden/CubeCopy", "Hidden/FrameDebuggerRenderTargetDisplay", "Hidden/Internal-Colored",
23+
"Hidden/Internal-CombineDepthNormals", "Hidden/Internal-CubemapToEquirect",
24+
"Hidden/Internal-DeferredReflections", "Hidden/Internal-DeferredShading",
25+
"Hidden/Internal-DepthNormalsTexture", "Hidden/Internal-Flare", "Hidden/Internal-GUIRoundedRect",
26+
"Hidden/Internal-GUIRoundedRectWithColorPerBorder", "Hidden/Internal-GUITexture",
27+
"Hidden/Internal-GUITextureBlit", "Hidden/Internal-GUITextureClip", "Hidden/Internal-GUITextureClipText",
28+
"Hidden/Internal-Halo", "Hidden/Internal-MotionVectors", "Hidden/Internal-ODSWorldTexture",
29+
"Hidden/Internal-PrePassLighting", "Hidden/Internal-ScreenSpaceShadows", "Hidden/Internal-StencilWrite",
30+
"Hidden/Internal-UIRAtlasBlitCopy", "Hidden/Internal-UIRDefault", "Hidden/InternalClear",
31+
"Hidden/InternalErrorShader", "Hidden/Post FX/Ambient Occlusion", "Hidden/Post FX/Blit",
32+
"Hidden/Post FX/Bloom", "Hidden/Post FX/Builtin Debug Views", "Hidden/Post FX/Depth Of Field",
33+
"Hidden/Post FX/Eye Adaptation", "Hidden/Post FX/Fog", "Hidden/Post FX/FXAA",
34+
"Hidden/Post FX/Grain Generator", "Hidden/Post FX/Lut Generator", "Hidden/Post FX/Motion Blur",
35+
"Hidden/Post FX/Screen Space Reflection", "Hidden/Post FX/Temporal Anti-aliasing",
36+
"hidden/SuperSystems/Wireframe-Global", "hidden/SuperSystems/Wireframe-Shaded-Unlit-Global",
37+
"hidden/SuperSystems/Wireframe-Transparent-Culled-Global",
38+
"hidden/SuperSystems/Wireframe-Transparent-Global", "Hidden/TextCore/Distance Field SSD",
39+
"Hidden/VideoComposite", "Hidden/VideoDecode", "Hidden/VideoDecodeOSX",
40+
"Hidden/VR/BlitFromTex2DToTexArraySlice", "Hidden/VR/BlitTexArraySlice", "Legacy Shaders/Diffuse",
41+
"Legacy Shaders/Particles/Additive", "Legacy Shaders/Particles/Alpha Blended Premultiply",
42+
"Legacy Shaders/Particles/Alpha Blended", "Legacy Shaders/Transparent/VertexLit",
43+
"Legacy Shaders/VertexLit", "Mobile/Unlit (Supports Lightmap)", "Particles/Standard Unlit",
44+
"Skybox/Procedural", "Spaventacorvi/Glitter/Glitter F - Bumped Specular",
45+
"Spaventacorvi/Holographic/Holo D - Specular Textured", "Sprites/Default", "Sprites/Diffuse",
46+
"Sprites/Mask", "Standard (Specular setup)", "Standard", "SuperSystems/Wireframe-Transparent-Culled",
47+
"TextMeshPro/Bitmap Custom Atlas", "TextMeshPro/Bitmap", "TextMeshPro/Distance Field (Surface)",
48+
"TextMeshPro/Distance Field Overlay", "TextMeshPro/Distance Field", "TextMeshPro/Mobile/Bitmap",
49+
"TextMeshPro/Mobile/Distance Field (Surface)", "TextMeshPro/Mobile/Distance Field - Masking",
50+
"TextMeshPro/Mobile/Distance Field Overlay", "TextMeshPro/Mobile/Distance Field", "TextMeshPro/Sprite",
51+
"UI/Default", "Hidden/Post FX/Uber"
52+
};
53+
54+
// just as cursed as above, but hey it still saves on disk space
55+
public List<string> TrombLoaderShaderNames = new List<string>
56+
{
57+
"Hidden/Internal-DeferredShading", "Hidden/Internal-DeferredReflections", "Hidden/Internal-ScreenSpaceShadows",
58+
"Hidden/Internal-PrePassLighting", "Hidden/Internal-DepthNormalsTexture", "Hidden/Internal-MotionVectors",
59+
"Hidden/Internal-Halo", "Hidden/Internal-Flare", "Hidden/CubeBlur", "Hidden/CubeCopy", "Hidden/CubeBlend",
60+
"Hidden/BlitCopy", "Legacy Shaders/Self-Illumin/VertexLit", "Legacy Shaders/Self-Illumin/Diffuse",
61+
"Legacy Shaders/Reflective/VertexLit", "Legacy Shaders/Reflective/Specular", "Legacy Shaders/Transparent/Diffuse",
62+
"Legacy Shaders/Transparent/Bumped Diffuse", "Legacy Shaders/Transparent/Cutout/VertexLit",
63+
"Legacy Shaders/Transparent/Cutout/Diffuse", "Legacy Shaders/Particles/~Additive-Multiply",
64+
"Legacy Shaders/Particles/Additive (Soft)", "Particles/Standard Surface", "Hidden/Nature/Terrain/Utilities",
65+
"Hidden/TerrainEngine/Details/Vertexlit", "Hidden/TerrainEngine/Details/WavingDoublePass",
66+
"Hidden/TerrainEngine/Details/BillboardWavingDoublePass", "Hidden/TerrainEngine/BillboardTree",
67+
"Hidden/TerrainEngine/Splatmap/Diffuse-Base", "Hidden/TerrainEngine/Splatmap/Diffuse-BaseGen",
68+
"Hidden/TerrainEngine/Splatmap/Diffuse-AddPass", "Nature/Terrain/Diffuse", "Hidden/Internal-GUITextureClip",
69+
"Hidden/Internal-GUITextureClipText", "Hidden/Internal-GUITexture", "Hidden/Internal-GUITextureBlit",
70+
"Hidden/Internal-GUIRoundedRect", "Hidden/Internal-UIRDefault", "Hidden/Internal-UIRAtlasBlitCopy",
71+
"Hidden/Internal-GUIRoundedRectWithColorPerBorder", "Mobile/VertexLit", "Mobile/Diffuse", "Mobile/Particles/Additive",
72+
"Unlit/Transparent", "Unlit/Transparent Cutout", "Unlit/Texture", "Unlit/Color", "Hidden/VideoComposite",
73+
"Hidden/VideoDecode", "Hidden/VideoDecodeOSX", "Hidden/VideoDecodeAndroid", "Hidden/VideoDecodeML", "Hidden/Compositing",
74+
"Hidden/Shader Forge/SFN_Blend_Divide", "Hidden/Shader Forge/SFN_Time", "Hidden/Shader Forge/SFN_Blend_Subtract",
75+
"Hidden/Shader Forge/SFN_UVTile", "Hidden/Shader Forge/SFN_Blend_PinLight", "Hidden/Shader Forge/FillColor",
76+
"Hidden/Shader Forge/SFN_Blend_LinearDodge", "Hidden/Shader Forge/SFN_Noise", "Hidden/Shader Forge/SFN_TexCoord",
77+
"Hidden/Shader Forge/SFN_ArcTan2_ZTO", "Hidden/Shader Forge/SFN_Blend_Multiply", "Hidden/Shader Forge/SFN_Blend_Overlay",
78+
"Hidden/Shader Forge/SFN_Add_2", "Hidden/Shader Forge/SFN_ArcTan2_ZTOW", "Hidden/Shader Forge/SFN_Tex2d_UV",
79+
"Hidden/Shader Forge/ExtractChannel", "Hidden/Shader Forge/SFN_Tex2d_NoInputs", "Hidden/Shader Forge/SFN_Blend_ColorDodge",
80+
"Hidden/Shader Forge/SFN_ArcTan2_NOTO", "Hidden/Shader Forge/SFN_Distance", "Hidden/Shader Forge/SFN_Posterize",
81+
"Hidden/Shader Forge/SFN_ComponentMask_CC2", "Hidden/Shader Forge/SFN_ComponentMask_CC3",
82+
"Hidden/Shader Forge/SFN_ComponentMask_CC1", "Hidden/Shader Forge/SFN_Blend_ColorBurn", "Hidden/Shader Forge/SFN_ArcTan",
83+
"Hidden/Shader Forge/SFN_Blend_Difference", "Hidden/Shader Forge/SFN_Blend_Screen", "Hidden/Shader Forge/SFN_Append",
84+
"Hidden/Shader Forge/SFN_Blend_LinearBurn", "Hidden/Shader Forge/SFN_Blend_Darken", "Hidden/Shader Forge/SFN_Multiply_2",
85+
"Hidden/Shader Forge/SFN_Lerp", "Hidden/Shader Forge/SFN_Abs", "Shader Forge/TransparentControl",
86+
"Shader Forge/SpiralClock", "Shader Forge/Spiral", "Shader Forge/ClockSpiralFinal"
87+
};
88+
1589
private void OnEnable()
1690
{
1791
tromboneBackground = (Camera)target;
@@ -27,26 +101,61 @@ public override void OnInspectorGUI()
27101
{
28102
string path = EditorUtility.SaveFilePanel("Save Trombone Background", string.Empty, "bg.trombackground", "trombackground");
29103

30-
BuildTargetGroup selectedBuildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
31-
BuildTarget activeBuildTarget = EditorUserBuildSettings.activeBuildTarget;
104+
BuildTargetGroup selectedBuildTargetGroup = BuildTargetGroup.Standalone;
105+
BuildTarget activeBuildTarget = BuildTarget.StandaloneWindows64;
32106

33107
GameObject clonedTromboneBackground = null;
34108

35109
try
36110
{
37111
if (!string.IsNullOrEmpty(path))
38112
{
113+
string fileName = Path.GetFileName(path);
114+
string folderPath = Path.GetDirectoryName(path);
115+
116+
// macOS Shader compiling
117+
var shaders = Resources.FindObjectsOfTypeAll<Shader>();
118+
119+
var filteredShaders = new List<Shader>();
120+
121+
foreach (var shader in shaders)
122+
{
123+
// probably don't need to check for null here but just to be safe
124+
if (shader == null || shader.name == "Standard") continue;
125+
126+
// as far as i'm aware Unity doesn't list hidden shaders in the editor UI
127+
// so hopefully excluding them won't break anything
128+
if (shader.name.StartsWith("Hidden/")) continue;
129+
130+
if (BaseGameShaderNames.Contains(shader.name) || TrombLoaderShaderNames.Contains(shader.name)) continue;
131+
132+
if (filteredShaders.Contains(shader)) continue;
133+
134+
if (shader.hideFlags.HasFlag(HideFlags.DontSave) || shader.hideFlags.HasFlag(HideFlags.HideAndDontSave)) continue;
135+
136+
Debug.Log($"Found shader {shader.name} to build for macOS");
137+
filteredShaders.Add(shader);
138+
}
139+
39140
clonedTromboneBackground = Instantiate(tromboneBackground.gameObject);
40141

142+
var macShadersBuilt = true;
143+
144+
if (filteredShaders.Any())
145+
{
146+
MacShaderPicker window = CreateInstance<MacShaderPicker>();
147+
window.titleContent = new GUIContent("macOS Shader Bundle Builder");
148+
window.Init(filteredShaders, folderPath, clonedTromboneBackground);
149+
window.ShowModalUtility();
150+
macShadersBuilt = window.HasBuilt;
151+
}
152+
41153
// serialize
42154
foreach (var manager in clonedTromboneBackground.gameObject.GetComponentsInChildren<TromboneEventManager>())
43155
{
44156
manager.SerializeAllGenericEvents();
45157
}
46158

47-
string fileName = Path.GetFileName(path);
48-
string folderPath = Path.GetDirectoryName(path);
49-
50159
int serializedCount = 0;
51160
// serialize video clips because unity REALLY does not like making them work in assetbundles
52161
foreach (var videoPlayer in clonedTromboneBackground.gameObject.GetComponentsInChildren<VideoPlayer>())
@@ -111,7 +220,14 @@ public override void OnInspectorGUI()
111220

112221
AssetDatabase.Refresh();
113222

114-
EditorUtility.DisplayDialog("Exportation Successful!", "Exportation Successful!", "OK");
223+
if (macShadersBuilt)
224+
{
225+
EditorUtility.DisplayDialog("Exportation Successful!", "Exportation Successful!", "OK");
226+
}
227+
else
228+
{
229+
EditorUtility.DisplayDialog("Exportation Successful!", "No macOS shaders were built.", "OK");
230+
}
115231

116232
if (clonedTromboneBackground != null) DestroyImmediate(clonedTromboneBackground);
117233

@@ -131,4 +247,4 @@ public override void OnInspectorGUI()
131247
}
132248
}
133249
}
134-
}
250+
}

Assets/Editor/MacShaderBuilder.cs

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
using System.Collections.Generic;
2+
using System.IO;
3+
using System.Linq;
4+
using UnityEditor;
5+
using UnityEngine;
6+
using UnityEngine.UI;
7+
using TMPro;
8+
9+
public class MacShaderPicker : EditorWindow
10+
{
11+
private Dictionary<Shader, bool> ShaderList = new Dictionary<Shader, bool>();
12+
private string FolderPath;
13+
public bool HasBuilt = false;
14+
public MacShaderPrefs shaderPrefs;
15+
16+
Vector2 scrollPosition;
17+
List<Shader> SceneShaders = new List<Shader>();
18+
19+
public void Init(List<Shader> shaders, string path, GameObject background)
20+
{
21+
ShaderList.Clear();
22+
shaderPrefs = AssetDatabase.LoadAssetAtPath<MacShaderPrefs>("Assets/Resources/MacShaderPrefs.asset");
23+
if (shaderPrefs == null)
24+
{
25+
shaderPrefs = CreateInstance<MacShaderPrefs>();
26+
if (!AssetDatabase.IsValidFolder("Assets/Resources"))
27+
{
28+
AssetDatabase.CreateFolder("Assets", "Resources");
29+
}
30+
AssetDatabase.CreateAsset(shaderPrefs, "Assets/Resources/MacShaderPrefs.asset");
31+
AssetDatabase.SaveAssets();
32+
}
33+
34+
CheckScene(background);
35+
36+
foreach (var shader in shaders)
37+
{
38+
if (shaderPrefs.blocklist.Contains(shader.name))
39+
{
40+
Debug.Log($"Shader {shader.name} is blocked");
41+
ShaderList[shader] = false;
42+
}
43+
else if (shaderPrefs.allowlist.Contains(shader.name) || SceneShaders.Contains(shader))
44+
{
45+
Debug.Log($"Shader {shader.name} is allowed");
46+
ShaderList[shader] = true;
47+
}
48+
else
49+
{
50+
Debug.Log($"Default behaviour for {shader.name}");
51+
ShaderList[shader] = false;
52+
}
53+
}
54+
FolderPath = path;
55+
}
56+
57+
public void OnGUI()
58+
{
59+
GUILayout.Label("Shaders to include:");
60+
61+
scrollPosition = GUILayout.BeginScrollView(scrollPosition);
62+
63+
var style = GUI.skin.GetStyle("Toggle");
64+
65+
for (int i = 0; i < ShaderList.Count; i++)
66+
{
67+
var shader = ShaderList.ElementAt(i).Key;
68+
var active = ShaderList.ElementAt(i).Value;
69+
if (SceneShaders.Contains(shader))
70+
{
71+
style.fontStyle = FontStyle.Bold;
72+
}
73+
else
74+
{
75+
style.fontStyle = FontStyle.Normal;
76+
77+
}
78+
ShaderList[shader] = GUILayout.Toggle(active, shader.name, style);
79+
}
80+
81+
GUILayout.EndScrollView();
82+
83+
GUILayout.Box(
84+
"To make sure your background appears correctly on macOS we need to build a bundle containing Mac-compatible shaders. " +
85+
"To save on disk space, you can exclude shaders you know you aren't using in your scene. " +
86+
"If you're not sure what to exclude, you can just leave everything selected at the expense of a slightly larger shader bundle." +
87+
"\n\nShaders that were found within the scene in its current state are highlighted in bold and are selected by default, " +
88+
"but this may not include all of the shaders that are used in your project."
89+
);
90+
91+
string btnName;
92+
93+
if (ShaderList.ContainsValue(true))
94+
{
95+
btnName = "Build Them Shaders!";
96+
}
97+
else
98+
{
99+
btnName = "Continue Without Building Shaders";
100+
}
101+
102+
if (GUILayout.Button(btnName))
103+
{
104+
shaderPrefs.blocklist = new List<string>();
105+
foreach(var item in ShaderList)
106+
{
107+
if (item.Value)
108+
{
109+
shaderPrefs.allowlist.Add(item.Key.name);
110+
}
111+
else
112+
{
113+
shaderPrefs.blocklist.Add(item.Key.name);
114+
}
115+
}
116+
117+
AssetDatabase.SaveAssets();
118+
119+
if (ShaderList.ContainsValue(true))
120+
{
121+
BuildShaders();
122+
HasBuilt = true;
123+
}
124+
else
125+
{
126+
HasBuilt = false;
127+
}
128+
Close();
129+
}
130+
}
131+
132+
void CheckScene(GameObject background)
133+
{
134+
SceneShaders.Clear();
135+
136+
var materials = new[]
137+
{
138+
background.GetComponentsInChildren<Renderer>(true).SelectMany(renderer => renderer.sharedMaterials),
139+
background.GetComponentsInChildren<TMP_Text>(true).Select(textMesh => textMesh.fontSharedMaterial),
140+
background.GetComponentsInChildren<Graphic>(true).Select(graphics => graphics.material)
141+
}.SelectMany(x => x);
142+
143+
foreach (var material in materials)
144+
{
145+
SceneShaders.Add(material.shader);
146+
}
147+
}
148+
149+
void BuildShaders()
150+
{
151+
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Standalone, BuildTarget.StandaloneOSX);
152+
153+
GameObject shaderParent = new GameObject("_Shaders");
154+
if (!AssetDatabase.IsValidFolder("Assets/SerializedMaterials"))
155+
{
156+
AssetDatabase.CreateFolder("Assets", "SerializedMaterials");
157+
}
158+
for (int i = 0; i < ShaderList.Count; i++)
159+
{
160+
if (ShaderList.ElementAt(i).Value)
161+
{
162+
continue;
163+
}
164+
var shader = ShaderList.ElementAt(i).Key;
165+
166+
var mat = new Material(shader);
167+
168+
AssetDatabase.CreateAsset(mat, "Assets/SerializedMaterials/" + i + ".mat");
169+
170+
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
171+
172+
cube.name = i.ToString();
173+
cube.transform.SetParent(shaderParent.transform);
174+
cube.GetComponent<Renderer>().sharedMaterial = mat;
175+
}
176+
177+
string shaderFileName = Path.GetFileName("ShaderCache_OSX.DONOTDELETE");
178+
string shaderPath = Path.Combine(FolderPath, shaderFileName);
179+
180+
PrefabUtility.SaveAsPrefabAsset(shaderParent, "Assets/_Shaders.prefab");
181+
AssetBundleBuild shaderBundleBuild = default;
182+
shaderBundleBuild.assetBundleName = shaderFileName;
183+
shaderBundleBuild.assetNames = new string[] {"Assets/_Shaders.prefab"};
184+
185+
BuildPipeline.BuildAssetBundles(Application.temporaryCachePath,
186+
new AssetBundleBuild[] {shaderBundleBuild}, BuildAssetBundleOptions.ForceRebuildAssetBundle,
187+
BuildTarget.StandaloneOSX);
188+
189+
AssetDatabase.DeleteAsset("Assets/_Shaders.prefab");
190+
191+
if (File.Exists(shaderPath)) File.Delete(shaderPath);
192+
193+
File.Move(Path.Combine(Application.temporaryCachePath, shaderFileName), shaderPath);
194+
195+
DestroyImmediate(shaderParent);
196+
197+
AssetDatabase.DeleteAsset("Assets/SerializedMaterials");
198+
199+
AssetDatabase.Refresh();
200+
201+
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Standalone, BuildTarget.StandaloneWindows64);
202+
}
203+
}

0 commit comments

Comments
 (0)