This commit is contained in:
SoulliesOfficial
2026-07-17 17:46:16 -04:00
parent b00ac27e3a
commit 40fa80cd70
1178 changed files with 51090 additions and 0 deletions

View File

@@ -0,0 +1,394 @@
using System;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
public class ShaderGUIFloatItem:ShaderGUIItem
{
private readonly Func<bool> _isVisible;
public ShaderGUIFloatItem(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem, Func<bool> isVisible = null) :
base(rootItem, parentItem: parentItem)
{
_isVisible = isVisible;
base.InitTriggerByChild();
}
public override void OnGUI()
{
if (_isVisible != null && !_isVisible())
{
return;
}
base.OnGUI();
}
public override void DrawController()
{
float value = DraggableLabelFloat.Handle(LabelRect, PropertyInfo.Property.floatValue, sensitivity: -1f);//拖动Label控件可以操作Float参数
value = EditorGUI.FloatField(ControlRect, value);
SetFloatIfDifferent(PropertyInfo.Property, value);
}
}
public class ShaderGUISliderItem:ShaderGUIItem
{
public float Min = 0;
public float Max = 1;
public string RangePropertyName;
ShaderPropertyInfo _rangePropertyInfo;
private readonly Func<bool> _isVisible;
private const float SliderFrontGap = 5f;
private const float SliderBackGap = 2f;
private const float RangeFieldWidth = 30f;
public override void InitTriggerByChild()
{
if (RangePropertyName != null)
{
_rangePropertyInfo = RootItem.PropertyInfoDic[RangePropertyName];
Min = _rangePropertyInfo.Property.vectorValue.x;
Max = _rangePropertyInfo.Property.vectorValue.y;
}
base.InitTriggerByChild();
}
public ShaderGUISliderItem(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem, Func<bool> isVisible = null) :
base(rootItem, parentItem: parentItem)
{
_isVisible = isVisible;
}
public override void OnGUI()
{
if (_isVisible != null && !_isVisible())
{
return;
}
if (_rangePropertyInfo == null)
{
base.OnGUI();
return;
}
GetRect();
using (ParentControlDisabledScope())
{
EditorGUI.LabelField(LabelRect, GuiContent);
}
using (ParentControlDisabledScope())
{
EditorGUI.BeginChangeCheck();
using (new EditorGUIIndentLevelScope(0))
{
DrawController();
}
EditorGUI.showMixedValue = false;
if (EditorGUI.EndChangeCheck())
{
OnEndChange();
}
}
DrawResetButton();
DrawBlock();
}
public override void DrawController()
{
if (_rangePropertyInfo != null)
{
Rect minRect = ControlRect;
minRect.width = RangeFieldWidth;
Rect maxRect = ControlRect;
maxRect.x = ControlRect.xMax - RangeFieldWidth;
maxRect.width = RangeFieldWidth;
Rect sliderRect = ControlRect;
sliderRect.x = minRect.xMax + SliderFrontGap;
sliderRect.width = Mathf.Max(0f, maxRect.x - sliderRect.x - SliderBackGap + EditorGUI.indentLevel * UnityEditorGUIIndentWidth);
RangeVecHasMixedValue(out bool minValueHasMixed,out bool maxValueHasMixed);
Vector4 rangeVector = _rangePropertyInfo.Property.vectorValue;
float min = rangeVector.x;
float max = rangeVector.y;
EditorGUI.showMixedValue = minValueHasMixed;
bool minAnimatedScope = BeginAnimatedPropertyBackground(minRect, _rangePropertyInfo.Property);
min = EditorGUI.FloatField(minRect, min);
EndAnimatedPropertyBackground(minAnimatedScope);
EditorGUI.showMixedValue = maxValueHasMixed;
bool maxAnimatedScope = BeginAnimatedPropertyBackground(maxRect, _rangePropertyInfo.Property);
max = EditorGUI.FloatField(maxRect, max);
EndAnimatedPropertyBackground(maxAnimatedScope);
rangeVector.x = min;
rangeVector.y = max;
SetVectorIfDifferent(_rangePropertyInfo.Property, rangeVector);
float sliderMin = Mathf.Min(min, max);
float sliderMax = Mathf.Max(min, max);
float value = DraggableLabelFloat.Handle(
LabelRect,
PropertyInfo.Property.floatValue,
DraggableLabelFloat.GetSensitivityByRange(sliderMin, sliderMax),
sliderMin,
sliderMax);
EditorGUI.showMixedValue = PropertyInfo.Property.hasMixedValue;
bool sliderAnimatedScope = BeginAnimatedPropertyBackground(sliderRect, PropertyInfo.Property);
value = SliderNoIndent(sliderRect, value, sliderMin, sliderMax);
EndAnimatedPropertyBackground(sliderAnimatedScope);
SetFloatIfDifferent(PropertyInfo.Property, Mathf.Clamp(value, sliderMin, sliderMax));
EditorGUI.showMixedValue = false;
}
else
{
float value = DraggableLabelFloat.Handle(
LabelRect,
PropertyInfo.Property.floatValue,
DraggableLabelFloat.GetSensitivityByRange(Min, Max),
Min,
Max);
value = EditorGUI.Slider(ControlRect, value,Min,Max);
SetFloatIfDifferent(PropertyInfo.Property, value);
}
}
private static float SliderNoIndent(Rect rect, float value, float min, float max)
{
int indentLevel = EditorGUI.indentLevel;
try
{
EditorGUI.indentLevel = 0;
return EditorGUI.Slider(rect, value, min, max);
}
finally
{
EditorGUI.indentLevel = indentLevel;
}
}
void RangeVecHasMixedValue( out bool minValueHasMixed, out bool maxValueHasMixed)
{
minValueHasMixed = false;
maxValueHasMixed = false;
if (RootItem.Mats.Count > 1)
{
MaterialProperty rangeProperty = _rangePropertyInfo.Property;
float minValue = 0;
float maxValue = 0;
for (int i = 0; i < RootItem.Mats.Count; i++)
{
Vector4 rangeVec = RootItem.Mats[i].GetVector(RangePropertyName);
if (i == 0)
{
minValue = rangeVec.x;
maxValue = rangeVec.y;
}
else
{
if (!Mathf.Approximately(minValue, rangeVec.x))
{
minValueHasMixed = true;
}
if (!Mathf.Approximately(maxValue, rangeVec.y))
{
maxValueHasMixed = true;
}
}
}
}
}
bool RangePropIsDefaultValue()
{
MaterialProperty rangeProperty = _rangePropertyInfo.Property;
return rangeProperty.vectorValue == RootItem.Shader.GetPropertyDefaultVectorValue(_rangePropertyInfo.Index) && !rangeProperty.hasMixedValue;
}
public override void CheckIsPropertyModified(bool isCallByChild = false)
{
if (RangePropertyName != null)
{
if (!isCallByChild) //只有自身Reset了才需要查询自己的状态是否正确
{
bool isDefaultValue = true;
float defaultValue = RootItem.Shader.GetPropertyDefaultFloatValue(PropertyInfo.Index);
isDefaultValue = Mathf.Approximately(PropertyInfo.Property.floatValue, defaultValue);
Vector4 defaultRangeVec = RootItem.Shader.GetPropertyDefaultVectorValue(_rangePropertyInfo.Index);
isDefaultValue &= _rangePropertyInfo.Property.vectorValue == defaultRangeVec;
base.CheckIsPropertyModified(isCallByChild);
if (isDefaultValue == PropertyIsDefaultValue)
{
return; //如果状态没有改变,就不需要做任何操作
}
else
{
PropertyIsDefaultValue = isDefaultValue;
}
}
HasModified = !PropertyIsDefaultValue;
foreach (var childItem in ChildrenItemList)
{
HasModified |= childItem.HasModified;
}
ParentItem?.CheckIsPropertyModified(true);
}
else
{
base.CheckIsPropertyModified(isCallByChild);
}
}
public override void ExecuteReset(bool isCallByParent = false)
{
if (RangePropertyName != null)
{
PropertyInfo.Property.floatValue = RootItem.Shader.GetPropertyDefaultFloatValue(PropertyInfo.Index);
_rangePropertyInfo.Property.vectorValue =
RootItem.Shader.GetPropertyDefaultVectorValue(_rangePropertyInfo.Index);
PropertyIsDefaultValue = true;
foreach (var childItem in ChildrenItemList)
{
childItem.ExecuteReset(true);
}
HasModified = false;
if (!isCallByParent) //直接由用户触发重置
{
ParentItem?.CheckIsPropertyModified(true);
}
}
else
{
base.ExecuteReset(isCallByParent);
}
}
}
//用于滑动控制Label的方案。
// DraggableLabelFloat.cs
public static class DraggableLabelFloat
{
// 为每个控件实例缓存一次拖拽状态
private static readonly System.Collections.Generic.Dictionary<int, DragState> s_Drag =
new System.Collections.Generic.Dictionary<int, DragState>();
private class DragState
{
public float startValue;
public float dragX; // 累计水平位移(单位:像素)
}
public static float Handle(Rect labelRect, float value, float sensitivity = -1f, float? min = null, float? max = null)
{
if (!GUI.enabled)
{
return value;
}
EditorGUIUtility.AddCursorRect(labelRect, MouseCursor.SlideArrow);
int id = GUIUtility.GetControlID(FocusType.Passive, labelRect);
Event e = Event.current;
switch (e.GetTypeForControl(id))
{
case EventType.MouseDown:
if (labelRect.Contains(e.mousePosition) && e.button == 0)
{
GUIUtility.hotControl = id;
e.Use();
EditorGUIUtility.SetWantsMouseJumping(1);
s_Drag[id] = new DragState
{
startValue = value,
dragX = 0f
};
}
break;
case EventType.MouseDrag:
if (GUIUtility.hotControl == id && s_Drag.TryGetValue(id, out var st))
{
// 关键:使用 Event.delta 累加位移,兼容越界/跳回
st.dragX += e.delta.x;
float baseSens = sensitivity > 0f
? sensitivity
: 0.003f * Mathf.Max(1f, Mathf.Abs(st.startValue));
float modifier = 1f;
if (e.shift) modifier *= 0.1f;
if (e.control || e.command) modifier *= 10f;
float accel = 1f + 0.15f * Mathf.Clamp01(Mathf.Abs(st.dragX) / 50f);
float newValue = st.startValue + st.dragX * baseSens * modifier * accel;
if (min.HasValue) newValue = Mathf.Max(min.Value, newValue);
if (max.HasValue) newValue = Mathf.Min(max.Value, newValue);
if (!float.IsNaN(newValue) && !float.IsInfinity(newValue) && !Mathf.Approximately(newValue, value))
{
GUI.changed = true;
value = newValue;
}
e.Use();
}
break;
case EventType.MouseUp:
if (GUIUtility.hotControl == id)
{
GUIUtility.hotControl = 0;
EditorGUIUtility.SetWantsMouseJumping(0);
s_Drag.Remove(id);
e.Use();
}
break;
case EventType.KeyDown:
// 可选ESC 取消拖拽并还原
if (GUIUtility.hotControl == id && e.keyCode == KeyCode.Escape && s_Drag.TryGetValue(id, out var st2))
{
value = st2.startValue;
GUI.changed = true;
GUIUtility.hotControl = 0;
EditorGUIUtility.SetWantsMouseJumping(0);
s_Drag.Remove(id);
e.Use();
}
break;
}
return value;
}
public static float GetSensitivityByRange(float min, float max)
{
float range = Mathf.Abs(max - min);
if (float.IsNaN(range) || float.IsInfinity(range) || Mathf.Approximately(range, 0f))
{
return -1f;
}
return range * 0.003f;
}
}
}