1010using UnityEngine . UIElements ;
1111using UnityEditorInternal ;
1212using UnityEditor . ShaderGraph . Serialization ;
13+ using System . Text . RegularExpressions ;
1314
1415namespace 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
0 commit comments