Skip to content

Commit 470d32e

Browse files
KarlBKentKarl Kent
authored andcommitted
Xp vfx user keywords (#46)
* User Keywords initial work * Update ShaderInputPropertyDrawer.cs Prevent shadergraph from adding nodes if limit is exceeded, so it doesnt serialize and cause UI Issues. * Update ShaderGraphImporter.cs Bring the Importer versioning up to latest Co-authored-by: Karl Kent <karl.kent@gmail.com> Xp vfx user keywords (#49) * Adding Missing shader keyword util, from PR Missed this due to workflow issues Co-authored-by: Karl Kent <karl.kent@gmail.com>
1 parent c3fc567 commit 470d32e

File tree

12 files changed

+547
-19
lines changed

12 files changed

+547
-19
lines changed

com.unity.shadergraph/Editor/Data/Util/KeywordUtil.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,34 @@ public static string ToDefineString(this KeywordDescriptor keyword, int value)
9797
}
9898
}
9999

100+
public static int GetKeywordPermutationCount(this GraphData graph)
101+
{
102+
// Gather all unique keywords from the Graph including Sub Graphs
103+
IEnumerable<ShaderKeyword> allKeywords = graph.keywords;
104+
var subGraphNodes = graph.GetNodes<SubGraphNode>();
105+
foreach (SubGraphNode subGraphNode in subGraphNodes)
106+
{
107+
if (subGraphNode.asset == null)
108+
{
109+
continue;
110+
}
111+
allKeywords = allKeywords.Union(subGraphNode.asset.keywords);
112+
}
113+
allKeywords = allKeywords.Distinct();
114+
115+
// Get permutation count for all Keywords
116+
int permutationCount = 1;
117+
foreach (ShaderKeyword keyword in allKeywords)
118+
{
119+
if (keyword.keywordType == KeywordType.Boolean)
120+
permutationCount *= 2;
121+
else
122+
permutationCount *= keyword.entries.Count;
123+
}
124+
125+
return permutationCount;
126+
}
127+
100128
public static string GetKeywordPermutationSetConditional(List<int> permutationSet)
101129
{
102130
StringBuilder sb = new StringBuilder();

com.unity.shadergraph/Editor/Drawing/Inspector/PropertyDrawers/ShaderInputPropertyDrawer.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,6 +1234,12 @@ void KeywordAddEntry(ReorderableList list)
12341234
if(!(shaderInput is ShaderKeyword keyword))
12351235
return;
12361236

1237+
if (graphData.GetKeywordPermutationCount() > ShaderGraphPreferences.variantLimit)
1238+
{
1239+
Debug.LogError($"Error in Shader Graph: {ShaderKeyword.kVariantLimitWarning}");
1240+
return;
1241+
}
1242+
12371243
this._preChangeValueCallback("Add Keyword Entry");
12381244

12391245
int index = GetFirstUnusedID();

com.unity.shadergraph/Editor/Generation/GraphCode.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ public struct GraphCode
88
public string code { get; internal set; }
99
public ShaderGraphRequirements requirements { get; internal set; }
1010
public IEnumerable<AbstractShaderProperty> properties;
11+
public IEnumerable<ShaderInput> keywords;
1112
}
1213
}

com.unity.shadergraph/Editor/Generation/ShaderGraphVfxAsset.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public sealed class ShaderGraphVfxAsset : ScriptableObject, ISerializationCallba
3232
private class ShaderGraphVfxAssetData : JsonObject
3333
{
3434
public List<JsonData<AbstractShaderProperty>> m_Properties = new List<JsonData<AbstractShaderProperty>>();
35+
public List<JsonData<ShaderKeyword>> m_Keywords = new List<JsonData<ShaderKeyword>>();
3536
}
3637

3738
public const int BaseColorSlotId = 1;
@@ -135,6 +136,14 @@ public List<AbstractShaderProperty> properties
135136
return m_Data.m_Properties.SelectValue().ToList();
136137
}
137138
}
139+
internal List<ShaderKeyword> Keywords
140+
{
141+
get
142+
{
143+
EnsureKeywords();
144+
return m_Data.m_Keywords.SelectValue().ToList();
145+
}
146+
}
138147

139148
internal void SetProperties(List<AbstractShaderProperty> propertiesList)
140149
{
@@ -148,6 +157,16 @@ internal void SetProperties(List<AbstractShaderProperty> propertiesList)
148157
m_SerializedVfxAssetData = new SerializationHelper.JSONSerializedElement() { JSONnodeData = json };
149158
m_Data = null;
150159
}
160+
internal void SetKeywords(List<ShaderKeyword> keywordList)
161+
{
162+
m_Data.m_Keywords.Clear();
163+
foreach(var keyword in keywordList)
164+
{
165+
m_Data.m_Keywords.Add(keyword);
166+
}
167+
var json = MultiJson.Serialize(m_Data);
168+
m_SerializedVfxAssetData = new SerializationHelper.JSONSerializedElement() { JSONnodeData = json };
169+
}
151170

152171
void EnsureProperties()
153172
{
@@ -163,6 +182,15 @@ void EnsureProperties()
163182
}
164183
}
165184

185+
void EnsureKeywords()
186+
{
187+
if((m_Data == null || m_Data.m_Keywords == null) && !String.IsNullOrEmpty(m_SerializedVfxAssetData.JSONnodeData))
188+
{
189+
m_Data = new ShaderGraphVfxAssetData();
190+
MultiJson.Deserialize(m_Data , m_SerializedVfxAssetData.JSONnodeData);
191+
}
192+
}
193+
166194
void ISerializationCallbackReceiver.OnAfterDeserialize()
167195
{
168196
m_Data = null;
@@ -201,7 +229,7 @@ public GraphCode GetCode(OutputMetadata[] outputs)
201229
Array.Sort(propertyIndices);
202230
var filteredProperties = propertyIndices.Select(i => properties[i]).ToArray();
203231
graphCode.properties = filteredProperties;
204-
232+
205233
return graphCode;
206234
}
207235
}

com.unity.shadergraph/Editor/Importers/ShaderGraphImporter.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ namespace UnityEditor.ShaderGraph
2929
// + 1 Bump ShaderImporter version after bugfix to DotsDeformation.hlsl::FetchComputeVertexData() to tangentOS.w in tangentOS output so mirrored normals produce correct normal maps.
3030
// + 1 Bump ShaderImporter version after stripping LIGHTMAP_ON variants from shadergraph codegen in 9.x.x/custom/cherry-pick.
3131
// + 1 Bump ShaderImporter version after Return positionDS from ObjectSpacePosition in Decal Shader Graphs
32+
// + 1 Bump ShaderImporter version after VFXGraph Keyword Support Added.
3233
// [ScriptedImporter(115, Extension, -902)]
33-
[ScriptedImporter(118, Extension, -902)]
34+
[ScriptedImporter(119, Extension, -902)]
3435
#else
3536
// [ScriptedImporter(47, Extension, -902)]
36-
[ScriptedImporter(50, Extension, -902)]
37+
[ScriptedImporter(51, Extension, -902)]
3738
// custom-end
3839
#endif
3940

@@ -651,7 +652,17 @@ void AddCoordinateSpaceSnippets(InterpolatorType interpolatorType, Func<ShaderGr
651652
sharedCodeIndices.Add(codeSnippets.Count);
652653
codeSnippets.Add($"{outputStructName} {evaluationFunctionName}({nl}{indent}{inputStructName} IN");
653654

655+
var keywords = new List<ShaderKeyword>();
656+
foreach ( var keyword in graph.keywords)
657+
{
658+
if (keyword.isExposable && !keyword.isBuiltIn)
659+
{
660+
keywords.Add(keyword);
661+
}
662+
}
663+
654664
var inputProperties = new List<AbstractShaderProperty>();
665+
655666
var portPropertyIndices = new List<int>[ports.Count];
656667
for (var portIndex = 0; portIndex < ports.Count; portIndex++)
657668
{
@@ -753,6 +764,7 @@ void AddCoordinateSpaceSnippets(InterpolatorType interpolatorType, Func<ShaderGr
753764
asset.outputStructName = outputStructName;
754765
asset.portRequirements = portRequirements;
755766
asset.concretePrecision = graph.concretePrecision;
767+
asset.SetKeywords(keywords);
756768
asset.SetProperties(inputProperties);
757769
asset.outputPropertyIndices = new IntArray[ports.Count];
758770
for (var portIndex = 0; portIndex < ports.Count; portIndex++)

com.unity.visualeffectgraph/Editor/Core/VFXSerializer.cs

Lines changed: 87 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,11 @@ public static string Save(object obj)
323323
}
324324
return JsonUtility.ToJson(gw);
325325
}
326+
else if (obj is VFXUserKeyword)
327+
{
328+
VFXUserKeyword keyword = obj as VFXUserKeyword;
329+
return JsonUtility.ToJson(keyword);
330+
}
326331
else if (obj is string)
327332
{
328333
return "\"" + ((string)obj).Replace("\"", "\\\"") + "\"";
@@ -334,18 +339,23 @@ public static string Save(object obj)
334339
else if (obj.GetType().IsArrayOrList())
335340
{
336341
IList list = (IList)obj;
337-
338-
System.Text.StringBuilder sb = new System.Text.StringBuilder();
339-
sb.Append('[');
340-
for (int i = 0; i < list.Count; ++i)
342+
if (list.Count > 0)
341343
{
342-
sb.Append(Save(list[i]));
343-
sb.Append(',');
344+
System.Text.StringBuilder sb = new System.Text.StringBuilder();
345+
sb.Append('[');
346+
for (int i = 0; i < list.Count; ++i)
347+
{
348+
sb.Append(Save(list[i]));
349+
sb.Append(',');
350+
}
351+
352+
sb.Length = sb.Length - 1;
353+
sb.Append(']');
354+
355+
return sb.ToString();
344356
}
345-
sb.Length = sb.Length - 1;
346-
sb.Append(']');
347357

348-
return sb.ToString();
358+
return "[]";
349359
}
350360
else
351361
{
@@ -472,6 +482,23 @@ public static object Load(System.Type type, string text, object oldValue)
472482
var obj = new SerializableType(text.Substring(1, text.Length - 2));
473483
return obj;
474484
}
485+
else if (type.IsAssignableFrom(typeof(List<VFXUserKeyword>)))
486+
{
487+
List<string> TopLevelObjectsElements = ParseTopLevelObjectsFromJsonObjectArrayString(text);
488+
489+
List<VFXUserKeyword> ObjectElements = new List<VFXUserKeyword>();
490+
491+
foreach (var topLevelObject in TopLevelObjectsElements)
492+
{
493+
var element = JsonUtility.FromJson<VFXUserKeyword>(topLevelObject);
494+
if (element != null)
495+
{
496+
ObjectElements.Add((element));
497+
}
498+
}
499+
500+
return ObjectElements;
501+
}
475502
else if (type.IsArrayOrList())
476503
{
477504
List<string> elements = ParseArray(text);
@@ -596,8 +623,58 @@ internal static List<string> ParseArray(string arrayText)
596623
}
597624
error:
598625
Debug.LogError("Couln't parse array" + arrayText + " from " + cur);
599-
600626
return null;
601627
}
628+
/*
629+
* Used to parse top-level objects form a JSON string, returning the JSON specific to that object in each element.
630+
*/
631+
internal static List<string> ParseTopLevelObjectsFromJsonObjectArrayString(string arrayText)
632+
{
633+
List<string> elements = new List<string>();
634+
635+
int cur = 0;
636+
637+
bool ignoreNext = false;
638+
int depth = 0;
639+
bool isInString = false;
640+
int prevElementStart = 0;
641+
642+
foreach (char c in arrayText)
643+
{
644+
switch (c)
645+
{
646+
case '{':
647+
if (!isInString)
648+
prevElementStart = cur;
649+
depth++;
650+
break;
651+
case '}':
652+
if (!isInString)
653+
depth--;
654+
if (depth == 0)
655+
{
656+
elements.Add(arrayText.Substring(prevElementStart, cur - prevElementStart + 1));
657+
}
658+
break;
659+
case '"':
660+
if (!isInString)
661+
isInString = true;
662+
else if (!ignoreNext)
663+
isInString = false;
664+
break;
665+
case '\\':
666+
if (isInString)
667+
{
668+
ignoreNext = !ignoreNext;
669+
}
670+
break;
671+
default:
672+
ignoreNext = false;
673+
break;
674+
}
675+
++cur;
676+
}
677+
return elements;
678+
}
602679
}
603680
}

0 commit comments

Comments
 (0)