Hue Preserving Color Blending
TMPro_ContextMenus.cs
1 using UnityEngine;
2 using UnityEditor;
3 using System.IO;
4 using System.Collections;
5 
6 
7 namespace TMPro.EditorUtilities
8 {
9 
10  public class TMP_ContextMenus : Editor
11  {
12 
13  private static Texture m_copiedTexture;
14 
15  private static Material m_copiedProperties;
16  private static Material m_copiedAtlasProperties;
17 
18 
19  // Add a Context Menu to the Texture Editor Panel to allow Copy / Paste of Texture.
20  [MenuItem("CONTEXT/Texture/Copy", false, 2000)]
21  static void CopyTexture(MenuCommand command)
22  {
23  m_copiedTexture = command.context as Texture;
24  }
25 
26 
27  // Select the currently assigned material or material preset.
28  [MenuItem("CONTEXT/Material/Select Material", false, 500)]
29  static void SelectMaterial(MenuCommand command)
30  {
31  Material mat = command.context as Material;
32 
33  // Select current material
34  EditorUtility.FocusProjectWindow();
35  EditorGUIUtility.PingObject(mat);
36  }
37 
38 
39  // Add a Context Menu to allow easy duplication of the Material.
40  [MenuItem("CONTEXT/Material/Create Material Preset", false)]
41  static void DuplicateMaterial(MenuCommand command)
42  {
43  // Get the type of text object
44  // If material is not a base material, we get material leaks...
45 
46  Material source_Mat = (Material)command.context;
47  if (!EditorUtility.IsPersistent(source_Mat))
48  {
49  Debug.LogWarning("Material is an instance and cannot be converted into a permanent asset.");
50  return;
51  }
52 
53 
54  string assetPath = AssetDatabase.GetAssetPath(source_Mat).Split('.')[0];
55 
56  Material duplicate = new Material(source_Mat);
57 
58  // Need to manually copy the shader keywords
59  duplicate.shaderKeywords = source_Mat.shaderKeywords;
60 
61  AssetDatabase.CreateAsset(duplicate, AssetDatabase.GenerateUniqueAssetPath(assetPath + ".mat"));
62 
63  // Assign duplicate Material to selected object (if one is)
64  if (Selection.activeGameObject != null)
65  {
66  TMP_Text textObject = Selection.activeGameObject.GetComponent<TMP_Text>();
67  if (textObject != null)
68  {
69  textObject.fontSharedMaterial = duplicate;
70  }
71  else
72  {
73  TMP_SubMesh subMeshObject = Selection.activeGameObject.GetComponent<TMP_SubMesh>();
74 
75  if (subMeshObject != null)
76  subMeshObject.sharedMaterial = duplicate;
77  else
78  {
79  TMP_SubMeshUI subMeshUIObject = Selection.activeGameObject.GetComponent<TMP_SubMeshUI>();
80 
81  if (subMeshUIObject != null)
82  subMeshUIObject.sharedMaterial = duplicate;
83  }
84  }
85  }
86 
87  // Ping newly created Material Preset.
88  EditorUtility.FocusProjectWindow();
89  EditorGUIUtility.PingObject(duplicate);
90  }
91 
92 
93  //[MenuItem("CONTEXT/MaterialComponent/Copy Material Properties", false)]
94  [MenuItem("CONTEXT/Material/Copy Material Properties", false)]
95  static void CopyMaterialProperties(MenuCommand command)
96  {
97  Material mat = null;
98  if (command.context.GetType() == typeof(Material))
99  mat = (Material)command.context;
100  else
101  {
102  mat = Selection.activeGameObject.GetComponent<CanvasRenderer>().GetMaterial();
103  }
104 
105  m_copiedProperties = new Material(mat);
106 
107  m_copiedProperties.shaderKeywords = mat.shaderKeywords;
108 
109  m_copiedProperties.hideFlags = HideFlags.DontSave;
110  }
111 
112 
113  // PASTE MATERIAL
114  //[MenuItem("CONTEXT/MaterialComponent/Paste Material Properties", false)]
115  [MenuItem("CONTEXT/Material/Paste Material Properties", false)]
116  static void PasteMaterialProperties(MenuCommand command)
117  {
118 
119  if (m_copiedProperties == null)
120  {
121  Debug.LogWarning("No Material Properties to Paste. Use Copy Material Properties first.");
122  return;
123  }
124 
125  Material mat = null;
126  if (command.context.GetType() == typeof(Material))
127  mat = (Material)command.context;
128  else
129  {
130  mat = Selection.activeGameObject.GetComponent<CanvasRenderer>().GetMaterial();
131  }
132 
133  Undo.RecordObject(mat, "Paste Material");
134 
135  ShaderUtilities.GetShaderPropertyIDs(); // Make sure we have valid Property IDs
136  if (mat.HasProperty(ShaderUtilities.ID_GradientScale))
137  {
138  // Preserve unique SDF properties from destination material.
139  m_copiedProperties.SetTexture(ShaderUtilities.ID_MainTex, mat.GetTexture(ShaderUtilities.ID_MainTex));
140  m_copiedProperties.SetFloat(ShaderUtilities.ID_GradientScale, mat.GetFloat(ShaderUtilities.ID_GradientScale));
141  m_copiedProperties.SetFloat(ShaderUtilities.ID_TextureWidth, mat.GetFloat(ShaderUtilities.ID_TextureWidth));
142  m_copiedProperties.SetFloat(ShaderUtilities.ID_TextureHeight, mat.GetFloat(ShaderUtilities.ID_TextureHeight));
143  }
144 
145  EditorShaderUtilities.CopyMaterialProperties(m_copiedProperties, mat);
146 
147  // Copy ShaderKeywords from one material to the other.
148  mat.shaderKeywords = m_copiedProperties.shaderKeywords;
149 
150  // Let TextMeshPro Objects that this mat has changed.
151  TMPro_EventManager.ON_MATERIAL_PROPERTY_CHANGED(true, mat);
152  }
153 
154 
155  // Enable Resetting of Material properties without losing unique properties of the font atlas.
156  //[MenuItem("CONTEXT/MaterialComponent/Reset", false, 2100)]
157  [MenuItem("CONTEXT/Material/Reset", false, 2100)]
158  static void ResetSettings(MenuCommand command)
159  {
160 
161  Material mat = null;
162  if (command.context.GetType() == typeof(Material))
163  mat = (Material)command.context;
164  else
165  {
166  mat = Selection.activeGameObject.GetComponent<CanvasRenderer>().GetMaterial();
167  }
168 
169  Undo.RecordObject(mat, "Reset Material");
170 
171  ShaderUtilities.GetShaderPropertyIDs(); // Make sure we have valid Property IDs
172  if (mat.HasProperty(ShaderUtilities.ID_GradientScale))
173  {
174  // Copy unique properties of the SDF Material
175  var texture = mat.GetTexture(ShaderUtilities.ID_MainTex);
176  var gradientScale = mat.GetFloat(ShaderUtilities.ID_GradientScale);
177  var texWidth = mat.GetFloat(ShaderUtilities.ID_TextureWidth);
178  var texHeight = mat.GetFloat(ShaderUtilities.ID_TextureHeight);
179  var stencilId = mat.GetFloat(ShaderUtilities.ID_StencilID);
180  var stencilComp = mat.GetFloat(ShaderUtilities.ID_StencilComp);
181  var normalWeight = mat.GetFloat(ShaderUtilities.ID_WeightNormal);
182  var boldWeight = mat.GetFloat(ShaderUtilities.ID_WeightBold);
183 
184  // Reset the material
185  Unsupported.SmartReset(mat);
186 
187  // Reset ShaderKeywords
188  mat.shaderKeywords = new string[0]; // { "BEVEL_OFF", "GLOW_OFF", "UNDERLAY_OFF" };
189 
190  // Copy unique material properties back to the material.
191  mat.SetTexture(ShaderUtilities.ID_MainTex, texture);
192  mat.SetFloat(ShaderUtilities.ID_GradientScale, gradientScale);
193  mat.SetFloat(ShaderUtilities.ID_TextureWidth, texWidth);
194  mat.SetFloat(ShaderUtilities.ID_TextureHeight, texHeight);
195  mat.SetFloat(ShaderUtilities.ID_StencilID, stencilId);
196  mat.SetFloat(ShaderUtilities.ID_StencilComp, stencilComp);
197  mat.SetFloat(ShaderUtilities.ID_WeightNormal, normalWeight);
198  mat.SetFloat(ShaderUtilities.ID_WeightBold, boldWeight);
199  }
200  else
201  {
202  Unsupported.SmartReset(mat);
203  }
204 
205  TMPro_EventManager.ON_MATERIAL_PROPERTY_CHANGED(true, mat);
206  }
207 
208 
209 
210  //This function is used for debugging and fixing potentially broken font atlas links.
211  [MenuItem("CONTEXT/Material/Copy Atlas", false, 2000)]
212  static void CopyAtlas(MenuCommand command)
213  {
214  Material mat = command.context as Material;
215 
216  m_copiedAtlasProperties = new Material(mat);
217  m_copiedAtlasProperties.hideFlags = HideFlags.DontSave;
218  }
219 
220 
221  // This function is used for debugging and fixing potentially broken font atlas links
222  [MenuItem("CONTEXT/Material/Paste Atlas", false, 2001)]
223  static void PasteAtlas(MenuCommand command)
224  {
225  Material mat = command.context as Material;
226 
227  if (m_copiedAtlasProperties != null)
228  {
229  Undo.RecordObject(mat, "Paste Texture");
230 
231  ShaderUtilities.GetShaderPropertyIDs(); // Make sure we have valid Property IDs
232  mat.SetTexture(ShaderUtilities.ID_MainTex, m_copiedAtlasProperties.GetTexture(ShaderUtilities.ID_MainTex));
233  mat.SetFloat(ShaderUtilities.ID_GradientScale, m_copiedAtlasProperties.GetFloat(ShaderUtilities.ID_GradientScale));
234  mat.SetFloat(ShaderUtilities.ID_TextureWidth, m_copiedAtlasProperties.GetFloat(ShaderUtilities.ID_TextureWidth));
235  mat.SetFloat(ShaderUtilities.ID_TextureHeight, m_copiedAtlasProperties.GetFloat(ShaderUtilities.ID_TextureHeight));
236  }
237  else if (m_copiedTexture != null)
238  {
239  Undo.RecordObject(mat, "Paste Texture");
240 
241  mat.SetTexture(ShaderUtilities.ID_MainTex, m_copiedTexture);
242  }
243 
244  //DestroyImmediate(m_copiedAtlasProperties);
245  }
246 
247  // Context Menus for TMPro Font Assets
248  //This function is used for debugging and fixing potentially broken font atlas links.
249  [MenuItem("CONTEXT/TMP_FontAsset/Extract Atlas", false, 2100)]
250  static void ExtractAtlas(MenuCommand command)
251  {
252  TMP_FontAsset font = command.context as TMP_FontAsset;
253 
254  string fontPath = AssetDatabase.GetAssetPath(font);
255  string texPath = Path.GetDirectoryName(fontPath) + "/" + Path.GetFileNameWithoutExtension(fontPath) + " Atlas.png";
256 
257  // Create a Serialized Object of the texture to allow us to make it readable.
258  SerializedObject texprop = new SerializedObject(font.material.GetTexture(ShaderUtilities.ID_MainTex));
259  texprop.FindProperty("m_IsReadable").boolValue = true;
260  texprop.ApplyModifiedProperties();
261 
262  // Create a copy of the texture.
263  Texture2D tex = Instantiate(font.material.GetTexture(ShaderUtilities.ID_MainTex)) as Texture2D;
264 
265  // Set the texture to not readable again.
266  texprop.FindProperty("m_IsReadable").boolValue = false;
267  texprop.ApplyModifiedProperties();
268 
269  Debug.Log(texPath);
270  // Saving File for Debug
271  var pngData = tex.EncodeToPNG();
272  File.WriteAllBytes(texPath, pngData);
273 
274  AssetDatabase.Refresh();
275  DestroyImmediate(tex);
276  }
277 
282  [MenuItem("CONTEXT/TMP_FontAsset/Update Atlas Texture...", false, 2000)]
283  static void RegenerateFontAsset(MenuCommand command)
284  {
285  TMP_FontAsset fontAsset = command.context as TMP_FontAsset;
286 
287  if (fontAsset != null)
288  {
289  TMPro_FontAssetCreatorWindow.ShowFontAtlasCreatorWindow(fontAsset);
290  }
291  }
292 
293 
294  [MenuItem("CONTEXT/TrueTypeFontImporter/Create TMP Font Asset...", false, 200)]
295  static void CreateFontAsset(MenuCommand command)
296  {
297  TrueTypeFontImporter importer = command.context as TrueTypeFontImporter;
298 
299  if (importer != null)
300  {
301  Font sourceFontFile = AssetDatabase.LoadAssetAtPath<Font>(importer.assetPath);
302 
303  if (sourceFontFile)
304  TMPro_FontAssetCreatorWindow.ShowFontAtlasCreatorWindow(sourceFontFile);
305  }
306  }
307  }
308 }
static void RegenerateFontAsset(MenuCommand command)
Base class which contains common properties and functions shared between the TextMeshPro and TextMesh...
Definition: TMP_Text.cs:110
Material sharedMaterial
The material to be assigned to this text object.
Definition: TMP_SubMesh.cs:69
Material material
The material used by this asset.
Definition: TMP_Asset.cs:18
virtual Material fontSharedMaterial
The material to be assigned to this text object.
Definition: TMP_Text.cs:155
Material sharedMaterial
The material to be assigned to this text object.