698 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			698 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using UnityEngine; | |||
|  | using UnityEditor; | |||
|  | 
 | |||
|  | namespace TMPro.EditorUtilities | |||
|  | { | |||
|  |     /// <summary>Base class for TextMesh Pro shader GUIs.</summary> | |||
|  |     public abstract class TMP_BaseShaderGUI : ShaderGUI | |||
|  |     { | |||
|  |         /// <summary>Representation of a #pragma shader_feature.</summary> | |||
|  |         /// <description>It is assumed that the first feature option is for no keyword (underscores).</description> | |||
|  |         protected class ShaderFeature | |||
|  |         { | |||
|  |             public string undoLabel; | |||
|  | 
 | |||
|  |             public GUIContent label; | |||
|  | 
 | |||
|  |             /// <summary>The keyword labels, for display. Include the no-keyword as the first option.</summary> | |||
|  |             public GUIContent[] keywordLabels; | |||
|  | 
 | |||
|  |             /// <summary>The shader keywords. Exclude the no-keyword option.</summary> | |||
|  |             public string[] keywords; | |||
|  | 
 | |||
|  |             int m_State; | |||
|  | 
 | |||
|  |             public bool Active | |||
|  |             { | |||
|  |                 get { return m_State >= 0; } | |||
|  |             } | |||
|  | 
 | |||
|  |             public int State | |||
|  |             { | |||
|  |                 get { return m_State; } | |||
|  |             } | |||
|  | 
 | |||
|  |             public void ReadState(Material material) | |||
|  |             { | |||
|  |                 for (int i = 0; i < keywords.Length; i++) | |||
|  |                 { | |||
|  |                     if (material.IsKeywordEnabled(keywords[i])) | |||
|  |                     { | |||
|  |                         m_State = i; | |||
|  |                         return; | |||
|  |                     } | |||
|  |                 } | |||
|  | 
 | |||
|  |                 m_State = -1; | |||
|  |             } | |||
|  | 
 | |||
|  |             public void SetActive(bool active, Material material) | |||
|  |             { | |||
|  |                 m_State = active ? 0 : -1; | |||
|  |                 SetStateKeywords(material); | |||
|  |             } | |||
|  | 
 | |||
|  |             public void DoPopup(MaterialEditor editor, Material material) | |||
|  |             { | |||
|  |                 EditorGUI.BeginChangeCheck(); | |||
|  |                 int selection = EditorGUILayout.Popup(label, m_State + 1, keywordLabels); | |||
|  |                 if (EditorGUI.EndChangeCheck()) | |||
|  |                 { | |||
|  |                     m_State = selection - 1; | |||
|  |                     editor.RegisterPropertyChangeUndo(undoLabel); | |||
|  |                     SetStateKeywords(material); | |||
|  |                 } | |||
|  |             } | |||
|  | 
 | |||
|  |             void SetStateKeywords(Material material) | |||
|  |             { | |||
|  |                 for (int i = 0; i < keywords.Length; i++) | |||
|  |                 { | |||
|  |                     if (i == m_State) | |||
|  |                     { | |||
|  |                         material.EnableKeyword(keywords[i]); | |||
|  |                     } | |||
|  |                     else | |||
|  |                     { | |||
|  |                         material.DisableKeyword(keywords[i]); | |||
|  |                     } | |||
|  |                 } | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         static GUIContent s_TempLabel = new GUIContent(); | |||
|  | 
 | |||
|  |         protected static bool s_DebugExtended; | |||
|  | 
 | |||
|  |         static int s_UndoRedoCount, s_LastSeenUndoRedoCount; | |||
|  | 
 | |||
|  |         static float[][] s_TempFloats = | |||
|  |         { | |||
|  |             null, new float[1], new float[2], new float[3], new float[4] | |||
|  |         }; | |||
|  | 
 | |||
|  |         protected static GUIContent[] s_XywhVectorLabels = | |||
|  |         { | |||
|  |             new GUIContent("X"), | |||
|  |             new GUIContent("Y"), | |||
|  |             new GUIContent("W", "Width"), | |||
|  |             new GUIContent("H", "Height") | |||
|  |         }; | |||
|  | 
 | |||
|  |         protected static GUIContent[] s_LbrtVectorLabels = | |||
|  |         { | |||
|  |             new GUIContent("L", "Left"), | |||
|  |             new GUIContent("B", "Bottom"), | |||
|  |             new GUIContent("R", "Right"), | |||
|  |             new GUIContent("T", "Top") | |||
|  |         }; | |||
|  | 
 | |||
|  |         protected static GUIContent[] s_CullingTypeLabels = | |||
|  |         { | |||
|  |             new GUIContent("Off"), | |||
|  |             new GUIContent("Front"), | |||
|  |             new GUIContent("Back") | |||
|  |         }; | |||
|  | 
 | |||
|  |         static TMP_BaseShaderGUI() | |||
|  |         { | |||
|  |             // Keep track of how many undo/redo events happened. | |||
|  |             Undo.undoRedoPerformed += () => s_UndoRedoCount += 1; | |||
|  |         } | |||
|  | 
 | |||
|  |         bool m_IsNewGUI = true; | |||
|  | 
 | |||
|  |         float m_DragAndDropMinY; | |||
|  | 
 | |||
|  |         protected MaterialEditor m_Editor; | |||
|  | 
 | |||
|  |         protected Material m_Material; | |||
|  |         private int m_ShaderID; | |||
|  | 
 | |||
|  |         protected MaterialProperty[] m_Properties; | |||
|  | 
 | |||
|  |         void PrepareGUI() | |||
|  |         { | |||
|  |             m_IsNewGUI = false; | |||
|  |             ShaderUtilities.GetShaderPropertyIDs(); | |||
|  | 
 | |||
|  |             // New GUI just got constructed. This happens in response to a selection, | |||
|  |             // but also after undo/redo events. | |||
|  |             if (s_LastSeenUndoRedoCount != s_UndoRedoCount) | |||
|  |             { | |||
|  |                 // There's been at least one undo/redo since the last time this GUI got constructed. | |||
|  |                 // Maybe the undo/redo was for this material? Assume that is was. | |||
|  |                 TMPro_EventManager.ON_MATERIAL_PROPERTY_CHANGED(true, m_Material); | |||
|  |             } | |||
|  | 
 | |||
|  |             s_LastSeenUndoRedoCount = s_UndoRedoCount; | |||
|  |         } | |||
|  | 
 | |||
|  |         public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) | |||
|  |         { | |||
|  |             m_Editor = materialEditor; | |||
|  |             m_Material = materialEditor.target as Material; | |||
|  |             this.m_Properties = properties; | |||
|  | 
 | |||
|  |             if (m_IsNewGUI) | |||
|  |                 PrepareGUI(); | |||
|  | 
 | |||
|  |             DoDragAndDropBegin(); | |||
|  |             EditorGUI.BeginChangeCheck(); | |||
|  |             DoGUI(); | |||
|  |             if (EditorGUI.EndChangeCheck()) | |||
|  |             { | |||
|  |                 TMPro_EventManager.ON_MATERIAL_PROPERTY_CHANGED(true, m_Material); | |||
|  |             } | |||
|  | 
 | |||
|  |             DoDragAndDropEnd(); | |||
|  |         } | |||
|  | 
 | |||
|  |         public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader) | |||
|  |         { | |||
|  |             base.AssignNewShaderToMaterial(material, oldShader, newShader); | |||
|  | 
 | |||
|  |             TMPro_EventManager.ON_MATERIAL_PROPERTY_CHANGED(true, material); | |||
|  |         } | |||
|  | 
 | |||
|  |         /// <summary>Override this method to create the specific shader GUI.</summary> | |||
|  |         protected abstract void DoGUI(); | |||
|  | 
 | |||
|  |         static string[] s_PanelStateLabel = new string[] { "\t- <i>Click to collapse</i> -", "\t- <i>Click to expand</i>  -" }; | |||
|  | 
 | |||
|  |         protected bool BeginPanel(string panel, bool expanded) | |||
|  |         { | |||
|  |             EditorGUI.indentLevel = 0; | |||
|  | 
 | |||
|  |             EditorGUILayout.BeginVertical(EditorStyles.helpBox); | |||
|  |             Rect r = EditorGUI.IndentedRect(GUILayoutUtility.GetRect(20, 18)); | |||
|  |             r.x += 20; | |||
|  |             r.width += 6; | |||
|  | 
 | |||
|  |             bool enabled = GUI.enabled; | |||
|  |             GUI.enabled = true; | |||
|  |             expanded = TMP_EditorUtility.EditorToggle(r, expanded, new GUIContent(panel), TMP_UIStyleManager.panelTitle); | |||
|  |             r.width -= 30; | |||
|  |             EditorGUI.LabelField(r, new GUIContent(expanded ? s_PanelStateLabel[0] : s_PanelStateLabel[1]), TMP_UIStyleManager.rightLabel); | |||
|  |             GUI.enabled = enabled; | |||
|  | 
 | |||
|  |             EditorGUI.indentLevel += 1; | |||
|  |             EditorGUI.BeginDisabledGroup(false); | |||
|  | 
 | |||
|  |             return expanded; | |||
|  |         } | |||
|  | 
 | |||
|  |         protected bool BeginPanel(string panel, ShaderFeature feature, bool expanded, bool readState = true) | |||
|  |         { | |||
|  |             EditorGUI.indentLevel = 0; | |||
|  | 
 | |||
|  |             if (readState) | |||
|  |             { | |||
|  |                 feature.ReadState(m_Material); | |||
|  |             } | |||
|  | 
 | |||
|  |             EditorGUI.BeginChangeCheck(); | |||
|  | 
 | |||
|  |             EditorGUILayout.BeginVertical(EditorStyles.helpBox); | |||
|  |             GUILayout.BeginHorizontal(); | |||
|  | 
 | |||
|  |             Rect r = EditorGUI.IndentedRect(GUILayoutUtility.GetRect(20, 20, GUILayout.Width(20f))); | |||
|  |             bool active = EditorGUI.Toggle(r, feature.Active); | |||
|  | 
 | |||
|  |             if (EditorGUI.EndChangeCheck()) | |||
|  |             { | |||
|  |                 m_Editor.RegisterPropertyChangeUndo(feature.undoLabel); | |||
|  |                 feature.SetActive(active, m_Material); | |||
|  |             } | |||
|  | 
 | |||
|  |             r = EditorGUI.IndentedRect(GUILayoutUtility.GetRect(20, 18)); | |||
|  |             r.width += 6; | |||
|  | 
 | |||
|  |             bool enabled = GUI.enabled; | |||
|  |             GUI.enabled = true; | |||
|  |             expanded = TMP_EditorUtility.EditorToggle(r, expanded, new GUIContent(panel), TMP_UIStyleManager.panelTitle); | |||
|  |             r.width -= 10; | |||
|  |             EditorGUI.LabelField(r, new GUIContent(expanded ? s_PanelStateLabel[0] : s_PanelStateLabel[1]), TMP_UIStyleManager.rightLabel); | |||
|  |             GUI.enabled = enabled; | |||
|  | 
 | |||
|  |             GUILayout.EndHorizontal(); | |||
|  | 
 | |||
|  |             EditorGUI.indentLevel += 1; | |||
|  |             EditorGUI.BeginDisabledGroup(!active); | |||
|  | 
 | |||
|  |             return expanded; | |||
|  |         } | |||
|  | 
 | |||
|  |         public void EndPanel() | |||
|  |         { | |||
|  |             EditorGUI.EndDisabledGroup(); | |||
|  |             EditorGUI.indentLevel -= 1; | |||
|  |             EditorGUILayout.EndVertical(); | |||
|  |         } | |||
|  | 
 | |||
|  |         MaterialProperty BeginProperty(string name) | |||
|  |         { | |||
|  |             MaterialProperty property = FindProperty(name, m_Properties); | |||
|  |             EditorGUI.BeginChangeCheck(); | |||
|  |             EditorGUI.showMixedValue = property.hasMixedValue; | |||
|  |             m_Editor.BeginAnimatedCheck(Rect.zero, property); | |||
|  | 
 | |||
|  |             return property; | |||
|  |         } | |||
|  | 
 | |||
|  |         bool EndProperty() | |||
|  |         { | |||
|  |             m_Editor.EndAnimatedCheck(); | |||
|  |             EditorGUI.showMixedValue = false; | |||
|  |             return EditorGUI.EndChangeCheck(); | |||
|  |         } | |||
|  | 
 | |||
|  |         protected void DoPopup(string name, string label, GUIContent[] options) | |||
|  |         { | |||
|  |             MaterialProperty property = BeginProperty(name); | |||
|  |             s_TempLabel.text = label; | |||
|  |             int index = EditorGUILayout.Popup(s_TempLabel, (int)property.floatValue, options); | |||
|  |             if (EndProperty()) | |||
|  |             { | |||
|  |                 property.floatValue = index; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         protected void DoCubeMap(string name, string label) | |||
|  |         { | |||
|  |             DoTexture(name, label, typeof(Cubemap)); | |||
|  |         } | |||
|  | 
 | |||
|  |         protected void DoTexture2D(string name, string label, bool withTilingOffset = false, string[] speedNames = null) | |||
|  |         { | |||
|  |             DoTexture(name, label, typeof(Texture2D), withTilingOffset, speedNames); | |||
|  |         } | |||
|  | 
 | |||
|  |         void DoTexture(string name, string label, System.Type type, bool withTilingOffset = false, string[] speedNames = null) | |||
|  |         { | |||
|  |             float objFieldSize = 60f; | |||
|  |             bool smallLayout = EditorGUIUtility.currentViewWidth <= 330f && (withTilingOffset || speedNames != null); | |||
|  |             float controlHeight = smallLayout ? objFieldSize * 2 : objFieldSize; | |||
|  | 
 | |||
|  |             MaterialProperty property = FindProperty(name, m_Properties); | |||
|  |             m_Editor.BeginAnimatedCheck(Rect.zero, property); | |||
|  | 
 | |||
|  |             Rect rect = EditorGUILayout.GetControlRect(true, controlHeight); | |||
|  |             float totalWidth = rect.width; | |||
|  |             rect.width = EditorGUIUtility.labelWidth + objFieldSize; | |||
|  |             rect.height = objFieldSize; | |||
|  |             s_TempLabel.text = label; | |||
|  | 
 | |||
|  |             EditorGUI.BeginChangeCheck(); | |||
|  |             Object tex = EditorGUI.ObjectField(rect, s_TempLabel, property.textureValue, type, false); | |||
|  |             if (EditorGUI.EndChangeCheck()) | |||
|  |             { | |||
|  |                 property.textureValue = tex as Texture; | |||
|  |             } | |||
|  | 
 | |||
|  |             float additionalHeight = controlHeight - objFieldSize; | |||
|  |             float xOffset = smallLayout ? rect.width - objFieldSize : rect.width; | |||
|  | 
 | |||
|  |             rect.y += additionalHeight; | |||
|  |             rect.x += xOffset; | |||
|  |             rect.width = totalWidth - xOffset; | |||
|  |             rect.height = EditorGUIUtility.singleLineHeight; | |||
|  | 
 | |||
|  |             if (withTilingOffset) | |||
|  |             { | |||
|  |                 DoTilingOffset(rect, property); | |||
|  |                 rect.y += (rect.height + 2f) * 2f; | |||
|  |             } | |||
|  | 
 | |||
|  |             m_Editor.EndAnimatedCheck(); | |||
|  | 
 | |||
|  |             if (speedNames != null) | |||
|  |             { | |||
|  |                 DoUVSpeed(rect, speedNames); | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         void DoTilingOffset(Rect rect, MaterialProperty property) | |||
|  |         { | |||
|  |             float labelWidth = EditorGUIUtility.labelWidth; | |||
|  |             int indentLevel = EditorGUI.indentLevel; | |||
|  |             EditorGUI.indentLevel = 0; | |||
|  |             EditorGUIUtility.labelWidth = Mathf.Min(40f, rect.width * 0.40f); | |||
|  | 
 | |||
|  |             Vector4 vector = property.textureScaleAndOffset; | |||
|  | 
 | |||
|  |             bool changed = false; | |||
|  |             float[] values = s_TempFloats[2]; | |||
|  | 
 | |||
|  |             s_TempLabel.text = "Tiling"; | |||
|  |             Rect vectorRect = EditorGUI.PrefixLabel(rect, s_TempLabel); | |||
|  |             values[0] = vector.x; | |||
|  |             values[1] = vector.y; | |||
|  | 
 | |||
|  |             EditorGUI.BeginChangeCheck(); | |||
|  |             EditorGUI.MultiFloatField(vectorRect, s_XywhVectorLabels, values); | |||
|  |             if (EditorGUI.EndChangeCheck()) | |||
|  |             { | |||
|  |                 vector.x = values[0]; | |||
|  |                 vector.y = values[1]; | |||
|  |                 changed = true; | |||
|  |             } | |||
|  | 
 | |||
|  |             rect.y += rect.height + 2f; | |||
|  |             s_TempLabel.text = "Offset"; | |||
|  |             vectorRect = EditorGUI.PrefixLabel(rect, s_TempLabel); | |||
|  |             values[0] = vector.z; | |||
|  |             values[1] = vector.w; | |||
|  | 
 | |||
|  |             EditorGUI.BeginChangeCheck(); | |||
|  |             EditorGUI.MultiFloatField(vectorRect, s_XywhVectorLabels, values); | |||
|  |             if (EditorGUI.EndChangeCheck()) | |||
|  |             { | |||
|  |                 vector.z = values[0]; | |||
|  |                 vector.w = values[1]; | |||
|  |                 changed = true; | |||
|  |             } | |||
|  | 
 | |||
|  |             if (changed) | |||
|  |             { | |||
|  |                 property.textureScaleAndOffset = vector; | |||
|  |             } | |||
|  | 
 | |||
|  |             EditorGUIUtility.labelWidth = labelWidth; | |||
|  |             EditorGUI.indentLevel = indentLevel; | |||
|  |         } | |||
|  | 
 | |||
|  |         protected void DoUVSpeed(Rect rect, string[] names) | |||
|  |         { | |||
|  |             float labelWidth = EditorGUIUtility.labelWidth; | |||
|  |             int indentLevel = EditorGUI.indentLevel; | |||
|  |             EditorGUI.indentLevel = 0; | |||
|  |             EditorGUIUtility.labelWidth = Mathf.Min(40f, rect.width * 0.40f); | |||
|  | 
 | |||
|  |             s_TempLabel.text = "Speed"; | |||
|  |             rect = EditorGUI.PrefixLabel(rect, s_TempLabel); | |||
|  | 
 | |||
|  |             EditorGUIUtility.labelWidth = 10f; | |||
|  |             rect.width = rect.width * 0.5f - 2f; | |||
|  | 
 | |||
|  |             if (names.Length == 1) | |||
|  |             { | |||
|  |                 DoFloat2(rect, names[0]); | |||
|  |             } | |||
|  |             else | |||
|  |             { | |||
|  |                 DoFloat(rect, names[0], "X"); | |||
|  |                 rect.x += rect.width + 4f; | |||
|  |                 DoFloat(rect, names[1], "Y"); | |||
|  |             } | |||
|  | 
 | |||
|  |             EditorGUIUtility.labelWidth = labelWidth; | |||
|  |             EditorGUI.indentLevel = indentLevel; | |||
|  |         } | |||
|  | 
 | |||
|  |         protected void DoToggle(string name, string label) | |||
|  |         { | |||
|  |             MaterialProperty property = BeginProperty(name); | |||
|  |             s_TempLabel.text = label; | |||
|  |             bool value = EditorGUILayout.Toggle(s_TempLabel, property.floatValue == 1f); | |||
|  |             if (EndProperty()) | |||
|  |             { | |||
|  |                 property.floatValue = value ? 1f : 0f; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         protected void DoFloat(string name, string label) | |||
|  |         { | |||
|  |             MaterialProperty property = BeginProperty(name); | |||
|  |             Rect rect = EditorGUILayout.GetControlRect(); | |||
|  |             rect.width = EditorGUIUtility.labelWidth + 55f; | |||
|  |             s_TempLabel.text = label; | |||
|  |             float value = EditorGUI.FloatField(rect, s_TempLabel, property.floatValue); | |||
|  |             if (EndProperty()) | |||
|  |             { | |||
|  |                 property.floatValue = value; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         protected void DoColor(string name, string label) | |||
|  |         { | |||
|  |             MaterialProperty property = BeginProperty(name); | |||
|  |             s_TempLabel.text = label; | |||
|  |             Color value = EditorGUI.ColorField(EditorGUILayout.GetControlRect(), s_TempLabel, property.colorValue, false, true, true); | |||
|  |             if (EndProperty()) | |||
|  |             { | |||
|  |                 property.colorValue = value; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         void DoFloat(Rect rect, string name, string label) | |||
|  |         { | |||
|  |             MaterialProperty property = BeginProperty(name); | |||
|  |             s_TempLabel.text = label; | |||
|  |             float value = EditorGUI.FloatField(rect, s_TempLabel, property.floatValue); | |||
|  |             if (EndProperty()) | |||
|  |             { | |||
|  |                 property.floatValue = value; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         void DoFloat2(Rect rect, string name) | |||
|  |         { | |||
|  |             MaterialProperty property = BeginProperty(name); | |||
|  | 
 | |||
|  |             float x = EditorGUI.FloatField(rect, "X", property.vectorValue.x); | |||
|  |             rect.x += rect.width + 4f; | |||
|  |             float y = EditorGUI.FloatField(rect, "Y", property.vectorValue.y); | |||
|  | 
 | |||
|  |             if (EndProperty()) | |||
|  |             { | |||
|  |                 property.vectorValue = new Vector2(x, y); | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         protected void DoOffset(string name, string label) | |||
|  |         { | |||
|  |             MaterialProperty property = BeginProperty(name); | |||
|  |             s_TempLabel.text = label; | |||
|  |             Vector2 value = EditorGUI.Vector2Field(EditorGUILayout.GetControlRect(), s_TempLabel, property.vectorValue); | |||
|  |             if (EndProperty()) | |||
|  |             { | |||
|  |                 property.vectorValue = value; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         protected void DoSlider(string name, string label) | |||
|  |         { | |||
|  |             MaterialProperty property = BeginProperty(name); | |||
|  |             Vector2 range = property.rangeLimits; | |||
|  |             s_TempLabel.text = label; | |||
|  |             float value = EditorGUI.Slider(EditorGUILayout.GetControlRect(), s_TempLabel, property.floatValue, range.x, range.y); | |||
|  |             if (EndProperty()) | |||
|  |             { | |||
|  |                 property.floatValue = value; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         protected void DoSlider(string name, Vector2 range, string label) | |||
|  |         { | |||
|  |             MaterialProperty property = BeginProperty(name); | |||
|  |             s_TempLabel.text = label; | |||
|  |             float value = EditorGUI.Slider(EditorGUILayout.GetControlRect(), s_TempLabel, property.floatValue, range.x, range.y); | |||
|  |             if (EndProperty()) | |||
|  |             { | |||
|  |                 property.floatValue = value; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         protected void DoSlider(string propertyName, string propertyField, string label) | |||
|  |         { | |||
|  |             MaterialProperty property = BeginProperty(propertyName); | |||
|  |             Vector2 range = property.rangeLimits; | |||
|  |             s_TempLabel.text = label; | |||
|  | 
 | |||
|  |             Vector4 value = property.vectorValue; | |||
|  | 
 | |||
|  |             switch (propertyField) | |||
|  |             { | |||
|  |                 case "X": | |||
|  |                     value.x = EditorGUI.Slider(EditorGUILayout.GetControlRect(), s_TempLabel, value.x, range.x, range.y); | |||
|  |                     break; | |||
|  |                 case "Y": | |||
|  |                     value.y = EditorGUI.Slider(EditorGUILayout.GetControlRect(), s_TempLabel, value.y, range.x, range.y); | |||
|  |                     break; | |||
|  |                 case "Z": | |||
|  |                     value.z = EditorGUI.Slider(EditorGUILayout.GetControlRect(), s_TempLabel, value.z, range.x, range.y); | |||
|  |                     break; | |||
|  |                 case "W": | |||
|  |                     value.w = EditorGUI.Slider(EditorGUILayout.GetControlRect(), s_TempLabel, value.w, range.x, range.y); | |||
|  |                     break; | |||
|  |             } | |||
|  | 
 | |||
|  |             if (EndProperty()) | |||
|  |             { | |||
|  |                 property.vectorValue = value; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         protected void DoSlider(string propertyName, string propertyField, Vector2 range, string label) | |||
|  |         { | |||
|  |             MaterialProperty property = BeginProperty(propertyName); | |||
|  |             s_TempLabel.text = label; | |||
|  | 
 | |||
|  |             Vector4 value = property.vectorValue; | |||
|  | 
 | |||
|  |             switch (propertyField) | |||
|  |             { | |||
|  |                 case "X": | |||
|  |                     value.x = EditorGUI.Slider(EditorGUILayout.GetControlRect(), s_TempLabel, value.x, range.x, range.y); | |||
|  |                     break; | |||
|  |                 case "Y": | |||
|  |                     value.y = EditorGUI.Slider(EditorGUILayout.GetControlRect(), s_TempLabel, value.y, range.x, range.y); | |||
|  |                     break; | |||
|  |                 case "Z": | |||
|  |                     value.z = EditorGUI.Slider(EditorGUILayout.GetControlRect(), s_TempLabel, value.z, range.x, range.y); | |||
|  |                     break; | |||
|  |                 case "W": | |||
|  |                     value.w = EditorGUI.Slider(EditorGUILayout.GetControlRect(), s_TempLabel, value.w, range.x, range.y); | |||
|  |                     break; | |||
|  |             } | |||
|  | 
 | |||
|  |             if (EndProperty()) | |||
|  |             { | |||
|  |                 property.vectorValue = value; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         protected void DoVector2(string name, string label) | |||
|  |         { | |||
|  |             MaterialProperty property = BeginProperty(name); | |||
|  |             s_TempLabel.text = label; | |||
|  |             Vector4 value = EditorGUILayout.Vector3Field(s_TempLabel, property.vectorValue); | |||
|  |             if (EndProperty()) | |||
|  |             { | |||
|  |                 property.vectorValue = value; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         protected void DoVector3(string name, string label) | |||
|  |         { | |||
|  |             MaterialProperty property = BeginProperty(name); | |||
|  |             s_TempLabel.text = label; | |||
|  |             Vector4 value = EditorGUILayout.Vector3Field(s_TempLabel, property.vectorValue); | |||
|  |             if (EndProperty()) | |||
|  |             { | |||
|  |                 property.vectorValue = value; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         protected void DoVector(string name, string label, GUIContent[] subLabels) | |||
|  |         { | |||
|  |             MaterialProperty property = BeginProperty(name); | |||
|  |             Rect rect = EditorGUILayout.GetControlRect(); | |||
|  |             s_TempLabel.text = label; | |||
|  |             rect = EditorGUI.PrefixLabel(rect, s_TempLabel); | |||
|  |             Vector4 vector = property.vectorValue; | |||
|  | 
 | |||
|  |             float[] values = s_TempFloats[subLabels.Length]; | |||
|  |             for (int i = 0; i < subLabels.Length; i++) | |||
|  |             { | |||
|  |                 values[i] = vector[i]; | |||
|  |             } | |||
|  | 
 | |||
|  |             EditorGUI.MultiFloatField(rect, subLabels, values); | |||
|  |             if (EndProperty()) | |||
|  |             { | |||
|  |                 for (int i = 0; i < subLabels.Length; i++) | |||
|  |                 { | |||
|  |                     vector[i] = values[i]; | |||
|  |                 } | |||
|  | 
 | |||
|  |                 property.vectorValue = vector; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         bool IsNewShader() | |||
|  |         { | |||
|  |             if (m_Material == null) | |||
|  |                 return false; | |||
|  | 
 | |||
|  |             int currentShaderID = m_Material.shader.GetInstanceID(); | |||
|  | 
 | |||
|  |             if (m_ShaderID == currentShaderID) | |||
|  |                 return false; | |||
|  | 
 | |||
|  |             m_ShaderID = currentShaderID; | |||
|  | 
 | |||
|  |             return true; | |||
|  |         } | |||
|  | 
 | |||
|  |         void DoDragAndDropBegin() | |||
|  |         { | |||
|  |             m_DragAndDropMinY = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true)).y; | |||
|  |         } | |||
|  | 
 | |||
|  |         void DoDragAndDropEnd() | |||
|  |         { | |||
|  |             Rect rect = GUILayoutUtility.GetRect(0f, 0f, GUILayout.ExpandWidth(true)); | |||
|  |             Event evt = Event.current; | |||
|  | 
 | |||
|  |             if (evt.type == EventType.DragUpdated) | |||
|  |             { | |||
|  |                 DragAndDrop.visualMode = DragAndDropVisualMode.Generic; | |||
|  |                 evt.Use(); | |||
|  |             } | |||
|  |             else if (evt.type == EventType.DragPerform && Rect.MinMaxRect(rect.xMin, m_DragAndDropMinY, rect.xMax, rect.yMax).Contains(evt.mousePosition)) | |||
|  |             { | |||
|  |                 DragAndDrop.AcceptDrag(); | |||
|  |                 evt.Use(); | |||
|  |                 Material droppedMaterial = DragAndDrop.objectReferences[0] as Material; | |||
|  |                 if (droppedMaterial && droppedMaterial != m_Material) | |||
|  |                 { | |||
|  |                     PerformDrop(droppedMaterial); | |||
|  |                 } | |||
|  |             } | |||
|  |             else if (evt.type == EventType.DragExited) | |||
|  |             { | |||
|  |                 if (IsNewShader()) | |||
|  |                     TMPro_EventManager.ON_MATERIAL_PROPERTY_CHANGED(true, m_Material); | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         void PerformDrop(Material droppedMaterial) | |||
|  |         { | |||
|  |             Texture droppedTex = droppedMaterial.GetTexture(ShaderUtilities.ID_MainTex); | |||
|  |             if (!droppedTex) | |||
|  |             { | |||
|  |                 return; | |||
|  |             } | |||
|  | 
 | |||
|  |             Texture currentTex = m_Material.GetTexture(ShaderUtilities.ID_MainTex); | |||
|  |             TMP_FontAsset requiredFontAsset = null; | |||
|  |             if (droppedTex != currentTex) | |||
|  |             { | |||
|  |                 requiredFontAsset = TMP_EditorUtility.FindMatchingFontAsset(droppedMaterial); | |||
|  |                 if (!requiredFontAsset) | |||
|  |                 { | |||
|  |                     return; | |||
|  |                 } | |||
|  |             } | |||
|  | 
 | |||
|  |             foreach (GameObject o in Selection.gameObjects) | |||
|  |             { | |||
|  |                 if (requiredFontAsset) | |||
|  |                 { | |||
|  |                     TMP_Text textComponent = o.GetComponent<TMP_Text>(); | |||
|  |                     if (textComponent) | |||
|  |                     { | |||
|  |                         Undo.RecordObject(textComponent, "Font Asset Change"); | |||
|  |                         textComponent.font = requiredFontAsset; | |||
|  |                     } | |||
|  |                 } | |||
|  | 
 | |||
|  |                 TMPro_EventManager.ON_DRAG_AND_DROP_MATERIAL_CHANGED(o, m_Material, droppedMaterial); | |||
|  |                 EditorUtility.SetDirty(o); | |||
|  |             } | |||
|  |         } | |||
|  |     } | |||
|  | } |