摄像机区域的架构改动
This commit is contained in:
8
Assets/LWGUI-1.14.1/Editor.meta
Normal file
8
Assets/LWGUI-1.14.1/Editor.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b52e0d522f65164499cf8492ceb64ba1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/LWGUI-1.14.1/Editor/CustomGUISample.meta
Normal file
8
Assets/LWGUI-1.14.1/Editor/CustomGUISample.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c58e502017a33d04bb7c64ae8348898d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
21
Assets/LWGUI-1.14.1/Editor/CustomGUISample/CustomFooter.cs
Normal file
21
Assets/LWGUI-1.14.1/Editor/CustomGUISample/CustomFooter.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace LWGUI.CustomGUISample
|
||||
{
|
||||
public static class CustomFooter
|
||||
{
|
||||
public static void DoCustomFooter(LWGUI lwgui)
|
||||
{
|
||||
// Draw your custom gui...
|
||||
|
||||
// Debug.Log(lwgui.shader);
|
||||
}
|
||||
|
||||
[InitializeOnLoadMethod]
|
||||
private static void RegisterEvent()
|
||||
{
|
||||
LWGUI.onDrawCustomFooter += DoCustomFooter;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 421a56cca25d486298053d5eeca0c669
|
||||
timeCreated: 1688612200
|
||||
21
Assets/LWGUI-1.14.1/Editor/CustomGUISample/CustomHeader.cs
Normal file
21
Assets/LWGUI-1.14.1/Editor/CustomGUISample/CustomHeader.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace LWGUI.CustomGUISample
|
||||
{
|
||||
public static class CustomHeader
|
||||
{
|
||||
public static void DoCustomHeader(LWGUI lwgui)
|
||||
{
|
||||
// Draw your custom gui...
|
||||
|
||||
// Debug.Log(lwgui.shader);
|
||||
}
|
||||
|
||||
[InitializeOnLoadMethod]
|
||||
private static void RegisterEvent()
|
||||
{
|
||||
LWGUI.onDrawCustomHeader += DoCustomHeader;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 12f48d96821d4f33aa8d9a7618a9ae0b
|
||||
timeCreated: 1688613396
|
||||
934
Assets/LWGUI-1.14.1/Editor/Helper.cs
Normal file
934
Assets/LWGUI-1.14.1/Editor/Helper.cs
Normal file
@@ -0,0 +1,934 @@
|
||||
// Copyright (c) Jason Ma
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Misc Function
|
||||
/// </summary>
|
||||
public class Helper
|
||||
{
|
||||
#region Engine Misc
|
||||
|
||||
public static void ObsoleteWarning(string obsoleteStr, string newStr)
|
||||
{
|
||||
Debug.LogWarning("'" + obsoleteStr + "' is Obsolete! Please use '" + newStr + "'!");
|
||||
}
|
||||
|
||||
public static bool PropertyValueEquals(MaterialProperty prop1, MaterialProperty prop2)
|
||||
{
|
||||
if (prop1.textureValue == prop2.textureValue
|
||||
&& prop1.vectorValue == prop2.vectorValue
|
||||
&& prop1.colorValue == prop2.colorValue
|
||||
&& prop1.floatValue == prop2.floatValue
|
||||
#if UNITY_2021_1_OR_NEWER
|
||||
&& prop1.intValue == prop2.intValue
|
||||
#endif
|
||||
)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsPropertyHideInInspector(MaterialProperty prop)
|
||||
{
|
||||
return (prop.flags & MaterialProperty.PropFlags.HideInInspector) != 0;
|
||||
}
|
||||
|
||||
public static string GetKeyWord(string keyWord, string propName)
|
||||
{
|
||||
string k;
|
||||
if (string.IsNullOrEmpty(keyWord) || keyWord == "__")
|
||||
{
|
||||
k = propName.ToUpperInvariant() + "_ON";
|
||||
}
|
||||
else
|
||||
{
|
||||
k = keyWord.ToUpperInvariant();
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
public static void SetShaderKeyWord(Object[] materials, string keyWord, bool isEnable)
|
||||
{
|
||||
if (string.IsNullOrEmpty(keyWord) || string.IsNullOrEmpty(keyWord)) return;
|
||||
|
||||
foreach (Material m in materials)
|
||||
{
|
||||
// delete "_" keywords
|
||||
if (keyWord == "_")
|
||||
{
|
||||
if (m.IsKeywordEnabled(keyWord))
|
||||
{
|
||||
m.DisableKeyword(keyWord);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m.IsKeywordEnabled(keyWord))
|
||||
{
|
||||
if (!isEnable) m.DisableKeyword(keyWord);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isEnable) m.EnableKeyword(keyWord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetShaderKeyWord(Object[] materials, string[] keyWords, int index)
|
||||
{
|
||||
Debug.Assert(keyWords.Length >= 1 && index < keyWords.Length && index >= 0,
|
||||
"KeyWords Length: " + keyWords.Length + " or Index: " + index + " Error! ");
|
||||
for (int i = 0; i < keyWords.Length; i++)
|
||||
{
|
||||
SetShaderKeyWord(materials, keyWords[i], index == i);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetShaderPassEnabled(Object[] materials, string[] lightModeNames, bool enabled)
|
||||
{
|
||||
if (lightModeNames.Length == 0) return;
|
||||
|
||||
foreach (Material material in materials)
|
||||
{
|
||||
for (int i = 0; i < lightModeNames.Length; i++)
|
||||
{
|
||||
material.SetShaderPassEnabled(lightModeNames[i], enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// make Drawer can get all current Material props by customShaderGUI
|
||||
/// Unity 2019.2+
|
||||
/// </summary>
|
||||
public static LWGUI GetLWGUI(MaterialEditor editor)
|
||||
{
|
||||
var customShaderGUI = ReflectionHelper.GetCustomShaderGUI(editor);
|
||||
if (customShaderGUI != null && customShaderGUI is LWGUI)
|
||||
{
|
||||
LWGUI gui = customShaderGUI as LWGUI;
|
||||
return gui;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("Please add \"CustomEditor \"LWGUI.LWGUI\"\" to the end of your shader!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void AdaptiveFieldWidth(GUIStyle style, GUIContent content, float extraWidth = 0)
|
||||
{
|
||||
var extraTextWidth = Mathf.Max(0, style.CalcSize(content).x + extraWidth - EditorGUIUtility.fieldWidth);
|
||||
EditorGUIUtility.labelWidth -= extraTextWidth;
|
||||
EditorGUIUtility.fieldWidth += extraTextWidth;
|
||||
}
|
||||
|
||||
public static void BeginProperty(Rect rect, MaterialProperty property, LWGUI lwgui)
|
||||
{
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
MaterialEditor.BeginProperty(rect, property);
|
||||
foreach (var extraPropName in lwgui.perShaderData.propertyDatas[property.name].extraPropNames)
|
||||
MaterialEditor.BeginProperty(rect, lwgui.perFrameData.propertyDatas[extraPropName].property);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void EndProperty(LWGUI lwgui, MaterialProperty property)
|
||||
{
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
MaterialEditor.EndProperty();
|
||||
foreach (var extraPropName in lwgui.perShaderData.propertyDatas[property.name].extraPropNames)
|
||||
MaterialEditor.EndProperty();
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool EndChangeCheck(LWGUI lwgui, MaterialProperty property)
|
||||
{
|
||||
return lwgui.perFrameData.EndChangeCheck(property.name);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Math
|
||||
|
||||
public static float PowPreserveSign(float f, float p)
|
||||
{
|
||||
float num = Mathf.Pow(Mathf.Abs(f), p);
|
||||
if ((double)f < 0.0)
|
||||
return -num;
|
||||
return num;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region GUI Styles
|
||||
|
||||
// Tips: Use properties to fix null reference errors
|
||||
|
||||
private static GUIStyle _guiStyles_IconButton;
|
||||
public static GUIStyle guiStyles_IconButton
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_guiStyles_IconButton == null)
|
||||
{
|
||||
_guiStyles_IconButton = new GUIStyle(
|
||||
#if UNITY_2021_2_OR_NEWER
|
||||
EditorStyles.iconButton
|
||||
#else
|
||||
"iconButton"
|
||||
#endif
|
||||
) { fixedHeight = 0, fixedWidth = 0 };
|
||||
}
|
||||
return _guiStyles_IconButton;
|
||||
}
|
||||
}
|
||||
|
||||
private static GUIStyle _guiStyle_Foldout;
|
||||
|
||||
public static GUIStyle guiStyle_Foldout
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_guiStyle_Foldout == null)
|
||||
{
|
||||
_guiStyle_Foldout =
|
||||
new GUIStyle(EditorStyles.miniButton)
|
||||
{
|
||||
contentOffset = new Vector2(22, 0),
|
||||
fixedHeight = 27,
|
||||
alignment = TextAnchor.MiddleLeft,
|
||||
font = EditorStyles.boldLabel.font,
|
||||
fontSize = EditorStyles.boldLabel.fontSize
|
||||
#if UNITY_2019_4_OR_NEWER
|
||||
+ 1,
|
||||
#endif
|
||||
};
|
||||
}
|
||||
return _guiStyle_Foldout;
|
||||
}
|
||||
}
|
||||
|
||||
private static GUIStyle _guiStyle_Helpbox;
|
||||
|
||||
public static GUIStyle guiStyle_Helpbox
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_guiStyle_Helpbox == null)
|
||||
{
|
||||
_guiStyle_Helpbox = new GUIStyle(EditorStyles.helpBox) { fontSize = 12 };
|
||||
}
|
||||
return _guiStyle_Helpbox;
|
||||
}
|
||||
}
|
||||
|
||||
private static GUIStyle _guiStyles_ToolbarSearchTextFieldPopup;
|
||||
public static GUIStyle guiStyles_ToolbarSearchTextFieldPopup
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_guiStyles_ToolbarSearchTextFieldPopup == null)
|
||||
{
|
||||
string toolbarSeachTextFieldPopupStr = "ToolbarSeachTextFieldPopup";
|
||||
{
|
||||
// ToolbarSeachTextFieldPopup has renamed at Unity 2021.3.28+
|
||||
#if !UNITY_2022_3_OR_NEWER
|
||||
string[] versionParts = Application.unityVersion.Split('.');
|
||||
int majorVersion = int.Parse(versionParts[0]);
|
||||
int minorVersion = int.Parse(versionParts[1]);
|
||||
Match patchVersionMatch = Regex.Match(versionParts[2], @"\d+");
|
||||
int patchVersion = int.Parse(patchVersionMatch.Value);
|
||||
if (majorVersion >= 2021 && minorVersion >= 3 && patchVersion >= 28)
|
||||
#endif
|
||||
{
|
||||
toolbarSeachTextFieldPopupStr = "ToolbarSearchTextFieldPopup";
|
||||
}
|
||||
}
|
||||
_guiStyles_ToolbarSearchTextFieldPopup = new GUIStyle(toolbarSeachTextFieldPopupStr);
|
||||
}
|
||||
return _guiStyles_ToolbarSearchTextFieldPopup;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Draw GUI for Drawer
|
||||
|
||||
// TODO: use Reflection
|
||||
// copy and edit of https://github.com/GucioDevs/SimpleMinMaxSlider/blob/master/Assets/SimpleMinMaxSlider/Scripts/Editor/MinMaxSliderDrawer.cs
|
||||
public static Rect[] SplitRect(Rect rectToSplit, int n)
|
||||
{
|
||||
Rect[] rects = new Rect[n];
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
rects[i] = new Rect(rectToSplit.position.x + (i * rectToSplit.width / n), rectToSplit.position.y,
|
||||
rectToSplit.width / n, rectToSplit.height);
|
||||
}
|
||||
|
||||
int padding = (int)rects[0].width - 50; // use 50, enough to show 0.xx (2 digits)
|
||||
int space = 5;
|
||||
|
||||
rects[0].width -= padding + space;
|
||||
rects[2].width -= padding + space;
|
||||
|
||||
rects[1].x -= padding;
|
||||
rects[1].width += padding * 2;
|
||||
|
||||
rects[2].x += padding + space;
|
||||
|
||||
return rects;
|
||||
}
|
||||
|
||||
|
||||
public static bool DrawFoldout(Rect rect, ref bool isFolding, bool toggleValue, bool hasToggle, GUIContent label)
|
||||
{
|
||||
var toggleRect = new Rect(rect.x + 8f, rect.y + 7f, 13f, 13f);
|
||||
|
||||
// Toggle Event
|
||||
if (hasToggle)
|
||||
{
|
||||
if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && toggleRect.Contains(Event.current.mousePosition))
|
||||
{
|
||||
toggleValue = !toggleValue;
|
||||
Event.current.Use();
|
||||
GUI.changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Button
|
||||
{
|
||||
// Cancel Right Click
|
||||
if (Event.current.type == EventType.MouseDown && Event.current.button == 1 && rect.Contains(Event.current.mousePosition))
|
||||
Event.current.Use();
|
||||
|
||||
var enabled = GUI.enabled;
|
||||
GUI.enabled = true;
|
||||
var guiColor = GUI.backgroundColor;
|
||||
GUI.backgroundColor = isFolding ? Color.white : new Color(0.85f, 0.85f, 0.85f);
|
||||
if (GUI.Button(rect, label, guiStyle_Foldout))
|
||||
{
|
||||
isFolding = !isFolding;
|
||||
GUI.changed = false;
|
||||
}
|
||||
GUI.backgroundColor = guiColor;
|
||||
GUI.enabled = enabled;
|
||||
}
|
||||
|
||||
// Toggle Icon
|
||||
if (hasToggle)
|
||||
{
|
||||
EditorGUI.Toggle(toggleRect, string.Empty, toggleValue);
|
||||
}
|
||||
|
||||
return toggleValue;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Draw GUI for Material
|
||||
|
||||
public static void DrawSplitLine()
|
||||
{
|
||||
var rect = EditorGUILayout.GetControlRect(true, 1);
|
||||
rect.x = 0;
|
||||
rect.width = EditorGUIUtility.currentViewWidth;
|
||||
EditorGUI.DrawRect(rect, new Color(0, 0, 0, 0.45f));
|
||||
}
|
||||
|
||||
private static readonly Texture2D _helpboxIcon = EditorGUIUtility.IconContent("console.infoicon").image as Texture2D;
|
||||
|
||||
public static void DrawHelpbox(PropertyStaticData propertyStaticData, PropertyDynamicData propertyDynamicData)
|
||||
{
|
||||
var helpboxStr = propertyStaticData.helpboxMessages;
|
||||
if (!string.IsNullOrEmpty(helpboxStr))
|
||||
{
|
||||
var content = new GUIContent(helpboxStr, _helpboxIcon);
|
||||
var helpboxRect = EditorGUI.IndentedRect(EditorGUILayout.GetControlRect(true, guiStyle_Helpbox.CalcHeight(content, EditorGUIUtility.currentViewWidth)));
|
||||
helpboxRect.xMax -= RevertableHelper.revertButtonWidth;
|
||||
GUI.Label(helpboxRect, content, guiStyle_Helpbox);
|
||||
// EditorGUI.HelpBox(helpboxRect, helpboxStr, MessageType.Info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static Texture _logo = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("26b9d845eb7b1a747bf04dc84e5bcc2c"));
|
||||
private static GUIContent _logoGuiContent = new GUIContent(string.Empty, _logo,
|
||||
"LWGUI (Light Weight Shader GUI)\n\n"
|
||||
+ "A Lightweight, Flexible, Powerful Unity Shader GUI system.\n\n"
|
||||
+ "Copyright (c) Jason Ma");
|
||||
|
||||
public static void DrawLogo()
|
||||
{
|
||||
var logoRect = EditorGUILayout.GetControlRect(false, _logo.height);
|
||||
var w = logoRect.width;
|
||||
logoRect.xMin += w * 0.5f - _logo.width * 0.5f;
|
||||
logoRect.xMax -= w * 0.5f - _logo.width * 0.5f;
|
||||
|
||||
if (EditorGUIUtility.currentViewWidth >= logoRect.width && GUI.Button(logoRect, _logoGuiContent, guiStyles_IconButton))
|
||||
{
|
||||
Application.OpenURL("https://github.com/JasonMa0012/LWGUI");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Toolbar Buttons
|
||||
private static Material _copiedMaterial;
|
||||
private static List<string> _copiedProps = new List<string>();
|
||||
|
||||
private static Texture _iconCopy = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("9cdef444d18d2ce4abb6bbc4fed4d109"));
|
||||
private static Texture _iconPaste = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("8e7a78d02e4c3574998524a0842a8ccb"));
|
||||
private static Texture _iconSelect = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("6f44e40b24300974eb607293e4224ecc"));
|
||||
private static Texture _iconCheckout = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("72488141525eaa8499e65e52755cb6d0"));
|
||||
private static Texture _iconExpand = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("2382450e7f4ddb94c9180d6634c41378"));
|
||||
private static Texture _iconCollapse = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("929b6e5dfacc42b429d715a3e1ca2b57"));
|
||||
private static Texture _iconVisibility = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("9576e23a695b35d49a9fc55c9a948b4f"));
|
||||
|
||||
private static GUIContent _guiContentCopy = new GUIContent("", _iconCopy, "Copy Material Properties");
|
||||
private static GUIContent _guiContentPaste = new GUIContent("", _iconPaste, "Paste Material Properties\n\nRight-click to paste values by type.");
|
||||
private static GUIContent _guiContentSelect = new GUIContent("", _iconSelect, "Select the Material Asset\n\nUsed to jump from a Runtime Material Instance to a Material Asset.");
|
||||
private static GUIContent _guiContentChechout = new GUIContent("", _iconCheckout, "Checkout selected Material Assets");
|
||||
private static GUIContent _guiContentExpand = new GUIContent("", _iconExpand, "Expand All Groups");
|
||||
private static GUIContent _guiContentCollapse = new GUIContent("", _iconCollapse, "Collapse All Groups");
|
||||
private static GUIContent _guiContentVisibility = new GUIContent("", _iconVisibility, "Display Mode");
|
||||
|
||||
private static string[] _materialInstanceNameEnd = new[] { "_Instantiated", " (Instance)" };
|
||||
|
||||
private enum CopyMaterialValueMask
|
||||
{
|
||||
Float = 1 << 0,
|
||||
Vector = 1 << 1,
|
||||
Texture = 1 << 2,
|
||||
Keyword = 1 << 3,
|
||||
RenderQueue = 1 << 4,
|
||||
Number = Float | Vector,
|
||||
All = (1 << 5) - 1,
|
||||
}
|
||||
|
||||
private static GUIContent[] _pasteMaterialMenus = new[]
|
||||
{
|
||||
new GUIContent("Paste Number Values"),
|
||||
new GUIContent("Paste Texture Values"),
|
||||
new GUIContent("Paste Keywords"),
|
||||
new GUIContent("Paste RenderQueue"),
|
||||
};
|
||||
|
||||
private static uint[] _pasteMaterialMenuValueMasks = new[]
|
||||
{
|
||||
(uint)CopyMaterialValueMask.Number,
|
||||
(uint)CopyMaterialValueMask.Texture,
|
||||
(uint)CopyMaterialValueMask.Keyword,
|
||||
(uint)CopyMaterialValueMask.RenderQueue,
|
||||
};
|
||||
|
||||
private static void DoPasteMaterialProperties(LWGUI lwgui , uint valueMask)
|
||||
{
|
||||
if (!_copiedMaterial)
|
||||
{
|
||||
Debug.LogError("Please copy Material Properties first!");
|
||||
return;
|
||||
}
|
||||
foreach (Material material in lwgui.materialEditor.targets)
|
||||
{
|
||||
if (!VersionControlHelper.Checkout(material))
|
||||
{
|
||||
Debug.LogError("Material: '" + lwgui.material.name + "' unable to write!");
|
||||
return;
|
||||
}
|
||||
|
||||
Undo.RecordObject(material, "Paste Material Properties");
|
||||
for (int i = 0; i < ShaderUtil.GetPropertyCount(_copiedMaterial.shader); i++)
|
||||
{
|
||||
var name = ShaderUtil.GetPropertyName(_copiedMaterial.shader, i);
|
||||
var type = ShaderUtil.GetPropertyType(_copiedMaterial.shader, i);
|
||||
PastePropertyValueToMaterial(material, name, name, type, valueMask);
|
||||
}
|
||||
if ((valueMask & (uint)CopyMaterialValueMask.Keyword) != 0)
|
||||
material.shaderKeywords = _copiedMaterial.shaderKeywords;
|
||||
if ((valueMask & (uint)CopyMaterialValueMask.RenderQueue) != 0)
|
||||
material.renderQueue = _copiedMaterial.renderQueue;
|
||||
}
|
||||
}
|
||||
|
||||
private static void PastePropertyValueToMaterial(Material material, string srcName, string dstName)
|
||||
{
|
||||
for (int i = 0; i < ShaderUtil.GetPropertyCount(_copiedMaterial.shader); i++)
|
||||
{
|
||||
var name = ShaderUtil.GetPropertyName(_copiedMaterial.shader, i);
|
||||
if (name == srcName)
|
||||
{
|
||||
var type = ShaderUtil.GetPropertyType(_copiedMaterial.shader, i);
|
||||
PastePropertyValueToMaterial(material, srcName, dstName, type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void PastePropertyValueToMaterial(Material material, string srcName, string dstName, ShaderUtil.ShaderPropertyType type, uint valueMask = (uint)CopyMaterialValueMask.All)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ShaderUtil.ShaderPropertyType.Color:
|
||||
if ((valueMask & (uint)CopyMaterialValueMask.Vector) != 0)
|
||||
material.SetColor(dstName, _copiedMaterial.GetColor(srcName));
|
||||
break;
|
||||
case ShaderUtil.ShaderPropertyType.Vector:
|
||||
if ((valueMask & (uint)CopyMaterialValueMask.Vector) != 0)
|
||||
material.SetVector(dstName, _copiedMaterial.GetVector(srcName));
|
||||
break;
|
||||
case ShaderUtil.ShaderPropertyType.TexEnv:
|
||||
if ((valueMask & (uint)CopyMaterialValueMask.Texture) != 0)
|
||||
material.SetTexture(dstName, _copiedMaterial.GetTexture(srcName));
|
||||
break;
|
||||
// Float
|
||||
default:
|
||||
if ((valueMask & (uint)CopyMaterialValueMask.Float) != 0)
|
||||
material.SetFloat(dstName, _copiedMaterial.GetFloat(srcName));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawToolbarButtons(ref Rect toolBarRect, LWGUI lwgui)
|
||||
{
|
||||
// Copy
|
||||
var buttonRectOffset = toolBarRect.height + 2;
|
||||
var buttonRect = new Rect(toolBarRect.x, toolBarRect.y, toolBarRect.height, toolBarRect.height);
|
||||
toolBarRect.xMin += buttonRectOffset;
|
||||
if (GUI.Button(buttonRect, _guiContentCopy, Helper.guiStyles_IconButton))
|
||||
{
|
||||
_copiedMaterial = UnityEngine.Object.Instantiate(lwgui.material);
|
||||
}
|
||||
|
||||
// Paste
|
||||
buttonRect.x += buttonRectOffset;
|
||||
toolBarRect.xMin += buttonRectOffset;
|
||||
// Right Click
|
||||
if (Event.current.type == EventType.MouseDown
|
||||
&& Event.current.button == 1
|
||||
&& buttonRect.Contains(Event.current.mousePosition))
|
||||
{
|
||||
EditorUtility.DisplayCustomMenu(new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 0, 0), _pasteMaterialMenus, -1,
|
||||
(data, options, selected) =>
|
||||
{
|
||||
DoPasteMaterialProperties(lwgui, _pasteMaterialMenuValueMasks[selected]);
|
||||
}, null);
|
||||
Event.current.Use();
|
||||
}
|
||||
// Left Click
|
||||
if (GUI.Button(buttonRect, _guiContentPaste, Helper.guiStyles_IconButton))
|
||||
{
|
||||
DoPasteMaterialProperties(lwgui, (uint)CopyMaterialValueMask.All);
|
||||
}
|
||||
|
||||
// Select Material Asset, jump from a Runtime Material Instance to a Material Asset
|
||||
buttonRect.x += buttonRectOffset;
|
||||
toolBarRect.xMin += buttonRectOffset;
|
||||
if (GUI.Button(buttonRect, _guiContentSelect, Helper.guiStyles_IconButton))
|
||||
{
|
||||
if (AssetDatabase.Contains(lwgui.material))
|
||||
{
|
||||
Selection.activeObject = lwgui.material;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get Material Asset name
|
||||
var name = lwgui.material.name;
|
||||
foreach (var nameEnd in _materialInstanceNameEnd)
|
||||
{
|
||||
if (name.EndsWith(nameEnd))
|
||||
{
|
||||
name = name.Substring(0, name.Length - nameEnd.Length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get path
|
||||
var guids = AssetDatabase.FindAssets("t:Material " + name);
|
||||
var paths = guids.Select(((guid, i) =>
|
||||
{
|
||||
var filePath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
var fileName = System.IO.Path.GetFileNameWithoutExtension(filePath);
|
||||
return (fileName == name && filePath.EndsWith(".mat")) ? filePath : null;
|
||||
})).Where((s => !string.IsNullOrEmpty(s))).ToArray();
|
||||
|
||||
// Select Asset
|
||||
if (paths.Length == 0)
|
||||
{
|
||||
Debug.LogError("Can not find Material Assets with name: " + name);
|
||||
}
|
||||
else if (paths.Length > 1)
|
||||
{
|
||||
var str = string.Empty;
|
||||
foreach (string path in paths)
|
||||
{
|
||||
str += "\n" + path;
|
||||
}
|
||||
Debug.LogWarning("Multiple Material Assets with the same name have been found, select only the first one:" + str);
|
||||
Selection.activeObject = AssetDatabase.LoadAssetAtPath<Material>(paths[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Selection.activeObject = AssetDatabase.LoadAssetAtPath<Material>(paths[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Checkout
|
||||
buttonRect.x += buttonRectOffset;
|
||||
toolBarRect.xMin += buttonRectOffset;
|
||||
if (GUI.Button(buttonRect, _guiContentChechout, Helper.guiStyles_IconButton))
|
||||
{
|
||||
foreach (var material in lwgui.materialEditor.targets)
|
||||
{
|
||||
VersionControlHelper.Checkout(material);
|
||||
}
|
||||
}
|
||||
|
||||
// Expand
|
||||
buttonRect.x += buttonRectOffset;
|
||||
toolBarRect.xMin += buttonRectOffset;
|
||||
if (GUI.Button(buttonRect, _guiContentExpand, Helper.guiStyles_IconButton))
|
||||
{
|
||||
foreach (var propertyStaticDataPair in lwgui.perShaderData.propertyDatas)
|
||||
{
|
||||
if (propertyStaticDataPair.Value.isMain || propertyStaticDataPair.Value.isAdvancedHeader)
|
||||
propertyStaticDataPair.Value.isExpanding = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Collapse
|
||||
buttonRect.x += buttonRectOffset;
|
||||
toolBarRect.xMin += buttonRectOffset;
|
||||
if (GUI.Button(buttonRect, _guiContentCollapse, Helper.guiStyles_IconButton))
|
||||
{
|
||||
foreach (var propertyStaticDataPair in lwgui.perShaderData.propertyDatas)
|
||||
{
|
||||
if (propertyStaticDataPair.Value.isMain || propertyStaticDataPair.Value.isAdvancedHeader)
|
||||
propertyStaticDataPair.Value.isExpanding = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Display Mode
|
||||
buttonRect.x += buttonRectOffset;
|
||||
toolBarRect.xMin += buttonRectOffset;
|
||||
var color = GUI.color;
|
||||
if (!lwgui.perShaderData.displayModeData.IsDefaultDisplayMode())
|
||||
GUI.color = Color.yellow;
|
||||
if (GUI.Button(buttonRect, _guiContentVisibility, Helper.guiStyles_IconButton))
|
||||
{
|
||||
string[] displayModeMenus = new[]
|
||||
{
|
||||
"Show All Advanced (" + lwgui.perShaderData.displayModeData.advancedCount + " of " + lwgui.perShaderData.propertyDatas.Count + ")",
|
||||
"Show All Hidden (" + lwgui.perShaderData.displayModeData.hiddenCount + " of " + lwgui.perShaderData.propertyDatas.Count + ")",
|
||||
"Show Only Modified (" + lwgui.perFrameData.modifiedCount + " of " + lwgui.perShaderData.propertyDatas.Count + ")",
|
||||
};
|
||||
bool[] enabled = new[] { true, true, true };
|
||||
bool[] separator = new bool[3];
|
||||
int[] selected = new[]
|
||||
{
|
||||
lwgui.perShaderData.displayModeData.showAllAdvancedProperties ? 0 : -1,
|
||||
lwgui.perShaderData.displayModeData.showAllHiddenProperties ? 1 : -1,
|
||||
lwgui.perShaderData.displayModeData.showOnlyModifiedProperties ? 2 : -1,
|
||||
};
|
||||
ReflectionHelper.DisplayCustomMenuWithSeparators(new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 0, 0),
|
||||
displayModeMenus, enabled, separator, selected,
|
||||
(data, options, selectedIndex) =>
|
||||
{
|
||||
switch (selectedIndex)
|
||||
{
|
||||
case 0:
|
||||
lwgui.perShaderData.displayModeData.showAllAdvancedProperties = !lwgui.perShaderData.displayModeData.showAllAdvancedProperties;
|
||||
lwgui.perShaderData.ToggleShowAllAdvancedProperties();
|
||||
break;
|
||||
case 1:
|
||||
lwgui.perShaderData.displayModeData.showAllHiddenProperties = !lwgui.perShaderData.displayModeData.showAllHiddenProperties;
|
||||
break;
|
||||
case 2:
|
||||
lwgui.perShaderData.displayModeData.showOnlyModifiedProperties = !lwgui.perShaderData.displayModeData.showOnlyModifiedProperties;
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
GUI.color = color;
|
||||
|
||||
toolBarRect.xMin += 2;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Search Field
|
||||
private static readonly int s_TextFieldHash = "EditorTextField".GetHashCode();
|
||||
private static readonly GUIContent[] _searchModeMenus =
|
||||
(new GUIContent[(int)SearchMode.Num]).Select(((guiContent, i) =>
|
||||
{
|
||||
if (i == (int)SearchMode.Num)
|
||||
return null;
|
||||
|
||||
return new GUIContent(((SearchMode)i).ToString());
|
||||
})).ToArray();
|
||||
|
||||
|
||||
/// <returns>is has changed?</returns>
|
||||
public static bool DrawSearchField(Rect rect, LWGUI lwgui)
|
||||
{
|
||||
bool hasChanged = false;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
var revertButtonRect = RevertableHelper.SplitRevertButtonRect(ref rect);
|
||||
|
||||
// Get internal TextField ControlID
|
||||
int controlId = GUIUtility.GetControlID(s_TextFieldHash, FocusType.Keyboard, rect) + 1;
|
||||
|
||||
// searching mode
|
||||
Rect modeRect = new Rect(rect);
|
||||
modeRect.width = 20f;
|
||||
if (Event.current.type == UnityEngine.EventType.MouseDown && modeRect.Contains(Event.current.mousePosition))
|
||||
{
|
||||
EditorUtility.DisplayCustomMenu(rect, _searchModeMenus, (int)lwgui.perShaderData.searchMode,
|
||||
(data, options, selected) =>
|
||||
{
|
||||
lwgui.perShaderData.searchMode = (SearchMode)selected;
|
||||
hasChanged = true;
|
||||
}, null);
|
||||
Event.current.Use();
|
||||
}
|
||||
|
||||
lwgui.perShaderData.searchString = EditorGUI.TextField(rect, String.Empty, lwgui.perShaderData.searchString, guiStyles_ToolbarSearchTextFieldPopup);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
hasChanged = true;
|
||||
|
||||
// revert button
|
||||
if (!string.IsNullOrEmpty(lwgui.perShaderData.searchString)
|
||||
&& RevertableHelper.DrawRevertButton(revertButtonRect))
|
||||
{
|
||||
lwgui.perShaderData.searchString = string.Empty;
|
||||
hasChanged = true;
|
||||
GUIUtility.keyboardControl = 0;
|
||||
}
|
||||
|
||||
// display search mode
|
||||
if (GUIUtility.keyboardControl != controlId
|
||||
&& string.IsNullOrEmpty(lwgui.perShaderData.searchString)
|
||||
&& Event.current.type == UnityEngine.EventType.Repaint)
|
||||
{
|
||||
using (new EditorGUI.DisabledScope(true))
|
||||
{
|
||||
#if UNITY_2019_2_OR_NEWER
|
||||
var disableTextRect = new Rect(rect.x, rect.y, rect.width,
|
||||
guiStyles_ToolbarSearchTextFieldPopup.fixedHeight > 0.0
|
||||
? guiStyles_ToolbarSearchTextFieldPopup.fixedHeight
|
||||
: rect.height);
|
||||
#else
|
||||
var disableTextRect = rect;
|
||||
disableTextRect.yMin -= 3f;
|
||||
#endif
|
||||
disableTextRect = guiStyles_ToolbarSearchTextFieldPopup.padding.Remove(disableTextRect);
|
||||
int fontSize = EditorStyles.label.fontSize;
|
||||
EditorStyles.label.fontSize = guiStyles_ToolbarSearchTextFieldPopup.fontSize;
|
||||
EditorStyles.label.Draw(disableTextRect, new GUIContent(lwgui.perShaderData.searchMode.ToString()), false, false, false, false);
|
||||
EditorStyles.label.fontSize = fontSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasChanged) lwgui.perShaderData.UpdateSearchFilter();
|
||||
|
||||
return hasChanged;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Context Menu
|
||||
|
||||
private static void EditPresetEvent(string mode, ShaderPropertyPreset presetAsset, ShaderPropertyPreset.Preset activePreset, MaterialProperty prop, LWGUI lwgui)
|
||||
{
|
||||
if (!VersionControlHelper.Checkout(presetAsset))
|
||||
{
|
||||
Debug.LogError("Can not edit the preset: " + presetAsset);
|
||||
return;
|
||||
}
|
||||
switch (mode)
|
||||
{
|
||||
case "Add":
|
||||
case "Update":
|
||||
activePreset.AddOrUpdateIncludeExtraProperties(lwgui, prop);
|
||||
break;
|
||||
case "Remove":
|
||||
activePreset.RemoveIncludeExtraProperties(lwgui, prop.name);
|
||||
break;
|
||||
}
|
||||
EditorUtility.SetDirty(presetAsset);
|
||||
}
|
||||
|
||||
public static void DoPropertyContextMenus(Rect rect, MaterialProperty prop, LWGUI lwgui)
|
||||
{
|
||||
if (Event.current.type != EventType.ContextClick || !rect.Contains(Event.current.mousePosition)) return;
|
||||
|
||||
Event.current.Use();
|
||||
var propStaticData = lwgui.perShaderData.propertyDatas[prop.name];
|
||||
var menus = new GenericMenu();
|
||||
|
||||
// 2022+ Material Varant Menus
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
ReflectionHelper.HandleApplyRevert(menus, prop);
|
||||
#endif
|
||||
|
||||
// Copy
|
||||
menus.AddItem(new GUIContent("Copy"), false, () =>
|
||||
{
|
||||
_copiedMaterial = UnityEngine.Object.Instantiate(lwgui.material);
|
||||
_copiedProps.Clear();
|
||||
_copiedProps.Add(prop.name);
|
||||
foreach (var extraPropName in propStaticData.extraPropNames)
|
||||
{
|
||||
_copiedProps.Add(extraPropName);
|
||||
}
|
||||
|
||||
// Copy Children
|
||||
foreach (var childPropStaticData in propStaticData.children)
|
||||
{
|
||||
_copiedProps.Add(childPropStaticData.name);
|
||||
foreach (var extraPropName in childPropStaticData.extraPropNames)
|
||||
{
|
||||
_copiedProps.Add(extraPropName);
|
||||
}
|
||||
|
||||
foreach (var childChildPropStaticData in childPropStaticData.children)
|
||||
{
|
||||
_copiedProps.Add(childChildPropStaticData.name);
|
||||
foreach (var extraPropName in childChildPropStaticData.extraPropNames)
|
||||
{
|
||||
_copiedProps.Add(extraPropName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// Paste
|
||||
GenericMenu.MenuFunction pasteAction = () =>
|
||||
{
|
||||
foreach (Material material in prop.targets)
|
||||
{
|
||||
if (!VersionControlHelper.Checkout(material))
|
||||
{
|
||||
Debug.LogError("Material: '" + lwgui.material.name + "' unable to write!");
|
||||
return;
|
||||
}
|
||||
|
||||
Undo.RecordObject(material, "Paste Material Properties");
|
||||
|
||||
var index = 0;
|
||||
|
||||
PastePropertyValueToMaterial(material, _copiedProps[index++], prop.name);
|
||||
foreach (var extraPropName in propStaticData.extraPropNames)
|
||||
{
|
||||
if (index == _copiedProps.Count) break;
|
||||
PastePropertyValueToMaterial(material, _copiedProps[index++], extraPropName);
|
||||
}
|
||||
|
||||
// Paste Children
|
||||
foreach (var childPropStaticData in propStaticData.children)
|
||||
{
|
||||
if (index == _copiedProps.Count) break;
|
||||
PastePropertyValueToMaterial(material, _copiedProps[index++], childPropStaticData.name);
|
||||
foreach (var extraPropName in childPropStaticData.extraPropNames)
|
||||
{
|
||||
if (index == _copiedProps.Count) break;
|
||||
PastePropertyValueToMaterial(material, _copiedProps[index++], extraPropName);
|
||||
}
|
||||
|
||||
foreach (var childChildPropStaticData in childPropStaticData.children)
|
||||
{
|
||||
if (index == _copiedProps.Count) break;
|
||||
PastePropertyValueToMaterial(material, _copiedProps[index++], childChildPropStaticData.name);
|
||||
foreach (var extraPropName in childChildPropStaticData.extraPropNames)
|
||||
{
|
||||
if (index == _copiedProps.Count) break;
|
||||
PastePropertyValueToMaterial(material, _copiedProps[index++], extraPropName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
if (_copiedMaterial != null && _copiedProps.Count > 0 && GUI.enabled)
|
||||
menus.AddItem(new GUIContent("Paste"), false, pasteAction);
|
||||
else
|
||||
menus.AddDisabledItem(new GUIContent("Paste"));
|
||||
|
||||
menus.AddSeparator("");
|
||||
|
||||
// Copy Display Name
|
||||
menus.AddItem(new GUIContent("Copy Display Name"), false, () =>
|
||||
{
|
||||
EditorGUIUtility.systemCopyBuffer = propStaticData.displayName;
|
||||
});
|
||||
|
||||
// Copy Property Names
|
||||
menus.AddItem(new GUIContent("Copy Property Names"), false, () =>
|
||||
{
|
||||
EditorGUIUtility.systemCopyBuffer = prop.name;
|
||||
foreach (var extraPropName in propStaticData.extraPropNames)
|
||||
{
|
||||
EditorGUIUtility.systemCopyBuffer += ", " + extraPropName;
|
||||
}
|
||||
});
|
||||
|
||||
// menus.AddSeparator("");
|
||||
//
|
||||
// // Add to Favorites
|
||||
// menus.AddItem(new GUIContent("Add to Favorites"), false, () =>
|
||||
// {
|
||||
// });
|
||||
//
|
||||
// // Remove from Favorites
|
||||
// menus.AddItem(new GUIContent("Remove from Favorites"), false, () =>
|
||||
// {
|
||||
// });
|
||||
|
||||
// Preset
|
||||
if (GUI.enabled)
|
||||
{
|
||||
menus.AddSeparator("");
|
||||
foreach (var activePresetData in lwgui.perFrameData.activePresets)
|
||||
{
|
||||
if (activePresetData.property == prop) continue;
|
||||
|
||||
var activePreset = activePresetData.preset;
|
||||
var presetAsset = lwgui.perShaderData.propertyDatas[activePresetData.property.name].propertyPresetAsset;
|
||||
var presetPropDisplayName = lwgui.perShaderData.propertyDatas[activePresetData.property.name].displayName;
|
||||
|
||||
if (activePreset.GetPropertyValue(prop.name) != null)
|
||||
{
|
||||
menus.AddItem(new GUIContent("Update to Preset/" + presetPropDisplayName + "/" + activePreset.presetName), false, () => EditPresetEvent("Update", presetAsset, activePreset, prop, lwgui));
|
||||
menus.AddItem(new GUIContent("Remove from Preset/" + presetPropDisplayName + "/" + activePreset.presetName), false, () => EditPresetEvent("Remove", presetAsset, activePreset, prop, lwgui));
|
||||
}
|
||||
else
|
||||
{
|
||||
menus.AddItem(new GUIContent("Add to Preset/" + presetPropDisplayName + "/" + activePreset.presetName), false, () => EditPresetEvent("Add", presetAsset, activePreset, prop, lwgui));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
menus.ShowAsContext();
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
3
Assets/LWGUI-1.14.1/Editor/Helper.cs.meta
Normal file
3
Assets/LWGUI-1.14.1/Editor/Helper.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bc93109edd264b6aa0265609cb38cc58
|
||||
timeCreated: 1687336811
|
||||
179
Assets/LWGUI-1.14.1/Editor/LWGUI.cs
Normal file
179
Assets/LWGUI-1.14.1/Editor/LWGUI.cs
Normal file
@@ -0,0 +1,179 @@
|
||||
// Copyright (c) Jason Ma
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
public delegate void LWGUICustomGUIEvent(LWGUI lwgui);
|
||||
|
||||
public class LWGUI : ShaderGUI
|
||||
{
|
||||
public MaterialProperty[] props;
|
||||
public MaterialEditor materialEditor;
|
||||
public Material material;
|
||||
public Shader shader;
|
||||
public PerShaderData perShaderData;
|
||||
public PerFrameData perFrameData;
|
||||
|
||||
public static LWGUICustomGUIEvent onDrawCustomHeader;
|
||||
public static LWGUICustomGUIEvent onDrawCustomFooter;
|
||||
|
||||
/// <summary>
|
||||
/// Called when switch to a new Material Window, each window has a LWGUI instance
|
||||
/// </summary>
|
||||
public LWGUI() { }
|
||||
|
||||
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
|
||||
{
|
||||
this.props = props;
|
||||
this.materialEditor = materialEditor;
|
||||
this.material = materialEditor.target as Material;
|
||||
this.shader = this.material.shader;
|
||||
this.perShaderData = MetaDataHelper.BuildPerShaderData(shader, props);
|
||||
this.perFrameData = MetaDataHelper.BuildPerFrameData(shader, material, props);
|
||||
|
||||
|
||||
// Custom Header
|
||||
if (onDrawCustomHeader != null)
|
||||
onDrawCustomHeader(this);
|
||||
|
||||
|
||||
// Toolbar
|
||||
bool enabled = GUI.enabled;
|
||||
GUI.enabled = true;
|
||||
var toolBarRect = EditorGUILayout.GetControlRect();
|
||||
toolBarRect.xMin = 2;
|
||||
|
||||
Helper.DrawToolbarButtons(ref toolBarRect, this);
|
||||
|
||||
Helper.DrawSearchField(toolBarRect, this);
|
||||
|
||||
GUILayoutUtility.GetRect(0, 0); // Space(0)
|
||||
GUI.enabled = enabled;
|
||||
Helper.DrawSplitLine();
|
||||
|
||||
|
||||
// Properties
|
||||
{
|
||||
// move fields left to make rect for Revert Button
|
||||
materialEditor.SetDefaultGUIWidths();
|
||||
RevertableHelper.InitRevertableGUIWidths();
|
||||
|
||||
// start drawing properties
|
||||
foreach (var prop in props)
|
||||
{
|
||||
var propStaticData = perShaderData.propertyDatas[prop.name];
|
||||
var propDynamicData = perFrameData.propertyDatas[prop.name];
|
||||
|
||||
// Visibility
|
||||
{
|
||||
if (!MetaDataHelper.GetPropertyVisibility(prop, material, this))
|
||||
continue;
|
||||
|
||||
if (propStaticData.parent != null
|
||||
&& (!MetaDataHelper.GetParentPropertyVisibility(propStaticData.parent, material, this)
|
||||
|| !MetaDataHelper.GetParentPropertyVisibility(propStaticData.parent.parent, material, this)))
|
||||
continue;
|
||||
}
|
||||
|
||||
// Indent
|
||||
var indentLevel = EditorGUI.indentLevel;
|
||||
if (propStaticData.isAdvancedHeader)
|
||||
EditorGUI.indentLevel++;
|
||||
if (propStaticData.parent != null)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
if (propStaticData.parent.parent != null)
|
||||
EditorGUI.indentLevel++;
|
||||
}
|
||||
|
||||
// Advanced Header
|
||||
if (propStaticData.isAdvancedHeader && !propStaticData.isAdvancedHeaderProperty)
|
||||
{
|
||||
DrawAdvancedHeader(propStaticData, prop);
|
||||
|
||||
if (!propStaticData.isExpanding)
|
||||
{
|
||||
RevertableHelper.SetRevertableGUIWidths();
|
||||
EditorGUI.indentLevel = indentLevel;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
DrawProperty(prop);
|
||||
|
||||
RevertableHelper.SetRevertableGUIWidths();
|
||||
EditorGUI.indentLevel = indentLevel;
|
||||
}
|
||||
|
||||
materialEditor.SetDefaultGUIWidths();
|
||||
}
|
||||
|
||||
|
||||
EditorGUILayout.Space();
|
||||
Helper.DrawSplitLine();
|
||||
EditorGUILayout.Space();
|
||||
|
||||
|
||||
// Render settings
|
||||
#if UNITY_2019_4_OR_NEWER
|
||||
if (SupportedRenderingFeatures.active.editableMaterialRenderQueue)
|
||||
#endif
|
||||
{
|
||||
materialEditor.RenderQueueField();
|
||||
}
|
||||
materialEditor.EnableInstancingField();
|
||||
materialEditor.LightmapEmissionProperty();
|
||||
materialEditor.DoubleSidedGIField();
|
||||
|
||||
|
||||
// Custom Footer
|
||||
if (onDrawCustomFooter != null)
|
||||
onDrawCustomFooter(this);
|
||||
|
||||
|
||||
// LOGO
|
||||
EditorGUILayout.Space();
|
||||
Helper.DrawLogo();
|
||||
}
|
||||
|
||||
private void DrawAdvancedHeader(PropertyStaticData propStaticData, MaterialProperty prop)
|
||||
{
|
||||
var rect = EditorGUILayout.GetControlRect();
|
||||
var revertButtonRect = RevertableHelper.SplitRevertButtonRect(ref rect);
|
||||
var label = string.IsNullOrEmpty(propStaticData.advancedHeaderString) ? "Advanced" : propStaticData.advancedHeaderString;
|
||||
propStaticData.isExpanding = EditorGUI.Foldout(rect, propStaticData.isExpanding, label);
|
||||
if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && rect.Contains(Event.current.mousePosition))
|
||||
propStaticData.isExpanding = !propStaticData.isExpanding;
|
||||
RevertableHelper.DrawRevertableProperty(revertButtonRect, prop, this, true);
|
||||
Helper.DoPropertyContextMenus(rect, prop, this);
|
||||
}
|
||||
|
||||
private void DrawProperty(MaterialProperty prop)
|
||||
{
|
||||
var propStaticData = perShaderData.propertyDatas[prop.name];
|
||||
var propDynamicData = perFrameData.propertyDatas[prop.name];
|
||||
|
||||
Helper.DrawHelpbox(propStaticData, propDynamicData);
|
||||
|
||||
var label = new GUIContent(propStaticData.displayName, MetaDataHelper.GetPropertyTooltip(propStaticData, propDynamicData));
|
||||
var height = materialEditor.GetPropertyHeight(prop, label.text);
|
||||
var rect = EditorGUILayout.GetControlRect(true, height);
|
||||
|
||||
var revertButtonRect = RevertableHelper.SplitRevertButtonRect(ref rect);
|
||||
|
||||
Helper.BeginProperty(rect, prop, this);
|
||||
Helper.DoPropertyContextMenus(rect, prop, this);
|
||||
RevertableHelper.FixGUIWidthMismatch(prop.type, materialEditor);
|
||||
if (propStaticData.isAdvancedHeaderProperty)
|
||||
propStaticData.isExpanding = EditorGUI.Foldout(rect, propStaticData.isExpanding, string.Empty);
|
||||
RevertableHelper.DrawRevertableProperty(revertButtonRect, prop, this, propStaticData.isMain || propStaticData.isAdvancedHeaderProperty);
|
||||
materialEditor.ShaderProperty(rect, prop, label);
|
||||
Helper.EndProperty(this, prop);
|
||||
}
|
||||
}
|
||||
} //namespace LWGUI
|
||||
11
Assets/LWGUI-1.14.1/Editor/LWGUI.cs.meta
Normal file
11
Assets/LWGUI-1.14.1/Editor/LWGUI.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b44ae323525d0c64c92721bfbd1ad8c5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
630
Assets/LWGUI-1.14.1/Editor/MetaDataHelper.cs
Normal file
630
Assets/LWGUI-1.14.1/Editor/MetaDataHelper.cs
Normal file
@@ -0,0 +1,630 @@
|
||||
// Copyright (c) Jason Ma
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
public enum SearchMode
|
||||
{
|
||||
Auto = 0, // Search by group first, and search by property when there are no results
|
||||
Property = 1, // Search by property
|
||||
Group = 2, // Search by group
|
||||
Num = 3
|
||||
}
|
||||
|
||||
public enum LogicalOperator
|
||||
{
|
||||
And,
|
||||
Or
|
||||
}
|
||||
|
||||
public struct DisplayModeData
|
||||
{
|
||||
public bool showAllAdvancedProperties;
|
||||
public bool showAllHiddenProperties;
|
||||
public bool showOnlyModifiedProperties;
|
||||
|
||||
public int advancedCount;
|
||||
public int hiddenCount;
|
||||
|
||||
public bool IsDefaultDisplayMode() { return !(showAllAdvancedProperties || showAllHiddenProperties || showOnlyModifiedProperties); }
|
||||
}
|
||||
|
||||
public class ShowIfData
|
||||
{
|
||||
public LogicalOperator logicalOperator = LogicalOperator.And;
|
||||
public string targetPropertyName = string.Empty;
|
||||
public CompareFunction compareFunction = CompareFunction.Equal;
|
||||
public float value = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// All static metadata for a Property, determined after the Shader is compiled.
|
||||
/// </summary>
|
||||
public class PropertyStaticData
|
||||
{
|
||||
public string name = string.Empty;
|
||||
public string displayName = string.Empty; // Decoded displayName (Helpbox and Tooltip are encoded in displayName)
|
||||
|
||||
// Structure
|
||||
public string groupName = string.Empty; // [Group(groupName)] / [Sub(groupName)] / [Advanced(groupName)]
|
||||
public bool isMain = false; // [Group]
|
||||
public bool isAdvanced = false; // [Advanced]
|
||||
public bool isAdvancedHeader = false; // the first [Advanced] in the same group
|
||||
public bool isAdvancedHeaderProperty = false;
|
||||
public string advancedHeaderString = string.Empty;
|
||||
public PropertyStaticData parent = null;
|
||||
public List<PropertyStaticData> children = new List<PropertyStaticData>();
|
||||
|
||||
// Visibility
|
||||
public string conditionalDisplayKeyword = string.Empty; // [Group(groupName_conditionalDisplayKeyword)]
|
||||
public bool isSearchMatched = true; // Draws when the search match is successful
|
||||
public bool isExpanding = false; // Draws when the group is expanding
|
||||
public bool isHidden = false; // [Hidden]
|
||||
public List<ShowIfData> showIfDatas = new List<ShowIfData>(); // [ShowIf()]
|
||||
|
||||
// Metadata
|
||||
public List<string> extraPropNames = new List<string>(); // Other Props that have been associated
|
||||
public string helpboxMessages = string.Empty;
|
||||
public string tooltipMessages = string.Empty;
|
||||
public ShaderPropertyPreset propertyPresetAsset = null; // The Referenced Preset Asset
|
||||
|
||||
public void AddExtraProperty(string propName)
|
||||
{
|
||||
if (!extraPropNames.Contains(propName)) extraPropNames.Add(propName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Consistent metadata across different material instances of the same Shader.
|
||||
/// </summary>
|
||||
public class PerShaderData
|
||||
{
|
||||
public Dictionary<string, PropertyStaticData> propertyDatas = new Dictionary<string, PropertyStaticData>();
|
||||
public SearchMode searchMode = SearchMode.Auto;
|
||||
public string searchString = string.Empty;
|
||||
public List<string> favoriteproperties = new List<string>();
|
||||
public DisplayModeData displayModeData = new DisplayModeData();
|
||||
|
||||
|
||||
public void BuildPropertyStaticData(Shader shader, MaterialProperty[] props)
|
||||
{
|
||||
// Get Property Static Data
|
||||
foreach (var prop in props)
|
||||
{
|
||||
var propStaticData = new PropertyStaticData(){ name = prop.name };
|
||||
propertyDatas[prop.name] = propStaticData;
|
||||
|
||||
List<MaterialPropertyDrawer> decoratorDrawers;
|
||||
var drawer = ReflectionHelper.GetPropertyDrawer(shader, prop, out decoratorDrawers);
|
||||
if (decoratorDrawers != null && decoratorDrawers.Count > 0)
|
||||
{
|
||||
foreach (var decoratorDrawer in decoratorDrawers)
|
||||
{
|
||||
if (decoratorDrawer is IBaseDrawer)
|
||||
(decoratorDrawer as IBaseDrawer).BuildStaticMetaData(shader, prop, props, propStaticData);
|
||||
}
|
||||
}
|
||||
if (drawer != null)
|
||||
{
|
||||
if (drawer is IBaseDrawer)
|
||||
(drawer as IBaseDrawer).BuildStaticMetaData(shader, prop, props, propStaticData);
|
||||
}
|
||||
|
||||
DecodeMetaDataFromDisplayName(prop, propStaticData);
|
||||
}
|
||||
|
||||
// Check Data
|
||||
foreach (var prop in props)
|
||||
{
|
||||
var propStaticData = propertyDatas[prop.name];
|
||||
propStaticData.extraPropNames.RemoveAll((extraPropName =>
|
||||
string.IsNullOrEmpty(extraPropName) || !propertyDatas.ContainsKey(extraPropName)));
|
||||
}
|
||||
|
||||
// Build Property Structure
|
||||
{
|
||||
var groupToMainPropertyDic = new Dictionary<string, MaterialProperty>();
|
||||
|
||||
// Collection Groups
|
||||
foreach (var prop in props)
|
||||
{
|
||||
var propData = propertyDatas[prop.name];
|
||||
if (propData.isMain
|
||||
&& !string.IsNullOrEmpty(propData.groupName)
|
||||
&& !groupToMainPropertyDic.ContainsKey(propData.groupName))
|
||||
groupToMainPropertyDic.Add(propData.groupName, prop);
|
||||
}
|
||||
|
||||
// Register SubProps
|
||||
foreach (var prop in props)
|
||||
{
|
||||
var propData = propertyDatas[prop.name];
|
||||
if (!propData.isMain
|
||||
&& !string.IsNullOrEmpty(propData.groupName))
|
||||
{
|
||||
foreach (var groupName in groupToMainPropertyDic.Keys)
|
||||
{
|
||||
if (propData.groupName.StartsWith(groupName))
|
||||
{
|
||||
// Update Structure
|
||||
var mainProp = groupToMainPropertyDic[groupName];
|
||||
propData.parent = propertyDatas[mainProp.name];
|
||||
propertyDatas[mainProp.name].children.Add(propData);
|
||||
|
||||
// Split groupName and conditional display keyword
|
||||
if (propData.groupName.Length > groupName.Length)
|
||||
{
|
||||
propData.conditionalDisplayKeyword =
|
||||
propData.groupName.Substring(groupName.Length, propData.groupName.Length - groupName.Length).ToUpper();
|
||||
propData.groupName = groupName;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build Display Mode Data
|
||||
{
|
||||
PropertyStaticData lastPropData = null;
|
||||
PropertyStaticData lastHeaderPropData = null;
|
||||
for (int i = 0; i < props.Length; i++)
|
||||
{
|
||||
var prop = props[i];
|
||||
var propStaticData = propertyDatas[prop.name];
|
||||
|
||||
// Counting
|
||||
if (propStaticData.isHidden
|
||||
|| (propStaticData.parent != null
|
||||
&& (propStaticData.parent.isHidden
|
||||
|| (propStaticData.parent.parent != null && propStaticData.parent.parent.isHidden))))
|
||||
displayModeData.hiddenCount++;
|
||||
if (propStaticData.isAdvanced
|
||||
|| (propStaticData.parent != null
|
||||
&& (propStaticData.parent.isAdvanced
|
||||
|| (propStaticData.parent.parent != null && propStaticData.parent.parent.isAdvanced))))
|
||||
displayModeData.advancedCount++;
|
||||
|
||||
// Build Advanced Structure
|
||||
if (propStaticData.isAdvanced)
|
||||
{
|
||||
// If it is the first prop in a Advanced Block, set to Header
|
||||
if (lastPropData == null
|
||||
|| !lastPropData.isAdvanced
|
||||
|| propStaticData.isAdvancedHeaderProperty
|
||||
|| (!string.IsNullOrEmpty(propStaticData.advancedHeaderString)
|
||||
&& propStaticData.advancedHeaderString != lastPropData.advancedHeaderString))
|
||||
{
|
||||
propStaticData.isAdvancedHeader = true;
|
||||
lastHeaderPropData = propStaticData;
|
||||
}
|
||||
// Else set to child
|
||||
else
|
||||
{
|
||||
propStaticData.parent = lastHeaderPropData;
|
||||
lastHeaderPropData.children.Add(propStaticData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
lastPropData = propStaticData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly string _tooltipSplitter = "#";
|
||||
private static readonly string _helpboxSplitter = "%";
|
||||
|
||||
public void DecodeMetaDataFromDisplayName(MaterialProperty prop, PropertyStaticData propStaticData)
|
||||
{
|
||||
var tooltips = prop.displayName.Split(new String[] { _tooltipSplitter }, StringSplitOptions.None);
|
||||
if (tooltips.Length > 1)
|
||||
{
|
||||
for (int i = 1; i <= tooltips.Length - 1; i++)
|
||||
{
|
||||
var str = tooltips[i];
|
||||
var helpboxIndex = tooltips[i].IndexOf(_helpboxSplitter, StringComparison.Ordinal);
|
||||
if (helpboxIndex > 0)
|
||||
str = tooltips[i].Substring(0, helpboxIndex);
|
||||
propStaticData.tooltipMessages += str + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
var helpboxes = prop.displayName.Split(new String[] { _helpboxSplitter }, StringSplitOptions.None);
|
||||
if (helpboxes.Length > 1)
|
||||
{
|
||||
for (int i = 1; i <= helpboxes.Length - 1; i++)
|
||||
{
|
||||
var str = helpboxes[i];
|
||||
var tooltipIndex = helpboxes[i].IndexOf(_tooltipSplitter, StringComparison.Ordinal);
|
||||
if (tooltipIndex > 0)
|
||||
str = tooltips[i].Substring(0, tooltipIndex);
|
||||
propStaticData.helpboxMessages += str + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (propStaticData.helpboxMessages.EndsWith("\n"))
|
||||
propStaticData.helpboxMessages = propStaticData.helpboxMessages.Substring(0, propStaticData.helpboxMessages.Length - 1);
|
||||
|
||||
propStaticData.displayName = prop.displayName.Split(new String[] { _tooltipSplitter, _helpboxSplitter }, StringSplitOptions.None)[0];
|
||||
}
|
||||
|
||||
public void UpdateSearchFilter()
|
||||
{
|
||||
var isSearchStringEmpty = string.IsNullOrEmpty(searchString);
|
||||
var searchStringLower = searchString.ToLower();
|
||||
var searchKeywords = searchStringLower.Split(' ', ',', ';', '|', ',', ';'); // Some possible separators
|
||||
|
||||
// The First Search
|
||||
foreach (var propertyData in propertyDatas)
|
||||
{
|
||||
propertyData.Value.isSearchMatched = isSearchStringEmpty
|
||||
? true
|
||||
: IsWholeWordMatch(propertyData.Value.displayName, propertyData.Key, searchKeywords);
|
||||
}
|
||||
|
||||
// Further adjust visibility
|
||||
if (!isSearchStringEmpty)
|
||||
{
|
||||
var searchModeTemp = searchMode;
|
||||
// Auto: search by group first, and search by property when there are no results
|
||||
if (searchModeTemp == SearchMode.Auto)
|
||||
{
|
||||
// if has no group
|
||||
if (!propertyDatas.Any((propertyData => propertyData.Value.isSearchMatched && propertyData.Value.isMain)))
|
||||
searchModeTemp = SearchMode.Property;
|
||||
else
|
||||
searchModeTemp = SearchMode.Group;
|
||||
}
|
||||
|
||||
// search by property
|
||||
if (searchModeTemp == SearchMode.Property)
|
||||
{
|
||||
// when a SubProp is displayed, the MainProp is also displayed
|
||||
foreach (var propertyData in propertyDatas)
|
||||
{
|
||||
if (propertyData.Value.isMain && propertyData.Value.children.Any((childPropertyData => childPropertyData.isSearchMatched)))
|
||||
propertyData.Value.isSearchMatched = true;
|
||||
}
|
||||
}
|
||||
// search by group
|
||||
else if (searchModeTemp == SearchMode.Group)
|
||||
{
|
||||
// when search by group, all SubProps should display with MainProp
|
||||
foreach (var propertyData in propertyDatas)
|
||||
{
|
||||
if (propertyData.Value.isMain)
|
||||
foreach (var childPropertyData in propertyData.Value.children)
|
||||
childPropertyData.isSearchMatched = propertyData.Value.isSearchMatched;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsWholeWordMatch(string displayName, string propertyName, string[] searchingKeywords)
|
||||
{
|
||||
bool contains = true;
|
||||
displayName = displayName.ToLower();
|
||||
var name = propertyName.ToLower();
|
||||
|
||||
foreach (var keyword in searchingKeywords)
|
||||
{
|
||||
var isMatch = false;
|
||||
isMatch |= displayName.Contains(keyword);
|
||||
isMatch |= name.Contains(keyword);
|
||||
contains &= isMatch;
|
||||
}
|
||||
return contains;
|
||||
}
|
||||
|
||||
public void ToggleShowAllAdvancedProperties()
|
||||
{
|
||||
foreach (var propertyStaticDataPair in propertyDatas)
|
||||
{
|
||||
if (propertyStaticDataPair.Value.isAdvancedHeader)
|
||||
propertyStaticDataPair.Value.isExpanding = displayModeData.showAllAdvancedProperties;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Property metadata dynamically generated perframe
|
||||
/// </summary>
|
||||
public class PropertyDynamicData
|
||||
{
|
||||
public MaterialProperty property;
|
||||
public MaterialProperty defualtProperty; // Default values may be overridden by Preset
|
||||
public string defaultValueDescription = string.Empty; // Description of the default values used in Tooltip
|
||||
public bool hasModified = false; // Are properties modified in the material?
|
||||
public bool hasChildrenModified = false; // Are Children properties modified in the material?
|
||||
public bool hasRevertChanged = false; // Used to call property EndChangeCheck()
|
||||
public bool isShowing = true; // ShowIf() result
|
||||
|
||||
}
|
||||
|
||||
public class PersetDynamicData
|
||||
{
|
||||
public ShaderPropertyPreset.Preset preset;
|
||||
public MaterialProperty property;
|
||||
|
||||
public PersetDynamicData(ShaderPropertyPreset.Preset preset, MaterialProperty property)
|
||||
{
|
||||
this.preset = preset;
|
||||
this.property = property;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Each frame of each material may have different metadata.
|
||||
/// </summary>
|
||||
public class PerFrameData
|
||||
{
|
||||
public Dictionary<string, PropertyDynamicData> propertyDatas = new Dictionary<string, PropertyDynamicData>();
|
||||
public List<PersetDynamicData> activePresets = new List<PersetDynamicData>();
|
||||
|
||||
public int modifiedCount = 0;
|
||||
|
||||
public void BuildPerFrameData(Shader shader, Material material, MaterialProperty[] props, PerShaderData perShaderData)
|
||||
{
|
||||
// Get active presets
|
||||
foreach (var prop in props)
|
||||
{
|
||||
List<MaterialPropertyDrawer> decoratorDrawers;
|
||||
var drawer = ReflectionHelper.GetPropertyDrawer(shader, prop, out decoratorDrawers);
|
||||
|
||||
// Get Presets
|
||||
if (drawer != null)
|
||||
{
|
||||
if (drawer is IBasePresetDrawer)
|
||||
{
|
||||
var activePreset = (drawer as IBasePresetDrawer).GetActivePreset(prop, perShaderData.propertyDatas[prop.name].propertyPresetAsset);
|
||||
if (activePreset != null)
|
||||
{
|
||||
activePresets.Add(new PersetDynamicData(activePreset, prop));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply presets to default material
|
||||
{
|
||||
var defaultMaterial =
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
material.parent ? UnityEngine.Object.Instantiate(material.parent) :
|
||||
#endif
|
||||
new Material(shader);
|
||||
|
||||
foreach (var activePreset in activePresets)
|
||||
activePreset.preset.ApplyToDefaultMaterial(defaultMaterial);
|
||||
|
||||
var defaultProperties = MaterialEditor.GetMaterialProperties(new[] { defaultMaterial });
|
||||
Debug.Assert(defaultProperties.Length == props.Length);
|
||||
|
||||
for (int i = 0; i < props.Length; i++)
|
||||
{
|
||||
Debug.Assert(props[i].name == defaultProperties[i].name);
|
||||
Debug.Assert(!propertyDatas.ContainsKey(props[i].name));
|
||||
|
||||
var hasModified = !Helper.PropertyValueEquals(props[i], defaultProperties[i]);
|
||||
if (hasModified) modifiedCount++;
|
||||
propertyDatas.Add(props[i].name, new PropertyDynamicData()
|
||||
{
|
||||
property = props[i],
|
||||
defualtProperty = defaultProperties[i],
|
||||
hasModified = hasModified
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var prop in props)
|
||||
{
|
||||
var propStaticData = perShaderData.propertyDatas[prop.name];
|
||||
var propDynamicData = propertyDatas[prop.name];
|
||||
|
||||
// Override parent hasModified
|
||||
if (propDynamicData.hasModified)
|
||||
{
|
||||
var parentPropData = propStaticData.parent;
|
||||
if (parentPropData != null)
|
||||
{
|
||||
propertyDatas[parentPropData.name].hasChildrenModified = true;
|
||||
if (parentPropData.parent != null)
|
||||
propertyDatas[parentPropData.parent.name].hasChildrenModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Get default value descriptions
|
||||
List<MaterialPropertyDrawer> decoratorDrawers;
|
||||
var drawer = ReflectionHelper.GetPropertyDrawer(shader, prop, out decoratorDrawers);
|
||||
{
|
||||
if (decoratorDrawers != null && decoratorDrawers.Count > 0)
|
||||
{
|
||||
foreach (var decoratorDrawer in decoratorDrawers)
|
||||
{
|
||||
if (decoratorDrawer is IBaseDrawer)
|
||||
(decoratorDrawer as IBaseDrawer).GetDefaultValueDescription(shader, prop, perShaderData, this);
|
||||
}
|
||||
}
|
||||
if (drawer != null)
|
||||
{
|
||||
if (drawer is IBaseDrawer)
|
||||
(drawer as IBaseDrawer).GetDefaultValueDescription(shader, prop, perShaderData, this);
|
||||
}
|
||||
if (string.IsNullOrEmpty(propDynamicData.defaultValueDescription))
|
||||
propDynamicData.defaultValueDescription =
|
||||
RevertableHelper.GetPropertyDefaultValueText(propDynamicData.defualtProperty);
|
||||
}
|
||||
|
||||
// Get ShowIf() results
|
||||
foreach (var showIfData in propStaticData.showIfDatas)
|
||||
{
|
||||
var propCurrentValue = propertyDatas[showIfData.targetPropertyName].property.floatValue;
|
||||
bool compareResult;
|
||||
|
||||
switch (showIfData.compareFunction)
|
||||
{
|
||||
case CompareFunction.Less:
|
||||
compareResult = propCurrentValue < showIfData.value;
|
||||
break;
|
||||
case CompareFunction.LessEqual:
|
||||
compareResult = propCurrentValue <= showIfData.value;
|
||||
break;
|
||||
case CompareFunction.Greater:
|
||||
compareResult = propCurrentValue > showIfData.value;
|
||||
break;
|
||||
case CompareFunction.NotEqual:
|
||||
compareResult = propCurrentValue != showIfData.value;
|
||||
break;
|
||||
case CompareFunction.GreaterEqual:
|
||||
compareResult = propCurrentValue >= showIfData.value;
|
||||
break;
|
||||
default:
|
||||
compareResult = propCurrentValue == showIfData.value;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (showIfData.logicalOperator)
|
||||
{
|
||||
case LogicalOperator.And:
|
||||
propDynamicData.isShowing &= compareResult;
|
||||
break;
|
||||
case LogicalOperator.Or:
|
||||
propDynamicData.isShowing |= compareResult;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MaterialProperty GetProperty(string propName)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(propName) && propertyDatas.ContainsKey(propName))
|
||||
return propertyDatas[propName].property;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public MaterialProperty GetDefaultProperty(string propName)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(propName) && propertyDatas.ContainsKey(propName))
|
||||
return propertyDatas[propName].defualtProperty;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool EndChangeCheck(string propName = null)
|
||||
{
|
||||
var result = EditorGUI.EndChangeCheck();
|
||||
if (!string.IsNullOrEmpty(propName))
|
||||
{
|
||||
result |= propertyDatas[propName].hasRevertChanged;
|
||||
propertyDatas[propName].hasRevertChanged = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public class MetaDataHelper
|
||||
{
|
||||
private static Dictionary<Shader, PerShaderData> _shaderDataDic = new Dictionary<Shader, PerShaderData>();
|
||||
|
||||
public static PerShaderData BuildPerShaderData(Shader shader, MaterialProperty[] props)
|
||||
{
|
||||
if (!_shaderDataDic.ContainsKey(shader))
|
||||
{
|
||||
var perShaderData = new PerShaderData();
|
||||
perShaderData.BuildPropertyStaticData(shader, props);
|
||||
_shaderDataDic.Add(shader, perShaderData);
|
||||
}
|
||||
return _shaderDataDic[shader];
|
||||
}
|
||||
|
||||
public static void ForceRebuildPerShaderData(Shader shader)
|
||||
{
|
||||
if (shader && _shaderDataDic.ContainsKey(shader))
|
||||
_shaderDataDic.Remove(shader);
|
||||
}
|
||||
|
||||
public static PerFrameData BuildPerFrameData(Shader shader, Material material, MaterialProperty[] props)
|
||||
{
|
||||
var perFrameData = new PerFrameData();
|
||||
perFrameData.BuildPerFrameData(shader, material, props, _shaderDataDic[shader]);
|
||||
return perFrameData;
|
||||
}
|
||||
|
||||
public static string GetPropertyTooltip(PropertyStaticData propertyStaticData, PropertyDynamicData propertyDynamicData)
|
||||
{
|
||||
var str = propertyStaticData.tooltipMessages;
|
||||
if (!string.IsNullOrEmpty(str))
|
||||
str += "\n\n";
|
||||
str += "Property Name: " + propertyDynamicData.property.name + "\n";
|
||||
str += "Default Value: " + propertyDynamicData.defaultValueDescription;
|
||||
return str;
|
||||
}
|
||||
|
||||
private static readonly string _tooltipString = "#";
|
||||
private static readonly string _helpboxString = "%";
|
||||
|
||||
public static string GetPropertyDisplayName(Shader shader, MaterialProperty prop)
|
||||
{
|
||||
var tooltipIndex = prop.displayName.IndexOf(_tooltipString, StringComparison.Ordinal);
|
||||
var helpboxIndex = prop.displayName.IndexOf(_helpboxString, StringComparison.Ordinal);
|
||||
var minIndex = tooltipIndex == -1 ? helpboxIndex : tooltipIndex;
|
||||
if (tooltipIndex != -1 && helpboxIndex != -1)
|
||||
minIndex = Mathf.Min(minIndex, helpboxIndex);
|
||||
if (minIndex == -1)
|
||||
return prop.displayName;
|
||||
else if (minIndex == 0)
|
||||
return string.Empty;
|
||||
else
|
||||
return prop.displayName.Substring(0, minIndex);
|
||||
}
|
||||
|
||||
public static bool GetPropertyVisibility(MaterialProperty prop, Material material, LWGUI lwgui)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
var propertyStaticData = lwgui.perShaderData.propertyDatas[prop.name];
|
||||
var propertyDynamicData = lwgui.perFrameData.propertyDatas[prop.name];
|
||||
var displayModeData = lwgui.perShaderData.displayModeData;
|
||||
|
||||
if ( // if HideInInspector
|
||||
Helper.IsPropertyHideInInspector(prop)
|
||||
// if Search Filtered
|
||||
|| !propertyStaticData.isSearchMatched
|
||||
// if the Conditional Display Keyword is not active
|
||||
|| (!string.IsNullOrEmpty(propertyStaticData.conditionalDisplayKeyword) && !material.shaderKeywords.Any((str => str == propertyStaticData.conditionalDisplayKeyword)))
|
||||
|| (!displayModeData.showAllHiddenProperties && propertyStaticData.isHidden)
|
||||
// if show modified only
|
||||
|| (displayModeData.showOnlyModifiedProperties && !(propertyDynamicData.hasModified || propertyDynamicData.hasChildrenModified))
|
||||
// ShowIf() == false
|
||||
|| !propertyDynamicData.isShowing
|
||||
)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static bool GetParentPropertyVisibility(PropertyStaticData parentPropStaticData, Material material, LWGUI lwgui)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
if (parentPropStaticData != null
|
||||
&& (!lwgui.perShaderData.propertyDatas[parentPropStaticData.name].isExpanding
|
||||
|| !MetaDataHelper.GetPropertyVisibility(lwgui.perFrameData.propertyDatas[parentPropStaticData.name].property, material, lwgui)))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/LWGUI-1.14.1/Editor/MetaDataHelper.cs.meta
Normal file
3
Assets/LWGUI-1.14.1/Editor/MetaDataHelper.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 481e689c921a4e138739b26b793b41f6
|
||||
timeCreated: 1687336811
|
||||
62
Assets/LWGUI-1.14.1/Editor/PresetHelper.cs
Normal file
62
Assets/LWGUI-1.14.1/Editor/PresetHelper.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) Jason Ma
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
public class PresetHelper
|
||||
{
|
||||
private static Dictionary<string /*FileName*/, ShaderPropertyPreset> _loadedPresets = new Dictionary<string, ShaderPropertyPreset>();
|
||||
|
||||
private static bool _isInitComplete;
|
||||
|
||||
public static bool IsInitComplete { get { return _isInitComplete; } }
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
if (!_isInitComplete)
|
||||
{
|
||||
ForceInit();
|
||||
}
|
||||
}
|
||||
|
||||
public static void ForceInit()
|
||||
{
|
||||
_loadedPresets.Clear();
|
||||
_isInitComplete = false;
|
||||
var GUIDs = AssetDatabase.FindAssets("t:" + typeof(ShaderPropertyPreset));
|
||||
foreach (var GUID in GUIDs)
|
||||
{
|
||||
var preset = AssetDatabase.LoadAssetAtPath<ShaderPropertyPreset>(AssetDatabase.GUIDToAssetPath(GUID));
|
||||
AddPreset(preset);
|
||||
}
|
||||
_isInitComplete = true;
|
||||
}
|
||||
|
||||
public static void AddPreset(ShaderPropertyPreset preset)
|
||||
{
|
||||
if (!preset) return;
|
||||
if (!_loadedPresets.ContainsKey(preset.name))
|
||||
{
|
||||
_loadedPresets.Add(preset.name, preset);
|
||||
// Debug.Log(preset.name);
|
||||
}
|
||||
}
|
||||
|
||||
public static ShaderPropertyPreset GetPresetFile(string presetFileName)
|
||||
{
|
||||
if (!_loadedPresets.ContainsKey(presetFileName) || !_loadedPresets[presetFileName])
|
||||
ForceInit();
|
||||
|
||||
if (!_loadedPresets.ContainsKey(presetFileName) || !_loadedPresets[presetFileName])
|
||||
{
|
||||
Debug.LogError("Invalid ShaderPropertyPreset: ‘" + presetFileName + "’ !");
|
||||
return null;
|
||||
}
|
||||
|
||||
return _loadedPresets[presetFileName];
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/LWGUI-1.14.1/Editor/PresetHelper.cs.meta
Normal file
3
Assets/LWGUI-1.14.1/Editor/PresetHelper.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 48e58de7087c42f88a2a18c52b6ce131
|
||||
timeCreated: 1687336811
|
||||
343
Assets/LWGUI-1.14.1/Editor/RampHelper.cs
Normal file
343
Assets/LWGUI-1.14.1/Editor/RampHelper.cs
Normal file
@@ -0,0 +1,343 @@
|
||||
// Copyright (c) Jason Ma
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
public class RampHelper
|
||||
{
|
||||
#region RampEditor
|
||||
[Serializable]
|
||||
public class GradientObject : ScriptableObject
|
||||
{
|
||||
[SerializeField] public Gradient gradient = new Gradient();
|
||||
}
|
||||
|
||||
public static readonly string projectPath = Application.dataPath.Substring(0, Application.dataPath.Length - 6);
|
||||
|
||||
public static string lastSavePath
|
||||
{
|
||||
get { return EditorPrefs.GetString("LWGUI_GradientSavePath_" + Application.version, Application.dataPath); }
|
||||
set
|
||||
{
|
||||
if (value.Contains(projectPath))
|
||||
EditorPrefs.SetString("LWGUI_GradientSavePath_" + Application.version, value);
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly GUIContent _iconAdd = new GUIContent(EditorGUIUtility.IconContent("d_Toolbar Plus").image, "Add"),
|
||||
_iconEdit = new GUIContent(EditorGUIUtility.IconContent("editicon.sml").image, "Edit"),
|
||||
_iconDiscard = new GUIContent(EditorGUIUtility.IconContent("d_TreeEditor.Refresh").image, "Discard"),
|
||||
_iconSave = new GUIContent(EditorGUIUtility.IconContent("SaveActive").image, "Save");
|
||||
|
||||
public static bool RampEditor(
|
||||
Rect buttonRect,
|
||||
MaterialProperty prop,
|
||||
SerializedProperty serializedProperty,
|
||||
bool isDirty,
|
||||
string defaultFileName,
|
||||
string rootPath,
|
||||
int defaultWidth,
|
||||
int defaultHeight,
|
||||
out Texture2D newTexture,
|
||||
out bool doSave,
|
||||
out bool doDiscard)
|
||||
{
|
||||
newTexture = null;
|
||||
var hasChange = false;
|
||||
var shouldCreate = false;
|
||||
var singleButtonWidth = buttonRect.width * 0.25f;
|
||||
var editRect = new Rect(buttonRect.x + singleButtonWidth * 0, buttonRect.y, singleButtonWidth, buttonRect.height);
|
||||
var saveRect = new Rect(buttonRect.x + singleButtonWidth * 1, buttonRect.y, singleButtonWidth, buttonRect.height);
|
||||
var addRect = new Rect(buttonRect.x + singleButtonWidth * 2, buttonRect.y, singleButtonWidth, buttonRect.height);
|
||||
var discardRect = new Rect(buttonRect.x + singleButtonWidth * 3, buttonRect.y, singleButtonWidth, buttonRect.height);
|
||||
|
||||
// Edit button event
|
||||
var currEvent = Event.current;
|
||||
if (currEvent.type == EventType.MouseDown && editRect.Contains(currEvent.mousePosition))
|
||||
{
|
||||
// if the current edited texture is null, create new one
|
||||
if (prop.textureValue == null)
|
||||
{
|
||||
shouldCreate = true;
|
||||
currEvent.Use();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Undo.RecordObject(prop.textureValue, "Edit Gradient");
|
||||
}
|
||||
}
|
||||
|
||||
// Gradient Editor
|
||||
var gradientPropertyRect = new Rect(editRect.x + 2, editRect.y + 2, editRect.width - 2, editRect.height - 2);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUI.PropertyField(gradientPropertyRect, serializedProperty, GUIContent.none);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
hasChange = true;
|
||||
}
|
||||
|
||||
// Edit button overlay
|
||||
if (currEvent.type == EventType.Repaint)
|
||||
{
|
||||
var isHover = editRect.Contains(currEvent.mousePosition);
|
||||
(new GUIStyle("button")).Draw(editRect, _iconEdit, isHover, false, false, false);
|
||||
}
|
||||
|
||||
// Create button
|
||||
if (GUI.Button(addRect, _iconAdd) || shouldCreate)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (!Directory.Exists(projectPath + rootPath))
|
||||
Directory.CreateDirectory(projectPath + rootPath);
|
||||
|
||||
var absPath = EditorUtility.SaveFilePanel("Create New Ramp Texture", rootPath, defaultFileName, "png");
|
||||
|
||||
if (absPath.StartsWith(projectPath + rootPath))
|
||||
{
|
||||
//Create texture and save PNG
|
||||
var saveUnityPath = absPath.Replace(projectPath, String.Empty);
|
||||
CreateAndSaveNewGradientTexture(defaultWidth, defaultHeight, saveUnityPath);
|
||||
// VersionControlHelper.Add(saveUnityPath);
|
||||
//Load created texture
|
||||
newTexture = AssetDatabase.LoadAssetAtPath<Texture2D>(saveUnityPath);
|
||||
break;
|
||||
}
|
||||
else if (absPath != String.Empty)
|
||||
{
|
||||
var retry = EditorUtility.DisplayDialog("Invalid Path", "Please select the subdirectory of '" + projectPath + rootPath + "'", "Retry", "Cancel");
|
||||
if (!retry) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save button
|
||||
var color = GUI.color;
|
||||
if (isDirty) GUI.color = Color.yellow;
|
||||
doSave = GUI.Button(saveRect, _iconSave);
|
||||
GUI.color = color;
|
||||
|
||||
// Discard button
|
||||
doDiscard = GUI.Button(discardRect, _iconDiscard);
|
||||
|
||||
return hasChange;
|
||||
}
|
||||
|
||||
public static bool HasGradient(AssetImporter assetImporter) { return assetImporter.userData.Contains("LWGUI");}
|
||||
|
||||
public static Gradient GetGradientFromTexture(Texture texture, out bool isDirty, bool doReimport = false)
|
||||
{
|
||||
isDirty = false;
|
||||
if (texture == null) return null;
|
||||
|
||||
var assetImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture));
|
||||
if (assetImporter != null && HasGradient(assetImporter))
|
||||
{
|
||||
GradientObject savedGradientObject, editingGradientObject;
|
||||
isDirty = DecodeGradientFromJSON(assetImporter.userData, out savedGradientObject, out editingGradientObject);
|
||||
return doReimport ? savedGradientObject.gradient : editingGradientObject.gradient;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Can not find texture: "
|
||||
+ texture.name
|
||||
+ " or it's userData on disk! \n"
|
||||
+ "If you are moving or copying the Ramp Map, make sure your .meta file is not lost!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetGradientToTexture(Texture texture, GradientObject gradientObject, bool doSaveToDisk = false)
|
||||
{
|
||||
if (texture == null || gradientObject.gradient == null) return;
|
||||
|
||||
var texture2D = (Texture2D)texture;
|
||||
// Save to texture
|
||||
var path = AssetDatabase.GetAssetPath(texture);
|
||||
var pixels = GetPixelsFromGradient(gradientObject.gradient, texture.width, texture.height);
|
||||
texture2D.SetPixels32(pixels);
|
||||
texture2D.Apply();
|
||||
|
||||
// Save gradient JSON to userData
|
||||
var assetImporter = AssetImporter.GetAtPath(path);
|
||||
GradientObject savedGradientObject, editingGradientObject;
|
||||
DecodeGradientFromJSON(assetImporter.userData, out savedGradientObject, out editingGradientObject);
|
||||
assetImporter.userData = EncodeGradientToJSON(doSaveToDisk ? gradientObject : savedGradientObject, gradientObject);
|
||||
|
||||
// Save texture to disk
|
||||
if (doSaveToDisk)
|
||||
{
|
||||
var systemPath = projectPath + path;
|
||||
VersionControlHelper.Checkout(path);
|
||||
File.WriteAllBytes(systemPath, texture2D.EncodeToPNG());
|
||||
assetImporter.SaveAndReimport();
|
||||
}
|
||||
}
|
||||
|
||||
private static string EncodeGradientToJSON(GradientObject savedGradientObject, GradientObject editingGradientObject)
|
||||
{
|
||||
string savedJSON = " ", editingJSON = " ";
|
||||
if (savedGradientObject != null)
|
||||
savedJSON = EditorJsonUtility.ToJson(savedGradientObject);
|
||||
if (editingGradientObject != null)
|
||||
editingJSON = EditorJsonUtility.ToJson(editingGradientObject);
|
||||
|
||||
return savedJSON + "#" + editingJSON;
|
||||
}
|
||||
|
||||
private static bool DecodeGradientFromJSON(string json, out GradientObject savedGradientObject, out GradientObject editingGradientObject)
|
||||
{
|
||||
var subJSONs = json.Split('#');
|
||||
savedGradientObject = ScriptableObject.CreateInstance<GradientObject>();
|
||||
if (subJSONs[0] != " ")
|
||||
EditorJsonUtility.FromJsonOverwrite(subJSONs[0], savedGradientObject);
|
||||
editingGradientObject = ScriptableObject.CreateInstance<GradientObject>();
|
||||
if (subJSONs[1] != " ")
|
||||
EditorJsonUtility.FromJsonOverwrite(subJSONs[1], editingGradientObject);
|
||||
return subJSONs[0] != subJSONs[1];
|
||||
}
|
||||
|
||||
public static bool CreateAndSaveNewGradientTexture(int width, int height, string unityPath)
|
||||
{
|
||||
var gradientObject = ScriptableObject.CreateInstance<GradientObject>();
|
||||
gradientObject.gradient = new Gradient();
|
||||
gradientObject.gradient.colorKeys = new[] { new GradientColorKey(Color.black, 0.0f), new GradientColorKey(Color.white, 1.0f) };
|
||||
gradientObject.gradient.alphaKeys = new[] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(1f, 1f) };
|
||||
|
||||
var ramp = CreateGradientTexture(gradientObject.gradient, width, height);
|
||||
var png = ramp.EncodeToPNG();
|
||||
Object.DestroyImmediate(ramp);
|
||||
|
||||
var systemPath = projectPath + unityPath;
|
||||
File.WriteAllBytes(systemPath, png);
|
||||
|
||||
AssetDatabase.ImportAsset(unityPath);
|
||||
var textureImporter = AssetImporter.GetAtPath(unityPath) as TextureImporter;
|
||||
textureImporter.wrapMode = TextureWrapMode.Clamp;
|
||||
textureImporter.isReadable = true;
|
||||
textureImporter.textureCompression = TextureImporterCompression.Uncompressed;
|
||||
textureImporter.alphaSource = TextureImporterAlphaSource.FromInput;
|
||||
textureImporter.mipmapEnabled = false;
|
||||
|
||||
var platformTextureSettings = textureImporter.GetDefaultPlatformTextureSettings();
|
||||
platformTextureSettings.format = TextureImporterFormat.ARGB32;
|
||||
platformTextureSettings.textureCompression = TextureImporterCompression.Uncompressed;
|
||||
textureImporter.SetPlatformTextureSettings(platformTextureSettings);
|
||||
|
||||
//Gradient data embedded in userData
|
||||
textureImporter.userData = EncodeGradientToJSON(gradientObject, gradientObject);
|
||||
textureImporter.SaveAndReimport();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static Texture2D CreateGradientTexture(Gradient gradient, int width, int height)
|
||||
{
|
||||
var ramp = new Texture2D(width, height, TextureFormat.RGBA32, true, true);
|
||||
var colors = GetPixelsFromGradient(gradient, width, height);
|
||||
ramp.SetPixels32(colors);
|
||||
ramp.Apply();
|
||||
return ramp;
|
||||
}
|
||||
|
||||
private static Color32[] GetPixelsFromGradient(Gradient gradient, int width, int height)
|
||||
{
|
||||
var pixels = new Color32[width * height];
|
||||
for (var x = 0; x < width; x++)
|
||||
{
|
||||
var delta = x / (float)width;
|
||||
if (delta < 0) delta = 0;
|
||||
if (delta > 1) delta = 1;
|
||||
var col = gradient.Evaluate(delta);
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
pixels[x + i * width] = col;
|
||||
}
|
||||
}
|
||||
return pixels;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region RampSelector
|
||||
public delegate void SwitchRampMapEvent(Texture2D selectedRamp);
|
||||
|
||||
public static void RampSelector(Rect rect, string rootPath, SwitchRampMapEvent switchRampMapEvent)
|
||||
{
|
||||
var e = Event.current;
|
||||
if (e.type == UnityEngine.EventType.MouseDown && rect.Contains(e.mousePosition))
|
||||
{
|
||||
e.Use();
|
||||
var textureGUIDs = AssetDatabase.FindAssets("t:Texture2D", new[] { rootPath });
|
||||
var rampMaps = textureGUIDs.Select((GUID) =>
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(GUID);
|
||||
var assetImporter = AssetImporter.GetAtPath(path);
|
||||
if (HasGradient(assetImporter))
|
||||
{
|
||||
return AssetDatabase.LoadAssetAtPath<Texture2D>(path);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}).ToArray();
|
||||
RampSelectorWindow.ShowWindow(rect, rampMaps, switchRampMapEvent);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class RampSelectorWindow : EditorWindow
|
||||
{
|
||||
private Texture2D[] _rampMaps;
|
||||
private Vector2 _scrollPosition;
|
||||
private RampHelper.SwitchRampMapEvent _switchRampMapEvent;
|
||||
|
||||
public static void ShowWindow(Rect rect, Texture2D[] rampMaps, RampHelper.SwitchRampMapEvent switchRampMapEvent)
|
||||
{
|
||||
RampSelectorWindow window = ScriptableObject.CreateInstance<RampSelectorWindow>();
|
||||
window.titleContent = new GUIContent("Ramp Selector");
|
||||
window.minSize = new Vector2(400, 500);
|
||||
window._rampMaps = rampMaps;
|
||||
window._switchRampMapEvent = switchRampMapEvent;
|
||||
window.ShowAuxWindow();
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
EditorGUILayout.BeginVertical();
|
||||
_scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);
|
||||
|
||||
foreach (Texture2D rampMap in _rampMaps)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (rampMap != null)
|
||||
{
|
||||
var guiContent = new GUIContent(rampMap.name);
|
||||
var rect = EditorGUILayout.GetControlRect();
|
||||
var buttonWidth = Mathf.Min(300f, Mathf.Max(GUI.skin.button.CalcSize(guiContent).x, rect.width * 0.35f));
|
||||
var buttonRect = new Rect(rect.x + rect.width - buttonWidth, rect.y, buttonWidth, rect.height);
|
||||
var previewRect = new Rect(rect.x, rect.y, rect.width - buttonWidth - 3.0f, rect.height);
|
||||
if (GUI.Button(buttonRect, guiContent) && _switchRampMapEvent != null)
|
||||
{
|
||||
_switchRampMapEvent(rampMap);
|
||||
Close();
|
||||
}
|
||||
EditorGUI.DrawPreviewTexture(previewRect, rampMap);
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/LWGUI-1.14.1/Editor/RampHelper.cs.meta
Normal file
3
Assets/LWGUI-1.14.1/Editor/RampHelper.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4581bed83f9b41e18444cb08b59ce839
|
||||
timeCreated: 1687336811
|
||||
167
Assets/LWGUI-1.14.1/Editor/ReflectionHelper.cs
Normal file
167
Assets/LWGUI-1.14.1/Editor/ReflectionHelper.cs
Normal file
@@ -0,0 +1,167 @@
|
||||
// Copyright (c) Jason Ma
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
public class ReflectionHelper
|
||||
{
|
||||
private static Assembly UnityEditor_Assembly = Assembly.GetAssembly(typeof(Editor));
|
||||
|
||||
#region MaterialPropertyHandler
|
||||
private static Type MaterialPropertyHandler_Type = UnityEditor_Assembly.GetType("UnityEditor.MaterialPropertyHandler");
|
||||
private static MethodInfo MaterialPropertyHandler_GetHandler_Method = MaterialPropertyHandler_Type.GetMethod("GetHandler", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
private static PropertyInfo MaterialPropertyHandler_PropertyDrawer_Property = MaterialPropertyHandler_Type.GetProperty("propertyDrawer");
|
||||
private static FieldInfo MaterialPropertyHandler_DecoratorDrawers_Field = MaterialPropertyHandler_Type.GetField("m_DecoratorDrawers", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
public static MaterialPropertyDrawer GetPropertyDrawer(Shader shader, MaterialProperty prop, out List<MaterialPropertyDrawer> decoratorDrawers)
|
||||
{
|
||||
decoratorDrawers = new List<MaterialPropertyDrawer>();
|
||||
var handler = MaterialPropertyHandler_GetHandler_Method.Invoke(null, new System.Object[] { shader, prop.name });
|
||||
if (handler != null && handler.GetType() == MaterialPropertyHandler_Type)
|
||||
{
|
||||
decoratorDrawers = MaterialPropertyHandler_DecoratorDrawers_Field.GetValue(handler) as List<MaterialPropertyDrawer>;
|
||||
return MaterialPropertyHandler_PropertyDrawer_Property.GetValue(handler, null) as MaterialPropertyDrawer;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static MaterialPropertyDrawer GetPropertyDrawer(Shader shader, MaterialProperty prop)
|
||||
{
|
||||
List<MaterialPropertyDrawer> decoratorDrawers;
|
||||
return GetPropertyDrawer(shader, prop, out decoratorDrawers);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region MaterialEditor
|
||||
private static Type MaterialEditor_Type = typeof(MaterialEditor);
|
||||
private static MethodInfo MaterialEditor_DoPowerRangeProperty_Method = MaterialEditor_Type.GetMethod("DoPowerRangeProperty", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
private static MethodInfo MaterialEditor_DefaultShaderPropertyInternal_Method = MaterialEditor_Type.GetMethod("DefaultShaderPropertyInternal", BindingFlags.NonPublic | BindingFlags.Instance, null,
|
||||
new []{typeof(Rect), typeof(MaterialProperty), typeof(GUIContent)}, null);
|
||||
#if !UNITY_2019_2_OR_NEWER
|
||||
private static FieldInfo MaterialEditor_CustomShaderGUI_Field = MaterialEditor_Type.GetField("m_CustomShaderGUI", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
#endif
|
||||
|
||||
public static ShaderGUI GetCustomShaderGUI(MaterialEditor editor)
|
||||
{
|
||||
#if !UNITY_2019_2_OR_NEWER
|
||||
return MaterialEditor_CustomShaderGUI_Field.GetValue(editor) as ShaderGUI;
|
||||
#else
|
||||
return editor.customShaderGUI;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static float DoPowerRangeProperty(Rect position, MaterialProperty prop, GUIContent label, float power)
|
||||
{
|
||||
return (float)MaterialEditor_DoPowerRangeProperty_Method.Invoke(null, new System.Object[] { position, prop, label, power });
|
||||
}
|
||||
|
||||
public static void DefaultShaderPropertyInternal(MaterialEditor editor, Rect position, MaterialProperty prop, GUIContent label)
|
||||
{
|
||||
MaterialEditor_DefaultShaderPropertyInternal_Method.Invoke(editor, new System.Object[] { position, prop, label });
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region EditorUtility
|
||||
private static Type EditorUtility_Type = typeof(EditorUtility);
|
||||
private static MethodInfo EditorUtility_DisplayCustomMenuWithSeparators_Method = EditorUtility_Type.GetMethod("DisplayCustomMenuWithSeparators", BindingFlags.NonPublic | BindingFlags.Static, null,
|
||||
new []{typeof(Rect), typeof(string[]), typeof(bool[]), typeof(bool[]), typeof(int[]), typeof(EditorUtility.SelectMenuItemFunction), typeof(object), typeof(bool)}, null);
|
||||
|
||||
public static void DisplayCustomMenuWithSeparators(
|
||||
Rect position,
|
||||
string[] options,
|
||||
bool[] enabled,
|
||||
bool[] separator,
|
||||
int[] selected,
|
||||
EditorUtility.SelectMenuItemFunction callback,
|
||||
object userData = null,
|
||||
bool showHotkey = false)
|
||||
{
|
||||
EditorUtility_DisplayCustomMenuWithSeparators_Method.Invoke(null, new System.Object[] { position, options, enabled, separator, selected, callback, userData, showHotkey });
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region MaterialEnumDrawer
|
||||
// UnityEditor.MaterialEnumDrawer(string enumName)
|
||||
private static System.Type[] _types;
|
||||
|
||||
public static System.Type[] GetAllTypes()
|
||||
{
|
||||
if (_types == null)
|
||||
{
|
||||
_types = ((IEnumerable<Assembly>)AppDomain.CurrentDomain.GetAssemblies())
|
||||
.SelectMany<Assembly, System.Type>((Func<Assembly, IEnumerable<System.Type>>)
|
||||
(assembly =>
|
||||
{
|
||||
if (assembly == null)
|
||||
return (IEnumerable<System.Type>)(new System.Type[0]);
|
||||
try
|
||||
{
|
||||
return (IEnumerable<System.Type>)assembly.GetTypes();
|
||||
}
|
||||
catch (ReflectionTypeLoadException ex)
|
||||
{
|
||||
Debug.LogError(ex);
|
||||
return (IEnumerable<System.Type>)(new System.Type[0]);
|
||||
}
|
||||
})).ToArray<System.Type>();
|
||||
}
|
||||
return _types;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Ramp
|
||||
private static Type EditorWindow_Type = typeof(EditorWindow);
|
||||
private static MethodInfo EditorWindow_ShowModal_Method = EditorWindow_Type.GetMethod("ShowModal", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
// UnityEditor.EditorWindow.ShowModal
|
||||
// Other windows will not be accessible and any script recompilation will not happen until this window is closed
|
||||
// https://docs.unity3d.com/ScriptReference/EditorWindow.ShowModal.html
|
||||
public static void ShowModal(EditorWindow window)
|
||||
{
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
window.ShowModal();
|
||||
#else
|
||||
EditorWindow_ShowModal_Method.Invoke(window, null);
|
||||
#endif
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region MaterialProperty.PropertyData
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
private static Type MaterialProperty_Type = typeof(MaterialProperty);
|
||||
private static Type PropertyData_Type = MaterialProperty_Type.GetNestedType("PropertyData", BindingFlags.NonPublic);
|
||||
// MergeStack(out bool lockedInChildren, out bool lockedByAncestor, out bool overriden)
|
||||
private static MethodInfo PropertyData_MergeStack_Method = PropertyData_Type.GetMethod("MergeStack", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
// HandleApplyRevert(GenericMenu menu, bool singleEditing, UnityEngine.Object[] targets)
|
||||
private static MethodInfo PropertyData_HandleApplyRevert_Method = PropertyData_Type.GetMethod("HandleApplyRevert", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
|
||||
public static void HandleApplyRevert(GenericMenu menu, MaterialProperty prop)
|
||||
{
|
||||
System.Object[] parameters = new System.Object[3];
|
||||
ReflectionHelper.PropertyData_MergeStack_Method.Invoke(null, parameters);
|
||||
bool lockedInChildren = (bool)parameters[0];
|
||||
bool lockedByAncestor = (bool)parameters[1];
|
||||
bool overriden = (bool)parameters[2];
|
||||
bool singleEditing = prop.targets.Length == 1;
|
||||
|
||||
if (overriden)
|
||||
{
|
||||
ReflectionHelper.PropertyData_HandleApplyRevert_Method.Invoke(null, new System.Object[]{menu, singleEditing, prop.targets});
|
||||
menu.AddSeparator("");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
3
Assets/LWGUI-1.14.1/Editor/ReflectionHelper.cs.meta
Normal file
3
Assets/LWGUI-1.14.1/Editor/ReflectionHelper.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3451be150a8485bbd83e66540024f35
|
||||
timeCreated: 1687336811
|
||||
189
Assets/LWGUI-1.14.1/Editor/RevertableHelper.cs
Normal file
189
Assets/LWGUI-1.14.1/Editor/RevertableHelper.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
// Copyright (c) Jason Ma
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for drawing Unreal Style Revertable Shader GUI
|
||||
/// </summary>
|
||||
public class RevertableHelper
|
||||
{
|
||||
public static readonly float revertButtonWidth = 15f;
|
||||
public static float fieldWidth;
|
||||
public static float labelWidth;
|
||||
|
||||
#region GUI Setting
|
||||
|
||||
public static void IndentRect(ref Rect rect)
|
||||
{
|
||||
rect.xMax -= RevertableHelper.revertButtonWidth;
|
||||
}
|
||||
|
||||
public static Rect SplitRevertButtonRect(ref Rect rect, bool isCallInDrawer = false)
|
||||
{
|
||||
float defaultHeightWithoutDrawers = EditorGUIUtility.singleLineHeight;
|
||||
var revertButtonRect = GetRevertButtonRect(defaultHeightWithoutDrawers, rect, isCallInDrawer);
|
||||
IndentRect(ref rect);
|
||||
return revertButtonRect;
|
||||
}
|
||||
|
||||
public static Rect GetRevertButtonRect(float propHeight, Rect rect, bool isCallInDrawer = false)
|
||||
{
|
||||
if (isCallInDrawer) rect.xMax += revertButtonWidth;
|
||||
var revertButtonRect = new Rect(rect.xMax - revertButtonWidth + 2f,
|
||||
rect.yMax - propHeight * 0.5f - revertButtonWidth * 0.5f,
|
||||
revertButtonWidth - 2f,
|
||||
revertButtonWidth - 3f);
|
||||
return revertButtonRect;
|
||||
}
|
||||
|
||||
public static void InitRevertableGUIWidths()
|
||||
{
|
||||
EditorGUIUtility.fieldWidth += RevertableHelper.revertButtonWidth;
|
||||
EditorGUIUtility.labelWidth -= RevertableHelper.revertButtonWidth;
|
||||
RevertableHelper.fieldWidth = EditorGUIUtility.fieldWidth;
|
||||
RevertableHelper.labelWidth = EditorGUIUtility.labelWidth;
|
||||
}
|
||||
|
||||
public static void SetRevertableGUIWidths()
|
||||
{
|
||||
EditorGUIUtility.fieldWidth = RevertableHelper.fieldWidth;
|
||||
EditorGUIUtility.labelWidth = RevertableHelper.labelWidth;
|
||||
}
|
||||
|
||||
public static void FixGUIWidthMismatch(MaterialProperty.PropType propType, MaterialEditor materialEditor)
|
||||
{
|
||||
switch (propType)
|
||||
{
|
||||
case MaterialProperty.PropType.Texture:
|
||||
case MaterialProperty.PropType.Range:
|
||||
materialEditor.SetDefaultGUIWidths();
|
||||
break;
|
||||
default:
|
||||
RevertableHelper.SetRevertableGUIWidths();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Property Handle
|
||||
|
||||
public static void SetPropertyToDefault(MaterialProperty defaultProp, MaterialProperty prop)
|
||||
{
|
||||
prop.vectorValue = defaultProp.vectorValue;
|
||||
prop.colorValue = defaultProp.colorValue;
|
||||
prop.floatValue = defaultProp.floatValue;
|
||||
prop.textureValue = defaultProp.textureValue;
|
||||
#if UNITY_2021_1_OR_NEWER
|
||||
prop.intValue = defaultProp.intValue;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static string GetPropertyDefaultValueText(MaterialProperty defaultProp)
|
||||
{
|
||||
string defaultText = String.Empty;
|
||||
switch (defaultProp.type)
|
||||
{
|
||||
case MaterialProperty.PropType.Color:
|
||||
defaultText += defaultProp.colorValue;
|
||||
break;
|
||||
case MaterialProperty.PropType.Float:
|
||||
case MaterialProperty.PropType.Range:
|
||||
defaultText += defaultProp.floatValue;
|
||||
break;
|
||||
#if UNITY_2021_1_OR_NEWER
|
||||
case MaterialProperty.PropType.Int:
|
||||
defaultText += defaultProp.intValue;
|
||||
break;
|
||||
#endif
|
||||
case MaterialProperty.PropType.Texture:
|
||||
defaultText += defaultProp.textureValue != null ? defaultProp.textureValue.name : "None";
|
||||
break;
|
||||
case MaterialProperty.PropType.Vector:
|
||||
defaultText += defaultProp.vectorValue;
|
||||
break;
|
||||
}
|
||||
return defaultText;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Draw revert button
|
||||
|
||||
public static bool DrawRevertableProperty(Rect position, MaterialProperty prop, LWGUI lwgui, bool isHeader = false)
|
||||
{
|
||||
bool hasModified = prop.hasMixedValue;
|
||||
|
||||
var propDynamicData = lwgui.perFrameData.propertyDatas[prop.name];
|
||||
var propStaticData = lwgui.perShaderData.propertyDatas[prop.name];
|
||||
if (!hasModified)
|
||||
hasModified = propDynamicData.hasModified;
|
||||
|
||||
if (!hasModified && isHeader)
|
||||
hasModified = propDynamicData.hasChildrenModified;
|
||||
|
||||
var extraPropNames = lwgui.perShaderData.propertyDatas[prop.name].extraPropNames;
|
||||
if (!hasModified && extraPropNames.Count > 0)
|
||||
hasModified = extraPropNames.Any((extraPropName => lwgui.perFrameData.propertyDatas[extraPropName].hasModified));
|
||||
|
||||
if (!hasModified)
|
||||
return false;
|
||||
|
||||
Rect rect = position;
|
||||
if (DrawRevertButton(rect))
|
||||
{
|
||||
DoRevertProperty(prop, lwgui);
|
||||
|
||||
foreach (var childStaticData in propStaticData.children)
|
||||
{
|
||||
DoRevertProperty(lwgui.perFrameData.propertyDatas[childStaticData.name].property, lwgui);
|
||||
foreach (var childChildStaticData in childStaticData.children)
|
||||
DoRevertProperty(lwgui.perFrameData.propertyDatas[childChildStaticData.name].property, lwgui);
|
||||
}
|
||||
|
||||
// refresh keywords
|
||||
MaterialEditor.ApplyMaterialPropertyDrawers(lwgui.materialEditor.targets);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void DoRevertProperty(MaterialProperty prop, LWGUI lwgui)
|
||||
{
|
||||
var propDynamicData = lwgui.perFrameData.propertyDatas[prop.name];
|
||||
var extraPropNames = lwgui.perShaderData.propertyDatas[prop.name].extraPropNames;
|
||||
propDynamicData.hasRevertChanged = true;
|
||||
SetPropertyToDefault(propDynamicData.defualtProperty, prop);
|
||||
foreach (var extraPropName in extraPropNames)
|
||||
{
|
||||
var extraPropDynamicData = lwgui.perFrameData.propertyDatas[extraPropName];
|
||||
extraPropDynamicData.hasRevertChanged = true;
|
||||
SetPropertyToDefault(extraPropDynamicData.defualtProperty, extraPropDynamicData.property);
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Texture _icon = AssetDatabase.LoadAssetAtPath<Texture>(AssetDatabase.GUIDToAssetPath("e7bc1130858d984488bca32b8512ca96"));
|
||||
|
||||
public static bool DrawRevertButton(Rect rect)
|
||||
{
|
||||
if (_icon == null) Debug.LogError("RevertIcon.png + meta is missing!");
|
||||
GUI.DrawTexture(rect, _icon);
|
||||
var e = Event.current;
|
||||
if (e.type == UnityEngine.EventType.MouseDown && rect.Contains(e.mousePosition))
|
||||
{
|
||||
e.Use();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
3
Assets/LWGUI-1.14.1/Editor/RevertableHelper.cs.meta
Normal file
3
Assets/LWGUI-1.14.1/Editor/RevertableHelper.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 259535769835488e9edaf21cbe36465d
|
||||
timeCreated: 1687336811
|
||||
1386
Assets/LWGUI-1.14.1/Editor/ShaderDrawer.cs
Normal file
1386
Assets/LWGUI-1.14.1/Editor/ShaderDrawer.cs
Normal file
File diff suppressed because it is too large
Load Diff
11
Assets/LWGUI-1.14.1/Editor/ShaderDrawer.cs.meta
Normal file
11
Assets/LWGUI-1.14.1/Editor/ShaderDrawer.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7661dfeec673f340b66ac769fa42d18
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
23
Assets/LWGUI-1.14.1/Editor/ShaderModifyListener.cs
Normal file
23
Assets/LWGUI-1.14.1/Editor/ShaderModifyListener.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) Jason Ma
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
public class ShaderModifyListener : AssetPostprocessor
|
||||
{
|
||||
private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
|
||||
{
|
||||
foreach (var assetPath in importedAssets)
|
||||
{
|
||||
if (Path.GetExtension(assetPath).Equals(".shader", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var shader = AssetDatabase.LoadAssetAtPath<Shader>(assetPath);
|
||||
MetaDataHelper.ForceRebuildPerShaderData(shader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/LWGUI-1.14.1/Editor/ShaderModifyListener.cs.meta
Normal file
3
Assets/LWGUI-1.14.1/Editor/ShaderModifyListener.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6143a217ed5c4b709eb585de3e8026d0
|
||||
timeCreated: 1693983094
|
||||
257
Assets/LWGUI-1.14.1/Editor/ShaderPropertyPreset.cs
Normal file
257
Assets/LWGUI-1.14.1/Editor/ShaderPropertyPreset.cs
Normal file
@@ -0,0 +1,257 @@
|
||||
// Copyright (c) 2022 Jason Ma
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
[CreateAssetMenu(fileName = "LWGUI_ShaderPropertyPreset.asset", menuName = "LWGUI/Shader Property Preset")]
|
||||
public class ShaderPropertyPreset : ScriptableObject
|
||||
{
|
||||
public enum PropertyType
|
||||
{
|
||||
Color,
|
||||
Vector,
|
||||
Float,
|
||||
Range,
|
||||
Texture,
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class PropertyValue
|
||||
{
|
||||
public PropertyValue(MaterialProperty prop)
|
||||
{
|
||||
CopyFromMaterialProperty(prop);
|
||||
}
|
||||
|
||||
public string propertyName;
|
||||
public PropertyType propertyType;
|
||||
public float floatValue;
|
||||
public Color colorValue;
|
||||
public Vector4 vectorValue;
|
||||
public Texture textureValue;
|
||||
|
||||
private int propertyNameID = -1;
|
||||
|
||||
public void Apply(Material material, bool isDefaultMaterial, PerFrameData perFrameData = null)
|
||||
{
|
||||
if (propertyNameID == -1 || !material.HasProperty(propertyNameID))
|
||||
propertyNameID = Shader.PropertyToID(propertyName);
|
||||
if (!material.HasProperty(propertyNameID))
|
||||
{
|
||||
var propertyNameLower = propertyName.ToLower();
|
||||
switch (propertyNameLower)
|
||||
{
|
||||
case "renderqueue":
|
||||
material.renderQueue = (int)floatValue;
|
||||
return;
|
||||
default:
|
||||
// Debug.LogWarning("Unable to find Preset Property: " + propertyName + " in Material: " + material + "!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var isPropertyOtherMaterials = !isDefaultMaterial && perFrameData == null;
|
||||
if (isPropertyOtherMaterials || isDefaultMaterial)
|
||||
{
|
||||
switch (propertyType)
|
||||
{
|
||||
case PropertyType.Color:
|
||||
material.SetColor(propertyNameID, colorValue);
|
||||
break;
|
||||
case PropertyType.Vector:
|
||||
material.SetVector(propertyNameID, vectorValue);
|
||||
break;
|
||||
case PropertyType.Float:
|
||||
case PropertyType.Range:
|
||||
material.SetFloat(propertyNameID, floatValue);
|
||||
break;
|
||||
case PropertyType.Texture:
|
||||
material.SetTexture(propertyNameID, textureValue);
|
||||
break;
|
||||
}
|
||||
|
||||
if (isPropertyOtherMaterials)
|
||||
MaterialEditor.ApplyMaterialPropertyDrawers(material);
|
||||
}
|
||||
else
|
||||
// is Property Primary Material
|
||||
{
|
||||
var propDynamicData = perFrameData.propertyDatas[propertyName];
|
||||
var prop = propDynamicData.property;
|
||||
switch (propertyType)
|
||||
{
|
||||
case PropertyType.Color:
|
||||
prop.colorValue = colorValue;
|
||||
break;
|
||||
case PropertyType.Vector:
|
||||
prop.vectorValue = vectorValue;
|
||||
break;
|
||||
case PropertyType.Float:
|
||||
case PropertyType.Range:
|
||||
prop.floatValue = floatValue;
|
||||
break;
|
||||
case PropertyType.Texture:
|
||||
prop.textureValue = textureValue;
|
||||
break;
|
||||
}
|
||||
|
||||
propDynamicData.hasRevertChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyFromMaterialProperty(MaterialProperty prop)
|
||||
{
|
||||
propertyName = prop.name;
|
||||
switch (prop.type)
|
||||
{
|
||||
case MaterialProperty.PropType.Color:
|
||||
propertyType = PropertyType.Color;
|
||||
colorValue = prop.colorValue;
|
||||
break;
|
||||
case MaterialProperty.PropType.Vector:
|
||||
propertyType = PropertyType.Vector;
|
||||
vectorValue = prop.vectorValue;
|
||||
break;
|
||||
#if UNITY_2021_1_OR_NEWER
|
||||
case MaterialProperty.PropType.Int:
|
||||
#endif
|
||||
case MaterialProperty.PropType.Float:
|
||||
propertyType = PropertyType.Float;
|
||||
floatValue = prop.floatValue;
|
||||
break;
|
||||
case MaterialProperty.PropType.Range:
|
||||
propertyType = PropertyType.Range;
|
||||
floatValue = prop.floatValue;
|
||||
break;
|
||||
case MaterialProperty.PropType.Texture:
|
||||
propertyType = PropertyType.Texture;
|
||||
textureValue = prop.textureValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnValidate()
|
||||
{
|
||||
propertyNameID = -1;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class Preset
|
||||
{
|
||||
public string presetName;
|
||||
public List<PropertyValue> propertyValues = new List<PropertyValue>();
|
||||
|
||||
public void ApplyToDefaultMaterial(Material material)
|
||||
{
|
||||
foreach (var propertyValue in propertyValues)
|
||||
propertyValue.Apply(material, true);
|
||||
}
|
||||
|
||||
public PropertyValue GetPropertyValue(string propName)
|
||||
{
|
||||
PropertyValue result = null;
|
||||
if (propertyValues != null)
|
||||
{
|
||||
foreach (var propertyValue in propertyValues)
|
||||
{
|
||||
if (propertyValue.propertyName == propName)
|
||||
{
|
||||
result = propertyValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void AddOrUpdate(MaterialProperty prop)
|
||||
{
|
||||
var propertyValue = GetPropertyValue(prop.name);
|
||||
if (propertyValue != null)
|
||||
propertyValue.CopyFromMaterialProperty(prop);
|
||||
else
|
||||
propertyValues.Add(new PropertyValue(prop));
|
||||
}
|
||||
|
||||
public void AddOrUpdateIncludeExtraProperties(LWGUI lwgui, MaterialProperty prop)
|
||||
{
|
||||
AddOrUpdate(prop);
|
||||
foreach (var extraPropName in lwgui.perShaderData.propertyDatas[prop.name].extraPropNames)
|
||||
{
|
||||
AddOrUpdate(lwgui.perFrameData.propertyDatas[extraPropName].property);
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(string propName)
|
||||
{
|
||||
var propertyValue = GetPropertyValue(propName);
|
||||
if (propertyValue != null)
|
||||
propertyValues.Remove(propertyValue);
|
||||
}
|
||||
|
||||
public void RemoveIncludeExtraProperties(LWGUI lwgui, string propName)
|
||||
{
|
||||
Remove(propName);
|
||||
foreach (var extraPropName in lwgui.perShaderData.propertyDatas[propName].extraPropNames)
|
||||
{
|
||||
Remove(lwgui.perFrameData.propertyDatas[extraPropName].property.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Preset> presets;
|
||||
|
||||
// private void Awake()
|
||||
// {
|
||||
// Debug.Log($"{this.name} Awake");
|
||||
// }
|
||||
//
|
||||
// private void OnDestroy()
|
||||
// {
|
||||
// Debug.Log($"{this.name} OnDestroy");
|
||||
// }
|
||||
//
|
||||
// private void OnDisable()
|
||||
// {
|
||||
// Debug.Log($"{this.name} OnDisable");
|
||||
// }
|
||||
//
|
||||
// private void Reset()
|
||||
// {
|
||||
// Debug.Log($"{this.name} Reset");
|
||||
// }
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
// Debug.Log($"{this.name} OnValidate");
|
||||
PresetHelper.ForceInit();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
// Debug.Log($"{this.name} OnEnable");
|
||||
// manually added when a preset is manually created
|
||||
if (PresetHelper.IsInitComplete)
|
||||
PresetHelper.AddPreset(this);
|
||||
}
|
||||
|
||||
public void ApplyToMaterials(UnityEngine.Object[] materials, int presetIndex, PerFrameData perFrameData)
|
||||
{
|
||||
if (this.presets.Count == 0) return;
|
||||
|
||||
int index = (int)Mathf.Min(this.presets.Count - 1, Mathf.Max(0, presetIndex));
|
||||
foreach (var propertyValue in this.presets[index].propertyValues)
|
||||
{
|
||||
for (int i = 0; i < materials.Length; i++)
|
||||
{
|
||||
var material = materials[i] as Material;
|
||||
propertyValue.Apply(material, false, i == 0 ? perFrameData : null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/LWGUI-1.14.1/Editor/ShaderPropertyPreset.cs.meta
Normal file
3
Assets/LWGUI-1.14.1/Editor/ShaderPropertyPreset.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 28fbcbca3fb14507af6ed5c104c40b84
|
||||
timeCreated: 1667657706
|
||||
83
Assets/LWGUI-1.14.1/Editor/VersionControlHelper.cs
Normal file
83
Assets/LWGUI-1.14.1/Editor/VersionControlHelper.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) Jason Ma
|
||||
using UnityEditor;
|
||||
using UnityEditor.VersionControl;
|
||||
using UnityEngine;
|
||||
|
||||
namespace LWGUI
|
||||
{
|
||||
public class VersionControlHelper
|
||||
{
|
||||
public static bool isVCEnabled { get { return Provider.enabled && Provider.isActive; } }
|
||||
|
||||
public static bool Checkout(UnityEngine.Object obj)
|
||||
{
|
||||
if (AssetDatabase.Contains(obj))
|
||||
{
|
||||
var path = AssetDatabase.GetAssetPath(obj);
|
||||
return Checkout(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Checkout(string projectRelativedPath)
|
||||
{
|
||||
if (isVCEnabled)
|
||||
{
|
||||
var vcAsset = Provider.GetAssetByPath(projectRelativedPath);
|
||||
if (vcAsset != null)
|
||||
{
|
||||
var statusTask = Provider.Status(vcAsset);
|
||||
statusTask.Wait();
|
||||
if (Provider.CheckoutIsValid(statusTask.assetList))
|
||||
{
|
||||
var checkOutTask = Provider.Checkout(vcAsset, CheckoutMode.Both);
|
||||
checkOutTask.Wait();
|
||||
if (checkOutTask.success)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (Provider.IsOpenForEdit(vcAsset))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Debug.LogError("Checkout '" + projectRelativedPath + "' failure!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool Add(string projectRelativedPath)
|
||||
{
|
||||
if (isVCEnabled)
|
||||
{
|
||||
var vcAsset = Provider.GetAssetByPath(projectRelativedPath);
|
||||
if (vcAsset != null)
|
||||
{
|
||||
var statusTask = Provider.Status(vcAsset);
|
||||
statusTask.Wait();
|
||||
if (Provider.AddIsValid(statusTask.assetList))
|
||||
{
|
||||
var addTask = Provider.Add(vcAsset, false);
|
||||
addTask.Wait();
|
||||
if (addTask.success)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.LogError("Add '" + projectRelativedPath + "' failure!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/LWGUI-1.14.1/Editor/VersionControlHelper.cs.meta
Normal file
3
Assets/LWGUI-1.14.1/Editor/VersionControlHelper.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f8e9e3181ad14421a67f641ab4aadc5c
|
||||
timeCreated: 1687333459
|
||||
Reference in New Issue
Block a user