using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using UnityEditor.Graphing;
using UnityEditor.ShaderGraph.Legacy;
using UnityEditor.ShaderGraph.Serialization;
using UnityEngine;
namespace UnityEditor.ShaderGraph
{
///
/// Minimal version of used for gathering dependencies. This allows us to not deserialize
/// all the nodes, ports, edges, groups etc., which is important as we cannot share data between
/// and
/// . The latter must always import fully, but for the former we
/// want to avoid the extra GC pressure.
///
[Serializable]
class MinimalGraphData
{
static Dictionary s_MinimalTypeMap = CreateMinimalTypeMap();
static Dictionary CreateMinimalTypeMap()
{
var types = new Dictionary();
foreach (var type in TypeCache.GetTypesWithAttribute())
{
var dependencyAttribute = (HasDependenciesAttribute)type.GetCustomAttributes(typeof(HasDependenciesAttribute), false)[0];
if (!typeof(IHasDependencies).IsAssignableFrom(dependencyAttribute.minimalType))
{
Debug.LogError($"{type} must implement {typeof(IHasDependencies)} to be used in {typeof(HasDependenciesAttribute)}");
continue;
}
types.Add(type.FullName, dependencyAttribute.minimalType);
var formerNameAttributes = (FormerNameAttribute[])type.GetCustomAttributes(typeof(FormerNameAttribute), false);
foreach (var formerNameAttribute in formerNameAttributes)
{
types.Add(formerNameAttribute.fullName, dependencyAttribute.minimalType);
}
}
return types;
}
[SerializeField]
List m_SerializableNodes = new List();
// gather all asset dependencies declared by nodes in the given (shadergraph or shadersubgraph) asset
// by reading the source file from disk, and doing a minimal parse
// returns true if it successfully gathered the dependencies, false if there was an error
public static bool GatherMinimalDependenciesFromFile(string assetPath, AssetCollection assetCollection)
{
var textGraph = FileUtilities.SafeReadAllText(assetPath);
// if we can't read the file, no dependencies can be gathered
if (string.IsNullOrEmpty(textGraph))
return false;
var entries = MultiJsonInternal.Parse(textGraph);
if (string.IsNullOrWhiteSpace(entries[0].type))
{
var minimalGraphData = JsonUtility.FromJson(textGraph);
entries.Clear();
foreach (var node in minimalGraphData.m_SerializableNodes)
{
entries.Add(new MultiJsonEntry(node.typeInfo.fullName, null, node.JSONnodeData));
AbstractMaterialNode0 amn = new AbstractMaterialNode0();
JsonUtility.FromJsonOverwrite(node.JSONnodeData, amn);
foreach (var slot in amn.m_SerializableSlots)
{
entries.Add(new MultiJsonEntry(slot.typeInfo.fullName, null, slot.JSONnodeData));
}
}
}
foreach (var entry in entries)
{
if (s_MinimalTypeMap.TryGetValue(entry.type, out var minimalType))
{
var instance = (IHasDependencies)Activator.CreateInstance(minimalType);
JsonUtility.FromJsonOverwrite(entry.json, instance);
instance.GetSourceAssetDependencies(assetCollection);
}
}
return true;
}
}
}