A game about forced loneliness, made by TACStudios
at master 102 lines 4.6 kB view raw
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Reflection; 5using UnityEditor.Graphing; 6using UnityEngine; 7 8namespace UnityEditor.ShaderGraph 9{ 10 sealed partial class GraphData : ISerializationCallbackReceiver 11 { 12 public static class GraphValidation 13 { 14 static Dictionary<Type, FieldInfo> s_ActiveSubTarget = new(); 15 static readonly PropertyInfo s_JsonData = typeof(Serialization.JsonData<SubTarget>).GetProperty("value"); 16 17 static SubTarget GetActiveSubTarget(Target target) 18 { 19 // All targets have an active subtarget but it's not accessible from ShaderGraph 20 // so we use reflection to access it 21 22 var type = target.GetType(); 23 if (!s_ActiveSubTarget.TryGetValue(type, out var activeSubTarget)) 24 { 25 activeSubTarget = type.GetField("m_ActiveSubTarget", BindingFlags.Instance | BindingFlags.NonPublic); 26 s_ActiveSubTarget.Add(type, activeSubTarget); 27 } 28 if (activeSubTarget != null) 29 { 30 var jsonData = activeSubTarget.GetValue(target); 31 if (jsonData != null) 32 { 33 return s_JsonData.GetValue(jsonData) as SubTarget; 34 } 35 } 36 return null; 37 } 38 39 public static void ValidateNode(AbstractMaterialNode node) 40 { 41 Type t = node.GetType(); 42 node.ValidateNode(); 43 if (!(node is BlockNode)) 44 { 45 bool disallowedByAnyTargets = false; 46 bool disallowedByAllTargets = true; 47 bool disallowedByAnySubTarget = false; 48 IEnumerable<Target> targets = node.owner.activeTargets; 49 if (node.owner.isSubGraph) 50 { 51 targets = node.owner.allPotentialTargets; 52 } 53 foreach (var target in targets) 54 { 55 //if at least one target doesn't allow a node, it is considered invalid 56 if (!target.IsNodeAllowedByTarget(t)) 57 { 58 disallowedByAnyTargets = true; 59 node.isValid = false; 60 node.owner.AddValidationError(node.objectId, $"{node.name} Node is not allowed by {target.displayName} implementation", Rendering.ShaderCompilerMessageSeverity.Warning); 61 node.owner.m_UnsupportedTargets.Add(target); 62 } 63 //at least one target does allow node, not going to be explicitly set inactive 64 else 65 { 66 disallowedByAllTargets = false; 67 } 68 69 var subtarget = GetActiveSubTarget(target); 70 if (subtarget != null && !subtarget.IsNodeAllowedBySubTarget(t)) 71 { 72 disallowedByAnySubTarget = true; 73 node.isValid = false; 74 node.owner.AddValidationError(node.objectId, $"{node.name} Node is not allowed by {subtarget.displayName} implementation", Rendering.ShaderCompilerMessageSeverity.Error); 75 } 76 } 77 if (!disallowedByAnyTargets && !disallowedByAnySubTarget) 78 { 79 node.isValid = true; 80 } 81 82 //Set ActiveState based on if all targets disallow this node 83 if (disallowedByAllTargets) 84 { 85 node.SetOverrideActiveState(AbstractMaterialNode.ActiveState.ExplicitInactive); 86 node.owner.AddValidationError(node.objectId, $"{node.name} Node is not allowed by any active targets, and will not be used in generation", Rendering.ShaderCompilerMessageSeverity.Warning); 87 } 88 else 89 { 90 node.SetOverrideActiveState(AbstractMaterialNode.ActiveState.Implicit); 91 } 92 } 93 } 94 95 public static void ValidateGraph(GraphData graph) 96 { 97 graph.m_UnsupportedTargets.Clear(); 98 GraphDataUtils.ApplyActionLeafFirst(graph, ValidateNode); 99 } 100 } 101 } 102}