A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3using UnityEngine;
4using UnityEngine.Profiling;
5
6namespace UnityEditor.ShaderGraph
7{
8 [GenerationAPI]
9 [InitializeOnLoad]
10 internal static class NodeClassCache
11 {
12 private class PostProcessor : AssetPostprocessor
13 {
14 static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
15 {
16 if (m_KnownSubGraphLookupTable != null)
17 {
18 foreach (string str in deletedAssets)
19 {
20 var guid = AssetDatabase.AssetPathToGUID(str);
21 if (m_KnownSubGraphLookupTable.ContainsKey(guid))
22 {
23 m_KnownSubGraphLookupTable.Remove(guid);
24 }
25 }
26 foreach (string str in movedFromAssetPaths)
27 {
28 var guid = AssetDatabase.AssetPathToGUID(str);
29 if (m_KnownSubGraphLookupTable.ContainsKey(guid))
30 {
31 m_KnownSubGraphLookupTable.Remove(guid);
32 }
33 }
34 }
35
36 foreach (string str in importedAssets)
37 {
38 if (str.EndsWith(ShaderSubGraphImporter.Extension))
39 {
40 UpdateSubGraphEntry(str);
41 }
42 }
43 foreach (string str in movedAssets)
44 {
45 if (str.EndsWith(ShaderSubGraphImporter.Extension))
46 {
47 UpdateSubGraphEntry(str);
48 }
49 }
50 }
51 }
52
53
54 private static Dictionary<Type, List<ContextFilterableAttribute>> m_KnownTypeLookupTable;
55 private static Dictionary<Type, List<ContextFilterableAttribute>> KnownTypeLookupTable
56 {
57 get
58 {
59 EnsureKnownTypeLookupTable();
60 return m_KnownTypeLookupTable;
61 }
62 }
63
64 public static IEnumerable<Type> knownNodeTypes
65 {
66 get => KnownTypeLookupTable.Keys;
67 }
68
69
70 private static Dictionary<string, SubGraphAsset> m_KnownSubGraphLookupTable;
71 private static Dictionary<string, SubGraphAsset> KnownSubGraphLookupTable
72 {
73 get
74 {
75 EnsureKnownSubGraphLookupTable();
76 return m_KnownSubGraphLookupTable;
77 }
78 }
79
80 public static IEnumerable<SubGraphAsset> knownSubGraphAssets
81 {
82 get => KnownSubGraphLookupTable.Values;
83 }
84
85 public static void UpdateSubGraphEntry(string path)
86 {
87 string guid = AssetDatabase.AssetPathToGUID(path);
88 if (guid.Length == 0)
89 {
90 return;
91 }
92 var asset = AssetDatabase.LoadAssetAtPath<SubGraphAsset>(path);
93
94 bool valid = asset != null && asset.isValid;
95 if (KnownSubGraphLookupTable.TryGetValue(guid, out SubGraphAsset known))
96 {
97 if (!valid)
98 {
99 KnownSubGraphLookupTable.Remove(guid);
100 }
101 else if (asset != known)
102 {
103 KnownSubGraphLookupTable[guid] = asset;
104 }
105 }
106 else if (valid)
107 {
108 KnownSubGraphLookupTable.Add(guid, asset);
109 }
110 }
111
112 public static IEnumerable<ContextFilterableAttribute> GetFilterableAttributesOnNodeType(Type nodeType)
113 {
114 if (nodeType == null)
115 {
116 throw new ArgumentNullException("Cannot get attributes on a null Type");
117 }
118
119 if (KnownTypeLookupTable.TryGetValue(nodeType, out List<ContextFilterableAttribute> filterableAttributes))
120 {
121 return filterableAttributes;
122 }
123 else
124 {
125 throw new ArgumentException($"The passed in Type {nodeType.FullName} was not found in the loaded assemblies as a child class of AbstractMaterialNode");
126 }
127 }
128
129 public static T GetAttributeOnNodeType<T>(Type nodeType) where T : ContextFilterableAttribute
130 {
131 var filterableAttributes = GetFilterableAttributesOnNodeType(nodeType);
132 foreach (var attr in filterableAttributes)
133 {
134 if (attr is T searchTypeAttr)
135 {
136 return searchTypeAttr;
137 }
138 }
139 return null;
140 }
141
142 private static void EnsureKnownTypeLookupTable()
143 {
144 if (m_KnownTypeLookupTable == null)
145 {
146 Profiler.BeginSample("EnsureKnownTypeLookupTable");
147 m_KnownTypeLookupTable = new Dictionary<Type, List<ContextFilterableAttribute>>();
148 foreach (Type nodeType in TypeCache.GetTypesDerivedFrom<AbstractMaterialNode>())
149 {
150 if (!nodeType.IsAbstract)
151 {
152 List<ContextFilterableAttribute> filterableAttributes = new List<ContextFilterableAttribute>();
153 foreach (Attribute attribute in Attribute.GetCustomAttributes(nodeType))
154 {
155 Type attributeType = attribute.GetType();
156 if (!attributeType.IsAbstract && attribute is ContextFilterableAttribute contextFilterableAttribute)
157 {
158 filterableAttributes.Add(contextFilterableAttribute);
159 }
160 }
161 m_KnownTypeLookupTable.Add(nodeType, filterableAttributes);
162 }
163 }
164 Profiler.EndSample();
165 }
166 }
167
168 private static void EnsureKnownSubGraphLookupTable()
169 {
170 if (m_KnownSubGraphLookupTable == null)
171 {
172 Profiler.BeginSample("EnsureKnownSubGraphLookupTable");
173 m_KnownSubGraphLookupTable = new Dictionary<string, SubGraphAsset>();
174 foreach (var guid in AssetDatabase.FindAssets(string.Format("t:{0}", typeof(SubGraphAsset))))
175 {
176 var asset = AssetDatabase.LoadAssetAtPath<SubGraphAsset>(AssetDatabase.GUIDToAssetPath(guid));
177 if (asset != null && asset.isValid)
178 {
179 m_KnownSubGraphLookupTable.Add(guid, asset);
180 }
181 }
182 Profiler.EndSample();
183 }
184 }
185
186 private static void DebugPrintKnownNodes()
187 {
188 foreach (var entry in KnownTypeLookupTable)
189 {
190 var nodeType = entry.Key;
191 var filterableAttributes = entry.Value;
192 String attrs = "";
193 foreach (var filterable in filterableAttributes)
194 {
195 attrs += filterable.ToString() + ", ";
196 }
197 Debug.Log(nodeType.ToString() + $": [{attrs}]");
198 }
199 }
200 }
201}