Hue Preserving Color Blending
TMP_SDFShaderGUI.cs
1 using UnityEngine;
2 using UnityEditor;
3 
4 namespace TMPro.EditorUtilities
5 {
7  {
8  static ShaderFeature s_OutlineFeature, s_UnderlayFeature, s_BevelFeature, s_GlowFeature, s_MaskFeature;
9 
10  static bool s_Face = true, s_Outline = true, s_Underlay, s_Lighting, s_Glow, s_Bevel, s_Light, s_Bump, s_Env;
11 
12  static string[]
13  s_FaceUvSpeedNames = { "_FaceUVSpeedX", "_FaceUVSpeedY" },
14  s_OutlineUvSpeedNames = { "_OutlineUVSpeedX", "_OutlineUVSpeedY" };
15 
16  static TMP_SDFShaderGUI()
17  {
18  s_OutlineFeature = new ShaderFeature()
19  {
20  undoLabel = "Outline",
21  keywords = new[] { "OUTLINE_ON" }
22  };
23 
24  s_UnderlayFeature = new ShaderFeature()
25  {
26  undoLabel = "Underlay",
27  keywords = new[] { "UNDERLAY_ON", "UNDERLAY_INNER" },
28  label = new GUIContent("Underlay Type"),
29  keywordLabels = new[]
30  {
31  new GUIContent("None"), new GUIContent("Normal"), new GUIContent("Inner")
32  }
33  };
34 
35  s_BevelFeature = new ShaderFeature()
36  {
37  undoLabel = "Bevel",
38  keywords = new[] { "BEVEL_ON" }
39  };
40 
41  s_GlowFeature = new ShaderFeature()
42  {
43  undoLabel = "Glow",
44  keywords = new[] { "GLOW_ON" }
45  };
46 
47  s_MaskFeature = new ShaderFeature()
48  {
49  undoLabel = "Mask",
50  keywords = new[] { "MASK_HARD", "MASK_SOFT" },
51  label = new GUIContent("Mask"),
52  keywordLabels = new[]
53  {
54  new GUIContent("Mask Off"), new GUIContent("Mask Hard"), new GUIContent("Mask Soft")
55  }
56  };
57  }
58 
59  protected override void DoGUI()
60  {
61  s_Face = BeginPanel("Face", s_Face);
62  if (s_Face)
63  {
64  DoFacePanel();
65  }
66 
67  EndPanel();
68 
69  s_Outline = m_Material.HasProperty(ShaderUtilities.ID_OutlineTex) ? BeginPanel("Outline", s_Outline) : BeginPanel("Outline", s_OutlineFeature, s_Outline);
70  if (s_Outline)
71  {
72  DoOutlinePanel();
73  }
74 
75  EndPanel();
76 
77  if (m_Material.HasProperty(ShaderUtilities.ID_UnderlayColor))
78  {
79  s_Underlay = BeginPanel("Underlay", s_UnderlayFeature, s_Underlay);
80  if (s_Underlay)
81  {
82  DoUnderlayPanel();
83  }
84 
85  EndPanel();
86  }
87 
88  if (m_Material.HasProperty("_SpecularColor"))
89  {
90  s_Lighting = BeginPanel("Lighting", s_BevelFeature, s_Lighting);
91  if (s_Lighting)
92  {
93  s_Bevel = BeginPanel("Bevel", s_Bevel);
94  if (s_Bevel)
95  {
96  DoBevelPanel();
97  }
98 
99  EndPanel();
100 
101  s_Light = BeginPanel("Local Lighting", s_Light);
102  if (s_Light)
103  {
104  DoLocalLightingPanel();
105  }
106 
107  EndPanel();
108 
109  s_Bump = BeginPanel("Bump Map", s_Bump);
110  if (s_Bump)
111  {
112  DoBumpMapPanel();
113  }
114 
115  EndPanel();
116 
117  s_Env = BeginPanel("Environment Map", s_Env);
118  if (s_Env)
119  {
120  DoEnvMapPanel();
121  }
122 
123  EndPanel();
124  }
125 
126  EndPanel();
127  }
128  else if (m_Material.HasProperty("_SpecColor"))
129  {
130  s_Bevel = BeginPanel("Bevel", s_Bevel);
131  if (s_Bevel)
132  {
133  DoBevelPanel();
134  }
135 
136  EndPanel();
137 
138  s_Light = BeginPanel("Surface Lighting", s_Light);
139  if (s_Light)
140  {
141  DoSurfaceLightingPanel();
142  }
143 
144  EndPanel();
145 
146  s_Bump = BeginPanel("Bump Map", s_Bump);
147  if (s_Bump)
148  {
149  DoBumpMapPanel();
150  }
151 
152  EndPanel();
153 
154  s_Env = BeginPanel("Environment Map", s_Env);
155  if (s_Env)
156  {
157  DoEnvMapPanel();
158  }
159 
160  EndPanel();
161  }
162 
163  if (m_Material.HasProperty(ShaderUtilities.ID_GlowColor))
164  {
165  s_Glow = BeginPanel("Glow", s_GlowFeature, s_Glow);
166  if (s_Glow)
167  {
168  DoGlowPanel();
169  }
170 
171  EndPanel();
172  }
173 
174  s_DebugExtended = BeginPanel("Debug Settings", s_DebugExtended);
175  if (s_DebugExtended)
176  {
177  DoDebugPanel();
178  }
179 
180  EndPanel();
181  }
182 
183  void DoFacePanel()
184  {
185  EditorGUI.indentLevel += 1;
186  DoColor("_FaceColor", "Color");
187  if (m_Material.HasProperty(ShaderUtilities.ID_FaceTex))
188  {
189  if (m_Material.HasProperty("_FaceUVSpeedX"))
190  {
191  DoTexture2D("_FaceTex", "Texture", true, s_FaceUvSpeedNames);
192  }
193  else
194  {
195  DoTexture2D("_FaceTex", "Texture", true);
196  }
197  }
198 
199  DoSlider("_OutlineSoftness", "Softness");
200  DoSlider("_FaceDilate", "Dilate");
201  if (m_Material.HasProperty(ShaderUtilities.ID_Shininess))
202  {
203  DoSlider("_FaceShininess", "Gloss");
204  }
205 
206  EditorGUI.indentLevel -= 1;
207  EditorGUILayout.Space();
208  }
209 
210  void DoOutlinePanel()
211  {
212  EditorGUI.indentLevel += 1;
213  DoColor("_OutlineColor", "Color");
214  if (m_Material.HasProperty(ShaderUtilities.ID_OutlineTex))
215  {
216  if (m_Material.HasProperty("_OutlineUVSpeedX"))
217  {
218  DoTexture2D("_OutlineTex", "Texture", true, s_OutlineUvSpeedNames);
219  }
220  else
221  {
222  DoTexture2D("_OutlineTex", "Texture", true);
223  }
224  }
225 
226  DoSlider("_OutlineWidth", "Thickness");
227  if (m_Material.HasProperty("_OutlineShininess"))
228  {
229  DoSlider("_OutlineShininess", "Gloss");
230  }
231 
232  EditorGUI.indentLevel -= 1;
233  EditorGUILayout.Space();
234  }
235 
236  void DoUnderlayPanel()
237  {
238  EditorGUI.indentLevel += 1;
239  s_UnderlayFeature.DoPopup(m_Editor, m_Material);
240  DoColor("_UnderlayColor", "Color");
241  DoSlider("_UnderlayOffsetX", "Offset X");
242  DoSlider("_UnderlayOffsetY", "Offset Y");
243  DoSlider("_UnderlayDilate", "Dilate");
244  DoSlider("_UnderlaySoftness", "Softness");
245  EditorGUI.indentLevel -= 1;
246  EditorGUILayout.Space();
247  }
248 
249  static GUIContent[] s_BevelTypeLabels =
250  {
251  new GUIContent("Outer Bevel"),
252  new GUIContent("Inner Bevel")
253  };
254 
255  void DoBevelPanel()
256  {
257  EditorGUI.indentLevel += 1;
258  DoPopup("_ShaderFlags", "Type", s_BevelTypeLabels);
259  DoSlider("_Bevel", "Amount");
260  DoSlider("_BevelOffset", "Offset");
261  DoSlider("_BevelWidth", "Width");
262  DoSlider("_BevelRoundness", "Roundness");
263  DoSlider("_BevelClamp", "Clamp");
264  EditorGUI.indentLevel -= 1;
265  EditorGUILayout.Space();
266  }
267 
268  void DoLocalLightingPanel()
269  {
270  EditorGUI.indentLevel += 1;
271  DoSlider("_LightAngle", "Light Angle");
272  DoColor("_SpecularColor", "Specular Color");
273  DoSlider("_SpecularPower", "Specular Power");
274  DoSlider("_Reflectivity", "Reflectivity Power");
275  DoSlider("_Diffuse", "Diffuse Shadow");
276  DoSlider("_Ambient", "Ambient Shadow");
277  EditorGUI.indentLevel -= 1;
278  EditorGUILayout.Space();
279  }
280 
281  void DoSurfaceLightingPanel()
282  {
283  EditorGUI.indentLevel += 1;
284  DoColor("_SpecColor", "Specular Color");
285  EditorGUI.indentLevel -= 1;
286  EditorGUILayout.Space();
287  }
288 
289  void DoBumpMapPanel()
290  {
291  EditorGUI.indentLevel += 1;
292  DoTexture2D("_BumpMap", "Texture");
293  DoSlider("_BumpFace", "Face");
294  DoSlider("_BumpOutline", "Outline");
295  EditorGUI.indentLevel -= 1;
296  EditorGUILayout.Space();
297  }
298 
299  void DoEnvMapPanel()
300  {
301  EditorGUI.indentLevel += 1;
302  DoColor("_ReflectFaceColor", "Face Color");
303  DoColor("_ReflectOutlineColor", "Outline Color");
304  DoCubeMap("_Cube", "Texture");
305  DoVector3("_EnvMatrixRotation", "Rotation");
306  EditorGUI.indentLevel -= 1;
307  EditorGUILayout.Space();
308  }
309 
310  void DoGlowPanel()
311  {
312  EditorGUI.indentLevel += 1;
313  DoColor("_GlowColor", "Color");
314  DoSlider("_GlowOffset", "Offset");
315  DoSlider("_GlowInner", "Inner");
316  DoSlider("_GlowOuter", "Outer");
317  DoSlider("_GlowPower", "Power");
318  EditorGUI.indentLevel -= 1;
319  EditorGUILayout.Space();
320  }
321 
322  void DoDebugPanel()
323  {
324  EditorGUI.indentLevel += 1;
325  DoTexture2D("_MainTex", "Font Atlas");
326  DoFloat("_GradientScale", "Gradient Scale");
327  DoFloat("_TextureWidth", "Texture Width");
328  DoFloat("_TextureHeight", "Texture Height");
329  EditorGUILayout.Space();
330  DoFloat("_ScaleX", "Scale X");
331  DoFloat("_ScaleY", "Scale Y");
332  DoSlider("_PerspectiveFilter", "Perspective Filter");
333  EditorGUILayout.Space();
334  DoFloat("_VertexOffsetX", "Offset X");
335  DoFloat("_VertexOffsetY", "Offset Y");
336 
337  if (m_Material.HasProperty(ShaderUtilities.ID_MaskCoord))
338  {
339  EditorGUILayout.Space();
340  s_MaskFeature.ReadState(m_Material);
341  s_MaskFeature.DoPopup(m_Editor, m_Material);
342  if (s_MaskFeature.Active)
343  {
344  DoMaskSubgroup();
345  }
346 
347  EditorGUILayout.Space();
348  DoVector("_ClipRect", "Clip Rect", s_LbrtVectorLabels);
349  }
350  else if (m_Material.HasProperty("_MaskTex"))
351  {
352  DoMaskTexSubgroup();
353  }
354  else if (m_Material.HasProperty(ShaderUtilities.ID_MaskSoftnessX))
355  {
356  EditorGUILayout.Space();
357  DoFloat("_MaskSoftnessX", "Softness X");
358  DoFloat("_MaskSoftnessY", "Softness Y");
359  DoVector("_ClipRect", "Clip Rect", s_LbrtVectorLabels);
360  }
361 
362  if (m_Material.HasProperty(ShaderUtilities.ID_StencilID))
363  {
364  EditorGUILayout.Space();
365  DoFloat("_Stencil", "Stencil ID");
366  DoFloat("_StencilComp", "Stencil Comp");
367  }
368 
369  EditorGUILayout.Space();
370 
371  EditorGUI.BeginChangeCheck();
372  bool useRatios = EditorGUILayout.Toggle("Use Ratios", !m_Material.IsKeywordEnabled("RATIOS_OFF"));
373  if (EditorGUI.EndChangeCheck())
374  {
375  m_Editor.RegisterPropertyChangeUndo("Use Ratios");
376  if (useRatios)
377  {
378  m_Material.DisableKeyword("RATIOS_OFF");
379  }
380  else
381  {
382  m_Material.EnableKeyword("RATIOS_OFF");
383  }
384  }
385 
386  EditorGUI.BeginDisabledGroup(true);
387  DoFloat("_ScaleRatioA", "Scale Ratio A");
388  DoFloat("_ScaleRatioB", "Scale Ratio B");
389  DoFloat("_ScaleRatioC", "Scale Ratio C");
390  EditorGUI.EndDisabledGroup();
391  EditorGUI.indentLevel -= 1;
392  EditorGUILayout.Space();
393  }
394 
395  void DoMaskSubgroup()
396  {
397  DoVector("_MaskCoord", "Mask Bounds", s_XywhVectorLabels);
398  if (Selection.activeGameObject != null)
399  {
400  Renderer renderer = Selection.activeGameObject.GetComponent<Renderer>();
401  if (renderer != null)
402  {
403  Rect rect = EditorGUILayout.GetControlRect();
404  rect.x += EditorGUIUtility.labelWidth;
405  rect.width -= EditorGUIUtility.labelWidth;
406  if (GUI.Button(rect, "Match Renderer Bounds"))
407  {
408  FindProperty("_MaskCoord", m_Properties).vectorValue = new Vector4(
409  0,
410  0,
411  Mathf.Round(renderer.bounds.extents.x * 1000) / 1000,
412  Mathf.Round(renderer.bounds.extents.y * 1000) / 1000
413  );
414  }
415  }
416  }
417 
418  if (s_MaskFeature.State == 1)
419  {
420  DoFloat("_MaskSoftnessX", "Softness X");
421  DoFloat("_MaskSoftnessY", "Softness Y");
422  }
423  }
424 
425  void DoMaskTexSubgroup()
426  {
427  EditorGUILayout.Space();
428  DoTexture2D("_MaskTex", "Mask Texture");
429  DoToggle("_MaskInverse", "Inverse Mask");
430  DoColor("_MaskEdgeColor", "Edge Color");
431  DoSlider("_MaskEdgeSoftness", "Edge Softness");
432  DoSlider("_MaskWipeControl", "Wipe Position");
433  DoFloat("_MaskSoftnessX", "Softness X");
434  DoFloat("_MaskSoftnessY", "Softness Y");
435  DoVector("_ClipRect", "Clip Rect", s_LbrtVectorLabels);
436  }
437  }
438 }
override void DoGUI()
Override this method to create the specific shader GUI.
Base class for TextMesh Pro shader GUIs.