A game about forced loneliness, made by TACStudios
1using System; 2using System.Linq; 3using System.Collections.Generic; 4using UnityEngine; 5using UnityEditor.ShaderGraph.Internal; 6using UnityEngine.Serialization; 7 8namespace UnityEditor.ShaderGraph 9{ 10 [Serializable] 11 class ShaderKeyword : ShaderInput 12 { 13 public const string kVariantLimitWarning = "Graph is generating too many variants. Either delete Keywords, reduce Keyword variants or increase the Shader Variant Limit in Preferences > Shader Graph."; 14 15 public ShaderKeyword() 16 { 17 } 18 19 public ShaderKeyword(KeywordType keywordType) 20 { 21 this.displayName = keywordType.ToString(); 22 this.keywordType = keywordType; 23 24 // Add sensible default entries for Enum type 25 if (keywordType == KeywordType.Enum) 26 { 27 m_Entries = new List<KeywordEntry>(); 28 m_Entries.Add(new KeywordEntry(1, "A", "A")); 29 m_Entries.Add(new KeywordEntry(2, "B", "B")); 30 m_Entries.Add(new KeywordEntry(3, "C", "C")); 31 } 32 } 33 34 public static ShaderKeyword CreateBuiltInKeyword(KeywordDescriptor descriptor) 35 { 36 if (descriptor.entries != null) 37 { 38 for (int i = 0; i < descriptor.entries.Length; i++) 39 { 40 if (descriptor.entries[i].id == -1) 41 descriptor.entries[i].id = i + 1; 42 } 43 } 44 45 return new ShaderKeyword() 46 { 47 isBuiltIn = true, 48 displayName = descriptor.displayName, 49 overrideReferenceName = descriptor.referenceName, 50 keywordType = descriptor.type, 51 keywordDefinition = descriptor.definition, 52 keywordScope = descriptor.scope, 53 value = descriptor.value, 54 entries = descriptor.entries.ToList(), 55 }; 56 } 57 58 [SerializeField] 59 private KeywordType m_KeywordType = KeywordType.Boolean; 60 61 public KeywordType keywordType 62 { 63 get => m_KeywordType; 64 set => m_KeywordType = value; 65 } 66 67 [SerializeField] 68 private KeywordDefinition m_KeywordDefinition = KeywordDefinition.ShaderFeature; 69 70 public KeywordDefinition keywordDefinition 71 { 72 get => m_KeywordDefinition; 73 set => m_KeywordDefinition = value; 74 } 75 76 [SerializeField] 77 private KeywordScope m_KeywordScope = KeywordScope.Local; 78 79 public KeywordScope keywordScope 80 { 81 get => m_KeywordScope; 82 set => m_KeywordScope = value; 83 } 84 85 [SerializeField] 86 private KeywordShaderStage m_KeywordStages = KeywordShaderStage.All; 87 88 public KeywordShaderStage keywordStages 89 { 90 get => m_KeywordStages; 91 set => m_KeywordStages = value; 92 } 93 94 [SerializeField] 95 private List<KeywordEntry> m_Entries; 96 97 public List<KeywordEntry> entries 98 { 99 get => m_Entries; 100 set => m_Entries = value; 101 } 102 103 [SerializeField] 104 private int m_Value; 105 106 public int value 107 { 108 get => m_Value; 109 set => m_Value = value; 110 } 111 112 [SerializeField] 113 private bool m_IsEditable = true; // this serializes !isBuiltIn 114 115 public bool isBuiltIn 116 { 117 get => !m_IsEditable; 118 set => m_IsEditable = !value; 119 } 120 121 internal override bool isCustomSlotAllowed => false; 122 123 internal override bool isExposable => !isBuiltIn && (keywordDefinition != KeywordDefinition.Predefined); 124 125 internal override bool isRenamable => !isBuiltIn; 126 127 internal override ConcreteSlotValueType concreteShaderValueType => keywordType.ToConcreteSlotValueType(); 128 129 public override string GetOldDefaultReferenceName() 130 { 131 // _ON suffix is required for exposing Boolean type to Material 132 var suffix = string.Empty; 133 if (keywordType == KeywordType.Boolean) 134 { 135 suffix = "_ON"; 136 } 137 138 return $"{keywordType.ToString()}_{objectId}{suffix}".ToUpper(); 139 } 140 141 public void AppendPropertyBlockStrings(ShaderStringBuilder builder) 142 { 143 if (isExposed) 144 { 145 switch (keywordType) 146 { 147 case KeywordType.Enum: 148 string enumTagString = $"[KeywordEnum({string.Join(", ", entries.Select(x => x.displayName))})]"; 149 builder.AppendLine($"{enumTagString}{referenceName}(\"{displayName}\", Float) = {value}"); 150 break; 151 case KeywordType.Boolean: 152 if (referenceName.EndsWith("_ON")) 153 builder.AppendLine($"[Toggle]{referenceName.Remove(referenceName.Length - 3, 3)}(\"{displayName}\", Float) = {value}"); 154 else 155 builder.AppendLine($"[Toggle({referenceName})]{referenceName}(\"{displayName}\", Float) = {value}"); 156 break; 157 default: 158 break; 159 } 160 } 161 } 162 163 public void AppendKeywordDeclarationStrings(ShaderStringBuilder builder) 164 { 165 if (keywordDefinition != KeywordDefinition.Predefined) 166 { 167 if (keywordType == KeywordType.Boolean) 168 KeywordUtil.GenerateBooleanKeywordPragmaStrings(referenceName, keywordDefinition, keywordScope, keywordStages, str => builder.AppendLine(str)); 169 else 170 KeywordUtil.GenerateEnumKeywordPragmaStrings(referenceName, keywordDefinition, keywordScope, keywordStages, entries, str => builder.AppendLine(str)); 171 } 172 } 173 174 public string GetKeywordPreviewDeclarationString() 175 { 176 switch (keywordType) 177 { 178 case KeywordType.Boolean: 179 return value == 1 ? $"#define {referenceName}" : string.Empty; 180 case KeywordType.Enum: 181 return $"#define {referenceName}_{entries[value].referenceName}"; 182 default: 183 throw new ArgumentOutOfRangeException(); 184 } 185 } 186 187 internal override ShaderInput Copy() 188 { 189 // Keywords copy reference name 190 // This is because keywords are copied between graphs 191 // When copying dependent nodes 192 return new ShaderKeyword() 193 { 194 displayName = displayName, 195 value = value, 196 isBuiltIn = isBuiltIn, 197 keywordType = keywordType, 198 keywordDefinition = keywordDefinition, 199 keywordScope = keywordScope, 200 entries = entries, 201 keywordStages = keywordStages, 202 overrideReferenceName = overrideReferenceName 203 }; 204 } 205 206 public override int latestVersion => 1; 207 public override void OnAfterDeserialize(string json) 208 { 209 if (sgVersion == 0) 210 { 211 // we now allow keywords to control whether they are exposed (for Material control) or not. 212 // old exposable keywords set their exposed state to maintain previous behavior 213 // (where bool keywords only showed up in the material when ending in "_ON") 214 if (isExposable) 215 { 216 if (m_KeywordType == KeywordType.Boolean) 217 generatePropertyBlock = referenceName.EndsWith("_ON"); 218 else // KeywordType.Enum 219 generatePropertyBlock = true; 220 } 221 ChangeVersion(1); 222 } 223 } 224 } 225}