1111 lines
46 KiB
C#
Executable file
1111 lines
46 KiB
C#
Executable file
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Threading.Tasks;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace Thry
|
|
{
|
|
public class GuiHelper
|
|
{
|
|
public const float SMALL_TEXTURE_VRAM_DISPLAY_WIDTH = 80;
|
|
|
|
public static void ConfigTextureProperty(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor, bool hasFoldoutProperties, bool skip_drag_and_drop_handling = false)
|
|
{
|
|
switch (Config.Singleton.default_texture_type)
|
|
{
|
|
case TextureDisplayType.small:
|
|
SmallTextureProperty(position, prop, label, editor, hasFoldoutProperties);
|
|
break;
|
|
case TextureDisplayType.big:
|
|
StylizedBigTextureProperty(position, prop, label, editor, hasFoldoutProperties, skip_drag_and_drop_handling);
|
|
break;
|
|
case TextureDisplayType.big_basic:
|
|
BigTexturePropertyBasic(position, prop, label, editor, hasFoldoutProperties, skip_drag_and_drop_handling);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public static float GetSmallTextureVRAMWidth(MaterialProperty textureProperty)
|
|
{
|
|
if (textureProperty.textureValue != null) return SMALL_TEXTURE_VRAM_DISPLAY_WIDTH;
|
|
return 0;
|
|
}
|
|
|
|
public static void SmallTextureProperty(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor, bool hasFoldoutProperties, Action extraFoldoutGUI = null)
|
|
{
|
|
// Border Code start
|
|
bool isFoldedOut = hasFoldoutProperties && DrawingData.IsEnabled && DrawingData.CurrentTextureProperty.showFoldoutProperties;
|
|
if(isFoldedOut)
|
|
{
|
|
Rect border = EditorGUILayout.BeginVertical();
|
|
GUILayoutUtility.GetRect(0, 5);
|
|
border = new RectOffset(EditorGUI.indentLevel * -15 - 26, 3, -3, -3).Add(border);
|
|
GUI.DrawTexture(border, Texture2D.whiteTexture, ScaleMode.StretchToFill, true, 0, Styles.COLOR_BACKGROUND_1, 3, 10);
|
|
}
|
|
// Border Code end
|
|
|
|
|
|
Rect thumbnailPos = position;
|
|
Rect foloutClickCheck = position;
|
|
Rect tooltipRect = position;
|
|
if (hasFoldoutProperties)
|
|
{
|
|
thumbnailPos.x += 20;
|
|
thumbnailPos.width -= 20;
|
|
}
|
|
editor.TexturePropertyMiniThumbnail(thumbnailPos, prop, label.text, label.tooltip);
|
|
//VRAM
|
|
Rect vramPos = Rect.zero;
|
|
if (DrawingData.CurrentTextureProperty.MaterialProperty.textureValue != null)
|
|
{
|
|
GUIContent content = new GUIContent(DrawingData.CurrentTextureProperty.VRAMString);
|
|
vramPos = thumbnailPos;
|
|
vramPos.x += thumbnailPos.width - SMALL_TEXTURE_VRAM_DISPLAY_WIDTH;
|
|
vramPos.width = SMALL_TEXTURE_VRAM_DISPLAY_WIDTH;
|
|
GUI.Label(vramPos, content, Styles.label_align_right);
|
|
}
|
|
//Prop right next to texture
|
|
if (DrawingData.CurrentTextureProperty.DoesReferencePropertyExist)
|
|
{
|
|
ShaderProperty property = ShaderEditor.Active.PropertyDictionary[DrawingData.CurrentTextureProperty.Options.reference_property];
|
|
Rect r = position;
|
|
r.x += EditorGUIUtility.labelWidth - CurrentIndentWidth();
|
|
r.width -= EditorGUIUtility.labelWidth - CurrentIndentWidth();
|
|
r.width -= vramPos.width;
|
|
foloutClickCheck.width -= r.width;
|
|
property.Draw(new CRect(r), new GUIContent());
|
|
property.tooltip.ConditionalDraw(r);
|
|
}
|
|
//Foldouts
|
|
if (hasFoldoutProperties && DrawingData.CurrentTextureProperty != null)
|
|
{
|
|
//draw dropdown triangle
|
|
Rect trianglePos = thumbnailPos;
|
|
trianglePos.x += DrawingData.CurrentTextureProperty.XOffset * 15 - 2;
|
|
//This is an invisible button with zero functionality. But it needs to be here so that the triangle click reacts fast
|
|
if (GUI.Button(trianglePos, "", GUIStyle.none)) { }
|
|
if (Event.current.type == EventType.Repaint)
|
|
EditorStyles.foldout.Draw(trianglePos, false, false, DrawingData.CurrentTextureProperty.showFoldoutProperties, false);
|
|
|
|
if (DrawingData.IsEnabled)
|
|
{
|
|
//sub properties
|
|
if (DrawingData.CurrentTextureProperty.showFoldoutProperties)
|
|
{
|
|
EditorGUI.indentLevel += 2;
|
|
extraFoldoutGUI?.Invoke();
|
|
if (DrawingData.CurrentTextureProperty.hasScaleOffset)
|
|
{
|
|
EditorGUI.showMixedValue = ShaderEditor.Active.Materials.Select(m => m.GetTextureScale(prop.name)).Distinct().Count() > 1 || ShaderEditor.Active.Materials.Select(m => m.GetTextureOffset(prop.name)).Distinct().Count() > 1;
|
|
ShaderEditor.Active.Editor.TextureScaleOffsetProperty(prop);
|
|
tooltipRect.height += GUILayoutUtility.GetLastRect().height;
|
|
}
|
|
//In case of locked material end disabled group here to allow editing of sub properties
|
|
if (ShaderEditor.Active.IsLockedMaterial) EditorGUI.EndDisabledGroup();
|
|
|
|
PropertyOptions options = DrawingData.CurrentTextureProperty.Options;
|
|
if (options.reference_properties != null)
|
|
foreach (string r_property in options.reference_properties)
|
|
{
|
|
ShaderProperty property = ShaderEditor.Active.PropertyDictionary[r_property];
|
|
property.Draw(useEditorIndent: true);
|
|
}
|
|
|
|
//readd disabled group
|
|
if (ShaderEditor.Active.IsLockedMaterial) EditorGUI.BeginDisabledGroup(false);
|
|
|
|
EditorGUI.indentLevel -= 2;
|
|
}
|
|
if (ShaderEditor.Input.LeftClick_IgnoreLockedAndUnityUses && foloutClickCheck.Contains(Event.current.mousePosition))
|
|
{
|
|
ShaderEditor.Input.Use();
|
|
DrawingData.CurrentTextureProperty.showFoldoutProperties = !DrawingData.CurrentTextureProperty.showFoldoutProperties;
|
|
}
|
|
}
|
|
}
|
|
|
|
Rect object_rect = new Rect(position);
|
|
object_rect.height = GUILayoutUtility.GetLastRect().y - object_rect.y + GUILayoutUtility.GetLastRect().height;
|
|
DrawingData.LastGuiObjectRect = object_rect;
|
|
DrawingData.TooltipCheckRect = tooltipRect;
|
|
|
|
// Border Code start
|
|
if(isFoldedOut)
|
|
{
|
|
GUILayoutUtility.GetRect(0, 5);
|
|
EditorGUILayout.EndVertical();
|
|
}
|
|
// Border Code end
|
|
}
|
|
|
|
|
|
static int s_texturePickerWindow = -1;
|
|
static MaterialProperty s_texturePickerWindowProperty = null;
|
|
public static void StylizedBigTextureProperty(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor, bool hasFoldoutProperties, bool skip_drag_and_drop_handling = false)
|
|
{
|
|
// add some padding at the top
|
|
position.y += 5;
|
|
|
|
position.x += (EditorGUI.indentLevel) * 15;
|
|
position.width -= (EditorGUI.indentLevel) * 15;
|
|
Rect border = new Rect(position);
|
|
border.height = 80; // for texture & offset
|
|
|
|
Rect[] additionRects = new Rect[(DrawingData.CurrentTextureProperty.DoesReferencePropertyExist ? 1 : 0) +
|
|
(DrawingData.CurrentTextureProperty.DoReferencePropertiesExist ? DrawingData.CurrentTextureProperty.Options.reference_properties.Length : 0)];
|
|
int i = 0;
|
|
|
|
if (DrawingData.CurrentTextureProperty.DoReferencePropertiesExist)
|
|
{
|
|
foreach (string r_property in DrawingData.CurrentTextureProperty.Options.reference_properties)
|
|
{
|
|
float height = editor.GetPropertyHeight(ShaderEditor.Active.PropertyDictionary[r_property].MaterialProperty);
|
|
additionRects[i++] = new Rect(border.x + 15, border.y + border.height - 8, border.width - 15, height);
|
|
border.height += height + 3; // add a little padding
|
|
}
|
|
}
|
|
if (DrawingData.CurrentTextureProperty.DoesReferencePropertyExist)
|
|
{
|
|
float height = editor.GetPropertyHeight(ShaderEditor.Active.PropertyDictionary[DrawingData.CurrentTextureProperty.Options.reference_property].MaterialProperty);
|
|
additionRects[i++] = new Rect(border.x + 15, border.y + border.height, border.width - 15, height);
|
|
border.height += height + 3; // add a little padding
|
|
}
|
|
Rect vramRect = new Rect(border.x + 30, border.y + border.height - 6, border.width - 15, EditorStyles.label.lineHeight);
|
|
border.height += EditorStyles.label.lineHeight;
|
|
|
|
// Reserve space
|
|
GUILayoutUtility.GetRect(0, border.height - position.height - 5);
|
|
|
|
GUI.DrawTexture(border, Texture2D.whiteTexture, ScaleMode.StretchToFill, false, 0, Styles.COLOR_BACKGROUND_1, 3, 10);
|
|
|
|
Rect previewSide = new Rect(border);
|
|
Rect optionsSide = new Rect(border);
|
|
previewSide.width = Mathf.Max(50, Mathf.Min(previewSide.height, previewSide.width - EditorGUIUtility.labelWidth - 50));
|
|
previewSide.x += optionsSide.width - previewSide.width;
|
|
optionsSide.width -= previewSide.width;
|
|
|
|
Rect previewRectBorder = new Rect(previewSide);
|
|
previewRectBorder.height = previewRectBorder.width;
|
|
Rect previewRect = new RectOffset(3, 3, 3, 3).Remove(previewRectBorder);
|
|
|
|
Rect buttonSelectRect = new RectOffset(20, 20, 0, 0).Remove(previewRectBorder);
|
|
buttonSelectRect.height = 20;
|
|
buttonSelectRect.y = previewRect.y + previewRect.height - buttonSelectRect.height + 2;
|
|
|
|
if (prop.hasMixedValue)
|
|
{
|
|
Rect mixedRect = new Rect(previewRect);
|
|
mixedRect.y -= 5;
|
|
mixedRect.x += mixedRect.width / 2 - 4;
|
|
GUI.Label(mixedRect, "_");
|
|
}
|
|
else if (prop.textureValue != null)
|
|
{
|
|
EditorGUI.DrawPreviewTexture(previewRect, prop.textureValue);
|
|
}
|
|
GUI.DrawTexture(previewRectBorder, Texture2D.whiteTexture, ScaleMode.StretchToFill, false, 0, Styles.COLOR_BACKGROUND_1, 3, 10);
|
|
|
|
//selection button and pinging
|
|
if (GUI.Button(buttonSelectRect, "Select", EditorStyles.miniButton))
|
|
{
|
|
OpenTexturePicker(prop);
|
|
}
|
|
else if (Event.current.type == EventType.MouseDown && previewRect.Contains(Event.current.mousePosition))
|
|
{
|
|
EditorGUIUtility.PingObject(prop.textureValue);
|
|
}
|
|
HandleTexturePicker(prop);
|
|
|
|
if (!skip_drag_and_drop_handling)
|
|
AcceptDragAndDrop(previewRect, prop);
|
|
|
|
//Change indent & label width
|
|
EditorGUI.indentLevel += 2;
|
|
float oldLabelWidth = EditorGUIUtility.labelWidth;
|
|
EditorGUIUtility.labelWidth = 80;
|
|
|
|
|
|
//scale offset rect + foldout properties
|
|
if (hasFoldoutProperties || DrawingData.CurrentTextureProperty.Options.reference_property != null)
|
|
{
|
|
if (DrawingData.CurrentTextureProperty.hasScaleOffset)
|
|
{
|
|
Rect scale_offset_rect = new RectOffset(30, 5, 37, 0).Remove(optionsSide);
|
|
scale_offset_rect.height = position.height;
|
|
EditorGUI.showMixedValue = ShaderEditor.Active.Materials.Select(m => m.GetTextureScale(prop.name)).Distinct().Count() > 1 || ShaderEditor.Active.Materials.Select(m => m.GetTextureOffset(prop.name)).Distinct().Count() > 1;
|
|
editor.TextureScaleOffsetProperty(scale_offset_rect, prop);
|
|
}
|
|
|
|
//In case of locked material end disabled group here to allow editing of sub properties
|
|
if (ShaderEditor.Active.IsLockedMaterial) EditorGUI.EndDisabledGroup();
|
|
|
|
PropertyOptions options = DrawingData.CurrentTextureProperty.Options;
|
|
if (options.reference_property != null)
|
|
{
|
|
ShaderProperty property = ShaderEditor.Active.PropertyDictionary[options.reference_property];
|
|
Rect r = additionRects[additionRects.Length - 1];
|
|
r.width = optionsSide.width - 20;
|
|
property.Draw(new CRect(r));
|
|
}
|
|
if (options.reference_properties != null)
|
|
{
|
|
i = 0;
|
|
foreach (string r_property in options.reference_properties)
|
|
{
|
|
ShaderProperty property = ShaderEditor.Active.PropertyDictionary[r_property];
|
|
Rect r = additionRects[i++];
|
|
r.width = optionsSide.width - 20;
|
|
property.Draw(new CRect(r));
|
|
}
|
|
}
|
|
|
|
//readd disabled group
|
|
if (ShaderEditor.Active.IsLockedMaterial) EditorGUI.BeginDisabledGroup(false);
|
|
}
|
|
|
|
//VRAM
|
|
if (DrawingData.CurrentTextureProperty.MaterialProperty.textureValue != null)
|
|
{
|
|
GUI.Label(vramRect, "VRAM:");
|
|
vramRect.x += EditorGUIUtility.labelWidth - 15;
|
|
GUI.Label(vramRect, DrawingData.CurrentTextureProperty.VRAMString);
|
|
}
|
|
|
|
//reset indent + label width
|
|
EditorGUI.indentLevel -= 2;
|
|
EditorGUIUtility.labelWidth = oldLabelWidth;
|
|
|
|
Rect label_rect = new RectOffset(-5, 0, -2, 0).Add(position);
|
|
GUI.Label(label_rect, label);
|
|
|
|
DrawingData.LastGuiObjectRect = border;
|
|
DrawingData.TooltipCheckRect = border;
|
|
}
|
|
|
|
public static void BigTexturePropertyBasic(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor, bool hasFoldoutProperties, bool skip_drag_and_drop_handling = false)
|
|
{
|
|
string text = label.text;
|
|
//VRAM
|
|
if (DrawingData.CurrentTextureProperty.MaterialProperty.textureValue != null)
|
|
{
|
|
text += " (VRAM: " + DrawingData.CurrentTextureProperty.VRAMString + ")";
|
|
}
|
|
GUILayoutUtility.GetRect(0, editor.GetPropertyHeight(prop) - EditorGUIUtility.singleLineHeight - 5);
|
|
editor.TextureProperty(position, prop, text);
|
|
DrawingData.LastGuiObjectRect = position;
|
|
DrawingData.TooltipCheckRect = position;
|
|
|
|
// Reference properties
|
|
EditorGUI.indentLevel += 1;
|
|
PropertyOptions options = DrawingData.CurrentTextureProperty.Options;
|
|
if (options.reference_property != null)
|
|
{
|
|
ShaderProperty property = ShaderEditor.Active.PropertyDictionary[options.reference_property];
|
|
property.Draw(useEditorIndent: true);
|
|
}
|
|
if (options.reference_properties != null)
|
|
foreach (string r_property in options.reference_properties)
|
|
{
|
|
ShaderProperty property = ShaderEditor.Active.PropertyDictionary[r_property];
|
|
property.Draw(useEditorIndent: true);
|
|
}
|
|
EditorGUI.indentLevel -= 1;
|
|
}
|
|
|
|
public static void OpenTexturePicker(MaterialProperty prop)
|
|
{
|
|
EditorGUIUtility.ShowObjectPicker<Texture>(prop.textureValue, false, "", 0);
|
|
s_texturePickerWindow = EditorGUIUtility.GetObjectPickerControlID();
|
|
s_texturePickerWindowProperty = prop;
|
|
}
|
|
|
|
public static bool HandleTexturePicker(MaterialProperty prop)
|
|
{
|
|
if (Event.current.commandName == "ObjectSelectorUpdated" && EditorGUIUtility.GetObjectPickerControlID() == s_texturePickerWindow && s_texturePickerWindowProperty.name == prop.name)
|
|
{
|
|
prop.textureValue = (Texture)EditorGUIUtility.GetObjectPickerObject();
|
|
ShaderEditor.RepaintActive();
|
|
return true;
|
|
}
|
|
if (Event.current.commandName == "ObjectSelectorClosed" && EditorGUIUtility.GetObjectPickerControlID() == s_texturePickerWindow)
|
|
{
|
|
s_texturePickerWindow = -1;
|
|
s_texturePickerWindowProperty = null;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static bool AcceptDragAndDrop(Rect r, MaterialProperty prop)
|
|
{
|
|
if ((ShaderEditor.Input.is_drag_drop_event) && r.Contains(ShaderEditor.Input.mouse_position) && DragAndDrop.objectReferences[0] is Texture)
|
|
{
|
|
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
|
|
if (ShaderEditor.Input.is_drop_event)
|
|
{
|
|
DragAndDrop.AcceptDrag();
|
|
prop.textureValue = (Texture)DragAndDrop.objectReferences[0];
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static Stack<int> s_previousIndentLevels = new Stack<int>();
|
|
public static void BeginCustomIndentLevel(int indent)
|
|
{
|
|
s_previousIndentLevels.Push(EditorGUI.indentLevel);
|
|
EditorGUI.indentLevel = indent;
|
|
}
|
|
|
|
public static void EndCustomIndentLevel()
|
|
{
|
|
EditorGUI.indentLevel = s_previousIndentLevels.Pop();
|
|
}
|
|
|
|
public static void MinMaxSlider(Rect settingsRect, GUIContent content, MaterialProperty prop)
|
|
{
|
|
bool changed = false;
|
|
Vector4 vec = prop.vectorValue;
|
|
Rect sliderRect = settingsRect;
|
|
|
|
EditorGUI.LabelField(settingsRect, content);
|
|
|
|
if (settingsRect.width > 160)
|
|
{
|
|
Rect numberRect = settingsRect;
|
|
numberRect.width = 65 + (EditorGUI.indentLevel - 1) * 15;
|
|
|
|
numberRect.x = EditorGUIUtility.labelWidth - (EditorGUI.indentLevel - 1) * 15;
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
EditorGUI.showMixedValue = prop.hasMixedValue;
|
|
vec.x = EditorGUI.FloatField(numberRect, vec.x, EditorStyles.textField);
|
|
changed |= EditorGUI.EndChangeCheck();
|
|
|
|
numberRect.x = settingsRect.xMax - numberRect.width;
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
EditorGUI.showMixedValue = prop.hasMixedValue;
|
|
vec.y = EditorGUI.FloatField(numberRect, vec.y);
|
|
changed |= EditorGUI.EndChangeCheck();
|
|
|
|
sliderRect.xMin = EditorGUIUtility.labelWidth - (EditorGUI.indentLevel - 1) * 15;
|
|
sliderRect.xMin += (65 + -8);
|
|
sliderRect.xMax -= (65 + -8);
|
|
}
|
|
|
|
vec.x = Mathf.Clamp(vec.x, vec.z, vec.y);
|
|
vec.y = Mathf.Clamp(vec.y, vec.x, vec.w);
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
EditorGUI.MinMaxSlider(sliderRect, ref vec.x, ref vec.y, vec.z, vec.w);
|
|
changed |= EditorGUI.EndChangeCheck();
|
|
|
|
if (changed)
|
|
{
|
|
prop.vectorValue = vec;
|
|
}
|
|
}
|
|
|
|
public static bool DrawListField<type>(List<type> list) where type : UnityEngine.Object
|
|
{
|
|
GUILayout.BeginHorizontal();
|
|
if (GUILayout.Button("Add", EditorStyles.miniButton))
|
|
list.Add(null);
|
|
if (GUILayout.Button("Remove", EditorStyles.miniButton))
|
|
if (list.Count > 0)
|
|
list.RemoveAt(list.Count - 1);
|
|
GUILayout.EndHorizontal();
|
|
|
|
for (int i = 0; i < list.Count; i++)
|
|
{
|
|
list[i] = (type)EditorGUILayout.ObjectField(list[i], typeof(type), false);
|
|
}
|
|
return false;
|
|
}
|
|
public static bool DrawListField<type>(List<type> list, float maxHeight, ref Vector2 scrollPosition) where type : UnityEngine.Object
|
|
{
|
|
GUILayout.BeginHorizontal();
|
|
if (GUILayout.Button("Add", EditorStyles.miniButton))
|
|
list.Add(null);
|
|
if (GUILayout.Button("Remove", EditorStyles.miniButton))
|
|
if (list.Count > 0)
|
|
list.RemoveAt(list.Count - 1);
|
|
GUILayout.EndHorizontal();
|
|
|
|
scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUILayout.MaxHeight(maxHeight));
|
|
for (int i = 0; i < list.Count; i++)
|
|
{
|
|
list[i] = (type)EditorGUILayout.ObjectField(list[i], typeof(type), false);
|
|
}
|
|
GUILayout.EndScrollView();
|
|
return false;
|
|
}
|
|
|
|
public static bool GUIDataStruct<t>(t data)
|
|
{
|
|
return GUIDataStruct<t>(data, new string[] { });
|
|
}
|
|
|
|
public static bool GUIDataStruct<t>(t data, string[] exclude)
|
|
{
|
|
Type type = data.GetType();
|
|
bool changed = false;
|
|
foreach (FieldInfo f in type.GetFields())
|
|
{
|
|
bool skip = false;
|
|
foreach (string s in exclude)
|
|
if (s == f.Name)
|
|
skip = true;
|
|
if (skip)
|
|
continue;
|
|
|
|
if (f.FieldType.IsEnum)
|
|
changed |= GUIEnum(f, data);
|
|
else if (f.FieldType == typeof(string))
|
|
changed |= GUIString(f, data);
|
|
else if (f.FieldType == typeof(int))
|
|
changed |= GUIInt(f, data);
|
|
else if (f.FieldType == typeof(float))
|
|
changed |= GUIFloat(f, data);
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
private static bool GUIEnum(FieldInfo f, object o)
|
|
{
|
|
EditorGUI.BeginChangeCheck();
|
|
Enum e = EditorGUILayout.EnumPopup(f.Name, (Enum)f.GetValue(o), GUILayout.ExpandWidth(false));
|
|
bool changed = EditorGUI.EndChangeCheck();
|
|
if (changed)
|
|
f.SetValue(o, e);
|
|
return changed;
|
|
}
|
|
|
|
private static bool GUIString(FieldInfo f, object o)
|
|
{
|
|
EditorGUI.BeginChangeCheck();
|
|
string s = EditorGUILayout.TextField(f.Name, (string)f.GetValue(o), GUILayout.ExpandWidth(false));
|
|
bool changed = EditorGUI.EndChangeCheck();
|
|
if (changed)
|
|
f.SetValue(o, s);
|
|
return changed;
|
|
}
|
|
|
|
private static bool GUIInt(FieldInfo f, object o)
|
|
{
|
|
EditorGUI.BeginChangeCheck();
|
|
int i = EditorGUILayout.IntField(f.Name, (int)f.GetValue(o), GUILayout.ExpandWidth(false));
|
|
bool changed = EditorGUI.EndChangeCheck();
|
|
if (changed)
|
|
f.SetValue(o, i);
|
|
return changed;
|
|
}
|
|
|
|
private static bool GUIFloat(FieldInfo f, object o)
|
|
{
|
|
EditorGUI.BeginChangeCheck();
|
|
float i = EditorGUILayout.FloatField(f.Name, (float)f.GetValue(o), GUILayout.ExpandWidth(false));
|
|
bool changed = EditorGUI.EndChangeCheck();
|
|
if (changed)
|
|
f.SetValue(o, i);
|
|
return changed;
|
|
}
|
|
|
|
public static void DrawLocaleSelection(GUIContent label, string[] locales, int selected)
|
|
{
|
|
EditorGUI.BeginChangeCheck();
|
|
selected = EditorGUILayout.Popup(label.text, selected, locales);
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
ShaderEditor.Active.PropertyDictionary[ShaderEditor.PROPERTY_NAME_LOCALE].MaterialProperty.floatValue = selected;
|
|
ShaderEditor.ReloadActive();
|
|
}
|
|
}
|
|
|
|
public static void DrawHeader(ref bool enabled, ref bool options, GUIContent name)
|
|
{
|
|
var r = EditorGUILayout.BeginHorizontal("box");
|
|
enabled = EditorGUILayout.Toggle(enabled, EditorStyles.radioButton, GUILayout.MaxWidth(15.0f));
|
|
options = GUI.Toggle(r, options, GUIContent.none, new GUIStyle());
|
|
EditorGUILayout.LabelField(name, Styles.dropDownHeaderLabel);
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
|
|
public static void DrawMasterLabel(string shaderName, Rect parent)
|
|
{
|
|
Rect rect = new Rect(0, parent.y, parent.width, 18);
|
|
EditorGUI.LabelField(rect, "<size=16>" + shaderName + "</size>", Styles.masterLabel);
|
|
}
|
|
|
|
public static float CurrentIndentWidth()
|
|
{
|
|
return EditorGUI.indentLevel * 15;
|
|
}
|
|
// Mimics the normal map import warning - written by Orels1
|
|
static bool TextureImportWarningBox(string message) {
|
|
GUILayout.BeginVertical(new GUIStyle(EditorStyles.helpBox));
|
|
GUILayout.Label(message, new GUIStyle(EditorStyles.label) {
|
|
fontSize = 10, wordWrap = true
|
|
});
|
|
EditorGUILayout.BeginHorizontal(new GUIStyle() {
|
|
alignment = TextAnchor.MiddleRight
|
|
}, GUILayout.Height(24));
|
|
EditorGUILayout.Space();
|
|
bool buttonPress = GUILayout.Button("Fix Now", new GUIStyle("button") {
|
|
stretchWidth = false,
|
|
margin = new RectOffset(0, 0, 0, 0),
|
|
padding = new RectOffset(9, 9, 0, 0)
|
|
}, GUILayout.Height(22));
|
|
EditorGUILayout.EndHorizontal();
|
|
GUILayout.EndVertical();
|
|
return buttonPress;
|
|
}
|
|
|
|
public static void ColorspaceWarning(MaterialProperty tex, bool shouldHaveSRGB) {
|
|
if (tex.textureValue) {
|
|
string texPath = AssetDatabase.GetAssetPath(tex.textureValue);
|
|
TextureImporter texImporter;
|
|
var importer = TextureImporter.GetAtPath(texPath) as TextureImporter;
|
|
if (importer != null) {
|
|
texImporter = (TextureImporter)importer;
|
|
if (texImporter.sRGBTexture != shouldHaveSRGB) {
|
|
if (TextureImportWarningBox(shouldHaveSRGB ? EditorLocale.editor.Get("colorSpaceWarningSRGB") : EditorLocale.editor.Get("colorSpaceWarningLinear"))) {
|
|
texImporter.sRGBTexture = shouldHaveSRGB;
|
|
texImporter.SaveAndReimport();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public class CustomGUIColor : IDisposable
|
|
{
|
|
Color _prev;
|
|
public CustomGUIColor(Color color)
|
|
{
|
|
_prev = GUI.color;
|
|
GUI.color = color;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
GUI.color = _prev;
|
|
}
|
|
}
|
|
|
|
public static bool Button(Rect r, GUIStyle style)
|
|
{
|
|
return GUI.Button(r, GUIContent.none, style);
|
|
}
|
|
|
|
public static bool Button(Rect r, string tooltip, GUIStyle style)
|
|
{
|
|
return GUI.Button(r, new GUIContent("", tooltip), style);
|
|
}
|
|
|
|
public static bool Button(GUIStyle style, int width, int height)
|
|
{
|
|
Rect r = GUILayoutUtility.GetRect(width, height);
|
|
return Button(r, style);
|
|
}
|
|
|
|
public static bool ButtonWithCursor(GUIStyle style, int width, int height)
|
|
{
|
|
Rect r = GUILayoutUtility.GetRect(width, height);
|
|
EditorGUIUtility.AddCursorRect(r, MouseCursor.Link);
|
|
return Button(r, style);
|
|
}
|
|
|
|
public static bool ButtonWithCursor(GUIStyle style, string tooltip, int width, int height)
|
|
{
|
|
Rect r = GUILayoutUtility.GetRect(width, height);
|
|
EditorGUIUtility.AddCursorRect(r, MouseCursor.Link);
|
|
return Button(r, tooltip, style);
|
|
}
|
|
|
|
public static bool ButtonWithCursor(GUIStyle style, string tooltip, int width, int height, out Rect r)
|
|
{
|
|
r = GUILayoutUtility.GetRect(width, height);
|
|
EditorGUIUtility.AddCursorRect(r, MouseCursor.Link);
|
|
return Button(r, tooltip, style);
|
|
}
|
|
|
|
public static bool Button(Rect r, string tooltip, GUIStyle style, Color c)
|
|
{
|
|
Color prevColor = GUI.backgroundColor;
|
|
GUI.backgroundColor = c;
|
|
bool b = GuiHelper.Button(r, tooltip, style);
|
|
GUI.backgroundColor = prevColor;
|
|
return b;
|
|
}
|
|
|
|
public static bool Button(GUIStyle style, int width, int height, Color c)
|
|
{
|
|
Color prevColor = GUI.backgroundColor;
|
|
GUI.backgroundColor = c;
|
|
bool b = GuiHelper.Button(style, width, height);
|
|
GUI.backgroundColor = prevColor;
|
|
return b;
|
|
}
|
|
|
|
public static bool Button(Rect r, GUIStyle style, Color c, bool doColor)
|
|
{
|
|
Color prevColor = GUI.backgroundColor;
|
|
if(doColor) GUI.backgroundColor = c;
|
|
bool b = GuiHelper.Button(r, style);
|
|
GUI.backgroundColor = prevColor;
|
|
return b;
|
|
}
|
|
|
|
#region SearchableEnumPopup
|
|
public class SearchableEnumPopup : EditorWindow
|
|
{
|
|
private static SearchableEnumPopup window;
|
|
public static void CreateSearchableEnumPopup(string[] options, string selected, Action<string> setter)
|
|
{
|
|
Vector2 pos = GUIUtility.GUIToScreenPoint(Event.current.mousePosition);
|
|
pos.x = Mathf.Min(EditorWindow.focusedWindow.position.x + EditorWindow.focusedWindow.position.width - 250, pos.x);
|
|
pos.y = Mathf.Min(EditorWindow.focusedWindow.position.y + EditorWindow.focusedWindow.position.height - 200, pos.y);
|
|
|
|
if (window != null)
|
|
window.Close();
|
|
window = ScriptableObject.CreateInstance<SearchableEnumPopup>();
|
|
window.position = new Rect(pos.x, pos.y, 250, 200);
|
|
window._options = options;
|
|
window._selected = selected;
|
|
window._setter = setter;
|
|
window._searchedFor = "";
|
|
window.ShowPopup();
|
|
}
|
|
|
|
private SearchableEnumPopup() { }
|
|
|
|
string[] _options;
|
|
string _selected;
|
|
string _searchedFor;
|
|
Action<string> _setter;
|
|
|
|
bool first = true;
|
|
|
|
private void OnGUI()
|
|
{
|
|
if (GUILayout.Button("Close")) this.Close();
|
|
GUI.SetNextControlName("SearchTextField");
|
|
_searchedFor = GUILayout.TextField(_searchedFor);
|
|
string seachTerm = _searchedFor.ToLowerInvariant().TrimStart('_');
|
|
string[] filteredOptions = _options.Where(o => o.TrimStart('_').ToLowerInvariant().StartsWith(seachTerm)).ToArray();
|
|
for (int i = 0; i < 7 && i < filteredOptions.Length; i++)
|
|
{
|
|
if (GUILayout.Button(filteredOptions[i]))
|
|
{
|
|
_selected = filteredOptions[i];
|
|
_setter.Invoke(_selected);
|
|
this.Close();
|
|
}
|
|
}
|
|
if (filteredOptions.Length > 7)
|
|
{
|
|
GUILayout.Label("... More");
|
|
}
|
|
if (first)
|
|
{
|
|
GUI.FocusControl("SearchTextField");
|
|
first = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
public class BetterTooltips
|
|
{
|
|
private static Tooltip activeTooltip;
|
|
|
|
public class Tooltip
|
|
{
|
|
private GUIContent content;
|
|
private bool empty;
|
|
|
|
public bool isSelected { get; private set; } = false;
|
|
|
|
private Rect containerRect;
|
|
private Rect contentRect;
|
|
|
|
readonly static Vector2 PADDING = new Vector2(10, 10);
|
|
|
|
public Tooltip(string text)
|
|
{
|
|
content = new GUIContent(text);
|
|
empty = string.IsNullOrWhiteSpace(text);
|
|
}
|
|
|
|
public Tooltip(string text, Texture texture)
|
|
{
|
|
content = new GUIContent(text, texture);
|
|
empty = string.IsNullOrWhiteSpace(text) && texture == null;
|
|
}
|
|
|
|
public void SetText(string text)
|
|
{
|
|
content.text = text;
|
|
empty &= string.IsNullOrWhiteSpace(text);
|
|
}
|
|
|
|
public void ConditionalDraw(Rect hoverOverRect)
|
|
{
|
|
if (empty) return;
|
|
bool isSelected = hoverOverRect.Contains(Event.current.mousePosition);
|
|
if (isSelected )
|
|
{
|
|
CalculatePositions(hoverOverRect);
|
|
activeTooltip = this;
|
|
this.isSelected = true;
|
|
}
|
|
}
|
|
|
|
private void CalculatePositions(Rect hoverOverRect)
|
|
{
|
|
Vector2 contentSize = EditorStyles.label.CalcSize(content);
|
|
Vector2 containerPosition = new Vector2(Event.current.mousePosition.x - contentSize.x / 2 - PADDING.x / 2, hoverOverRect.y - contentSize.y - PADDING.y - 3);
|
|
|
|
containerPosition.x = Mathf.Max(0, containerPosition.x);
|
|
containerPosition.x = Mathf.Min(EditorGUIUtility.currentViewWidth - contentSize.x - PADDING.x, containerPosition.x);
|
|
|
|
contentRect = new Rect(containerPosition + new Vector2(PADDING.x/2, PADDING.y/2), contentSize);
|
|
containerRect = new Rect(containerPosition, contentSize + new Vector2(PADDING.x, PADDING.y));
|
|
}
|
|
|
|
public void Draw()
|
|
{
|
|
EditorGUI.DrawRect(containerRect, Styles.COLOR_BG);
|
|
EditorGUI.LabelField(contentRect, content);
|
|
isSelected = false;
|
|
}
|
|
}
|
|
|
|
public static void DrawActive()
|
|
{
|
|
if(activeTooltip != null)
|
|
{
|
|
if (activeTooltip.isSelected)
|
|
{
|
|
activeTooltip.Draw();
|
|
}
|
|
else
|
|
{
|
|
activeTooltip = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public class FooterButton
|
|
{
|
|
private GUIContent content;
|
|
private bool isTextureContent;
|
|
const int texture_height = 40;
|
|
int texture_width;
|
|
private ButtonData data;
|
|
|
|
public FooterButton(ButtonData data)
|
|
{
|
|
this.data = data;
|
|
if (data != null)
|
|
{
|
|
if (data.texture == null)
|
|
{
|
|
content = new GUIContent(data.text, data.hover);
|
|
isTextureContent = false;
|
|
}
|
|
else
|
|
{
|
|
texture_width = (int)((float)data.texture.loaded_texture.width / data.texture.loaded_texture.height * texture_height);
|
|
content = new GUIContent(data.texture.loaded_texture, data.hover);
|
|
isTextureContent = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
content = new GUIContent();
|
|
}
|
|
}
|
|
|
|
public void Draw()
|
|
{
|
|
Rect cursorRect;
|
|
if (isTextureContent)
|
|
{
|
|
if(GUILayout.Button(content, new GUIStyle(), GUILayout.MaxWidth(texture_width), GUILayout.Height(texture_height))){
|
|
data.action.Perform(ShaderEditor.Active?.Materials);
|
|
}
|
|
cursorRect = GUILayoutUtility.GetLastRect();
|
|
GUILayout.Space(8);
|
|
}
|
|
else
|
|
{
|
|
if (GUILayout.Button(content, GUILayout.ExpandWidth(false), GUILayout.Height(texture_height)))
|
|
data.action.Perform(ShaderEditor.Active?.Materials);
|
|
cursorRect = GUILayoutUtility.GetLastRect();
|
|
GUILayout.Space(2);
|
|
}
|
|
EditorGUIUtility.AddCursorRect(cursorRect, MouseCursor.Link);
|
|
}
|
|
|
|
public static void DrawList(List<FooterButton> list)
|
|
{
|
|
EditorGUILayout.BeginHorizontal();
|
|
GUILayout.FlexibleSpace();
|
|
GUILayout.Space(2);
|
|
foreach (FooterButton b in list)
|
|
{
|
|
b.Draw();
|
|
}
|
|
GUILayout.FlexibleSpace();
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
}
|
|
|
|
public class ThryHeaderHandler
|
|
{
|
|
private MaterialProperty property;
|
|
|
|
private bool _isExpanded;
|
|
private string keyword;
|
|
private string end;
|
|
|
|
private bool _disableContentWhenKeywordOff;
|
|
|
|
int p_xOffset;
|
|
int p_xOffset_total;
|
|
public int xOffset
|
|
{
|
|
set
|
|
{
|
|
p_xOffset = value;
|
|
p_xOffset_total = value * 15 + 15;
|
|
}
|
|
}
|
|
|
|
private ButtonData button;
|
|
|
|
public ThryHeaderHandler(string end, string keyword, float disableContentWhenKeywordOff)
|
|
{
|
|
this.end = end;
|
|
this.keyword = keyword;
|
|
this._disableContentWhenKeywordOff = disableContentWhenKeywordOff == 1;
|
|
}
|
|
|
|
public ThryHeaderHandler(string end, string keyword) : this(end, keyword, 0) { }
|
|
public ThryHeaderHandler(string end) : this(end, null, 0) { }
|
|
public ThryHeaderHandler() : this(null, null, 0) { }
|
|
|
|
public string GetEndProperty()
|
|
{
|
|
return end;
|
|
}
|
|
|
|
public bool IsExpanded
|
|
{
|
|
get
|
|
{
|
|
return _isExpanded;
|
|
}
|
|
}
|
|
|
|
public bool DisableContent
|
|
{
|
|
get
|
|
{
|
|
return _disableContentWhenKeywordOff && !ShaderEditor.Active.Materials[0].IsKeywordEnabled(keyword);
|
|
}
|
|
}
|
|
|
|
public void Toggle()
|
|
{
|
|
_isExpanded = !_isExpanded;
|
|
foreach (Material m in ShaderEditor.Active.Materials) m.SetFloat(property.name, _isExpanded ? 1 : 0);
|
|
}
|
|
|
|
public void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor)
|
|
{
|
|
if (this.property == null)
|
|
{
|
|
this.property = prop;
|
|
this._isExpanded = prop.floatValue == 1;
|
|
}
|
|
|
|
PropertyOptions options = ShaderEditor.Active.CurrentProperty.Options;
|
|
Event e = Event.current;
|
|
|
|
position.width -= p_xOffset_total - position.x;
|
|
position.x = p_xOffset_total;
|
|
|
|
DrawingData.LastGuiObjectHeaderRect = position;
|
|
|
|
DrawBoxAndContent(position, e, label, options);
|
|
|
|
DrawSmallArrow(position, e);
|
|
HandleToggleInput(position);
|
|
}
|
|
|
|
private void DrawBoxAndContent(Rect rect, Event e, GUIContent content, PropertyOptions options)
|
|
{
|
|
if (options.reference_property != null && ShaderEditor.Active.PropertyDictionary.ContainsKey(options.reference_property))
|
|
{
|
|
GUI.Box(rect, new GUIContent(" " + content.text, content.tooltip), Styles.dropDownHeader);
|
|
DrawIcons(rect, options, e);
|
|
|
|
Rect togglePropertyRect = new Rect(rect);
|
|
togglePropertyRect.x += 5;
|
|
togglePropertyRect.y += 1;
|
|
togglePropertyRect.height -= 4;
|
|
togglePropertyRect.width = GUI.skin.font.fontSize * 3;
|
|
float fieldWidth = EditorGUIUtility.fieldWidth;
|
|
EditorGUIUtility.fieldWidth = 20;
|
|
ShaderProperty prop = ShaderEditor.Active.PropertyDictionary[options.reference_property];
|
|
|
|
int xOffset = prop.XOffset;
|
|
prop.XOffset = 0;
|
|
prop.Draw(new CRect(togglePropertyRect), new GUIContent(), isInHeader: true);
|
|
prop.XOffset = xOffset;
|
|
EditorGUIUtility.fieldWidth = fieldWidth;
|
|
}else if(keyword != null)
|
|
{
|
|
GUI.Box(rect, " " + content.text, Styles.dropDownHeader);
|
|
DrawIcons(rect, options, e);
|
|
|
|
Rect togglePropertyRect = new Rect(rect);
|
|
togglePropertyRect.x += 20;
|
|
togglePropertyRect.width = 20;
|
|
|
|
EditorGUI.BeginChangeCheck();
|
|
bool keywordOn = EditorGUI.Toggle(togglePropertyRect, "", ShaderEditor.Active.Materials[0].IsKeywordEnabled(keyword));
|
|
if (EditorGUI.EndChangeCheck())
|
|
{
|
|
MaterialHelper.ToggleKeyword(ShaderEditor.Active.Materials, keyword, keywordOn);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GUI.Box(rect, content, Styles.dropDownHeader);
|
|
DrawIcons(rect, options, e);
|
|
}
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Draws the icons for ShaderEditor features like linking and copying
|
|
/// </summary>
|
|
/// <param name="rect"></param>
|
|
/// <param name="e"></param>
|
|
private void DrawIcons(Rect rect, PropertyOptions options, Event e)
|
|
{
|
|
Rect buttonRect = new Rect(rect);
|
|
buttonRect.y += 1;
|
|
buttonRect.height -= 4;
|
|
buttonRect.width = buttonRect.height;
|
|
|
|
float right = rect.x + rect.width;
|
|
buttonRect.x = right - 56;
|
|
DrawHelpButton(buttonRect, options, e);
|
|
buttonRect.x = right - 38;
|
|
DrawLinkSettings(buttonRect, e);
|
|
buttonRect.x = right - 20;
|
|
DrawDowdownSettings(buttonRect, e);
|
|
}
|
|
|
|
private void DrawHelpButton(Rect rect, PropertyOptions options, Event e)
|
|
{
|
|
ButtonData button = this.button != null ? this.button : options.button_help;
|
|
if (button != null && button.condition_show.Test())
|
|
{
|
|
if (GuiHelper.Button(rect, Styles.icon_style_help))
|
|
{
|
|
ShaderEditor.Input.Use();
|
|
if (button.action != null) button.action.Perform(ShaderEditor.Active?.Materials);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DrawDowdownSettings(Rect rect, Event e)
|
|
{
|
|
if (GuiHelper.Button(rect, Styles.icon_style_menu))
|
|
{
|
|
ShaderEditor.Input.Use();
|
|
Rect buttonRect = new Rect(rect);
|
|
buttonRect.width = 150;
|
|
buttonRect.x = Mathf.Min(Screen.width - buttonRect.width, buttonRect.x);
|
|
buttonRect.height = 60;
|
|
float maxY = GUIUtility.ScreenToGUIPoint(new Vector2(0, EditorWindow.focusedWindow.position.y + Screen.height)).y - 2.5f * buttonRect.height;
|
|
buttonRect.y = Mathf.Min(buttonRect.y - buttonRect.height / 2, maxY);
|
|
|
|
ShowHeaderContextMenu(buttonRect, ShaderEditor.Active.CurrentProperty, ShaderEditor.Active.Materials[0]);
|
|
}
|
|
}
|
|
|
|
private void DrawLinkSettings(Rect rect, Event e)
|
|
{
|
|
if (GuiHelper.Button(rect, Styles.icon_style_linked, Styles.COLOR_ICON_ACTIVE_CYAN, MaterialLinker.IsLinked(ShaderEditor.Active.CurrentProperty.MaterialProperty)))
|
|
{
|
|
ShaderEditor.Input.Use();
|
|
List<Material> linked_materials = MaterialLinker.GetLinked(ShaderEditor.Active.CurrentProperty.MaterialProperty);
|
|
MaterialLinker.Popup(rect, linked_materials, ShaderEditor.Active.CurrentProperty.MaterialProperty);
|
|
}
|
|
}
|
|
|
|
void ShowHeaderContextMenu(Rect position, ShaderPart property, Material material)
|
|
{
|
|
var menu = new GenericMenu();
|
|
menu.AddItem(new GUIContent("Reset"), false, delegate ()
|
|
{
|
|
property.CopyFromMaterial(new Material(material.shader), true);
|
|
List<Material> linked_materials = MaterialLinker.GetLinked(property.MaterialProperty);
|
|
if (linked_materials != null)
|
|
foreach (Material m in linked_materials)
|
|
property.CopyToMaterial(m, true);
|
|
});
|
|
menu.AddItem(new GUIContent("Copy"), false, delegate ()
|
|
{
|
|
Mediator.copy_material = new Material(material);
|
|
Mediator.transfer_group = property;
|
|
});
|
|
menu.AddItem(new GUIContent("Paste"), false, delegate ()
|
|
{
|
|
if (Mediator.copy_material != null || Mediator.transfer_group != null)
|
|
{
|
|
property.TransferFromMaterialAndGroup(Mediator.copy_material, Mediator.transfer_group, true);
|
|
List<Material> linked_materials = MaterialLinker.GetLinked(property.MaterialProperty);
|
|
if (linked_materials != null)
|
|
foreach (Material m in linked_materials)
|
|
property.CopyToMaterial(m, true);
|
|
}
|
|
});
|
|
menu.DropDown(position);
|
|
}
|
|
|
|
private void DrawSmallArrow(Rect rect, Event e)
|
|
{
|
|
if (e.type == EventType.Repaint)
|
|
{
|
|
var toggleRect = new Rect(rect.x + 4f, rect.y + 2f, 13f, 13f);
|
|
EditorStyles.foldout.Draw(toggleRect, false, false, _isExpanded, false);
|
|
}
|
|
}
|
|
|
|
private void HandleToggleInput(Rect rect)
|
|
{
|
|
//Ignore unity uses is cause disabled will use the event to prevent toggling
|
|
if (ShaderEditor.Input.LeftClick_IgnoreLocked && rect.Contains(ShaderEditor.Input.mouse_position) && !ShaderEditor.Input.is_alt_down)
|
|
{
|
|
this.Toggle();
|
|
ShaderEditor.Input.Use();
|
|
}
|
|
}
|
|
}
|
|
} |