A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Reflection;
5using System.Text;
6using UnityEditor.Graphing;
7using UnityEditor.ShaderGraph.Legacy;
8using UnityEditor.ShaderGraph.Serialization;
9using UnityEngine;
10
11namespace UnityEditor.ShaderGraph
12{
13 /// <summary>
14 /// Minimal version of <see cref="GraphData"/> used for gathering dependencies. This allows us to not deserialize
15 /// all the nodes, ports, edges, groups etc., which is important as we cannot share data between
16 /// <see cref="ShaderSubGraphImporter.GatherDependenciesFromSourceFile"/> and
17 /// <see cref="ShaderSubGraphImporter.OnImportAsset"/>. The latter must always import fully, but for the former we
18 /// want to avoid the extra GC pressure.
19 /// </summary>
20 [Serializable]
21 class MinimalGraphData
22 {
23 static Dictionary<string, Type> s_MinimalTypeMap = CreateMinimalTypeMap();
24
25 static Dictionary<string, Type> CreateMinimalTypeMap()
26 {
27 var types = new Dictionary<string, Type>();
28 foreach (var type in TypeCache.GetTypesWithAttribute<HasDependenciesAttribute>())
29 {
30 var dependencyAttribute = (HasDependenciesAttribute)type.GetCustomAttributes(typeof(HasDependenciesAttribute), false)[0];
31 if (!typeof(IHasDependencies).IsAssignableFrom(dependencyAttribute.minimalType))
32 {
33 Debug.LogError($"{type} must implement {typeof(IHasDependencies)} to be used in {typeof(HasDependenciesAttribute)}");
34 continue;
35 }
36
37 types.Add(type.FullName, dependencyAttribute.minimalType);
38
39 var formerNameAttributes = (FormerNameAttribute[])type.GetCustomAttributes(typeof(FormerNameAttribute), false);
40 foreach (var formerNameAttribute in formerNameAttributes)
41 {
42 types.Add(formerNameAttribute.fullName, dependencyAttribute.minimalType);
43 }
44 }
45
46 return types;
47 }
48
49 [SerializeField]
50 List<SerializationHelper.JSONSerializedElement> m_SerializableNodes = new List<SerializationHelper.JSONSerializedElement>();
51
52 // gather all asset dependencies declared by nodes in the given (shadergraph or shadersubgraph) asset
53 // by reading the source file from disk, and doing a minimal parse
54 // returns true if it successfully gathered the dependencies, false if there was an error
55 public static bool GatherMinimalDependenciesFromFile(string assetPath, AssetCollection assetCollection)
56 {
57 var textGraph = FileUtilities.SafeReadAllText(assetPath);
58
59 // if we can't read the file, no dependencies can be gathered
60 if (string.IsNullOrEmpty(textGraph))
61 return false;
62
63 var entries = MultiJsonInternal.Parse(textGraph);
64
65 if (string.IsNullOrWhiteSpace(entries[0].type))
66 {
67 var minimalGraphData = JsonUtility.FromJson<MinimalGraphData>(textGraph);
68 entries.Clear();
69 foreach (var node in minimalGraphData.m_SerializableNodes)
70 {
71 entries.Add(new MultiJsonEntry(node.typeInfo.fullName, null, node.JSONnodeData));
72 AbstractMaterialNode0 amn = new AbstractMaterialNode0();
73 JsonUtility.FromJsonOverwrite(node.JSONnodeData, amn);
74 foreach (var slot in amn.m_SerializableSlots)
75 {
76 entries.Add(new MultiJsonEntry(slot.typeInfo.fullName, null, slot.JSONnodeData));
77 }
78 }
79 }
80
81 foreach (var entry in entries)
82 {
83 if (s_MinimalTypeMap.TryGetValue(entry.type, out var minimalType))
84 {
85 var instance = (IHasDependencies)Activator.CreateInstance(minimalType);
86 JsonUtility.FromJsonOverwrite(entry.json, instance);
87 instance.GetSourceAssetDependencies(assetCollection);
88 }
89 }
90
91 return true;
92 }
93 }
94}