Skip to content

Commit 9676b16

Browse files
FredMoreauEvergreen
authored andcommitted
[SG] Custom Includes, Pragmas and Defines
1 parent b8f4071 commit 9676b16

7 files changed

Lines changed: 389 additions & 81 deletions

File tree

Packages/com.unity.shadergraph/Editor/Data/Graphs/GraphData.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,49 @@ public GraphPrecision graphDefaultPrecision
335335
}
336336
}
337337

338+
#region Custom Graph Settings
339+
[SerializeField]
340+
internal List<string> m_CustomPragmas = new();
341+
342+
[Serializable]
343+
internal struct CustomDefineDescriptor
344+
{
345+
[SerializeField] string m_Define;
346+
[SerializeField] bool m_Enabled;
347+
348+
public CustomDefineDescriptor(string define)
349+
{
350+
this.m_Define = define;
351+
this.m_Enabled = true;
352+
}
353+
354+
public string Define { get => m_Define; set => m_Define = value; }
355+
public bool Enabled { get => m_Enabled; set => m_Enabled = value; }
356+
public bool IsValid => !String.IsNullOrEmpty(m_Define);
357+
}
358+
359+
[SerializeField]
360+
internal List<CustomDefineDescriptor> m_CustomDefines = new();
361+
362+
[Serializable]
363+
internal struct CustomIncludeDescriptor
364+
{
365+
[SerializeField] ShaderInclude m_Include;
366+
[SerializeField] bool m_IncludeWithPragmas;
367+
368+
public static implicit operator IncludeDescriptor(CustomIncludeDescriptor incl) =>
369+
new IncludeDescriptor(AssetDatabase.AssetPathToGUID(incl.IncludePath), incl.IncludePath, IncludeLocation.Graph, new FieldCondition[0] { }, incl.IncludeWithPragmas);
370+
371+
public ShaderInclude Include { get => m_Include; set => m_Include = value; }
372+
public string IncludePath => AssetDatabase.GetAssetPath(m_Include);
373+
public bool IncludeWithPragmas { get => m_IncludeWithPragmas; set => m_IncludeWithPragmas = value; }
374+
public bool IsValid => m_Include != null;
375+
}
376+
377+
[SerializeField]
378+
internal List<CustomIncludeDescriptor> m_CustomIncludes = new();
379+
#endregion // Custom Graph Settings
380+
338381
public ConcretePrecision graphDefaultConcretePrecision
339382
{
340383
get
@@ -2071,6 +2114,11 @@ public void ReplaceWith(GraphData other)
20712114
m_PreviewMode = other.m_PreviewMode;
20722115
m_OutputNode = other.m_OutputNode;
20732116

2117+
m_CustomPragmas.CopyFrom(other.m_CustomPragmas);
2118+
m_CustomDefines.CopyFrom(other.m_CustomDefines);
2119+
m_CustomIncludes.CopyFrom(other.m_CustomIncludes);
2120+
m_SubDatas.CopyFrom(other.m_SubDatas);
2121+
20742122
if ((this.vertexContext.position != other.vertexContext.position) ||
20752123
(this.fragmentContext.position != other.fragmentContext.position))
20762124
{

Packages/com.unity.shadergraph/Editor/Drawing/Inspector/PropertyDrawers/GraphDataPropertyDrawer.cs

Lines changed: 222 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using UnityEngine.UIElements;
1111
using UnityEditorInternal;
1212
using UnityEditor.ShaderGraph.Serialization;
13+
using System.Text.RegularExpressions;
1314

1415
namespace UnityEditor.ShaderGraph.Drawing.Inspector.PropertyDrawers
1516
{
@@ -18,21 +19,237 @@ public class GraphDataPropertyDrawer : IPropertyDrawer
1819
{
1920
public delegate void ChangeGraphDefaultPrecisionCallback(GraphPrecision newDefaultGraphPrecision);
2021
public delegate void PostTargetSettingsChangedCallback();
22+
internal delegate void GraphSettingsChangedCallback();
2123

24+
GraphSettingsChangedCallback m_changeGraphSettingsCallback;
2225
PostTargetSettingsChangedCallback m_postChangeTargetSettingsCallback;
2326
ChangeGraphDefaultPrecisionCallback m_changeGraphDefaultPrecisionCallback;
2427

28+
bool m_AdvancedSettingsFoldout;
29+
const string customPragmaTooltip = @"The following pragmas will be added in the given order, after other pragmas.
30+
Enter what comes after '#pragma' (e.g.: enable_debug_symbols or use_dxc)";
31+
const string customDefineTooltip = @"The following defines will be added in the given order, after other graph defines.
32+
Enter what comes after '#define' (e.g.: _DEBUG or MAX_STEPS 32 // your comments.)
33+
Uncheck the checkbox to temporarily disable the define.";
34+
const string customIncludeTooltip = @"The following hlsl files will be included in the given order, prior to other graph includes (e.g.: Custom Function Nodes).";
35+
2536
Dictionary<Target, bool> m_TargetFoldouts = new Dictionary<Target, bool>();
2637
Dictionary<AbstractShaderGraphDataExtension, bool> m_SubDataFoldouts = new Dictionary<AbstractShaderGraphDataExtension, bool>();
2738

28-
public void GetPropertyData(
39+
internal void GetPropertyData(
2940
PostTargetSettingsChangedCallback postChangeValueCallback,
41+
GraphSettingsChangedCallback changeGraphSettingsCallback,
3042
ChangeGraphDefaultPrecisionCallback changeGraphDefaultPrecisionCallback)
3143
{
3244
m_postChangeTargetSettingsCallback = postChangeValueCallback;
45+
m_changeGraphSettingsCallback = changeGraphSettingsCallback;
3346
m_changeGraphDefaultPrecisionCallback = changeGraphDefaultPrecisionCallback;
3447
}
3548

49+
VisualElement GetAdvancedSettings(GraphData graphData, Action onChange)
50+
{
51+
var element = new VisualElement() { name = "advGraphSettings" };
52+
53+
void RegisterActionToUndo(string actionName)
54+
{
55+
graphData.owner.RegisterCompleteObjectUndo(actionName);
56+
}
57+
58+
// Advanced Settings
59+
var advancedSettingsFoldout = new Foldout() { text = "Preprocessor Directives", value = m_AdvancedSettingsFoldout, name = "advGraphSettings" };
60+
advancedSettingsFoldout.style.unityFontStyleAndWeight = FontStyle.Bold;
61+
element.Add(advancedSettingsFoldout);
62+
advancedSettingsFoldout.AddToClassList("MainFoldout");
63+
advancedSettingsFoldout.RegisterValueChangedCallback(evt =>
64+
{
65+
m_AdvancedSettingsFoldout = evt.newValue;
66+
advancedSettingsFoldout.value = evt.newValue;
67+
onChange();
68+
});
69+
70+
if (advancedSettingsFoldout.value)
71+
{
72+
var advancedSettingsElement = new VisualElement();
73+
element.Add(advancedSettingsElement);
74+
75+
// Custom Pragmas
76+
var customPragmasList = new ReorderableListView<string>(
77+
graphData.m_CustomPragmas,
78+
new GUIContent("Pragmas", customPragmaTooltip));
79+
80+
customPragmasList.OnBeforeChangeCallback +=
81+
(ReorderableListView<string>.ListActionType changeType) =>
82+
{
83+
RegisterActionToUndo($"{changeType} Pragma");
84+
};
85+
86+
customPragmasList.OnChangeCallback +=
87+
(ReorderableListView<string>.ListActionType changeType) =>
88+
{
89+
onChange();
90+
};
91+
92+
customPragmasList.DrawItemCallback += (Rect rect, int idx) =>
93+
{
94+
EditorGUI.BeginChangeCheck();
95+
var data = graphData.m_CustomPragmas[idx];
96+
data = EditorGUI.DelayedTextField(rect, "", data);
97+
98+
if (EditorGUI.EndChangeCheck())
99+
{
100+
RegisterActionToUndo("Change Pragma");
101+
data = ValidatePragma(data);
102+
graphData.m_CustomPragmas[idx] = data;
103+
onChange();
104+
}
105+
};
106+
107+
advancedSettingsElement.Add(customPragmasList);
108+
109+
// Custom Defines
110+
var customDefineList = new ReorderableListView<GraphData.CustomDefineDescriptor>(
111+
graphData.m_CustomDefines,
112+
new GUIContent("Local Defines", customDefineTooltip));
113+
114+
customDefineList.OnNewItemCallback += () => new GraphData.CustomDefineDescriptor("_DEFINE");
115+
116+
customDefineList.OnBeforeChangeCallback +=
117+
(ReorderableListView<GraphData.CustomDefineDescriptor>.ListActionType changeType) =>
118+
{
119+
RegisterActionToUndo($"{changeType} Local Define");
120+
};
121+
122+
customDefineList.OnChangeCallback +=
123+
(ReorderableListView<GraphData.CustomDefineDescriptor>.ListActionType changeType) =>
124+
{
125+
onChange();
126+
};
127+
128+
customDefineList.DrawItemCallback += (Rect rect, int idx) =>
129+
{
130+
Rect objectFieldRect = new Rect(rect.x, rect.y, rect.width - 24, rect.height);
131+
Rect toggleRect = new Rect(objectFieldRect.max.x+8, rect.y, 24, rect.height);
132+
133+
var data = graphData.m_CustomDefines[idx];
134+
135+
EditorGUI.BeginChangeCheck();
136+
data.Define = EditorGUI.DelayedTextField(objectFieldRect, new GUIContent("", ""), data.Define);
137+
data.Enabled = EditorGUI.ToggleLeft(toggleRect, "", data.Enabled);
138+
139+
if (EditorGUI.EndChangeCheck())
140+
{
141+
RegisterActionToUndo("Change Local Define");
142+
data.Define = ValidateDefine(data.Define);
143+
graphData.m_CustomDefines[idx] = data;
144+
onChange();
145+
}
146+
};
147+
148+
advancedSettingsElement.Add(customDefineList);
149+
150+
// Custom Includes
151+
var customIncludeList = new ReorderableListView<GraphData.CustomIncludeDescriptor>(
152+
graphData.m_CustomIncludes,
153+
new GUIContent("Graph Includes", customIncludeTooltip));
154+
155+
customIncludeList.OnNewItemCallback += () => new GraphData.CustomIncludeDescriptor();
156+
157+
customIncludeList.OnBeforeChangeCallback +=
158+
(ReorderableListView<GraphData.CustomIncludeDescriptor>.ListActionType changeType) =>
159+
{
160+
RegisterActionToUndo($"{changeType} Graph Include");
161+
};
162+
163+
customIncludeList.OnChangeCallback +=
164+
(ReorderableListView<GraphData.CustomIncludeDescriptor>.ListActionType changeType) =>
165+
{
166+
onChange();
167+
};
168+
169+
customIncludeList.DrawItemCallback += (Rect rect, int idx) =>
170+
{
171+
const float labelWidth = 85f;
172+
Rect objectFieldRect = new Rect(rect.x, rect.y, rect.width - (labelWidth + 24), rect.height);
173+
Rect toggleRect = new Rect(objectFieldRect.max.x + 8, rect.y, labelWidth + 24, rect.height);
174+
175+
EditorGUI.BeginChangeCheck();
176+
var data = graphData.m_CustomIncludes[idx];
177+
var previousLabelWidth = EditorGUIUtility.labelWidth;
178+
EditorGUIUtility.labelWidth = labelWidth;
179+
data.Include = (ShaderInclude)EditorGUI.ObjectField(objectFieldRect, "", data.Include, typeof(ShaderInclude), false);
180+
data.IncludeWithPragmas = EditorGUI.Toggle(toggleRect, new GUIContent("with pragmas", "Should the pragma directives in the include also be included."), data.IncludeWithPragmas);
181+
EditorGUIUtility.labelWidth = previousLabelWidth;
182+
if (EditorGUI.EndChangeCheck())
183+
{
184+
RegisterActionToUndo("Change Graph Include");
185+
graphData.m_CustomIncludes[idx] = data;
186+
onChange();
187+
}
188+
};
189+
190+
advancedSettingsElement.Add(customIncludeList);
191+
}
192+
193+
return element;
194+
}
195+
196+
static string ValidatePragma(string input)
197+
{
198+
if (string.IsNullOrWhiteSpace(input))
199+
return "";
200+
201+
if (input.StartsWith("#pragma "))
202+
return input.Replace("#pragma ", "");
203+
204+
return input;
205+
}
206+
207+
static string ValidateDefine(string input)
208+
{
209+
if (string.IsNullOrWhiteSpace(input))
210+
return "";
211+
212+
if (input.StartsWith("#define "))
213+
input = input.Replace("#define ", "");
214+
215+
// Split comment
216+
string comment = "";
217+
var commentMatch = Regex.Match(input, @"//.*$");
218+
if (commentMatch.Success)
219+
{
220+
comment = commentMatch.Value;
221+
input = input.Substring(0, commentMatch.Index);
222+
}
223+
224+
// Normalize whitespace
225+
input = Regex.Replace(input, @"\s+", " ").Trim();
226+
227+
var parts = input.Split(' ', StringSplitOptions.RemoveEmptyEntries);
228+
229+
if (parts.Length == 0)
230+
return "";
231+
232+
// Clean NAME
233+
string name = Regex.Replace(parts[0], @"[^A-Za-z0-9_]", "");
234+
if (Regex.IsMatch(name, @"^[0-9]"))
235+
name = "_" + name;
236+
237+
// Clean VALUE
238+
string value = "";
239+
if (parts.Length > 1)
240+
value = Regex.Replace(parts[1], @"[^A-Za-z0-9_]", "");
241+
242+
// Rebuild
243+
string result = name;
244+
if (!string.IsNullOrEmpty(value))
245+
result += " " + value;
246+
247+
if (!string.IsNullOrEmpty(comment))
248+
result += " " + comment;
249+
250+
return result;
251+
}
252+
36253
VisualElement GetSettings(GraphData graphData, Action onChange)
37254
{
38255
var element = new VisualElement() { name = "graphSettings" };
@@ -45,7 +262,7 @@ void RegisterActionToUndo(string actionName)
45262
graphData.owner.RegisterCompleteObjectUndo(actionName);
46263
}
47264

48-
// Add Label
265+
// Targets
49266
var targetSettingsLabel = new Label("Target Settings");
50267
targetSettingsLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
51268
element.Add(new PropertyRow(targetSettingsLabel));
@@ -256,6 +473,9 @@ internal VisualElement CreateGUI(GraphData graphData)
256473

257474
propertySheet.Add(GetSettings(graphData, () => this.m_postChangeTargetSettingsCallback()));
258475

476+
if (!graphData.isSubGraph)
477+
propertySheet.Add(GetAdvancedSettings(graphData, () => this.m_changeGraphSettingsCallback()));
478+
259479
return propertySheet;
260480
}
261481

Packages/com.unity.shadergraph/Editor/Drawing/Inspector/PropertyDrawers/SwitchNodePropertyDrawer.cs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
using System;
22
using UnityEditor.Graphing;
3-
using UnityEngine.UIElements;
43
using UnityEngine;
5-
using System.Collections.Generic;
4+
using UnityEngine.UIElements;
65

76
namespace UnityEditor.ShaderGraph.Drawing.Inspector.PropertyDrawers
87
{
@@ -33,17 +32,23 @@ internal override void AddCustomNodeProperties(VisualElement parentElement, Abst
3332
return;
3433

3534
var listView = new ReorderableListView<SwitchNode.EntryCase>(node.m_cases, "Conditions");
36-
listView.InitializeItemCallback += (List<SwitchNode.EntryCase> List) =>
37-
{
38-
return new SwitchNode.EntryCase { comparisonType = ComparisonType.Equal, threshold = List.Count };
39-
};
4035

41-
listView.ValueChangedCallback += (List<SwitchNode.EntryCase> list) =>
42-
{
43-
node.owner.owner.RegisterCompleteObjectUndo("switch Entry List Change");
44-
node.Dirty(ModificationScope.Topological);
45-
node.UpdateNodeAfterDeserialization();
46-
};
36+
listView.OnNewItemCallback +=
37+
() => new SwitchNode.EntryCase { comparisonType = ComparisonType.Equal, threshold = node.m_cases.Count };
38+
39+
listView.OnBeforeChangeCallback +=
40+
(ReorderableListView<SwitchNode.EntryCase>.ListActionType changeType) =>
41+
{
42+
node.owner.owner.RegisterCompleteObjectUndo($"{changeType} Switch Condition");
43+
};
44+
45+
listView.OnChangeCallback +=
46+
(ReorderableListView<SwitchNode.EntryCase>.ListActionType changeType) =>
47+
{
48+
node.Dirty(ModificationScope.Topological);
49+
node.UpdateNodeAfterDeserialization();
50+
inspectorUpdateDelegate();
51+
};
4752

4853
listView.DrawItemCallback += (Rect rect, int idx) =>
4954
{

0 commit comments

Comments
 (0)