Files
ichni_Official/Packages/XuanXuanRenderUtility/Editor/ShaderGUIHelper.cs

1946 lines
83 KiB
C#
Raw Normal View History

2025-07-21 05:42:20 -04:00
using System;
using System.Collections.Generic;
2025-08-27 21:45:18 -04:00
using System.Linq;
2025-07-21 05:42:20 -04:00
using UnityEditor.AnimatedValues;
// using UnityEditor.Rendering.Universal.ShaderGUI;
using UnityEngine;
2025-08-27 21:45:18 -04:00
using Random = UnityEngine.Random;
using System.Reflection;
using UnityEngine.UIElements;
using UnityEditor;
namespace NBShaderEditor
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
/*
0 1matEditorMaterialPropertyMat以及Mat属性值ShaderFlag以及ShaderFlag值
1Mixed状态时propety.Value进行设置是不合法的Mixed状态才会完全设置property.Value值进行判断也是非法的Mixed的情况下Mats[i].Get或Set进行操作Flag亦同理
2drawBlock应该都传PropertyDrawBlock内能知道Mixed状态Block内需要判断状态是否明确才进行相关的操作
3drawBlock一般放需要绘制的行为OnValueChangeCheckBlock
4GUI上存储mixed状态-1UnKnownOrMixed枚举boolint值-1UnKnownOrMixed状态
5OnValueChange的情况下进行
6Toggle作用的方法EditorOnly的Property进行标记Toggle储存Keywords或者Flag应该是设定结果Toggle标记
7DrawVectorComponent这种多个GUI公用一个property属性的情况Component是否是Mixed的方案
*/
2025-07-21 05:42:20 -04:00
public class ShaderGUIHelper
{
2025-08-27 21:45:18 -04:00
public ShaderGUIHelper()
{
Undo.undoRedoPerformed += OnUndoRedoPerformed;
}
private void OnUndoRedoPerformed()//定义一个Undo回调
{
if(!shader) return;//会有一些空的Helper对象
DrawGradientUndoPerformed();
ResetTool?.NeedUpdate();
}
2025-07-21 05:42:20 -04:00
public class ShaderPropertyPack
{
public MaterialProperty property;
public string name;
2025-08-27 21:45:18 -04:00
public int index;
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
public List<Material> mats;
public MaterialEditor matEditor;
public Shader shader;
// public List<ShaderPropertyPack> ShaderPropertyPacks = new List<ShaderPropertyPack>();
public Dictionary<string, ShaderPropertyPack> ShaderPropertyPacksDic =
new Dictionary<string, ShaderPropertyPack>();
2025-07-21 05:42:20 -04:00
public ShaderFlagsBase[] shaderFlags = null;
2025-08-27 21:45:18 -04:00
public bool isClearUnUsedTexture = false;
Color defaultBackgroundColor;
Color animatedBackgroundColor=>Color.red;
2025-07-21 05:42:20 -04:00
public void Init(MaterialEditor materialEditor, MaterialProperty[] properties,
ShaderFlagsBase[] shaderFlags_in = null, List<Material> mats_in = null)
{
2025-08-27 21:45:18 -04:00
defaultBackgroundColor = GUI.backgroundColor;
2025-07-21 05:42:20 -04:00
shaderFlags = shaderFlags_in;
2025-08-27 21:45:18 -04:00
// ShaderPropertyPacks.Clear();
2025-07-21 05:42:20 -04:00
matEditor = materialEditor;
2025-08-27 21:45:18 -04:00
mats = mats_in;
if (mats[0].shader != shader)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
shader = mats[0].shader;
ShaderPropertyPacksDic.Clear();
for (int i = 0; i < ShaderUtil.GetPropertyCount(shader); i++)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
ShaderPropertyPack pack = new ShaderPropertyPack();
pack.name = ShaderUtil.GetPropertyName(shader, i);
for (int index = 0; index < properties.Length; ++index)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
if (properties[index] != null && properties[index].name == pack.name)
{
pack.property = properties[index];
pack.index = index;
break;
}
else
{
if (index == properties.Length - 1)
{
Debug.LogError(pack.name + "找不到Properties");
}
}
}
// ShaderPropertyPacks.Add(pack);
ShaderPropertyPacksDic.Add(pack.name,pack);
}
}
else
{
for (int i = 0; i < ShaderUtil.GetPropertyCount(shader); i++)
{
string propertyName = ShaderUtil.GetPropertyName(shader, i);
ShaderPropertyPacksDic[propertyName].property = properties[i];
}
}
if (ResetTool == null)
{
ResetTool = new ShaderGUIResetTool(this);
}
else
{
ResetTool.EndInit();
ResetTool.Update();
}
isClearUnUsedTexture = false;
}
private ShaderGUIToolBar _toolBar;
public ShaderGUIResetTool ResetTool;
public List<Renderer> renderersUsingThisMaterial = new List<Renderer>();
public bool IsPropertyAnimated(string propertyName,params string[] componentNames)
{
if (AnimationMode.InAnimationMode())
{
string propertyPath = "material." + propertyName;
foreach (var r in renderersUsingThisMaterial)
{
if (componentNames.Length > 0)
{
foreach (var component in componentNames)
{
string propertyPathWithComponent = propertyPath +"." +component;
if (AnimationMode.IsPropertyAnimated(r, propertyPathWithComponent))
{
return true;
}
}
2025-07-21 05:42:20 -04:00
}
else
{
2025-08-27 21:45:18 -04:00
if (AnimationMode.IsPropertyAnimated(r, propertyPath))
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
// Debug.Log(propertyName);
return true;
2025-07-21 05:42:20 -04:00
}
}
}
2025-08-27 21:45:18 -04:00
}
return false;
}
2025-07-21 05:42:20 -04:00
2025-08-27 21:45:18 -04:00
public void DrawToolBar()
{
if (_toolBar == null) _toolBar = new ShaderGUIToolBar(this);
_toolBar.DrawToolbar();
}
public void DrawToggleFoldOut(int foldOutFlagBit,int foldOutFlagIndex, int animBoolIndex,string label, string propertyName,
int flagBitsName = 0,
int flagIndex = 0, string shaderKeyword = null, string shaderPassName = null, bool isIndentBlock = true, FontStyle fontStyle = FontStyle.Normal,
Action<MaterialProperty> drawBlock = null,Action<MaterialProperty> drawEndChangeCheck = null,bool isSharedGlobalParent = false)
{
bool foldOutState = shaderFlags[0].CheckFlagBits(foldOutFlagBit, index: foldOutFlagIndex);
AnimBool animBool = GetAnimBool(foldOutFlagBit, animBoolIndex, foldOutFlagIndex); //foldOut里的第一组。
animBool.target = foldOutState;
DrawToggleFoldOut(ref animBool, label, propertyName, flagBitsName, flagIndex, shaderKeyword,
shaderPassName, isIndentBlock, fontStyle, drawBlock, drawEndChangeCheck,isSharedGlobalParent:isSharedGlobalParent);
foldOutState = animBool.target;
if (foldOutState)
{
shaderFlags[0].SetFlagBits(foldOutFlagBit, index: foldOutFlagIndex);
}
else
{
shaderFlags[0].ClearFlagBits(foldOutFlagBit, index: foldOutFlagIndex);
2025-07-21 05:42:20 -04:00
}
}
2025-08-27 21:45:18 -04:00
public void ColorProperty(string label, string propertyName,bool showAlpha = true)
{
EditorGUILayout.BeginHorizontal();
ShaderPropertyPack shaderPropertyPack = ShaderPropertyPacksDic[propertyName];
MaterialProperty prop = shaderPropertyPack.property;
Color color = shaderPropertyPack.property.colorValue;
Rect position = EditorGUILayout.GetControlRect();
// MaterialEditor.BeginProperty(position, prop);
EditorGUI.BeginChangeCheck();
2026-03-14 03:13:10 -04:00
bool hdr = (prop.propertyFlags & UnityEngine.Rendering.ShaderPropertyFlags.HDR) != 0;
2025-08-27 21:45:18 -04:00
if (IsPropertyAnimated(propertyName,"r","g","b","a"))
{
GUI.backgroundColor = animatedBackgroundColor;
}
color = EditorGUI.ColorField(position, new GUIContent(label), prop.colorValue, true, showAlpha, hdr);
GUI.backgroundColor = defaultBackgroundColor;
Action onEndChaneChange = () =>
{
prop.colorValue = color;
ResetTool.CheckOnValueChange((label,propertyName));
};
if (EditorGUI.EndChangeCheck())
{
onEndChaneChange();
}
ResetTool.DrawResetModifyButton(new Rect(),(label,shaderPropertyPack.name),shaderPropertyPack,resetAction: () =>
{
color = prop.colorValue;
},onValueChangedCallBack: onEndChaneChange);
// MaterialEditor.EndProperty();
// matEditor.ColorProperty(GetProperty(propertyName), label);
EditorGUILayout.EndHorizontal();
ResetTool.EndResetModifyButtonScope();
}
2025-07-21 05:42:20 -04:00
2025-08-27 21:45:18 -04:00
public void DrawBigBlockFoldOut(int foldOutFlagBit,int foldOutFlagIndex,int animBoolIndex ,string label, Action drawBlock,bool isResetButtonBias = true)
2025-07-21 05:42:20 -04:00
{
EditorGUILayout.Space();
2025-08-27 21:45:18 -04:00
DrawFoldOut(foldOutFlagBit,foldOutFlagIndex,animBoolIndex, label,FontStyle.Bold, drawBlock,isResetButtonBias);
2025-07-21 05:42:20 -04:00
GuiLine();
}
2025-08-27 21:45:18 -04:00
private AnimBool[] animBoolArr = new AnimBool[96];//先假定有3组。和存好的bit一一对应。
public AnimBool GetAnimBool(int flagBit, int AnimBoolIndex,int flagIndex)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
int bitPos = 0;
for (int i = 0; i < 32; i++)
{
if ((flagBit & (1 << i)) > 0)
{
bitPos = i;
break;
}
}
int arrIndex = AnimBoolIndex * 32 + bitPos;
// Debug.Log(arrIndex.ToString() +"---"+ animBoolArr[arrIndex]);
if (animBoolArr[arrIndex] == null)
{
animBoolArr[arrIndex] = new AnimBool(shaderFlags[0].CheckFlagBits(flagBit,index:flagIndex));
}
return animBoolArr[arrIndex];
}
public void DrawFoldOut(int foldOutFlagBit,int foldOutFlagIndex,int animBoolIndex, String label,FontStyle fontStyle = FontStyle.Normal, Action drawBlock = null,bool isResetButtonBias = true)
{
bool foldOutState = shaderFlags[0].CheckFlagBits(foldOutFlagBit, index: foldOutFlagIndex);
AnimBool animBool = GetAnimBool(foldOutFlagBit, animBoolIndex, foldOutFlagIndex);
animBool.target = foldOutState;
2025-07-21 05:42:20 -04:00
EditorGUILayout.BeginHorizontal();
var rect = EditorGUILayout.GetControlRect();
var foldoutRect = new Rect(rect.x, rect.y, rect.width, rect.height);
2025-08-27 21:45:18 -04:00
foldoutRect.width -= 2 * ResetTool.ResetButtonSize;
2025-07-21 05:42:20 -04:00
var labelRect = new Rect(rect.x + 2f, rect.y, rect.width - 2f, rect.height);
2025-08-27 21:45:18 -04:00
var resetRect = rect;
resetRect.x = rect.x + rect.width - ResetTool.ResetButtonSize ;
if (isResetButtonBias) resetRect.x -= 3f;
resetRect.width = ResetTool.ResetButtonSize;
animBool.target = EditorGUI.Foldout(foldoutRect, animBool.target, string.Empty, true);
2025-07-21 05:42:20 -04:00
FontStyle origFontStyle = EditorStyles.label.fontStyle;
2025-08-27 21:45:18 -04:00
EditorStyles.label.fontStyle = fontStyle;
2025-07-21 05:42:20 -04:00
EditorGUI.LabelField(labelRect, label);
EditorStyles.label.fontStyle = origFontStyle;
2025-08-27 21:45:18 -04:00
ResetTool.DrawResetModifyButton(resetRect,label);
2025-07-21 05:42:20 -04:00
EditorGUILayout.EndHorizontal();
2025-08-27 21:45:18 -04:00
float faded = animBool.faded;
2025-07-21 05:42:20 -04:00
if (faded == 0) faded = 0.00001f;
EditorGUILayout.BeginFadeGroup(faded);
EditorGUI.indentLevel++;
2025-08-27 21:45:18 -04:00
drawBlock?.Invoke();
2025-07-21 05:42:20 -04:00
EditorGUI.indentLevel--;
EditorGUILayout.EndFadeGroup();
2025-08-27 21:45:18 -04:00
foldOutState = animBool.target;
if (foldOutState)
{
shaderFlags[0].SetFlagBits(foldOutFlagBit, index: foldOutFlagIndex);
}
else
{
shaderFlags[0].ClearFlagBits(foldOutFlagBit, index: foldOutFlagIndex);
}
ResetTool.EndResetModifyButtonScope();
2025-07-21 05:42:20 -04:00
}
public void DrawBigBlockWithToggle(String label, string propertyName, int flagBitsName = 0, int flagIndex = 0,
string shaderKeyword = null, string shaderPassName = null, string shaderPassName2 = null,
2025-08-27 21:45:18 -04:00
Action<MaterialProperty> drawBlock = null)
2025-07-21 05:42:20 -04:00
{
DrawToggle(label, propertyName, flagBitsName, flagIndex, shaderKeyword, shaderPassName, shaderPassName2,
isIndentBlock: true, FontStyle.Bold, drawBlock: drawBlock);
GuiLine();
}
2025-08-27 21:45:18 -04:00
public void DrawToggleFoldOut(ref AnimBool foldOutAnimBool, String label, string propertyName,
2025-07-21 05:42:20 -04:00
int flagBitsName = 0,
int flagIndex = 0, string shaderKeyword = null, string shaderPassName = null, bool isIndentBlock = true,
FontStyle fontStyle = FontStyle.Normal,
2025-08-27 21:45:18 -04:00
Action<MaterialProperty> drawBlock = null, Action<MaterialProperty> drawEndChangeCheck = null,bool isSharedGlobalParent = false)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
ShaderPropertyPack propertyPack = ShaderPropertyPacksDic[propertyName];
MaterialProperty toggleProp = GetProperty(propertyName);
2025-07-21 05:42:20 -04:00
if (fontStyle == FontStyle.Bold)
{
EditorGUILayout.Space();
}
EditorGUILayout.BeginHorizontal();
var rect = EditorGUILayout.GetControlRect();
2025-08-27 21:45:18 -04:00
var toggleRect = rect;
toggleRect.x += EditorGUIUtility.labelWidth;
toggleRect.width -= EditorGUIUtility.labelWidth;
2025-07-21 05:42:20 -04:00
var foldoutRect = new Rect(rect.x, rect.y, rect.width, rect.height);
foldoutRect.width = toggleRect.x - foldoutRect.x;
2025-08-27 21:45:18 -04:00
var labelRect = new Rect(rect.x , rect.y, rect.width , rect.height);
2025-07-21 05:42:20 -04:00
2025-08-27 21:45:18 -04:00
// bool isToggle = false;
2025-07-21 05:42:20 -04:00
// 必须先画Toggle不然按钮会被FoldOut和Label覆盖。
2025-08-27 21:45:18 -04:00
DrawToggle(string.Empty, propertyName, flagBitsName, flagIndex, shaderKeyword, shaderPassName, isIndentBlock: false, fontStyle: FontStyle.Normal, rect: toggleRect, drawEndChangeCheck: drawEndChangeCheck,isSharedGlobalParent:isSharedGlobalParent);
2025-07-21 05:42:20 -04:00
foldOutAnimBool.target = EditorGUI.Foldout(foldoutRect, foldOutAnimBool.target, string.Empty, true);
var origFontStyle = EditorStyles.label.fontStyle;
EditorStyles.label.fontStyle = fontStyle;
2025-08-27 21:45:18 -04:00
2025-07-21 05:42:20 -04:00
EditorGUI.LabelField(labelRect, label);
EditorStyles.label.fontStyle = origFontStyle;
EditorGUILayout.EndHorizontal();
if (isIndentBlock) EditorGUI.indentLevel++;
float faded = foldOutAnimBool.faded;
if (faded == 0) faded = 0.00001f; //用于欺骗FadeGroup不要让他真的关闭了。这样会藏不住相关的GUI。我们的目的是GUI藏住但是逻辑还是在跑。drawBlock要执行。
EditorGUILayout.BeginFadeGroup(faded);
{
2025-08-27 21:45:18 -04:00
bool isDisabledGroup = toggleProp.hasMixedValue || toggleProp.floatValue < 0.5f;
EditorGUI.BeginDisabledGroup(isDisabledGroup);
drawBlock?.Invoke(toggleProp);
2025-07-21 05:42:20 -04:00
EditorGUI.EndDisabledGroup();
}
EditorGUILayout.EndFadeGroup();
if (isIndentBlock) EditorGUI.indentLevel--;
2025-08-27 21:45:18 -04:00
ResetTool.EndResetModifyButtonScope();//开始是在DrawToggle里开始的
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
public void DrawToggle(String label, string propertyName, int flagBitsName = 0, int flagIndex = 0,
2025-07-21 05:42:20 -04:00
string shaderKeyword = null, string shaderPassName = null, string shaderPassName2 = null,
bool isIndentBlock = true, FontStyle fontStyle = FontStyle.Normal, Rect rect = new Rect(),
2025-08-27 21:45:18 -04:00
Action<MaterialProperty> drawBlock = null, Action<MaterialProperty> drawEndChangeCheck = null,bool isSharedGlobalParent = false)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
if (GetProperty(propertyName) == null)
2025-07-21 05:42:20 -04:00
return;
2025-08-27 21:45:18 -04:00
2025-07-21 05:42:20 -04:00
if (fontStyle == FontStyle.Bold)
{
EditorGUILayout.Space();
}
2025-08-27 21:45:18 -04:00
MaterialProperty toggleProperty = GetProperty(propertyName);
ShaderPropertyPack propertyPack = ShaderPropertyPacksDic[propertyName];
EditorGUI.showMixedValue = toggleProperty.hasMixedValue;
2025-07-21 05:42:20 -04:00
EditorGUI.BeginChangeCheck();
2025-08-27 21:45:18 -04:00
bool isToggle = toggleProperty.floatValue > 0.5f ? true : false;
2025-07-21 05:42:20 -04:00
var origFontStyle = EditorStyles.label.fontStyle;
EditorStyles.label.fontStyle = fontStyle;
2025-08-27 21:45:18 -04:00
Rect resetButtonRect = rect;
if (label.Length == 0) //给FoldOut功能使用。
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
rect.x += 2f;
2025-07-21 05:42:20 -04:00
isToggle = EditorGUI.Toggle(rect, isToggle, EditorStyles.toggle);
2025-08-27 21:45:18 -04:00
resetButtonRect.x = resetButtonRect.x + resetButtonRect.width - ResetTool.ResetButtonSize;
resetButtonRect.width = ResetTool.ResetButtonSize;
2025-07-21 05:42:20 -04:00
}
else
{
2025-08-27 21:45:18 -04:00
EditorGUILayout.BeginHorizontal();
2025-07-21 05:42:20 -04:00
isToggle = EditorGUILayout.Toggle(label, isToggle);
}
2025-08-27 21:45:18 -04:00
2025-07-21 05:42:20 -04:00
EditorStyles.label.fontStyle = origFontStyle;
2025-08-27 21:45:18 -04:00
Action onEndChangeCheck = () =>
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
toggleProperty.floatValue = isToggle ? 1.0f : 0.0f;
ResetTool.CheckOnValueChange((label,propertyName));
if (!toggleProperty.hasMixedValue)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
for (int i = 0; i < mats.Count; i++)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
if (isToggle)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
mats[i].SetFloat(propertyName,1);
if (flagBitsName != 0 && shaderFlags[i] != null)
{
shaderFlags[i].SetFlagBits(flagBitsName, index: flagIndex);
}
if (shaderKeyword != null)
{
mats[i].EnableKeyword(shaderKeyword);
}
if (shaderPassName != null)
{
mats[i].SetShaderPassEnabled(shaderPassName, true);
}
if (shaderPassName2 != null)
{
mats[i].SetShaderPassEnabled(shaderPassName2, true);
}
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
else
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
mats[i].SetFloat(propertyName,0);
if (flagBitsName != 0 && shaderFlags[i] != null)
{
shaderFlags[i].ClearFlagBits(flagBitsName, index: flagIndex);
}
if (shaderKeyword != null)
{
mats[i].DisableKeyword(shaderKeyword);
}
if (shaderPassName != null)
{
mats[i].SetShaderPassEnabled(shaderPassName, false);
}
if (shaderPassName2 != null)
{
mats[i].SetShaderPassEnabled(shaderPassName2, false);
}
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
}
}
drawEndChangeCheck?.Invoke(toggleProperty);
};
if (EditorGUI.EndChangeCheck())
{
onEndChangeCheck();
}
ResetTool.DrawResetModifyButton(resetButtonRect,(label,propertyPack.name),propertyPack,resetAction: () =>
{
isToggle = propertyPack.property.floatValue > 0.5f ? true : false;
},onValueChangedCallBack:onEndChangeCheck,isSharedGlobalParent:isSharedGlobalParent);
if (label.Length > 0)
{
EditorGUILayout.EndHorizontal();
}
if (isIndentBlock) EditorGUI.indentLevel++;
drawBlock?.Invoke(toggleProperty);
if (isIndentBlock) EditorGUI.indentLevel--;
EditorGUI.showMixedValue = false;
if (rect.width <= 0)
{
ResetTool.EndResetModifyButtonScope();//如果是DrawFoldOut需要在DrawFoldOut里去结束。
}
}
2025-07-21 05:42:20 -04:00
2025-08-27 21:45:18 -04:00
void RangeVecHasMixedValue(string rangePropertyName, out bool minValueHasMixed, out bool maxValueHasMixed)
{
minValueHasMixed = false;
maxValueHasMixed = false;
if (mats.Count > 1)
{
MaterialProperty rangeProperty = GetProperty(rangePropertyName);
float minValue = 0;
float maxValue = 0;
for (int i = 0; i < mats.Count; i++)
{
Vector4 rangeVec = mats[i].GetVector(rangePropertyName);
if (i == 0)
{
minValue = rangeVec.x;
maxValue = rangeVec.y;
2025-07-21 05:42:20 -04:00
}
else
{
2025-08-27 21:45:18 -04:00
if (!Mathf.Approximately(minValue, rangeVec.x))
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
minValueHasMixed = true;
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
if (!Mathf.Approximately(maxValue, rangeVec.y))
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
maxValueHasMixed = true;
2025-07-21 05:42:20 -04:00
}
}
}
}
2025-08-27 21:45:18 -04:00
}
2025-07-21 05:42:20 -04:00
2025-08-27 21:45:18 -04:00
bool RangePropIsDefaultValue(string rangePropertyName)
{
MaterialProperty rangeProperty = GetProperty(rangePropertyName);
return mats[0].GetVector(rangePropertyName) == shader.GetPropertyDefaultVectorValue(ShaderPropertyPacksDic[rangePropertyName].index) && !rangeProperty.hasMixedValue;
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
void DrawSlider(string label, ref float value,ref float min,ref float max,bool isValueMixed,string rangePropertyName = null,bool propIsAnimated = false)
{
if (rangePropertyName == null)
{
EditorGUI.showMixedValue = isValueMixed;
if (propIsAnimated) GUI.backgroundColor = animatedBackgroundColor;
value = EditorGUILayout.Slider(label,value,min,max);
GUI.backgroundColor = defaultBackgroundColor;
EditorGUI.showMixedValue = false;
}
else
{
Rect rect = EditorGUILayout.GetControlRect();
Rect labelRect = rect;
labelRect.width = EditorGUIUtility.labelWidth;
Rect valueRect = rect;
valueRect.x += EditorGUIUtility.labelWidth;
valueRect.width -= EditorGUIUtility.labelWidth;
// EditorGUI.DrawRect(valueRect,Color.red);
float rangeWidth = 50f;
Rect minRect = valueRect;
minRect.width = rangeWidth;
minRect.x -= indent;
minRect.width += indent;
// EditorGUI.DrawRect(minRect,Color.green);
Rect maxRect = valueRect;
maxRect.x += valueRect.width;
maxRect.x -= rangeWidth;
maxRect.width = rangeWidth;
maxRect.x -= indent;
maxRect.width += indent;
valueRect.x += rangeWidth;
valueRect.width -= 2*rangeWidth;
valueRect.x -= indent;
valueRect.width += indent;
valueRect.x += 4f;
valueRect.width -= 8f;
EditorGUI.LabelField(labelRect, label);
RangeVecHasMixedValue(rangePropertyName,out bool minValueHasMixed,out bool maxValueHasMixed);
EditorGUI.showMixedValue = minValueHasMixed;
min = EditorGUI.FloatField(minRect, GUIContent.none, min);
EditorGUI.showMixedValue = maxValueHasMixed;
max = EditorGUI.FloatField(maxRect, GUIContent.none, max);
EditorGUI.showMixedValue = isValueMixed;
if (propIsAnimated)
{
GUI.backgroundColor = animatedBackgroundColor;
}
value = EditorGUI.Slider(valueRect, value, min, max);
GUI.backgroundColor = defaultBackgroundColor;
EditorGUI.showMixedValue = false;
}
}
2025-07-21 05:42:20 -04:00
2025-08-27 21:45:18 -04:00
public void DrawSlider(string label, string propertyName,float min = 0,float max = 1,string rangePropertyName = null, Action<float> drawBlock = null)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
bool hasMixedValue = GetProperty(propertyName).hasMixedValue;
2025-07-21 05:42:20 -04:00
float f = GetProperty(propertyName).floatValue;
2025-08-27 21:45:18 -04:00
bool customedRange = rangePropertyName != null;
Vector4 rangeVec = Vector4.zero;
if (customedRange)
{
rangeVec = GetProperty(rangePropertyName).vectorValue;
}
EditorGUILayout.BeginHorizontal();
2025-07-21 05:42:20 -04:00
EditorGUI.BeginChangeCheck();
2025-08-27 21:45:18 -04:00
if (IsPropertyAnimated(propertyName))
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
GUI.backgroundColor = animatedBackgroundColor;
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
bool isPropAnimated = IsPropertyAnimated(propertyName);
if (customedRange)
{
DrawSlider(label, ref f, ref rangeVec.x,ref rangeVec.y,hasMixedValue,rangePropertyName,isPropAnimated);
}
else
{
DrawSlider(label, ref f, ref min,ref max,hasMixedValue,propIsAnimated:isPropAnimated);
}
2025-07-21 05:42:20 -04:00
2025-08-27 21:45:18 -04:00
GUI.backgroundColor = defaultBackgroundColor;
Action endChangCallBack= () =>
{
GetProperty(propertyName).floatValue = f;
if (customedRange)
{
GetProperty(rangePropertyName).vectorValue = rangeVec;
}
ResetTool.CheckOnValueChange((label,propertyName));
};
2025-07-21 05:42:20 -04:00
EditorGUI.showMixedValue = false;
2025-08-27 21:45:18 -04:00
if (EditorGUI.EndChangeCheck())
{
endChangCallBack.Invoke();
}
ResetTool.DrawResetModifyButton(new Rect(),(label,propertyName),resetCallBack: () =>
{
f = shader.GetPropertyDefaultFloatValue(ShaderPropertyPacksDic[propertyName].index);
if (customedRange)
{
rangeVec = shader.GetPropertyDefaultVectorValue(ShaderPropertyPacksDic[rangePropertyName].index);
}
},onValueChangedCallBack: () =>
{
endChangCallBack();
}
,checkHasModifyOnValueChange:
() =>
{
bool isModify = !Mathf.Approximately(mats[0].GetFloat(propertyName),shader.GetPropertyDefaultFloatValue(ShaderPropertyPacksDic[propertyName].index));
if (customedRange)
{
isModify |= !RangePropIsDefaultValue(rangePropertyName);
}
return isModify;
},checkHasMixedValueOnValueChange:
() =>
{
bool hasMixedValue = false;
hasMixedValue |= GetProperty(propertyName).hasMixedValue;
if (customedRange)
{
RangeVecHasMixedValue(rangePropertyName,out bool minValueHasMixed,out bool maxValueHasMixed);
hasMixedValue |= minValueHasMixed;
hasMixedValue |= maxValueHasMixed;
}
return hasMixedValue;
});
EditorGUILayout.EndHorizontal();
drawBlock?.Invoke(f);
ResetTool.EndResetModifyButtonScope();
2025-07-21 05:42:20 -04:00
}
public void DrawFloat(string label, string propertyName, bool isReciprocal = false,
2025-08-27 21:45:18 -04:00
Action<MaterialProperty> drawBlock = null)
2025-07-21 05:42:20 -04:00
{
EditorGUI.showMixedValue = GetProperty(propertyName).hasMixedValue;
2025-08-27 21:45:18 -04:00
MaterialProperty floatProperty = GetProperty(propertyName);
float f = floatProperty.floatValue;
2025-07-21 05:42:20 -04:00
if (isReciprocal) f = 1 / f;
EditorGUI.BeginChangeCheck();
2025-08-27 21:45:18 -04:00
Action endChangeCallback = () =>
{
floatProperty.floatValue = f;
ResetTool.CheckOnValueChange((label,propertyName));
};
EditorGUILayout.BeginHorizontal();
if (IsPropertyAnimated(propertyName))
{
GUI.backgroundColor = animatedBackgroundColor;
}
2025-07-21 05:42:20 -04:00
f = EditorGUILayout.FloatField(label, f);
2025-08-27 21:45:18 -04:00
GUI.backgroundColor = defaultBackgroundColor;
2025-07-21 05:42:20 -04:00
if (isReciprocal) f = 1 / f;
if (EditorGUI.EndChangeCheck())
{
2025-08-27 21:45:18 -04:00
endChangeCallback.Invoke();
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
ResetTool.DrawResetModifyButton(new Rect(),(label,propertyName),ShaderPropertyPacksDic[propertyName],resetAction: () =>
{
f = floatProperty.floatValue;
},onValueChangedCallBack:endChangeCallback);
EditorGUILayout.EndHorizontal();
2025-07-21 05:42:20 -04:00
2025-08-27 21:45:18 -04:00
drawBlock?.Invoke(floatProperty);
2025-07-21 05:42:20 -04:00
EditorGUI.showMixedValue = false;
2025-08-27 21:45:18 -04:00
ResetTool.EndResetModifyButtonScope();
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
Vector2 GetVec2InVec4(Vector4 vec4,bool isFirstLine)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
if (isFirstLine)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
return new Vector2(vec4.x, vec4.y);
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
else
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
return new Vector2(vec4.z, vec4.w);
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
}
Vector4 SetVec2InVec4(Vector4 vec4,bool isFirstLine,Vector2 vec2Value)
{
if (isFirstLine)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
vec4.x = vec2Value.x;
vec4.y = vec2Value.y;
return vec4;
}
else
{
vec4.z = vec2Value.x;
vec4.w = vec2Value.y;
return vec4;
2025-07-21 05:42:20 -04:00
}
}
2025-08-27 21:45:18 -04:00
Vector2 GetVecInTwoLineDefaultValue(string propertyName, bool isFirstLine)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
ShaderPropertyPack propertyPack = ShaderPropertyPacksDic[propertyName];
Vector4 defaultVector = shader.GetPropertyDefaultVectorValue(propertyPack.index);
if (isFirstLine)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
return new Vector2(defaultVector.x, defaultVector.y);
}
else
{
return new Vector2(defaultVector.z, defaultVector.w);
}
}
bool Vector4In2LineHasMixedValue(string propertyName, bool isFirstLine)
{
MaterialProperty matProp = GetProperty(propertyName);
if (matProp.hasMixedValue)
{
Vector2 val = Vector2.zero;
for (int i = 0; i < mats.Count; i++)
{
Vector2 matValue = GetVec2InVec4(mats[i].GetVector(propertyName), isFirstLine);
if (i == 0)
{
val = matValue;
}
else
{
if (!val.Equals(matValue) )
{
return true;
}
}
}
}
return false;
}
public void DrawVector4In2Line(string propertyName, string label , bool isFirstLine,
Action drawBlock = null)
{
EditorGUI.showMixedValue = Vector4In2LineHasMixedValue(propertyName, isFirstLine);
MaterialProperty property = GetProperty(propertyName);
(string,string) nameTuple = (label,propertyName);
EditorGUI.BeginChangeCheck();
EditorGUILayout.BeginHorizontal();
Vector2 vec2 = GetVec2InVec4(property.vectorValue, isFirstLine);
// vec2 = EditorGUILayout.Vector2Field(label, vec2);
Rect rect = EditorGUILayout.GetControlRect(true);
Rect labelRect = rect;
labelRect.width = EditorGUIUtility.labelWidth - indent;
EditorGUI.LabelField(labelRect, label);
Rect vec2Rect = rect;
vec2Rect.x += labelRect.width;
vec2Rect.width -= labelRect.width;
if (isFirstLine)
{
if (IsPropertyAnimated(propertyName, "x", "y"))
{
GUI.backgroundColor = animatedBackgroundColor;
}
}
else
{
if (IsPropertyAnimated(propertyName, "z", "w"))
{
GUI.backgroundColor = animatedBackgroundColor;
}
}
vec2 = EditorGUI.Vector2Field(vec2Rect,"", vec2);
GUI.backgroundColor = defaultBackgroundColor;
Action vec2OnEndChangeCheck = () =>
{
int shaderID = Shader.PropertyToID(propertyName);
for (int i = 0; i < mats.Count; i++)
{
Vector4 vec4 = mats[i].GetVector(shaderID);
vec4 = SetVec2InVec4(vec4, isFirstLine, vec2);
if (mats.Count == 1)
{
GetProperty(propertyName).vectorValue = vec4; //为了K动画多选不能K动画。
}
else
{
mats[i].SetVector(shaderID, vec4);
}
}
ResetTool.CheckOnValueChange(nameTuple);
};
if (EditorGUI.EndChangeCheck())
{
vec2OnEndChangeCheck();
}
EditorGUI.showMixedValue = false;
ResetTool.DrawResetModifyButton(new Rect(),nameTuple,
resetCallBack:()=>
{
vec2 = GetVecInTwoLineDefaultValue(propertyName, isFirstLine);
vec2OnEndChangeCheck();
},
onValueChangedCallBack:vec2OnEndChangeCheck,
checkHasModifyOnValueChange: () => GetVec2InVec4(mats[0].GetVector(propertyName), isFirstLine) != GetVecInTwoLineDefaultValue(propertyName, isFirstLine),
checkHasMixedValueOnValueChange:()=>Vector4In2LineHasMixedValue(propertyName, isFirstLine));
drawBlock?.Invoke();
ResetTool.EndResetModifyButtonScope();
EditorGUILayout.EndHorizontal();
}
float GetCompInVec4(Vector4 vec, string comp)
{
float f = 0;
switch (comp)
{
case "x":
2025-07-21 05:42:20 -04:00
f = vec.x;
break;
case "y":
f = vec.y;
break;
case "z":
f = vec.z;
break;
case "w":
f = vec.w;
break;
}
return f;
}
2025-08-27 21:45:18 -04:00
float GetCompDefaultValueInVec4(string propertyName, string comp)
{
ShaderPropertyPack propertyPack = ShaderPropertyPacksDic[propertyName];
Vector4 defaultValue = shader.GetPropertyDefaultVectorValue(propertyPack.index);
return GetCompInVec4(defaultValue, comp);
}
2025-07-21 05:42:20 -04:00
Vector4 SetCompInVec4(Vector4 vec, string comp, float value)
{
switch (comp)
{
case "x":
vec.x = value;
break;
case "y":
vec.y = value;
break;
case "z":
vec.z = value;
break;
case "w":
vec.w = value;
break;
}
return vec;
}
2025-08-27 21:45:18 -04:00
bool Vector4ComponentHasMixedValue(string propertyName, string channel)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
MaterialProperty property = GetProperty(propertyName);
if (property.hasMixedValue)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
float val = 0;
for (int i = 0; i < mats.Count; i++)
{
if (i == 0)
{
val = GetCompInVec4(mats[i].GetVector(propertyName),channel) ;
}
else
{
if (!val.Equals(GetCompInVec4(mats[i].GetVector(propertyName),channel)) )
{
return true;
}
}
}
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
return false;
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
public void DrawVector4Component(string label, string propertyName, string channel, bool isSlider,float minValue = 0,float maxValue = 1,
string rangeVecPropName = null, float powerSlider = 1, float multiplier = 1,
bool isReciprocal = false, Action<float,bool> drawBlock = null, Action<float,bool> drawEndChangeCheckBlock = null)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
bool hasMixedValue = Vector4ComponentHasMixedValue(propertyName, channel);
(string, string) nameTuple = (label, propertyName);
2025-07-21 05:42:20 -04:00
Vector4 vec = GetProperty(propertyName).vectorValue;
float f = GetCompInVec4(vec, channel);
2025-08-27 21:45:18 -04:00
Vector4 rangeVec = Vector4.zero;
bool isCustomedRange = rangeVecPropName != null;
if (isCustomedRange)
{
rangeVec = GetProperty(rangeVecPropName).vectorValue;
}
2025-07-21 05:42:20 -04:00
f *= multiplier;
if (isReciprocal) f = 1 / f;
2025-08-27 21:45:18 -04:00
EditorGUILayout.BeginHorizontal();
2025-07-21 05:42:20 -04:00
EditorGUI.BeginChangeCheck();
2025-08-27 21:45:18 -04:00
bool propIsAnimated = IsPropertyAnimated(propertyName, channel);
2025-07-21 05:42:20 -04:00
if (isSlider)
{
if (powerSlider > 1)
{
2025-08-27 21:45:18 -04:00
if (propIsAnimated) GUI.backgroundColor = animatedBackgroundColor;
f = PowerSlider(EditorGUILayout.GetControlRect(new GUILayoutOption[] { GUILayout.Height(18) }),
new GUIContent(label), f, minValue, maxValue, powerSlider);
GUI.backgroundColor = defaultBackgroundColor;
2025-07-21 05:42:20 -04:00
}
else
{
2025-08-27 21:45:18 -04:00
if (isCustomedRange)
{
DrawSlider(label,ref f,ref rangeVec.x,ref rangeVec.y,hasMixedValue,rangeVecPropName,propIsAnimated);
}
else
{
DrawSlider(label,ref f,ref minValue,ref maxValue,hasMixedValue,propIsAnimated:propIsAnimated);
}
2025-07-21 05:42:20 -04:00
}
}
else
{
2025-08-27 21:45:18 -04:00
EditorGUI.showMixedValue = hasMixedValue;
if(propIsAnimated) GUI.backgroundColor = animatedBackgroundColor;
2025-07-21 05:42:20 -04:00
f = EditorGUILayout.FloatField(label, f);
2025-08-27 21:45:18 -04:00
GUI.backgroundColor = defaultBackgroundColor;
EditorGUI.showMixedValue = false;
2025-07-21 05:42:20 -04:00
}
if (isReciprocal) f = 1 / f;
f /= multiplier;
2025-08-27 21:45:18 -04:00
Action floatVecEndChangeCheck = () =>
{
int id= Shader.PropertyToID(propertyName);
for (int i = 0; i < mats.Count; i++)
{
Vector4 val = mats[i].GetVector(id);
val = SetCompInVec4(val, channel, f);
if (mats.Count == 1)
{
GetProperty(propertyName).vectorValue = val;//为了K动画多选不能K动画。
}
else
{
mats[i].SetVector(id, val);
}
if (isCustomedRange)
{
mats[i].SetVector(rangeVecPropName, rangeVec);
}
}
drawEndChangeCheckBlock?.Invoke(f, hasMixedValue);
ResetTool.CheckOnValueChange(nameTuple);
};
2025-07-21 05:42:20 -04:00
if (EditorGUI.EndChangeCheck())
{
2025-08-27 21:45:18 -04:00
floatVecEndChangeCheck();
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
ResetTool.DrawResetModifyButton(new Rect(),nameTuple,
resetCallBack:()=>
{
f = GetCompDefaultValueInVec4(propertyName, channel);
if (isCustomedRange)
{
rangeVec = shader.GetPropertyDefaultVectorValue(ShaderPropertyPacksDic[rangeVecPropName].index);
}
floatVecEndChangeCheck();
},onValueChangedCallBack:floatVecEndChangeCheck,
checkHasModifyOnValueChange: () =>
{
bool isEqual = Mathf.Approximately(GetCompInVec4(mats[0].GetVector(propertyName), channel), GetCompDefaultValueInVec4(propertyName, channel));
if (isCustomedRange)
{
isEqual &= RangePropIsDefaultValue(rangeVecPropName);
}
return !isEqual;
},
checkHasMixedValueOnValueChange: () =>
{
bool hasMixedValue = Vector4ComponentHasMixedValue(propertyName, channel);
if (isCustomedRange)
{
RangeVecHasMixedValue(rangeVecPropName, out bool minValueHasMixed, out bool maxValueHasMixed);
hasMixedValue |= minValueHasMixed;
hasMixedValue |= maxValueHasMixed;
}
2025-07-21 05:42:20 -04:00
2025-08-27 21:45:18 -04:00
return hasMixedValue;
});
EditorGUILayout.EndHorizontal();
drawBlock?.Invoke(f,hasMixedValue);
ResetTool.EndResetModifyButtonScope();
2025-07-21 05:42:20 -04:00
EditorGUI.showMixedValue = false;
}
public void DrawVector4XYZComponet(string label, string propertyName, Action<Vector3> drawBlock = null)
{
EditorGUI.showMixedValue = GetProperty(propertyName).hasMixedValue;
2025-08-27 21:45:18 -04:00
(string, string) nameTuple = (label, propertyName);
2025-07-21 05:42:20 -04:00
Vector4 originVec = GetProperty(propertyName).vectorValue;
Vector3 vec = originVec;
EditorGUI.BeginChangeCheck();
2025-08-27 21:45:18 -04:00
EditorGUILayout.BeginHorizontal();
2025-07-21 05:42:20 -04:00
vec = EditorGUILayout.Vector3Field(label, vec);
2025-08-27 21:45:18 -04:00
EditorGUI.showMixedValue = false;
Action drawEndChangeCheck = () =>
2025-07-21 05:42:20 -04:00
{
GetProperty(propertyName).vectorValue = new Vector4(vec.x, vec.y, vec.z, originVec.w);
2025-08-27 21:45:18 -04:00
ResetTool.CheckOnValueChange(nameTuple);
};
if (EditorGUI.EndChangeCheck())
{
drawEndChangeCheck();
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
ResetTool.DrawResetModifyButton(new Rect(),nameTuple,ShaderPropertyPacksDic[propertyName],resetAction: () =>
{
vec = GetProperty(propertyName).vectorValue;
},onValueChangedCallBack:drawEndChangeCheck,vectorValeType:VectorValeType.XYZ);
EditorGUILayout.EndHorizontal();
2025-07-21 05:42:20 -04:00
drawBlock?.Invoke(vec);
2025-08-27 21:45:18 -04:00
ResetTool.EndResetModifyButtonScope();
2025-07-21 05:42:20 -04:00
}
public enum SamplerWarpMode
{
Repeat,
Clamp,
RepeatX_ClampY,
ClampX_RepeatY
}
public Rect GetRectAfterLabelWidth(Rect rect, bool ignoreIndent = false)
{
Rect rectAfterLabelWidth = MaterialEditor.GetRectAfterLabelWidth(rect); //右边缘是准的。
Rect leftAlignedFieldRect = MaterialEditor.GetLeftAlignedFieldRect(rect); //左边缘是准的实际有2f空隙。
float x = leftAlignedFieldRect.x + 2f;
float width = rectAfterLabelWidth.x + rectAfterLabelWidth.width - x;
var newRec = new Rect(x, rectAfterLabelWidth.y, width, rectAfterLabelWidth.height);
if (ignoreIndent)
{
float indent = (float)EditorGUI.indentLevel * 15f;
newRec.x -= indent;
newRec.width += indent;
}
return newRec;
}
2025-08-27 21:45:18 -04:00
public void DrawTextureFoldOut(int foldOutFlagBit,int foldOutFlagIndex,int animBoolIndex,string label, string texturePropertyName,
string colorPropertyName = null, bool drawScaleOffset = true, bool drawWrapMode = false,
int flagBitsName = 0, int flagIndex = 2, Action<MaterialProperty> drawBlock = null)
{
bool foldOutState = shaderFlags[0].CheckFlagBits(foldOutFlagBit, index: foldOutFlagIndex);
AnimBool animBool = GetAnimBool(foldOutFlagBit, animBoolIndex, foldOutFlagIndex);
animBool.target = foldOutState;
DrawTextureFoldOut(ref animBool, label, texturePropertyName, colorPropertyName, drawScaleOffset,
drawWrapMode, flagBitsName, flagIndex, drawBlock);
foldOutState = animBool.target;
if (foldOutState)
{
shaderFlags[0].SetFlagBits(foldOutFlagBit, index: foldOutFlagIndex);
}
else
{
shaderFlags[0].ClearFlagBits(foldOutFlagBit, index: foldOutFlagIndex);
}
}
2025-07-21 05:42:20 -04:00
public void DrawTextureFoldOut(ref AnimBool foldOutAnimBool, string label, string texturePropertyName,
string colorPropertyName = null, bool drawScaleOffset = true, bool drawWrapMode = false,
2025-08-27 21:45:18 -04:00
int wrapModeFlagBitsName = 0, int flagIndex = 2, Action<MaterialProperty> drawBlock = null)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
// EditorGUILayout.BeginHorizontal();
// var rect = EditorGUILayout.GetControlRect(false,68f);//MaterialEditor.GetTextureFieldHeight() => 64f;
// var foldoutRect = new Rect(rect.x, rect.y, rect.width , rect.height);
// var textureThumbnialRect = new Rect(rect.x , rect.y, rect.width, rect.height);
// Texture texture = matEditor.TextureProperty(textureThumbnialRect,GetProperty(texturePropertyName), label, drawScaleOffset);
Texture texture = TextureProperty(GetProperty(texturePropertyName), label, drawScaleOffset);
// EditorGUILayout.EndHorizontal();
2025-07-21 05:42:20 -04:00
if (colorPropertyName != null)
{
2025-08-27 21:45:18 -04:00
// Rect colorPropRect = GetRectAfterLabelWidth(rect, true);
2025-07-21 05:42:20 -04:00
// colorPropRect.x -= EditorGUI.indentLevel
2025-08-27 21:45:18 -04:00
// EditorGUI.indentLevel++;
// Rect colorPropRect = EditorGUILayout.GetControlRect(false);
// Color color = matEditor.ColorProperty(colorPropRect, GetProperty(colorPropertyName), "");
ColorProperty("",colorPropertyName,true);
// EditorGUI.indentLevel--;
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
var foldoutRect = EditorGUILayout.GetControlRect(false);//MaterialEditor.GetTextureFieldHeight() => 64f;
Rect labelRect = foldoutRect;
labelRect.width = EditorGUIUtility.labelWidth;
EditorGUI.LabelField(labelRect, label+"相关功能", EditorStyles.boldLabel);
foldOutAnimBool.target = EditorGUI.Foldout(foldoutRect, foldOutAnimBool.target, "", true);
2025-07-21 05:42:20 -04:00
float faded = foldOutAnimBool.faded;
if (faded == 0) faded = 0.00001f;
EditorGUILayout.BeginFadeGroup(faded);
EditorGUI.BeginDisabledGroup(texture == null);
2025-08-27 21:45:18 -04:00
DrawAfterTexture(true, label, texturePropertyName, drawWrapMode, wrapModeFlagBitsName, flagIndex,
2025-07-21 05:42:20 -04:00
drawBlock);
EditorGUI.EndDisabledGroup();
EditorGUILayout.EndFadeGroup();
}
public void DrawTexture(string label, string texturePropertyName, string colorPropertyName = null,
2025-08-27 21:45:18 -04:00
bool drawScaleOffset = true, bool drawWrapMode = false, int wrapModeFlagBitsName = 0, int flagIndex = 2,
Action<MaterialProperty> drawBlock = null)
2025-07-21 05:42:20 -04:00
{
bool hasTexture = mats[0].GetTexture(texturePropertyName) != null;
2025-08-27 21:45:18 -04:00
Texture texture = TextureProperty(GetProperty(texturePropertyName), label, drawScaleOffset);
if (colorPropertyName != null)
{
ColorProperty("",colorPropertyName,true);
}
DrawAfterTexture(hasTexture, label, texturePropertyName, drawWrapMode, wrapModeFlagBitsName,
2025-07-21 05:42:20 -04:00
flagIndex, drawBlock);
}
2025-08-27 21:45:18 -04:00
Texture TextureProperty(MaterialProperty textureProperty, string label, bool drawScaleOffset)
{
ShaderPropertyPack texturePropertyPack = ShaderPropertyPacksDic[textureProperty.name];
if (!GUI.enabled && isClearUnUsedTexture&&textureProperty.textureValue)
{
Debug.Log("清除掉贴图:"+textureProperty.name,textureProperty.textureValue);
texturePropertyPack.property.textureValue = null;
}
float indentWidth = 15f;
float currentIndentWidth = EditorGUI.indentLevel * indentWidth;
float singleLineHeight = EditorGUIUtility.singleLineHeight;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.GetControlRect(GUILayout.Width(EditorGUI.indentLevel * indentWidth));
float textureFieldHeight = 3*singleLineHeight;
var textureRect = EditorGUILayout.GetControlRect(GUILayout.Height(textureFieldHeight),GUILayout.Width(textureFieldHeight));
EditorGUILayout.BeginVertical();
var textureLabelRect = EditorGUILayout.GetControlRect();
textureLabelRect.x -= currentIndentWidth;
textureLabelRect.width += currentIndentWidth;
EditorGUI.LabelField(textureLabelRect,label,EditorStyles.boldLabel);
var textureResetButtonRect = textureLabelRect;
textureResetButtonRect.x += textureResetButtonRect.width;
textureResetButtonRect.x -= ResetTool.ResetButtonSize;
textureResetButtonRect.width = ResetTool.ResetButtonSize;
float tillingOffsetLabelWidth = 30f;
Rect tillingRect = EditorGUILayout.GetControlRect();
Rect tillingVec2Rect = tillingRect;
tillingVec2Rect.x += tillingOffsetLabelWidth;
tillingVec2Rect.width -= tillingOffsetLabelWidth;
tillingVec2Rect.width -= ResetTool.ResetButtonSize;
tillingVec2Rect.width -= 2f;
Rect tillingResetButtonRect = tillingRect;
tillingResetButtonRect.x = tillingResetButtonRect.x + tillingResetButtonRect.width - ResetTool.ResetButtonSize;
tillingResetButtonRect.width = ResetTool.ResetButtonSize;
Rect offsetRect = EditorGUILayout.GetControlRect();
Rect offsetVec2Rect = offsetRect;
offsetVec2Rect.x += tillingOffsetLabelWidth;
offsetVec2Rect.width -= tillingOffsetLabelWidth;
offsetVec2Rect.width -= ResetTool.ResetButtonSize;
offsetVec2Rect.width -= 2f;
Rect offsetResetButtonRect = offsetRect;
offsetResetButtonRect.x = offsetResetButtonRect.x + offsetResetButtonRect.width - ResetTool.ResetButtonSize;
offsetResetButtonRect.width = ResetTool.ResetButtonSize;
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
Texture texture = textureProperty.textureValue;
Action drawTextureEndChangeCheck = () =>
{
textureProperty.textureValue = texture;
ResetTool.CheckOnValueChange((label,texturePropertyPack.property.name));
};
EditorGUI.BeginChangeCheck();
texture = (Texture)EditorGUI.ObjectField(textureRect,texture,typeof(Texture2D));
if (EditorGUI.EndChangeCheck())
{
drawTextureEndChangeCheck();
}
ResetTool.DrawResetModifyButton(textureResetButtonRect,(label,texturePropertyPack.name),texturePropertyPack,resetAction: () =>
{
texture = null;
},onValueChangedCallBack:drawTextureEndChangeCheck);
ResetTool.EndResetModifyButtonScope();
if (drawScaleOffset)
{
DrawScaleOffset(texturePropertyPack, tillingRect, tillingVec2Rect, tillingResetButtonRect, offsetRect,
offsetVec2Rect, offsetResetButtonRect);
}
return texture;
}
2025-07-21 05:42:20 -04:00
2025-08-27 21:45:18 -04:00
static float indent => (float) EditorGUI.indentLevel * 15f;
public void TextureScaleOffsetProperty(string texturePropertyName)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
ShaderPropertyPack texturePropertyPack = ShaderPropertyPacksDic[texturePropertyName];
// EditorGUILayout.BeginHorizontal();
Rect tillingRect = EditorGUILayout.GetControlRect();
// EditorGUILayout.EndHorizontal();
Rect tillingLabelRect = new Rect(tillingRect.x + indent, tillingRect.y, EditorGUIUtility.labelWidth - indent, tillingRect.height);
tillingLabelRect.width = EditorGUIUtility.labelWidth;
Rect tillingVec2Rect = tillingRect;
tillingVec2Rect.x += tillingLabelRect.width;
tillingVec2Rect.x -= indent;
tillingVec2Rect.width -= 3f;
tillingVec2Rect.width -= tillingLabelRect.width;
tillingVec2Rect.width += indent;
tillingVec2Rect.width -= ResetTool.ResetButtonSize;
Rect tillingResetButtonRect = tillingRect;
tillingResetButtonRect.x = tillingResetButtonRect.x + tillingResetButtonRect.width - ResetTool.ResetButtonSize;
tillingResetButtonRect.width = ResetTool.ResetButtonSize;
Rect offsetRect = EditorGUILayout.GetControlRect();
Rect offsetLabelRect = new Rect(offsetRect.x + indent, offsetRect.y, EditorGUIUtility.labelWidth - indent, offsetRect.height);
offsetLabelRect.width = EditorGUIUtility.labelWidth;
Rect offsetVec2Rect = offsetRect;
offsetVec2Rect.x += offsetLabelRect.width;
offsetVec2Rect.x -= indent;
offsetVec2Rect.width -= 3f;
offsetVec2Rect.width -= offsetLabelRect.width;
offsetVec2Rect.width += indent;
offsetVec2Rect.width -= ResetTool.ResetButtonSize;
Rect offsetResetButtonRect = offsetRect;
offsetResetButtonRect.x = offsetResetButtonRect.x + offsetResetButtonRect.width - ResetTool.ResetButtonSize;
offsetResetButtonRect.width = ResetTool.ResetButtonSize;
DrawScaleOffset(texturePropertyPack,tillingLabelRect,tillingVec2Rect,tillingResetButtonRect,offsetLabelRect,offsetVec2Rect,offsetResetButtonRect);
}
public void DrawScaleOffset(ShaderPropertyPack texturePropertyPack, Rect tillingRect, Rect tillingVec2Rect,
Rect tillingResetButtonRect, Rect offsetRect, Rect offsetVec2Rect, Rect offsetResetButtonRect)
{
MaterialProperty textureProperty = texturePropertyPack.property;
Vector4 tillingOffset = textureProperty.textureScaleAndOffset;
string tillingLabel = "Tilling";
var tillingTuple = (tillingLabel, textureProperty.name + "_ST");
GUI.Label(tillingRect,tillingLabel);
Vector2 tilling = new Vector2(tillingOffset.x, tillingOffset.y);
Action drawTillingEndChangeCheck = () =>
{
tillingOffset.x = tilling.x;
tillingOffset.y = tilling.y;
textureProperty.textureScaleAndOffset = tillingOffset;
ResetTool.CheckOnValueChange(tillingTuple);
};
EditorGUI.BeginChangeCheck();
if (IsPropertyAnimated(tillingTuple.Item2, "x","y") )
{
GUI.backgroundColor = animatedBackgroundColor;
}
tilling = EditorGUI.Vector2Field(tillingVec2Rect, "", tilling);
GUI.backgroundColor = defaultBackgroundColor;
if (EditorGUI.EndChangeCheck())
{
drawTillingEndChangeCheck();
}
ResetTool.DrawResetModifyButton(tillingResetButtonRect,tillingTuple,texturePropertyPack,resetAction: () =>
{
tilling = Vector2.one;
},onValueChangedCallBack:drawTillingEndChangeCheck,VectorValeType.Tilling);
ResetTool.EndResetModifyButtonScope();
string offsetLabel = "Offset";
var offsetTuple = (offsetLabel, textureProperty.name + "_ST");
GUI.Label(offsetRect,offsetLabel);
Vector2 offset = new Vector2(tillingOffset.z, tillingOffset.w);
Action drawOffsetEndChangeCheck = () =>
{
tillingOffset.z = offset.x;
tillingOffset.w = offset.y;
textureProperty.textureScaleAndOffset = tillingOffset;
ResetTool.CheckOnValueChange(offsetTuple);
};
EditorGUI.BeginChangeCheck();
if (IsPropertyAnimated(offsetTuple.Item2, "z","w"))
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
GUI.backgroundColor = animatedBackgroundColor;
}
offset = EditorGUI.Vector2Field(offsetVec2Rect, "", offset);
GUI.backgroundColor = defaultBackgroundColor;
if (EditorGUI.EndChangeCheck())
{
drawOffsetEndChangeCheck();
}
ResetTool.DrawResetModifyButton(offsetResetButtonRect,offsetTuple,texturePropertyPack,resetAction: () =>
{
offset = Vector2.zero;
},onValueChangedCallBack:drawOffsetEndChangeCheck,VectorValeType.Offset);
ResetTool.EndResetModifyButtonScope();
}
bool WrapModeFlagHasMixedValue(int wrapModeFlagBitsName, int flagIndex)
{
int tmpWrapMode = 0;
for (int i = 0; i < shaderFlags.Length; i++)
{
if (i == 0)
{
tmpWrapMode = GetWrapModeFlagValue(wrapModeFlagBitsName,flagIndex,shaderFlags[i]);
}
else
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
if (!tmpWrapMode.Equals(GetWrapModeFlagValue(wrapModeFlagBitsName, flagIndex, shaderFlags[i])))
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
return true;
2025-07-21 05:42:20 -04:00
}
}
}
2025-08-27 21:45:18 -04:00
return false;
}
int GetWrapModeFlagValue(int wrapModeFlagBitsName, int flagIndex,ShaderFlagsBase shaderFlag)
{
int tmpWrapMode = shaderFlag.CheckFlagBits(wrapModeFlagBitsName, index: flagIndex) ? 1 : 0;
tmpWrapMode = shaderFlag.CheckFlagBits(wrapModeFlagBitsName << 16, index: flagIndex)
? tmpWrapMode + 2
: tmpWrapMode;
return tmpWrapMode;
}
void SetWrapModeFlagValue(int wrapModeFlagBitsName, int flagIndex,int wrapModeValue)
{
for (int i = 0; i < shaderFlags.Length; i++)
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
switch (wrapModeValue)
{
case 0:
shaderFlags[i].ClearFlagBits(wrapModeFlagBitsName, index: flagIndex);
shaderFlags[i].ClearFlagBits(wrapModeFlagBitsName << 16, index: flagIndex);
break;
case 1:
shaderFlags[i].SetFlagBits(wrapModeFlagBitsName, index: flagIndex);
shaderFlags[i].ClearFlagBits(wrapModeFlagBitsName << 16, index: flagIndex);
break;
case 2:
shaderFlags[i].ClearFlagBits(wrapModeFlagBitsName, index: flagIndex);
shaderFlags[i].SetFlagBits(wrapModeFlagBitsName << 16, index: flagIndex);
break;
case 3:
shaderFlags[i].SetFlagBits(wrapModeFlagBitsName, index: flagIndex);
shaderFlags[i].SetFlagBits(wrapModeFlagBitsName << 16, index: flagIndex);
break;
}
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
}
2025-07-21 05:42:20 -04:00
2025-08-27 21:45:18 -04:00
public void DrawWrapMode(string texturelabel,int wrapModeFlagBitsName = 0, int flagIndex = 2)
{
bool hasMixedValue = WrapModeFlagHasMixedValue(wrapModeFlagBitsName, flagIndex);
EditorGUI.showMixedValue = hasMixedValue;
string wrapLabel = texturelabel + "循环模式";
(string, string) wrapNameTuple = (wrapLabel, "");
int tmpWrapMode = GetWrapModeFlagValue(wrapModeFlagBitsName, flagIndex,shaderFlags[0]);
Action onWrapModeEndChangeCheck = () =>
{
SetWrapModeFlagValue(wrapModeFlagBitsName, flagIndex, tmpWrapMode);
hasMixedValue = WrapModeFlagHasMixedValue(wrapModeFlagBitsName, flagIndex);
ResetTool.CheckOnValueChange(wrapNameTuple);
};
EditorGUI.BeginChangeCheck();
EditorGUILayout.BeginHorizontal();
tmpWrapMode = EditorGUILayout.Popup(new GUIContent(wrapLabel), tmpWrapMode,
Enum.GetNames(typeof(SamplerWarpMode)));
if (EditorGUI.EndChangeCheck())
{
onWrapModeEndChangeCheck();
}
ResetTool.DrawResetModifyButton(new Rect(),wrapNameTuple,resetCallBack: () =>
{
tmpWrapMode = 0;
},onValueChangedCallBack:onWrapModeEndChangeCheck,() =>
{
bool hasModified = GetWrapModeFlagValue(wrapModeFlagBitsName, flagIndex,shaderFlags[0]) != 0 ? true : false;
return hasModified;
}, () => WrapModeFlagHasMixedValue(wrapModeFlagBitsName, flagIndex));
EditorGUILayout.EndHorizontal();
ResetTool.EndResetModifyButtonScope();
}
public void DrawAfterTexture(bool hasTexture, string label, string texturePropertyName, bool drawWrapMode = false, int wrapModeFlagBitsName = 0, int flagIndex = 2,
Action<MaterialProperty> drawBlock = null)
{
// EditorGUI.indentLevel++;
EditorGUI.BeginDisabledGroup(!hasTexture);
if (drawWrapMode)
{
DrawWrapMode(label, wrapModeFlagBitsName,flagIndex);
}
drawBlock?.Invoke(GetProperty(texturePropertyName));
// EditorGUI.indentLevel--;
2025-07-21 05:42:20 -04:00
EditorGUI.EndDisabledGroup();
}
public void DrawPopUp(string label, string propertyName, string[] options, string[] toolTips = null,
2025-08-27 21:45:18 -04:00
Action<MaterialProperty> drawBlock = null,Action<MaterialProperty> drawOnValueChangedBlock = null,bool isSharedGlobalParent = false)
2025-07-21 05:42:20 -04:00
{
MaterialProperty property = GetProperty(propertyName);
if (property == null) return;
EditorGUI.showMixedValue = property.hasMixedValue;
float mode = property.floatValue;
EditorGUI.BeginChangeCheck();
GUIContent[] optionGUIContents = new GUIContent[options.Length];
for (int i = 0; i < optionGUIContents.Length; i++)
{
if (toolTips != null && toolTips.Length == options.Length)
{
optionGUIContents[i] = new GUIContent(options[i], toolTips[i]);
}
else
{
optionGUIContents[i] = new GUIContent(options[i]);
}
}
2025-08-27 21:45:18 -04:00
Action drawOnValueChanged = () =>
{
property.floatValue = mode;
drawOnValueChangedBlock?.Invoke(property);
ResetTool.CheckOnValueChange((label,propertyName));
};
2025-07-21 05:42:20 -04:00
2025-08-27 21:45:18 -04:00
EditorGUILayout.BeginHorizontal();
2025-07-21 05:42:20 -04:00
mode = EditorGUILayout.Popup(new GUIContent(label), (int)mode, optionGUIContents);
if (EditorGUI.EndChangeCheck())
{
2025-08-27 21:45:18 -04:00
drawOnValueChanged.Invoke();
2025-07-21 05:42:20 -04:00
}
2025-08-27 21:45:18 -04:00
ResetTool.DrawResetModifyButton(new Rect(),(label,propertyName),ShaderPropertyPacksDic[propertyName],resetAction: () =>
{
mode = property.floatValue;
},onValueChangedCallBack:drawOnValueChanged);
EditorGUILayout.EndHorizontal();
2025-07-21 05:42:20 -04:00
2025-08-27 21:45:18 -04:00
drawBlock?.Invoke(property);
ResetTool.EndResetModifyButtonScope();
2025-07-21 05:42:20 -04:00
EditorGUI.showMixedValue = false;
}
public MaterialProperty GetProperty(string propertyName)
{
2025-08-27 21:45:18 -04:00
// foreach (ShaderPropertyPack pack in ShaderPropertyPacks)
// {
// if (pack.name == propertyName)
// {
// return pack.property;
// }
// }
if (ShaderPropertyPacksDic.ContainsKey(propertyName))
2025-07-21 05:42:20 -04:00
{
2025-08-27 21:45:18 -04:00
return ShaderPropertyPacksDic[propertyName].property;
2025-07-21 05:42:20 -04:00
}
// Debug.LogError("材质球" + mat.name + "找不到属性" + propertyName, mat);
return null;
}
2025-08-27 21:45:18 -04:00
bool RenderQueueHasMixedValue()
{
int queue = 0;
for (int i = 0; i < mats.Count; i++)
{
if (i == 0)
{
queue = mats[i].renderQueue;
}
else
{
if (queue != mats[i].renderQueue)
{
return true;
}
}
}
return false;
}
2025-07-21 05:42:20 -04:00
public void DrawRenderQueue(MaterialProperty queueBiasProp)
{
2025-08-27 21:45:18 -04:00
Rect rect = EditorGUILayout.GetControlRect();
Rect labelRect = new Rect(rect.x, rect.y, EditorGUIUtility.labelWidth, rect.height);
int queueLabelWidth = 55;
Rect queueLabelRect = new Rect(labelRect.x , labelRect.y, queueLabelWidth, rect.height);
Rect queueNumberRect = new Rect(queueLabelRect.x + queueLabelWidth , queueLabelRect.y,EditorGUIUtility.labelWidth - queueLabelWidth, rect.height);
EditorGUI.LabelField(queueLabelRect, "Queue:" );
EditorGUI.showMixedValue = RenderQueueHasMixedValue();
EditorGUI.BeginDisabledGroup(true);
EditorGUI.TextField(queueNumberRect, mats[0].renderQueue.ToString());
EditorGUI.EndDisabledGroup();
EditorGUI.showMixedValue = false;
Rect afterLabelRect = GetRectAfterLabelWidth(rect);
2025-07-21 05:42:20 -04:00
int QueueBias = (int)queueBiasProp.floatValue;
2025-08-27 21:45:18 -04:00
EditorGUI.showMixedValue = queueBiasProp.hasMixedValue;
EditorGUI.BeginChangeCheck();
QueueBias = EditorGUI.IntField(afterLabelRect, "QueueBias:", QueueBias);
if (EditorGUI.EndChangeCheck())
{
queueBiasProp.floatValue = QueueBias;
}
EditorGUI.showMixedValue = false;
2025-07-21 05:42:20 -04:00
}
void GuiLine(int i_height = 1)
{
Rect rect = EditorGUILayout.GetControlRect(false, i_height);
rect.height = i_height;
EditorGUI.DrawRect(rect, new Color(0.5f, 0.5f, 0.5f, 0.5f));
}
public static float PowerSlider(Rect position, GUIContent label, float value, float leftValue, float rightValue,
float power)
{
var editorGuiType = typeof(EditorGUI);
var methodInfo = editorGuiType.GetMethod(
"PowerSlider",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static,
null,
new[] { typeof(Rect), typeof(GUIContent), typeof(float), typeof(float), typeof(float), typeof(float) },
null);
if (methodInfo != null)
{
return (float)methodInfo.Invoke(null,
new object[] { position, label, value, leftValue, rightValue, power });
}
return leftValue;
}
2025-08-27 21:45:18 -04:00
private GradientAlphaKey[] defaultGradientAlphaKey = new GradientAlphaKey[]
{ new GradientAlphaKey(1, 0), new GradientAlphaKey(1, 1) };
float RGBLuminance(Color color)
{
return 0.2126f* color.r + 0.7152f * color.g + 0.0722f * color.b;
}
private bool isUpateGradientPickerCache = false;
public void DrawGradientUndoPerformed()
{
isUpateGradientPickerCache = true;
}
Dictionary<Gradient,bool> gradientsUpdateDic = new Dictionary<Gradient,bool>();
void GetGradientKeyCount(MaterialProperty countProperty,
MaterialProperty[] colorProperties, MaterialProperty[] alphaProperties,out int countPropertyIntValue,out int colorKeysCount,out int alphaKeysCount)
{
countPropertyIntValue = countProperty.intValue;
if (colorProperties != null && alphaProperties != null)
{
colorKeysCount = countPropertyIntValue & 0xFFFF;
alphaKeysCount = countPropertyIntValue >> 16;
}
else
{
colorKeysCount = countPropertyIntValue;
alphaKeysCount = 2;
}
}
bool GradientPropertyHasMixedValue(MaterialProperty countProperty,
MaterialProperty[] colorProperties = null, MaterialProperty[] alphaProperties = null)
{
GetGradientKeyCount(countProperty, colorProperties, alphaProperties,out int countPropertyIntValue, out int colorKeysCount,out int alphaKeysCount);
bool hasMixedValue = false;
hasMixedValue |= countProperty.hasMixedValue;
if (colorProperties != null)
{
for(int i = 0; i < colorKeysCount; i++)
{
hasMixedValue |= colorProperties[i].hasMixedValue;
}
}
if (alphaProperties != null)
{
for (int i = 0; i < Mathf.CeilToInt(alphaKeysCount/2f); i++)
{
hasMixedValue |= alphaProperties[i].hasMixedValue;
}
}
return hasMixedValue;
}
void GetGradientConditionBool(MaterialProperty[] colorProperties,
MaterialProperty[] alphaProperties, out bool isBlackAndWhiteGradient,
out bool isNoAlphaColorGradient)
{
isBlackAndWhiteGradient = colorProperties == null && alphaProperties != null;
isNoAlphaColorGradient = colorProperties != null && alphaProperties == null;
}
void SetGradientByProperty(Gradient gradient, MaterialProperty countProperty,
MaterialProperty[] colorProperties = null, MaterialProperty[] alphaProperties = null)
{
GetGradientConditionBool(colorProperties,alphaProperties,out bool isBlackAndWhiteGradient,out bool isNoAlphaColorGradient);
GetGradientKeyCount(countProperty, colorProperties, alphaProperties,out int countPropertyIntValue, out int colorKeysCount,out int alphaKeysCount);
if (colorProperties != null || isBlackAndWhiteGradient)
{
GradientColorKey[] colorKeys;
if (gradient.colorKeys.Length != colorKeysCount)
{
colorKeys = new GradientColorKey[colorKeysCount];
}
else
{
colorKeys = gradient.colorKeys;
}
for (int i = 0; i < colorKeysCount; i++)
{
if (isBlackAndWhiteGradient)
{
Vector4 vec = alphaProperties[i / 2].vectorValue;
Color c = Color.white;
if (i % 2 == 0)
{
c.r = vec.x;
c.g = vec.x;
c.b = vec.x;
}
else
{
c.r = vec.z;
c.g = vec.z;
c.b = vec.z;
}
// Debug.Log(i);
// Debug.Log(c);
colorKeys[i].color = c;
colorKeys[i].time = i % 2 == 0 ? vec.y : vec.w;
}
else
{
Color c = colorProperties[i].colorValue;
colorKeys[i].color = c;
colorKeys[i].time = c.a;
}
}
gradient.colorKeys = colorKeys;
}
if (isBlackAndWhiteGradient || isNoAlphaColorGradient || alphaProperties == null)
{
gradient.alphaKeys = defaultGradientAlphaKey;
}
else
{
GradientAlphaKey[] alphaKeys;
if (gradient.alphaKeys.Length != alphaKeysCount)
{
alphaKeys = new GradientAlphaKey[alphaKeysCount];
}
else
{
alphaKeys = gradient.alphaKeys;
}
for (int i = 0; i < alphaKeysCount ; i++)
{
Vector4 vec = alphaProperties[i / 2].vectorValue;
if (i % 2 == 0)
{
alphaKeys[i].alpha = vec.x;
alphaKeys[i].time = vec.y;
}
else
{
alphaKeys[i].alpha = vec.z;
alphaKeys[i].time = vec.w;
}
}
gradient.alphaKeys = alphaKeys;
}
}
//如果是黑白Gradient则取Gradient的颜色的黑白值这样在面板上可视化比较好
//如果既有颜色也有Alpha。则在CountProperty上采取前16位和后16位编码。
//原则gradient对象只是一个操作中介。取值应该直接在MatProperty上去Set值也应该在验证合法后才能Set不合法应该提出警告。
public void DrawGradient(Gradient gradient,bool hdr,ColorSpace colorSpace,string label,int maxCount,string countPropertyName,MaterialProperty[] colorProperties = null,MaterialProperty[] alphaProperties = null)
{
(string,string) nameTuple = (label, countPropertyName);
if (isUpateGradientPickerCache)
{
foreach (var keys in gradientsUpdateDic.Keys.ToList())
{
gradientsUpdateDic[keys] = true;
}
isUpateGradientPickerCache = false;
}
MaterialProperty countProperty = GetProperty(countPropertyName);
Rect rect = EditorGUILayout.GetControlRect();
// var labelRect = new Rect(rect.x + 2f, rect.y, rect.width - 2f, rect.height);
// EditorGUI.LabelField(labelRect,label);
var gradientRect = rect;
gradientRect.width -= ResetTool.ResetButtonSize;
gradientRect.width -= 2f;
var gradientResetButtonRect = rect;
gradientResetButtonRect.x = gradientResetButtonRect.x + gradientResetButtonRect.width - ResetTool.ResetButtonSize;
gradientResetButtonRect.width = ResetTool.ResetButtonSize;
if (gradient == null||gradientsUpdateDic[gradient])
{
if (gradient == null)
{
gradient = new Gradient();
// gradient.colorSpace = ColorSpace.Gamma;
gradientsUpdateDic.Add(gradient,false);
}
gradientsUpdateDic[gradient] = false;
SetGradientByProperty(gradient,countProperty, colorProperties, alphaProperties);
GradientReflectionHelper.RefreshGradientData();
// Debug.Log("----------------SetCurrentGradient------------------");
}
EditorGUI.showMixedValue = GradientPropertyHasMixedValue(countProperty, colorProperties, alphaProperties);
GetGradientKeyCount(countProperty, colorProperties, alphaProperties,out int countPropertyIntValue, out int colorKeysCount,out int alphaKeysCount);
GetGradientConditionBool(colorProperties, alphaProperties,out bool isBlackAndWhiteGradient,out bool isNoAlphaColorGradient);
EditorGUI.BeginChangeCheck();
gradient = EditorGUI.GradientField(gradientRect, new GUIContent(label),gradient,hdr,colorSpace);
Action onGradientEndChangeCheck = () =>
{
gradientsUpdateDic[gradient] = true;
int countPropertyValue = countPropertyIntValue;
if (colorProperties != null || isBlackAndWhiteGradient)
{
int finalColorKeysCount = gradient.colorKeys.Length;
if (finalColorKeysCount <= maxCount)
{
if (isBlackAndWhiteGradient)
{
int floatPropertyCount = Mathf.CeilToInt((float)finalColorKeysCount / (2f));
for (int i = 0; i < floatPropertyCount; i++)
{
Vector4 vec = Vector4.zero;
vec.x = gradient.colorKeys[i*2].color.r;
vec.y = gradient.colorKeys[i*2].time;
if (i * 2 + 1 < gradient.colorKeys.Length)
{
vec.z = gradient.colorKeys[i * 2 + 1].color.r;
vec.w = gradient.colorKeys[i * 2 + 1].time;
}
alphaProperties[i].vectorValue = vec;
}
}
else
{
for (int i = 0; i < finalColorKeysCount; i++)
{
Color c = gradient.colorKeys[i].color;
c.a = gradient.colorKeys[i].time;
colorProperties[i].colorValue = c;
}
}
countPropertyValue &= (0xFFFF <<16);
countPropertyValue |= finalColorKeysCount;
}
}
if (!(isBlackAndWhiteGradient || isNoAlphaColorGradient || alphaProperties == null))
{
int finalAlphaKeysCount = gradient.alphaKeys.Length;
if (finalAlphaKeysCount <= maxCount)
{
int floatPropertyCount = Mathf.CeilToInt((float)finalAlphaKeysCount / (2f));
for (int i = 0; i < floatPropertyCount; i++)
{
Vector4 vec = Vector4.zero;
vec.x = gradient.alphaKeys[i*2].alpha;
vec.y = gradient.alphaKeys[i*2].time;
if (i * 2 + 1 < gradient.alphaKeys.Length)
{
vec.z = gradient.alphaKeys[i * 2 + 1].alpha;
vec.w = gradient.alphaKeys[i * 2 + 1].time;
}
alphaProperties[i].vectorValue = vec;
}
countPropertyValue &= (0xFFFF);
int alphaCount = finalAlphaKeysCount << 16;
countPropertyValue |= alphaCount;
}
}
countProperty.intValue = countPropertyValue;
ResetTool.CheckOnValueChange(nameTuple);
};
if (EditorGUI.EndChangeCheck())
{
onGradientEndChangeCheck();
}
ResetTool.DrawResetModifyButton(gradientResetButtonRect,nameTuple,resetCallBack: () =>
{
ShaderPropertyPack countPropPack = ShaderPropertyPacksDic[countPropertyName];
countPropPack.property.intValue = 2;
if (colorProperties != null)
{
foreach (var colorProp in colorProperties)
{
ShaderPropertyPack colorPropPack = ShaderPropertyPacksDic[colorProp.name];
colorPropPack.property.colorValue =
shader.GetPropertyDefaultVectorValue(colorPropPack.index);
}
}
if (alphaProperties != null)
{
foreach (var alphaProps in alphaProperties)
{
ShaderPropertyPack alphaPropPack = ShaderPropertyPacksDic[alphaProps.name];
alphaPropPack.property.vectorValue = shader.GetPropertyDefaultVectorValue(alphaPropPack.index);
}
}
SetGradientByProperty(gradient,countProperty, colorProperties, alphaProperties);
},onValueChangedCallBack:onGradientEndChangeCheck,
checkHasMixedValueOnValueChange: () =>
GradientPropertyHasMixedValue(countProperty, colorProperties, alphaProperties),
checkHasModifyOnValueChange: () =>
{
bool hasModified = false;
ShaderPropertyPack countPropPack = ShaderPropertyPacksDic[countPropertyName];
bool hasCountModified = !Mathf.Approximately(mats[0].GetInteger(countPropPack.name),2);
hasModified |= hasCountModified;
if (colorProperties != null)
{
foreach (var colorProp in colorProperties)
{
ShaderPropertyPack colorPropPack = ShaderPropertyPacksDic[colorProp.name];
hasModified |= mats[0].GetVector(colorPropPack.name) !=
shader.GetPropertyDefaultVectorValue(colorPropPack.index);
}
}
if (alphaProperties != null)
{
foreach (var alphaProps in alphaProperties)
{
ShaderPropertyPack alphaPropPack = ShaderPropertyPacksDic[alphaProps.name];
Vector4 vec = mats[0].GetVector(alphaPropPack.name);
Vector4 defaultVec = shader.GetPropertyDefaultVectorValue(alphaPropPack.index);
hasModified |= vec != defaultVec;
}
}
return hasModified;
});
ResetTool.EndResetModifyButtonScope();
}
}
public enum VectorValeType
{
X,Y,Z,W,XY,ZW,XYZ,XYZW,Tilling,Offset,Undefine
2025-07-21 05:42:20 -04:00
}
}