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,450 @@
using System;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using NBShader;
namespace NBShaderEditor
{
public enum RenderFace
{
Front = 2,
Back = 1,
Both = 0
}
public enum ForceZWriteMode
{
Default = 0,
ForceOn = 1,
ForceOff = 2
}
public class BaseOptionBigBlockItem : BigBlockItem
{
private readonly NBShaderRootItem _nbRootItem;
private readonly ShaderGUIFloatItem _baseColorIntensityItem;
private readonly ShaderGUISliderItem _alphaAllItem;
private readonly BlockItem _colorAdjustmentBlock;
private readonly ToggleItem _colorAdjustmentOnlyMainTexItem;
private readonly PropertyToggleBlockItem _hueShiftBlock;
private readonly ShaderGUISliderItem _hueShiftSlider;
private readonly CustomDataSelectItem _hueShiftCustomDataItem;
private readonly PropertyToggleBlockItem _saturabilityBlock;
private readonly ShaderGUISliderItem _saturabilitySlider;
private readonly CustomDataSelectItem _saturabilityCustomDataItem;
private readonly PropertyToggleBlockItem _contrastBlock;
private readonly ColorItem _contrastMidColorItem;
private readonly ShaderGUISliderItem _contrastSlider;
private readonly CustomDataSelectItem _contrastCustomDataItem;
private readonly PropertyToggleBlockItem _baseMapColorRefineBlock;
private readonly VectorComponentItem _baseMapColorRefineA;
private readonly VectorComponentItem _baseMapColorRefineBPower;
private readonly VectorComponentItem _baseMapColorRefineBMultiply;
private readonly VectorComponentItem _baseMapColorRefineLerp;
private readonly ToggleItem _colorMultiAlphaItem;
private readonly ZTestItem _zTestItem;
private readonly CullModeItem _cullItem;
private readonly ToggleItem _backFirstPassItem;
private readonly ForceZWriteItem _forceZWriteItem;
private readonly ToggleItem _affectsShadowsItem;
private readonly ToggleItem _transparentShadowDitherItem;
private readonly PropertyToggleBlockItem _baseBackColorBlock;
private readonly ColorItem _baseBackColorItem;
private readonly PropertyToggleBlockItem _distanceFadeBlock;
private readonly Vector2LineItem _fadeRangeItem;
private readonly PropertyToggleBlockItem _softParticlesBlock;
private readonly Vector2LineItem _softParticleFadeItem;
private readonly ToggleItem _stencilWithoutPlayerItem;
private readonly ToggleItem _ignoreVertexColorItem;
private readonly ShaderGUISliderItem _fogIntensityItem;
public BaseOptionBigBlockItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) :
base(
rootItem,
parentItem,
"_BaseOptionBigBlockItemFoldOut",
() => Content("block.base", "Base Options", "Global controls"))
{
_nbRootItem = rootItem;
_baseColorIntensityItem = new ShaderGUIFloatItem(rootItem, this)
{
PropertyName = "_BaseColorIntensityForTimeline",
GuiContent = Content("base.colorIntensity", "Base Color Intensity")
};
_baseColorIntensityItem.InitTriggerByChild();
_alphaAllItem = new ShaderGUISliderItem(rootItem, this)
{
PropertyName = "_AlphaAll",
GuiContent = Content("base.alphaAll", "Overall Alpha"),
RangePropertyName = "AlphaAllRangeVec"
};
_alphaAllItem.InitTriggerByChild();
_colorAdjustmentBlock = new BlockItem(
rootItem,
this,
"_BaseColorAdjustmentFoldOut",
() => Content("base.colorAdjustment", "Color Adjustment"));
_colorAdjustmentOnlyMainTexItem = new ToggleItem(
rootItem,
_colorAdjustmentBlock,
"_ColorAdjustmentOnlyAffectMainTex",
() => Content("base.colorAdjustment.onlyMainTex", "Only Affect Main Texture"),
enabled => rootItem.SyncService.ApplyToggleFlag(
NBShaderFlags.FLAG_BIT_PARTICLE_COLOR_ADJUSTMENT_ONLY_AFFECT_MAINTEX,
enabled));
_hueShiftBlock = new PropertyToggleBlockItem(
rootItem,
_colorAdjustmentBlock,
"_HueShiftFoldOut",
"_HueShift_Toggle",
() => Content("base.hueShift", "Hue Shift"),
NBShaderFlags.FLAG_BIT_HUESHIFT_ON);
_hueShiftSlider = new ShaderGUISliderItem(rootItem, _hueShiftBlock)
{
PropertyName = "_HueShift",
GuiContent = Content("base.hueShift.value", "Hue"),
Min = 0f,
Max = 1f
};
_hueShiftSlider.InitTriggerByChild();
_hueShiftCustomDataItem = new CustomDataSelectItem(
rootItem,
_hueShiftBlock,
NBShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_HUESHIFT,
0,
() => Content("base.hueShift.customData", "Hue Custom Data"),
IsParticleMode);
_saturabilityBlock = new PropertyToggleBlockItem(
rootItem,
_colorAdjustmentBlock,
"_SaturabilityFoldOut",
"_ChangeSaturability_Toggle",
() => Content("base.saturability", "Saturation"),
NBShaderFlags.FLAG_BIT_SATURABILITY_ON);
_saturabilitySlider = new ShaderGUISliderItem(rootItem, _saturabilityBlock)
{
PropertyName = "_Saturability",
GuiContent = Content("base.saturability.value", "Saturation"),
RangePropertyName = "SaturabilityRangeVec"
};
_saturabilitySlider.InitTriggerByChild();
_saturabilityCustomDataItem = new CustomDataSelectItem(
rootItem,
_saturabilityBlock,
NBShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_SATURATE,
1,
() => Content("base.saturability.customData", "Saturation Custom Data"),
IsParticleMode);
_contrastBlock = new PropertyToggleBlockItem(
rootItem,
_colorAdjustmentBlock,
"_ContrastFoldOut",
"_Contrast_Toggle",
() => Content("base.contrast", "Contrast"),
NBShaderFlags.FLAG_BIT_PARTICLE_1_MAINTEX_CONTRAST,
1);
_contrastMidColorItem = new ColorItem(rootItem, _contrastBlock, "_ContrastMidColor", () => Content("base.contrast.mid", "Contrast Mid Color"));
_contrastSlider = new ShaderGUISliderItem(rootItem, _contrastBlock)
{
PropertyName = "_Contrast",
GuiContent = Content("base.contrast.value", "Contrast"),
Min = 0f,
Max = 5f
};
_contrastSlider.InitTriggerByChild();
_contrastCustomDataItem = new CustomDataSelectItem(
rootItem,
_contrastBlock,
NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_MAINTEX_CONTRAST,
2,
() => Content("base.contrast.customData", "Contrast Custom Data"),
IsParticleMode);
_baseMapColorRefineBlock = new PropertyToggleBlockItem(
rootItem,
_colorAdjustmentBlock,
"_BaseMapColorRefineFoldOut",
"_BaseMapColorRefine_Toggle",
() => Content("base.colorRefine", "Color Refine"),
NBShaderFlags.FLAG_BIT_PARTICLE_1_MAINTEX_COLOR_REFINE,
1);
_baseMapColorRefineA = new VectorComponentItem(rootItem, _baseMapColorRefineBlock, "_BaseMapColorRefine", 0, () => Content("base.colorRefine.a", "A Main Color Multiply"), false);
_baseMapColorRefineBPower = new VectorComponentItem(rootItem, _baseMapColorRefineBlock, "_BaseMapColorRefine", 1, () => Content("base.colorRefine.bPower", "B Main Color Power"), false);
_baseMapColorRefineBMultiply = new VectorComponentItem(rootItem, _baseMapColorRefineBlock, "_BaseMapColorRefine", 2, () => Content("base.colorRefine.bMultiply", "B After Power Multiply"), false);
_baseMapColorRefineLerp = new VectorComponentItem(rootItem, _baseMapColorRefineBlock, "_BaseMapColorRefine", 3, () => Content("base.colorRefine.lerp", "A/B Lerp"), true, 0f, 1f);
_colorMultiAlphaItem = new ToggleItem(
rootItem,
_colorAdjustmentBlock,
"_ColorMultiAlpha",
() => Content("base.colorMultiAlpha", "Color Multiply Alpha"),
enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_COLOR_MULTI_ALPHA, enabled));
_zTestItem = new ZTestItem(rootItem, this);
_cullItem = new CullModeItem(rootItem, this);
_backFirstPassItem = new ToggleItem(
rootItem,
this,
"_BackFirstPassToggle",
() => Content("base.backFirstPass", "Back First Pass"),
OnBackFirstPassChanged,
() => Is3DTransparent());
_forceZWriteItem = new ForceZWriteItem(rootItem, this);
_affectsShadowsItem = new ToggleItem(
rootItem,
this,
"_AffectsShadows",
() => Content("base.affectsShadows", "Affects Shadows"),
_ => rootItem.SyncService.SyncMaterialState(),
Is3DMode);
_transparentShadowDitherItem = new ToggleItem(
rootItem,
this,
"_TransparentShadowDitherToggle",
() => Content("base.transparentShadowDither", "Transparent Dither Shadows"),
_ => rootItem.SyncService.SyncMaterialState(),
ShouldDrawTransparentShadowDither);
_baseBackColorBlock = new PropertyToggleBlockItem(
rootItem,
this,
"_BaseBackColorFoldOut",
"_BaseBackColor_Toggle",
() => Content("base.backColor", "Back Color"),
NBShaderFlags.FLAG_BIT_PARTICLE_BACKCOLOR,
0,
isVisible: Is3DMode);
_baseBackColorItem = new ColorItem(rootItem, _baseBackColorBlock, "_BaseBackColor", () => Content("base.backColor.color", "Back Color"));
_distanceFadeBlock = new PropertyToggleBlockItem(
rootItem,
this,
"_DistanceFadeFoldOut",
"_DistanceFade_Toggle",
() => Content("base.distanceFade", "Distance Fade"),
keyword: "_DISTANCE_FADE",
isVisible: Is3DMode);
_fadeRangeItem = new Vector2LineItem(rootItem, _distanceFadeBlock, "_Fade", true, () => Content("base.distanceFade.range", "Fade Range"));
_softParticlesBlock = new PropertyToggleBlockItem(
rootItem,
this,
"_SoftParticlesFoldOut",
"_SoftParticlesEnabled",
() => Content("base.softParticles", "Soft Particles"),
keyword: "_SOFTPARTICLES_ON",
isVisible: Is3DMode);
_softParticleFadeItem = new Vector2LineItem(rootItem, _softParticlesBlock, "_SoftParticleFadeParams", true, () => Content("base.softParticles.range", "Near/Far Fade"));
_stencilWithoutPlayerItem = new NBShaderKeywordToggleItem(
rootItem,
this,
"_StencilWithoutPlayerToggle",
"_STENCIL_WITHOUT_PLAYER",
() => Content("base.stencilWithoutPlayer", "Stencil Without Player"),
OnStencilWithoutPlayerChanged,
Is3DMode);
_ignoreVertexColorItem = new ToggleItem(
rootItem,
this,
"_IgnoreVetexColor_Toggle",
() => Content("base.ignoreVertexColor", "Ignore Vertex Color"),
enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_1_IGNORE_VERTEX_COLOR, enabled, 1),
Is3DMode);
_fogIntensityItem = new ShaderGUISliderItem(rootItem, this)
{
PropertyName = "_fogintensity",
GuiContent = Content("base.fogIntensity", "Fog Intensity"),
Min = 0f,
Max = 1f
};
_fogIntensityItem.InitTriggerByChild();
InitTriggerByChild();
}
public override void DrawBlock()
{
_baseColorIntensityItem.OnGUI();
_alphaAllItem.OnGUI();
_colorAdjustmentBlock.OnGUI();
_zTestItem.OnGUI();
_cullItem.OnGUI();
_backFirstPassItem.OnGUI();
DrawBackFirstPassWarning();
_forceZWriteItem.OnGUI();
_affectsShadowsItem.OnGUI();
_transparentShadowDitherItem.OnGUI();
_baseBackColorBlock.OnGUI();
_distanceFadeBlock.OnGUI();
_softParticlesBlock.OnGUI();
_stencilWithoutPlayerItem.OnGUI();
_ignoreVertexColorItem.OnGUI();
if (Is3DMode())
{
_fogIntensityItem.OnGUI();
}
else if (_nbRootItem.PropertyInfoDic.ContainsKey("_fogintensity"))
{
_nbRootItem.PropertyInfoDic["_fogintensity"].Property.floatValue = 0f;
}
}
private bool Is3DMode()
{
return _nbRootItem.Context.UIEffectEnabled == MixedBool.False;
}
private bool Is3DTransparent()
{
return Is3DMode() && _nbRootItem.Context.TransparentMode == TransparentMode.Transparent;
}
private bool IsParticleMode()
{
return _nbRootItem.Context.ParticleMode == MixedBool.True;
}
private bool ShouldDrawTransparentShadowDither()
{
return Is3DTransparent() &&
_nbRootItem.PropertyInfoDic.TryGetValue("_AffectsShadows", out ShaderPropertyInfo info) &&
!info.Property.hasMixedValue &&
info.Property.floatValue > 0.5f;
}
private void DrawBackFirstPassWarning()
{
if (!Is3DTransparent() ||
!_nbRootItem.PropertyInfoDic.ContainsKey("_BackFirstPassToggle") ||
_nbRootItem.PropertyInfoDic["_BackFirstPassToggle"].Property.hasMixedValue ||
_nbRootItem.PropertyInfoDic["_BackFirstPassToggle"].Property.floatValue <= 0.5f)
{
return;
}
DrawLayoutHelpBox(
NBShaderInspectorLocalization.GetInspectorText(
"base.backFirstPass.warning",
"预渲染反面会导致打断动态合批,请谨慎使用。"),
MessageType.Warning);
}
private void OnBackFirstPassChanged(bool enabled)
{
_nbRootItem.SyncService.ApplyShaderPass("SRPDefaultUnlit", enabled);
if (enabled && _nbRootItem.PropertyInfoDic.ContainsKey("_Cull"))
{
_nbRootItem.PropertyInfoDic["_Cull"].Property.floatValue = (float)RenderFace.Front;
}
}
private void OnStencilWithoutPlayerChanged(bool enabled)
{
_nbRootItem.SyncService.ApplyStencilPreset(enabled ? "ParticleWithoutPlayer" : "ParticleBaseDefault");
if (_nbRootItem.PropertyInfoDic.ContainsKey("_CustomStencilTest"))
{
_nbRootItem.PropertyInfoDic["_CustomStencilTest"].Property.floatValue = enabled ? 1f : 0f;
}
}
private static GUIContent Content(string key, string fallback, string tip = "")
{
return NBShaderInspectorLocalization.MakeInspectorContent(key, fallback, tip);
}
}
public class ZTestItem : ShaderGUIPopUpItem
{
private static readonly string[] Options = Enum.GetNames(typeof(CompareFunction));
public ZTestItem(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) : base(rootItem, parentItem: parentItem)
{
PropertyName = "_ZTest";
GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("base.ztest", "ZTest");
PopUpNames = NBShaderInspectorLocalization.GetInspectorOptions("base.ztest", Options);
InitTriggerByChild();
}
public override void OnGUI()
{
if (RootItem is NBShaderRootItem nbRootItem)
{
if (nbRootItem.Context.UIEffectEnabled == MixedBool.True)
{
if (!Mathf.Approximately(PropertyInfo.Property.floatValue, (float)CompareFunction.LessEqual))
{
PropertyInfo.Property.floatValue = (float)CompareFunction.LessEqual;
}
return;
}
if (nbRootItem.Context.UIEffectEnabled == MixedBool.Mixed)
{
return;
}
}
base.OnGUI();
}
}
public class CullModeItem : ShaderGUIPopUpItem
{
private static readonly string[] Options = { "Both", "Back", "Front" };
public CullModeItem(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) : base(rootItem, parentItem)
{
PropertyName = "_Cull";
GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("base.cull", "Cull");
PopUpNames = NBShaderInspectorLocalization.GetInspectorOptions("base.cull", Options);
InitTriggerByChild();
}
public override void OnGUI()
{
base.OnGUI();
}
}
public class ForceZWriteItem : ShaderGUIPopUpItem
{
private static readonly string[] Options = { "Default", "Force On", "Force Off" };
public ForceZWriteItem(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) : base(rootItem, parentItem)
{
PropertyName = "_ForceZWriteToggle";
GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("base.forceZWrite", "Force ZWrite");
PopUpNames = NBShaderInspectorLocalization.GetInspectorOptions("base.forceZWrite", Options);
InitTriggerByChild();
}
public override void OnGUI()
{
base.OnGUI();
}
public override void OnEndChange()
{
base.OnEndChange();
if (RootItem is NBShaderRootItem nbRootItem)
{
nbRootItem.SyncService.SyncMaterialState();
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 135aa1fd916c4155b15cada119fdf3fd
timeCreated: 1758549245

View File

@@ -0,0 +1,136 @@
namespace NBShaderEditor
{
public class FeatureBigBlockItem : BigBlockItem
{
public FeatureBigBlockItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(
rootItem,
parentItem,
"_FeatureBigBlockItemFoldOut",
() => NBShaderInspectorLocalization.MakeContent(
"inspector.block.feature.label",
"特效功能",
"inspector.block.feature.tip",
"遮罩、扭曲、溶解等特效功能"))
{
new MaskFeatureItem(rootItem, this);
new NoiseAndDistortFeatureItem(rootItem, this);
new ChromaticAberrationFeatureItem(rootItem, this);
new EmissionFeatureItem(rootItem, this);
new ColorBlendFeatureItem(rootItem, this);
new RampColorFeatureItem(rootItem, this);
new DissolveFeatureItem(rootItem, this);
new ProgramNoiseFeatureItem(rootItem, this);
new SharedUVFeatureItem(rootItem, this);
new FresnelFeatureItem(rootItem, this);
new VertexOffsetFeatureItem(rootItem, this);
new DepthFeatureItem(rootItem, this);
new ParallaxFeatureItem(rootItem, this);
new PortalFeatureItem(rootItem, this);
new FlipbookFeatureItem(rootItem, this);
new VatFeatureItem(rootItem, this);
InitTriggerByChild();
}
public override void DrawBlock()
{
for (int i = 0; i < ChildrenItemList.Count; i++)
{
ShaderGUIItem child = ChildrenItemList[i];
if (IsFeatureItemAllowed(child))
{
child.OnGUI();
}
}
}
private bool IsFeatureItemAllowed(ShaderGUIItem item)
{
if (item is DepthFeatureItem)
{
var rootItem = (NBShaderRootItem)RootItem;
return rootItem.Context == null ||
rootItem.Context.IsAnyKeywordAllowed("_DEPTH_DECAL", "_DEPTH_OUTLINE");
}
string keyword = GetFeatureKeyword(item);
return string.IsNullOrEmpty(keyword) || ((NBShaderRootItem)RootItem).Context.IsKeywordAllowed(keyword);
}
private static string GetFeatureKeyword(ShaderGUIItem item)
{
if (item is MaskFeatureItem)
{
return "_MASKMAP_ON";
}
if (item is NoiseAndDistortFeatureItem)
{
return "_NOISEMAP";
}
if (item is ChromaticAberrationFeatureItem)
{
return "_CHROMATIC_ABERRATION";
}
if (item is EmissionFeatureItem)
{
return "_EMISSION";
}
if (item is ColorBlendFeatureItem)
{
return "_COLORMAPBLEND";
}
if (item is RampColorFeatureItem)
{
return "_COLOR_RAMP";
}
if (item is DissolveFeatureItem)
{
return "_DISSOLVE";
}
if (item is ProgramNoiseFeatureItem)
{
return "_PROGRAM_NOISE";
}
if (item is SharedUVFeatureItem)
{
return "_SHARED_UV";
}
if (item is FresnelFeatureItem)
{
return "_FRESNEL";
}
if (item is ParallaxFeatureItem)
{
return "_PARALLAX_MAPPING";
}
if (item is VatFeatureItem)
{
return "_VAT";
}
if (item is FlipbookFeatureItem)
{
return "_FLIPBOOKBLENDING_ON";
}
if (item is VertexOffsetFeatureItem)
{
return "_VERTEX_OFFSET";
}
return null;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9bfc5d4ee5b1dc64caf81212c9880723
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6f682036413e49019b4856f356996a4c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,28 @@
using NBShader;
namespace NBShaderEditor
{
internal sealed class ChromaticAberrationFeatureItem : FeatureToggleFoldOutItem
{
public ChromaticAberrationFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(
rootItem,
parentItem,
"_ChromaticAberrationFoldOut",
"_Distortion_Choraticaberrat_Toggle",
"色散",
keyword: "_CHROMATIC_ABERRATION")
{
ShaderGUIItem chromaticNoiseAffect = new NoiseAffectItem(rootItem, this);
new ToggleItem(
rootItem,
chromaticNoiseAffect,
"_Distortion_Choraticaberrat_WithNoise_Toggle",
() => Content("色散强度受扭曲强度影响"),
enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_NOISE_CHORATICABERRAT_WITH_NOISE, enabled));
new VectorComponentItem(rootItem, this, "_DistortionDirection", 2, () => Content("色散强度"), false);
new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_CHORATICABERRAT_INTENSITY, 0, () => Content("色散强度自定义曲线"));
InitTriggerByChild();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d0e463cf92ee4725b57727544bc58488
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,29 @@
using System;
using NBShader;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
internal sealed class ColorBlendFeatureItem : FeatureToggleFoldOutItem
{
private static readonly string[] OnOffNames = { "关闭", "开启" };
public ColorBlendFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(rootItem, parentItem, "_ColorBlendBlockFoldOut", "_ColorBlendMap_Toggle", "渐变(颜色相乘)", keyword: "_COLORMAPBLEND")
{
AddTextureWithWrap(rootItem, this, "_ColorBlendMap", "颜色渐变贴图", NBShaderFlags.FLAG_BIT_WRAPMODE_COLORBLENDMAP, "_ColorBlendColor");
new UVModeSelectItem(rootItem, this, "_ColorBlendUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_COLOR_BLEND_MAP, 0, () => Content("颜色渐变贴图UV来源"), "_ColorBlendMap");
new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_X, 3, () => Content("颜色渐变贴图X轴偏移自定义曲线"));
new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_COLOR_BLEND_OFFSET_Y, 3, () => Content("颜色渐变贴图Y轴偏移自定义曲线"));
new VectorComponentItem(rootItem, this, "_ColorBlendVec", 3, () => Content("颜色渐变贴图旋转"), true, 0f, 360f);
new Vector2LineItem(rootItem, this, "_ColorBlendMapOffset", true, () => Content("颜色渐变贴图偏移速度"));
ShaderGUIItem colorBlendNoiseAffect = new NoiseAffectItem(rootItem, this);
new VectorComponentItem(rootItem, colorBlendNoiseAffect, "_ColorBlendVec", 0, () => Content("颜色渐变扭曲强度"), true);
new FeaturePopupItem(rootItem, this, "_ColorBlendAlphaMultiplyMode", () => Content("颜色渐变图Alpha作用"), OnOffNames,
property => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_COLOR_BLEND_ALPHA_MULTIPLY_MODE, property.floatValue > 0.5f));
new VectorComponentItem(rootItem, this, "_ColorBlendVec", 2, () => Content("颜色渐变图Alpha强度"), true);
InitTriggerByChild();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a4e1e4d5240a4b748b50807573e22ab8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,64 @@
using System;
using NBShader;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
internal sealed class DepthFeatureItem : ShaderGUIItem
{
public DepthFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(rootItem, parentItem)
{
new DepthOutlineFeatureItem(rootItem, this);
new ToggleItem(
rootItem,
this,
"_DepthDecal_Toggle",
() => FeatureToggleFoldOutItem.Content("深度贴花"),
rootItem.SyncService.ApplyDepthDecalEnabled,
FeatureToggleFoldOutItem.TierVisible(
rootItem,
"_DEPTH_DECAL",
() => rootItem.Context.UIEffectEnabled != MixedBool.True));
InitTriggerByChild();
}
public override void OnGUI()
{
for (int i = 0; i < ChildrenItemList.Count; i++)
{
ChildrenItemList[i].OnGUI();
}
}
public override void CheckIsPropertyModified(bool isCallByChild = false)
{
HasModified = false;
for (int i = 0; i < ChildrenItemList.Count; i++)
{
HasModified |= ChildrenItemList[i].HasModified;
}
ParentItem?.CheckIsPropertyModified(true);
}
}
internal sealed class DepthOutlineFeatureItem : FeatureToggleFoldOutItem
{
public DepthOutlineFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(
rootItem,
parentItem,
"_DepthOutlineBlockFoldOut",
"_DepthOutline_Toggle",
"深度描边",
keyword: "_DEPTH_OUTLINE",
isVisible: () => rootItem.Context.UIEffectEnabled != MixedBool.True)
{
new ColorItem(rootItem, this, "_DepthOutline_Color", () => Content("深度描边颜色"));
new Vector2LineItem(rootItem, this, "_DepthOutline_Vec", true, () => Content("深度描边距离"));
InitTriggerByChild();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0482c5f68e7b4438bc494df4ebf47267
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,83 @@
using System;
using NBShader;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
internal sealed class DissolveFeatureItem : FeatureToggleFoldOutItem
{
private static readonly string[] RampSourceNames = { "渐变", "贴图" };
private static readonly string[] BlendModeNames = { "叠加", "相乘" };
private static readonly string[] DissolveMaskModeNames = { "Process Dissolve", "Dissolve Mask" };
public DissolveFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(rootItem, parentItem, "_DissolveBlockFoldOut", "_Dissolve_Toggle", "溶解", keyword: "_DISSOLVE")
{
new NBShaderKeywordToggleItem(
rootItem,
this,
"_NB_Debug_Dissolve",
"NB_DEBUG_DISSOLVE",
() => Content("溶解度黑白值测试"),
isVisible: null);
TextureRelatedFoldOutItem dissolveMapRelatedFoldOut = AddTextureWithRelatedFoldOut(rootItem, this, "_DissolveMap", "溶解贴图", "_DissolveMapFoldOut", NBShaderFlags.FLAG_BIT_WRAPMODE_DISSOLVE_MAP);
new ColorChannelSelectItem(rootItem, dissolveMapRelatedFoldOut, NBShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MAP, 0, () => Content("溶解贴图通道选择"));
new CustomDataSelectItem(rootItem, dissolveMapRelatedFoldOut, NBShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_X, 1, () => Content("溶解贴图X轴偏移自定义曲线"));
new CustomDataSelectItem(rootItem, dissolveMapRelatedFoldOut, NBShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_OFFSET_Y, 1, () => Content("溶解贴图Y轴偏移自定义曲线"));
new UVModeSelectItem(rootItem, dissolveMapRelatedFoldOut, "_DissolveUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_DISSOLVE_MAP, 0, () => Content("溶解贴图UV来源"), "_DissolveMap");
new Vector2LineItem(rootItem, dissolveMapRelatedFoldOut, "_DissolveOffsetRotateDistort", true, () => Content("溶解贴图偏移速度"));
new VectorComponentItem(rootItem, dissolveMapRelatedFoldOut, "_DissolveOffsetRotateDistort", 2, () => Content("溶解贴图旋转"), true, 0f, 360f);
new PNoiseBlendModeItem(rootItem, this, NBShaderFlags.FLAG_BIT_PNOISE_BLEND_POS_0_DISSOLVE, "_DissolvePNoiseBlendOpacity", () => Content("溶解程序噪波混合"),
() => rootItem.Context.ProgramNoiseEnabled == MixedBool.True);
new VectorComponentItem(rootItem, this, "_Dissolve", 1, () => Content("溶解值Pow"), true, 0.001f, 10f);
new VectorComponentRangeSliderItem(rootItem, this, "_Dissolve", 0, "DissolveXRangeVec", () => Content("溶解强度"));
new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_DISSOLVE_INTENSITY, 0, () => Content("溶解强度自定义曲线"));
new VectorComponentItem(rootItem, this, "_Dissolve", 3, () => Content("溶解硬软度"), true, 0.001f, 1f);
ShaderGUIItem dissolveNoiseAffect = new NoiseAffectItem(rootItem, this);
new VectorComponentItem(rootItem, dissolveNoiseAffect, "_DissolveOffsetRotateDistort", 3, () => Content("溶解贴图扭曲强度"), false);
PropertyToggleBlockItem lineBlock = ToggleBlock(rootItem, "_DissolveLineFoldOut", "_DissolveLineMaskToggle", "溶解描边",
NBShaderFlags.FLAG_BIT_PARTICLE_1_DISSOLVE_LINE_MASK, 1, parent: this);
new ColorItem(rootItem, lineBlock, "_DissolveLineColor", () => Content("溶解描边颜色"));
new VectorComponentRangeSliderItem(rootItem, lineBlock, "_Dissolve_Vec2", 0, "Dissolve2XRangeVec", () => Content("描边位置"));
new VectorComponentRangeSliderItem(rootItem, lineBlock, "_Dissolve_Vec2", 1, "Dissolve2YRangeVec", () => Content("描边软硬"));
PropertyToggleBlockItem rampBlock = ToggleBlock(rootItem, "_DissolveRampFoldOut", "_Dissolve_useRampMap_Toggle", "溶解Ramp图功能",
parent: this, keyword: "_DISSOLVE_RAMP",
onValueChanged: _ => rootItem.SyncService.SyncMaterialState());
Func<bool> isDissolveRampMapVisible = TierVisible(rootItem, "_DISSOLVE_RAMP_MAP", () => IsPropertyMode(rootItem, "_DissolveRampSourceMode", 1));
new FeaturePopupItem(rootItem, rampBlock, "_DissolveRampSourceMode", () => Content("溶解Ramp模式"), RampSourceNames,
_ => rootItem.SyncService.SyncMaterialState(),
keyword: "_DISSOLVE_RAMP_MAP");
AddTextureWithWrap(rootItem, rampBlock, "_DissolveRampMap", "溶解Ramp图", NBShaderFlags.FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP, "_DissolveRampColor",
isDissolveRampMapVisible);
AddGradient(rootItem, rampBlock, "Ramp颜色", "_DissolveRampCount", "_DissolveRampColor", "_DissolveRampAlpha", hdr: true,
isVisible: () => IsPropertyMode(rootItem, "_DissolveRampSourceMode", 0));
new TextureScaleOffsetItem(rootItem, rampBlock, "_DissolveRampMap", false, () => IsPropertyMode(rootItem, "_DissolveRampSourceMode", 0), TillingContent, OffsetContent);
new ColorItem(rootItem, rampBlock, "_DissolveRampColor", () => Content("Ramp颜色叠加"), () => IsPropertyMode(rootItem, "_DissolveRampSourceMode", 0));
new WrapModeItem(rootItem, rampBlock, NBShaderFlags.FLAG_BIT_WRAPMODE_DISSOLVE_RAMPMAP, () => Content("溶解RampUV Wrap"), 2,
() => IsPropertyMode(rootItem, "_DissolveRampSourceMode", 0));
new FeaturePopupItem(rootItem, rampBlock, "_DissolveRampColorBlendMode", () => Content("溶解Ramp混合模式"), BlendModeNames,
property => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_1_DISSOLVE_RAMP_MULITPLY, property.floatValue > 0.5f, 1));
PropertyToggleBlockItem maskBlock = ToggleBlock(rootItem, "_DissolveMaskFoldOut", "_DissolveMask_Toggle", "溶解遮罩图(过程溶解)",
parent: this, keyword: "_DISSOLVE_MASK");
new FeaturePopupItem(rootItem, maskBlock, "_DissolveMaskMode", () => Content("溶解遮罩模式"), DissolveMaskModeNames);
AddTextureWithWrap(rootItem, maskBlock, "_DissolveMaskMap", "溶解遮罩图", NBShaderFlags.FLAG_BIT_WRAPMODE_DISSOLVE_MASKMAP);
new UVModeSelectItem(rootItem, maskBlock, "_DissolveMaskUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_DISSOLVE_MASK_MAP, 0, () => Content("溶解遮罩图UV来源"), "_DissolveMaskMap");
new ColorChannelSelectItem(rootItem, maskBlock, NBShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_DISSOLVE_MASK_MAP, 0, () => Content("溶解遮罩图通道选择"));
new VectorComponentItem(rootItem, maskBlock, "_Dissolve", 2, () => Content("溶解遮罩强度"), false, isVisible: () => !IsDissolveMaskStrengthSlider(rootItem));
new VectorComponentItem(rootItem, maskBlock, "_Dissolve", 2, () => Content("溶解遮罩强度"), true, 0f, 2f, () => IsDissolveMaskStrengthSlider(rootItem));
new CustomDataSelectItem(rootItem, maskBlock, NBShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_DISSOLVE_MASK_INTENSITY, 1, () => Content("溶解遮罩图强度自定义曲线"));
InitTriggerByChild();
}
private static bool IsDissolveMaskStrengthSlider(NBShaderRootItem rootItem)
{
return rootItem.PropertyInfoDic.TryGetValue("_DissolveMaskMode", out ShaderPropertyInfo info) &&
!info.Property.hasMixedValue &&
info.Property.floatValue > 0.5f;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 64cae13520d842939c7d27d6ffadd01d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,42 @@
using System;
using NBShader;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
internal sealed class EmissionFeatureItem : FeatureToggleFoldOutItem
{
public EmissionFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(rootItem, parentItem, "_EmissionBlockFoldOut", "_EmissionEnabled", "流光(颜色相加)", keyword: "_EMISSION")
{
AddTextureWithWrap(rootItem, this, "_EmissionMap", "流光贴图", NBShaderFlags.FLAG_BIT_WRAPMODE_EMISSIONMAP, "_EmissionMapColor");
new UVModeSelectItem(rootItem, this, "_EmissionUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_EMISSION_MAP, 0, () => Content("流光贴图UV来源"), "_EmissionMap");
new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_X, 3, () => Content("流光贴图X轴偏移自定义曲线"));
new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_EMISSION_OFFSET_Y, 3, () => Content("流光贴图Y轴偏移自定义曲线"));
ShaderGUISliderItem emissionMapUVRotationItem = new ShaderGUISliderItem(rootItem, this)
{
PropertyName = "_EmissionMapUVRotation",
GuiContent = Content("流光贴图旋转"),
Min = 0f,
Max = 360f
};
emissionMapUVRotationItem.InitTriggerByChild();
new Vector2LineItem(rootItem, this, "_EmissionMapUVOffset", true, () => Content("流光贴图偏移速度"));
ShaderGUIItem emissionNoiseAffect = new NoiseAffectItem(rootItem, this);
ShaderGUIFloatItem emissionDistortionIntensityItem = new ShaderGUIFloatItem(rootItem, emissionNoiseAffect)
{
PropertyName = "_Emi_Distortion_intensity",
GuiContent = Content("流光贴图扭曲强度")
};
emissionDistortionIntensityItem.InitTriggerByChild();
ShaderGUIFloatItem emissionMapColorIntensityItem = new ShaderGUIFloatItem(rootItem, this)
{
PropertyName = "_EmissionMapColorIntensity",
GuiContent = Content("流光颜色强度")
};
emissionMapColorIntensityItem.InitTriggerByChild();
InitTriggerByChild();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ed7051253ed04c968aa25e96aa0e5d5d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,175 @@
using System;
using NBShader;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
internal sealed class NoiseAffectItem : ShaderGUIItem
{
private readonly NBShaderRootItem _nbRootItem;
public NoiseAffectItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(rootItem, parentItem)
{
_nbRootItem = rootItem;
}
public override void OnGUI()
{
bool previousMixedValue = EditorGUI.showMixedValue;
bool noiseEnabledHasMixedValue = _nbRootItem.Context.NoiseEnabled == MixedBool.Mixed;
using (new InheritedControlDisabledScope(_nbRootItem.Context.NoiseEnabled == MixedBool.False))
{
for (int i = 0; i < ChildrenItemList.Count; i++)
{
EditorGUI.showMixedValue = noiseEnabledHasMixedValue;
ChildrenItemList[i].OnGUI();
}
}
EditorGUI.showMixedValue = previousMixedValue;
}
public override void CheckIsPropertyModified(bool isCallByChild = false)
{
HasModified = false;
for (int i = 0; i < ChildrenItemList.Count; i++)
{
HasModified |= ChildrenItemList[i].HasModified;
}
ParentItem?.CheckIsPropertyModified(true);
}
}
internal sealed class FlipbookFeatureItem : ToggleItem
{
private readonly NBShaderRootItem _nbRootItem;
public FlipbookFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(
rootItem,
parentItem,
"_FlipbookBlending",
() => FeatureToggleFoldOutItem.Content("序列帧融帧(丝滑)"),
rootItem.SyncService.ApplyFlipbookEnabled)
{
_nbRootItem = rootItem;
}
public override void DrawBlock()
{
if (PropertyInfo.Property.hasMixedValue || PropertyInfo.Property.floatValue <= 0.5f)
{
return;
}
if (_nbRootItem.Context.MeshSourceMode == MeshSourceMode.Particle ||
_nbRootItem.Context.MeshSourceMode == MeshSourceMode.UIParticle)
{
if (HasSpecialUVChannel())
{
using (ParentControlDisabledScope())
{
DrawLayoutHelpBox(
FeatureToggleFoldOutItem.Text(
"feature.flipbook.specialUvWarning.message",
"序列帧融帧和特殊UV通道同时开启粒子序列帧应该影响UV0和UV1两个通道特殊通道只能使用UV3原始UV"),
MessageType.Warning);
}
}
else
{
using (ParentControlDisabledScope())
{
DrawLayoutHelpBox(
FeatureToggleFoldOutItem.Text(
"feature.flipbook.particleInfo.message",
"AnimationSheet的AffectUVChannel需要有UV0和UV1"),
MessageType.Info);
}
}
return;
}
if (_nbRootItem.Context.MeshSourceMode == MeshSourceMode.Mesh)
{
using (ParentControlDisabledScope())
{
DrawLayoutHelpBox(
FeatureToggleFoldOutItem.Text(
"feature.flipbook.meshInfo.message",
"需要添加AnimationSheetHelper脚本"),
MessageType.Info);
}
}
}
private bool HasSpecialUVChannel()
{
for (int i = 0; i < _nbRootItem.ShaderFlags.Count; i++)
{
if (_nbRootItem.ShaderFlags[i] is NBShaderFlags flags &&
flags.CheckIsUVModeOn(NBShaderFlags.UVMode.SpecialUVChannel))
{
return true;
}
}
return false;
}
}
internal sealed class VatFrameCustomDataItem : CustomDataSelectItem
{
private readonly Func<bool> _isVisible;
private readonly Func<bool> _anyVatFrameCustomDataVisible;
public VatFrameCustomDataItem(
NBShaderRootItem rootItem,
ShaderGUIItem parentItem,
Func<GUIContent> contentProvider,
Func<bool> isVisible,
Func<bool> anyVatFrameCustomDataVisible)
: base(rootItem, parentItem, NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_VAT_FRAME, 2, contentProvider)
{
_isVisible = isVisible;
_anyVatFrameCustomDataVisible = anyVatFrameCustomDataVisible;
}
public override void OnGUI()
{
if (_isVisible != null && !_isVisible())
{
if (_anyVatFrameCustomDataVisible == null || !_anyVatFrameCustomDataVisible())
{
ClearVatFrameCustomData();
}
return;
}
base.OnGUI();
}
private void ClearVatFrameCustomData()
{
for (int i = 0; i < RootItem.ShaderFlags.Count; i++)
{
if (RootItem.ShaderFlags[i] is NBShaderFlags flags && flags.material != null)
{
if (flags.GetCustomDataFlag(NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_VAT_FRAME, 2) !=
NBShaderFlags.CutomDataComponent.Off)
{
flags.SetCustomDataFlag(
NBShaderFlags.CutomDataComponent.Off,
NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_VAT_FRAME,
2);
}
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2c8170a5849c4a5abf332cdf3832fa02
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,276 @@
using System;
using System.Collections.Generic;
using NBShader;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
internal abstract class FeatureToggleFoldOutItem : PropertyToggleBlockItem
{
private const string LocalizationTableName = NBShaderInspectorLocalization.TableName;
private static readonly Dictionary<string, GUIContent> ContentCache =
new Dictionary<string, GUIContent>(StringComparer.Ordinal);
private static readonly Dictionary<string, string[]> PopupOptionsCache =
new Dictionary<string, string[]>(StringComparer.Ordinal);
private static string s_CacheLanguage;
protected FeatureToggleFoldOutItem(
NBShaderRootItem rootItem,
ShaderGUIItem parentItem,
string foldOutPropertyName,
string togglePropertyName,
string label,
int flagBits = 0,
int flagIndex = 0,
string keyword = null,
Action<bool> onValueChanged = null,
Func<bool> isVisible = null,
bool bold = true)
: base(
rootItem,
parentItem,
foldOutPropertyName,
togglePropertyName,
() => Content(label),
flagBits,
flagIndex,
keyword,
onValueChanged: onValueChanged,
isVisible: isVisible,
bold: bold)
{
}
protected TextureRelatedFoldOutItem AddTextureWithRelatedFoldOut(
NBShaderRootItem rootItem,
ShaderGUIItem parent,
string texturePropertyName,
string label,
string foldOutPropertyName,
int wrapFlag,
string colorPropertyName = null,
Func<bool> isVisible = null)
{
new TextureItem(
rootItem,
parent,
texturePropertyName,
() => Content(label),
colorPropertyName,
isVisible: isVisible,
tillingContentProvider: TillingContent,
offsetContentProvider: OffsetContent);
TextureRelatedFoldOutItem relatedFoldOut = new TextureRelatedFoldOutItem(
rootItem,
parent,
foldOutPropertyName,
texturePropertyName,
() => Content(label + "相关功能"),
isVisible);
new WrapModeItem(rootItem, relatedFoldOut, wrapFlag, () => Content(label + " Wrap"), 2);
return relatedFoldOut;
}
protected void AddTextureWithWrap(
NBShaderRootItem rootItem,
ShaderGUIItem parent,
string texturePropertyName,
string label,
int wrapFlag,
string colorPropertyName = null,
Func<bool> isVisible = null)
{
new TextureItem(
rootItem,
parent,
texturePropertyName,
() => Content(label),
colorPropertyName,
isVisible: isVisible,
tillingContentProvider: TillingContent,
offsetContentProvider: OffsetContent);
new WrapModeItem(rootItem, parent, wrapFlag, () => Content(label + " Wrap"), 2, isVisible);
}
protected PropertyToggleBlockItem ToggleBlock(
NBShaderRootItem rootItem,
string foldOutPropertyName,
string togglePropertyName,
string label,
int flagBits = 0,
int flagIndex = 0,
ShaderGUIItem parent = null,
string keyword = null,
Action<bool> onValueChanged = null,
Func<bool> isVisible = null,
bool bold = false)
{
return new PropertyToggleBlockItem(
rootItem,
parent ?? this,
foldOutPropertyName,
togglePropertyName,
() => Content(label),
flagBits,
flagIndex,
keyword,
onValueChanged: onValueChanged,
isVisible: isVisible,
bold: bold);
}
protected static void AddGradient(
NBShaderRootItem rootItem,
ShaderGUIItem parent,
string label,
string countPropertyName,
string colorPrefix,
string alphaPrefix,
bool hdr = false,
Func<bool> isVisible = null)
{
new GradientItem(
rootItem,
parent,
countPropertyName,
6,
BuildPropertyNames(colorPrefix, 6),
BuildPropertyNames(alphaPrefix, 3),
() => Content(label),
hdr,
ColorSpace.Gamma,
isVisible);
}
protected static string[] BuildPropertyNames(string prefix, int count)
{
string[] names = new string[count];
for (int i = 0; i < count; i++)
{
names[i] = prefix + i;
}
return names;
}
protected static bool IsPropertyMode(NBShaderRootItem rootItem, string propertyName, int expectedMode)
{
return rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info) &&
!info.Property.hasMixedValue &&
Mathf.RoundToInt(info.Property.floatValue) == expectedMode;
}
protected static bool IsPropertyMode(NBShaderRootItem rootItem, string propertyName, params int[] expectedModes)
{
if (!rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info) ||
info.Property.hasMixedValue)
{
return false;
}
int value = Mathf.RoundToInt(info.Property.floatValue);
for (int i = 0; i < expectedModes.Length; i++)
{
if (value == expectedModes[i])
{
return true;
}
}
return false;
}
internal static GUIContent Content(string label)
{
EnsureCacheLanguage();
if (ContentCache.TryGetValue(label, out GUIContent cachedContent))
{
return cachedContent;
}
cachedContent = NBShaderInspectorLocalization.MakeInspectorContent("feature." + label, label);
ContentCache[label] = cachedContent;
return cachedContent;
}
protected static GUIContent TillingContent()
{
return LocalizedInspectorContent(LocalizationTableName, "common.tilling", "Tilling");
}
protected static GUIContent OffsetContent()
{
return LocalizedInspectorContent(LocalizationTableName, "common.offset", "Offset");
}
internal static string Text(string key, string fallback)
{
return LocalizedText(LocalizationTableName, key, fallback);
}
internal static string[] PopupOptions(string propertyName, string[] fallback)
{
EnsureCacheLanguage();
if (PopupOptionsCache.TryGetValue(propertyName, out string[] cachedOptions))
{
return cachedOptions;
}
cachedOptions = NBShaderInspectorLocalization.GetInspectorOptions("feature.popup." + propertyName, fallback);
PopupOptionsCache[propertyName] = cachedOptions;
return cachedOptions;
}
private static void EnsureCacheLanguage()
{
string currentLanguage = NBShaderInspectorLocalization.CurrentLanguage;
if (string.Equals(s_CacheLanguage, currentLanguage, StringComparison.Ordinal))
{
return;
}
s_CacheLanguage = currentLanguage;
ContentCache.Clear();
PopupOptionsCache.Clear();
}
internal static bool IsTierKeywordAllowed(NBShaderRootItem rootItem, string keyword)
{
return string.IsNullOrEmpty(keyword) ||
rootItem == null ||
rootItem.Context == null ||
rootItem.Context.IsKeywordAllowed(keyword);
}
internal static Func<bool> TierVisible(NBShaderRootItem rootItem, string keyword, Func<bool> isVisible = null)
{
return () => IsTierKeywordAllowed(rootItem, keyword) && (isVisible == null || isVisible());
}
}
internal sealed class FeaturePopupItem : ShaderGUIPopUpItem
{
public FeaturePopupItem(
ShaderGUIRootItem rootItem,
ShaderGUIItem parentItem,
string propertyName,
Func<GUIContent> contentProvider,
string[] popupNames,
Action<MaterialProperty> onValueChanged = null,
Func<bool> isVisible = null,
string keyword = null)
: base(
rootItem,
parentItem,
propertyName,
contentProvider,
() => FeatureToggleFoldOutItem.PopupOptions(propertyName, popupNames),
onValueChanged,
string.IsNullOrEmpty(keyword)
? isVisible
: FeatureToggleFoldOutItem.TierVisible(rootItem as NBShaderRootItem, keyword, isVisible))
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 355bed04b23c4ea093ad45991f0004a4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,50 @@
using System;
using NBShader;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
internal sealed class FresnelFeatureItem : FeatureToggleFoldOutItem
{
private static readonly string[] FresnelModeNames = { "颜色", "透明" };
public FresnelFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(rootItem, parentItem, "_FresnelBlockFoldOut", "_fresnelEnabled", "菲涅尔", keyword: "_FRESNEL")
{
new NBShaderKeywordToggleItem(
rootItem,
this,
"_NB_Debug_Fresnel",
"NB_DEBUG_FRESNEL",
() => Content("菲涅尔测试颜色"),
isVisible: null);
new FeaturePopupItem(rootItem, this, "_FresnelMode", () => Content("菲涅尔模式"), FresnelModeNames,
property => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_FRESNEL_FADE_ON, property.floatValue > 0.5f));
Func<bool> isFresnelColorMode = () => IsPropertyMode(rootItem, "_FresnelMode", 0);
new ColorItem(rootItem, this, "_FresnelColor", () => Content("菲涅尔颜色"), isFresnelColorMode);
new VectorComponentItem(rootItem, this, "_FresnelUnit", 2, () => Content("菲涅尔强度"), true);
new VectorComponentItem(rootItem, this, "_FresnelUnit", 0, () => Content("菲涅尔位置"), true, -1f, 1f);
new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_FRESNEL_OFFSET, 0, () => Content("菲涅尔位置自定义曲线"));
new VectorComponentItem(rootItem, this, "_FresnelUnit", 1, () => Content("菲涅尔范围Pow"), true, 0f, 10f);
new VectorComponentItem(rootItem, this, "_FresnelUnit", 3, () => Content("菲涅尔硬度"), true);
new ToggleItem(
rootItem,
this,
"_InvertFresnel_Toggle",
() => Content("翻转菲涅尔"),
enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_FRESNEL_INVERT_ON, enabled));
new ToggleItem(
rootItem,
this,
"_FresnelColorAffectByAlpha",
() => Content("菲涅尔颜色受Alpha影响"),
enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_FRESNEL_COLOR_AFFETCT_BY_ALPHA, enabled),
isFresnelColorMode);
new VectorComponentItem(rootItem, this, "_FresnelRotation", 0, () => Content("菲涅尔方向偏移X"), false);
new VectorComponentItem(rootItem, this, "_FresnelRotation", 1, () => Content("菲涅尔方向偏移Y"), false);
new VectorComponentItem(rootItem, this, "_FresnelRotation", 2, () => Content("菲涅尔方向偏移Z"), false);
InitTriggerByChild();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ee140beb49b74735960d38a89bd528fd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,171 @@
using System;
using NBShader;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
internal sealed class MaskFeatureItem : FeatureToggleFoldOutItem
{
private static readonly string[] TextureGradientNames = { "贴图", "渐变" };
public MaskFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(rootItem, parentItem, "_MaskBlockFoldOut", "_Mask_Toggle", "遮罩", keyword: "_MASKMAP_ON")
{
new NBShaderKeywordToggleItem(
rootItem,
this,
"_NB_Debug_Mask",
"NB_DEBUG_MASK",
() => Content("测试遮罩颜色"),
isVisible: null);
new VectorComponentItem(rootItem, this, "_MaskMapVec", 0, () => Content("遮罩强度"), true);
PropertyToggleBlockItem refineBlock = ToggleBlock(
rootItem,
"_MaskRefineFoldOut",
"_MaskRefineToggle",
"遮罩整体调整",
NBShaderFlags.FLAG_BIT_PARTICLE_1_MASK_REFINE,
1,
parent: this);
new VectorComponentItem(rootItem, refineBlock, "_MaskRefineVec", 0, () => Content("范围(Pow)"), false);
new VectorComponentItem(rootItem, refineBlock, "_MaskRefineVec", 1, () => Content("相乘"), false);
new VectorComponentItem(rootItem, refineBlock, "_MaskRefineVec", 2, () => Content("偏移(相加)"), false);
new PNoiseBlendModeItem(rootItem, this, NBShaderFlags.FLAG_BIT_PNOISE_BLEND_POS_0_MASK, "_MaskPNoiseBlendOpacity", () => Content("遮罩程序噪波混合"),
() => rootItem.Context.ProgramNoiseEnabled == MixedBool.True);
AddMaskMap(rootItem, this, "_MaskMap", "_MaskMapGradientToggle", "_MaskUVModeFoldOut", "遮罩",
NBShaderFlags.FLAG_BIT_WRAPMODE_MASKMAP,
NBShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP1,
NBShaderFlags.FLAG_BIT_UVMODE_POS_0_MASKMAP,
NBShaderFlags.FLAG_BIT_PARTICLE_1_MASKMAP_GRADIENT,
1,
"_MaskMapFoldOut");
new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_X, 0, () => Content("Mask图X轴偏移自定义曲线"));
new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_MASK_OFFSET_Y, 0, () => Content("Mask图Y轴偏移自定义曲线"));
new Vector2LineItem(rootItem, this, "_MaskMapOffsetAnition", true, () => Content("遮罩偏移速度"));
ShaderGUISliderItem maskMapUVRotationItem = new ShaderGUISliderItem(rootItem, this)
{
PropertyName = "_MaskMapUVRotation",
GuiContent = Content("遮罩旋转"),
Min = 0f,
Max = 360f
};
maskMapUVRotationItem.InitTriggerByChild();
PropertyToggleBlockItem rotateBlock = ToggleBlock(
rootItem,
"_MaskRotationFoldOut",
"_Mask_RotationToggle",
"遮罩旋转速度",
NBShaderFlags.FLAG_BIT_PARTILCE_MASKMAPROTATIONANIMATION_ON,
parent: this);
ShaderGUIFloatItem maskMapRotationSpeedItem = new ShaderGUIFloatItem(rootItem, rotateBlock)
{
PropertyName = "_MaskMapRotationSpeed",
GuiContent = Content("旋转速度")
};
maskMapRotationSpeedItem.InitTriggerByChild();
ShaderGUIItem maskNoiseAffect = new NoiseAffectItem(rootItem, this);
ShaderGUISliderItem maskDistortionIntensityItem = new ShaderGUISliderItem(rootItem, maskNoiseAffect)
{
PropertyName = "_MaskDistortion_intensity",
GuiContent = Content("遮罩扭曲强度"),
RangePropertyName = "MaskDistortionIntensityRangeVec"
};
maskDistortionIntensityItem.InitTriggerByChild();
PropertyToggleBlockItem mask2Block = ToggleBlock(
rootItem,
"_Mask2BlockFoldOut",
"_Mask2_Toggle",
"遮罩2",
parent: this,
keyword: "_MASKMAP2_ON");
AddMaskMap(rootItem, mask2Block, "_MaskMap2", "_MaskMap2GradientToggle", "_Mask2UVModeFoldOut", "遮罩2",
NBShaderFlags.FLAG_BIT_WRAPMODE_MASKMAP2,
NBShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP2,
NBShaderFlags.FLAG_BIT_UVMODE_POS_0_MASKMAP_2,
NBShaderFlags.FLAG_BIT_PARTICLE_1_MASKMAP_2_GRADIENT,
1);
new VectorComponentItem(rootItem, mask2Block, "_MaskMapVec", 1, () => Content("遮罩2旋转"), false);
new Vector2LineItem(rootItem, mask2Block, "_MaskMapOffsetAnition", false, () => Content("遮罩2偏移速度"));
PropertyToggleBlockItem mask3Block = ToggleBlock(
rootItem,
"_Mask3BlockFoldOut",
"_Mask3_Toggle",
"遮罩3",
parent: this,
keyword: "_MASKMAP3_ON");
AddMaskMap(rootItem, mask3Block, "_MaskMap3", "_MaskMap3GradientToggle", "_Mask3UVModeFoldOut", "遮罩3",
NBShaderFlags.FLAG_BIT_WRAPMODE_MASKMAP3,
NBShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_MASKMAP3,
NBShaderFlags.FLAG_BIT_UVMODE_POS_0_MASKMAP_3,
NBShaderFlags.FLAG_BIT_PARTICLE_1_MASKMAP_3_GRADIENT,
1);
new VectorComponentItem(rootItem, mask3Block, "_MaskMapVec", 2, () => Content("遮罩3旋转"), false);
new Vector2LineItem(rootItem, mask3Block, "_MaskMap3OffsetAnition", true, () => Content("遮罩3偏移速度"));
InitTriggerByChild();
}
private void AddMaskMap(
NBShaderRootItem rootItem,
ShaderGUIItem parent,
string texturePropertyName,
string modePropertyName,
string uvFoldOutPropertyName,
string label,
int wrapFlag,
int colorChannelFlagPos,
int uvModeFlagPos,
int gradientFlag,
int gradientFlagIndex,
string textureFoldOutPropertyName = null)
{
new FeaturePopupItem(rootItem, parent, modePropertyName, () => Content(label + "模式"), TextureGradientNames,
property => rootItem.SyncService.ApplyToggleFlag(gradientFlag, property.floatValue > 0.5f, gradientFlagIndex));
ShaderGUIItem textureParent = parent;
if (string.IsNullOrEmpty(textureFoldOutPropertyName))
{
AddTextureWithWrap(rootItem, parent, texturePropertyName, label + "贴图", wrapFlag,
isVisible: () => IsPropertyMode(rootItem, modePropertyName, 0));
}
else
{
textureParent = AddTextureWithRelatedFoldOut(rootItem, parent, texturePropertyName, label + "贴图", textureFoldOutPropertyName, wrapFlag,
isVisible: () => IsPropertyMode(rootItem, modePropertyName, 0));
}
new ColorChannelSelectItem(rootItem, textureParent, colorChannelFlagPos, 0, () => Content(label + "通道选择"),
() => IsPropertyMode(rootItem, modePropertyName, 0));
AddAlphaGradient(rootItem, parent, label + "渐变", texturePropertyName + "GradientCount", texturePropertyName + "GradientFloat",
() => IsPropertyMode(rootItem, modePropertyName, 1));
new TextureScaleOffsetItem(rootItem, parent, texturePropertyName, false, () => IsPropertyMode(rootItem, modePropertyName, 1), TillingContent, OffsetContent);
new WrapModeItem(rootItem, parent, wrapFlag, () => Content(label + "UV Wrap"), 2,
() => IsPropertyMode(rootItem, modePropertyName, 1));
new UVModeSelectItem(rootItem, parent, uvFoldOutPropertyName, uvModeFlagPos, 0, () => Content(label + "UV来源"), texturePropertyName, forceEnable: true);
}
private static void AddAlphaGradient(
NBShaderRootItem rootItem,
ShaderGUIItem parent,
string label,
string countPropertyName,
string alphaPrefix,
Func<bool> isVisible = null)
{
new GradientItem(
rootItem,
parent,
countPropertyName,
6,
Array.Empty<string>(),
BuildPropertyNames(alphaPrefix, 3),
() => Content(label),
false,
ColorSpace.Gamma,
isVisible);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c5fe236301944650a35adc509015737c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,519 @@
using System;
using System.Reflection;
using NBShader;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
namespace NBShaderEditor
{
internal sealed class NoiseAndDistortFeatureItem : FeatureToggleFoldOutItem
{
private static readonly string[] DistortModeNames = { "FlowMap/RG贴图", "折射率" };
private static readonly string[] ScreenDistortModeNames = { "No Screen Distort", "Deferred Distort", "Camera Opaque Distort" };
private const int ScreenDistortModeDeferred = 1;
private const int ScreenDistortModeCameraOpaque = 2;
private const string ScreenDistortKeyword = "_SCREEN_DISTORT_MODE";
private const string ScreenDistortModePropertyName = "_ScreenDistortModeToggle";
private const string RendererDataListPropertyName = "m_RendererDataList";
private const string LegacyRendererDataPropertyName = "m_RendererData";
private const string RendererFeaturesPropertyName = "m_RendererFeatures";
private const string OpaqueTexturePropertyName = "supportsCameraOpaqueTexture";
private const string OpaqueTextureSerializedPropertyName = "m_RequireOpaqueTexture";
private const string RendererFeatureActivePropertyName = "isActive";
private const string RendererFeatureActiveSerializedPropertyName = "m_Active";
private const string NBPostProcessTypeFullName = "NBShader.NBPostProcess";
private const string NBPostProcessTypeName = "NBPostProcess";
public NoiseAndDistortFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(rootItem, parentItem, "_NoiseBlockFoldOut", "_noisemapEnabled", "扭曲", keyword: "_NOISEMAP")
{
new NBShaderKeywordToggleItem(
rootItem,
this,
"_NB_Debug_Distort",
"NB_DEBUG_DISTORT",
() => Content("扭曲强度值测试"),
isVisible: null);
ShaderGUISliderItem noiseIntensityItem = new ShaderGUISliderItem(rootItem, this)
{
PropertyName = "_NoiseIntensity",
GuiContent = Content("整体扭曲强度"),
RangePropertyName = "_NoiseIntensityRangeVec"
};
noiseIntensityItem.InitTriggerByChild();
new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_NOISE_INTENSITY, 1, () => Content("扭曲强度自定义曲线"));
new FeaturePopupItem(rootItem, this, "_ScreenDistortModeToggle", () => Content("屏幕扰动模式"), ScreenDistortModeNames,
property => rootItem.SyncService.ApplyScreenDistortMode(Mathf.RoundToInt(property.floatValue)),
() => rootItem.Context.UIEffectEnabled != MixedBool.True,
ScreenDistortKeyword);
Func<bool> isDeferredDistortVisible = TierVisible(
rootItem,
ScreenDistortKeyword,
() => IsScreenDistortMode(rootItem, ScreenDistortModeDeferred));
Func<bool> isCameraOpaqueDistortVisible = TierVisible(
rootItem,
ScreenDistortKeyword,
() => IsScreenDistortMode(rootItem, ScreenDistortModeCameraOpaque));
Func<bool> isScreenDistortModeNeedsNBPostProcessVisible = () => isDeferredDistortVisible() || isCameraOpaqueDistortVisible();
Func<bool> isMissingNBPostProcessVisible = () => isScreenDistortModeNeedsNBPostProcessVisible() && !HasActiveNBPostProcessRendererFeature();
Func<bool> isMissingOpaqueTextureVisible = () => isCameraOpaqueDistortVisible() && !HasCameraOpaqueTextureCopyEnabled();
new PingableHelpBoxItem(
rootItem,
this,
() => Text(
"feature.screenDistort.missingNbPostProcess.message",
"Screen Distort requires an active NB Post Process Feature on at least one RendererData in the current URP Pipeline Asset."),
MessageType.Warning,
() => ButtonContent("feature.screenDistort.pingRendererData", "Ping Renderer"),
GetRendererDataForNBPostProcessPing,
isMissingNBPostProcessVisible);
new PingableHelpBoxItem(
rootItem,
this,
() => Text(
"feature.screenDistort.missingOpaqueTextureCopy.message",
"Camera Opaque Distort requires Opaque Texture to be enabled on the current URP Pipeline Asset."),
MessageType.Warning,
() => ButtonContent("feature.screenDistort.pingPipelineAsset", "Ping URP Asset"),
GetCurrentRenderPipelineAsset,
isMissingOpaqueTextureVisible);
ShaderGUISliderItem screenDistortIntensityItem = new ShaderGUISliderItem(
rootItem,
this,
TierVisible(
rootItem,
ScreenDistortKeyword,
() => rootItem.Context.UIEffectEnabled != MixedBool.True && IsPropertyGreater(rootItem, "_ScreenDistortModeToggle", 0.5f)))
{
PropertyName = "_ScreenDistortIntensity",
GuiContent = Content("屏幕扭曲强度"),
RangePropertyName = "_ScreenDistortIntensityRangeVec"
};
screenDistortIntensityItem.InitTriggerByChild();
new ToggleItem(
rootItem,
this,
"_DisableMainPassToggle",
() => Content("关闭主材质Pass"),
enabled =>
{
rootItem.SyncService.ApplyScreenDistortMode(GetIntProperty(rootItem, "_ScreenDistortModeToggle"));
},
TierVisible(
rootItem,
ScreenDistortKeyword,
() => rootItem.Context.UIEffectEnabled != MixedBool.True && IsPropertyGreater(rootItem, "_ScreenDistortModeToggle", 0.5f)));
PropertyToggleBlockItem screenAlphaBlock = ToggleBlock(
rootItem,
"_ScreenDistortAlphaFoldOut",
"_ScreenDistortAlphaRefineToggle",
"屏幕扭曲Alpha整体调整",
NBShaderFlags.FLAG_BIT_PARTICLE_1_SCREEN_DISTORT_ALPHA_REFINE,
1,
parent: this,
isVisible: TierVisible(
rootItem,
ScreenDistortKeyword,
() => rootItem.Context.UIEffectEnabled != MixedBool.True && IsPropertyGreater(rootItem, "_ScreenDistortModeToggle", 0.5f)));
ShaderGUIFloatItem screenDistortAlphaPowItem = new ShaderGUIFloatItem(rootItem, screenAlphaBlock)
{
PropertyName = "_ScreenDistortAlphaPow",
GuiContent = Content("范围(Pow)")
};
screenDistortAlphaPowItem.InitTriggerByChild();
ShaderGUIFloatItem screenDistortAlphaMultiItem = new ShaderGUIFloatItem(rootItem, screenAlphaBlock)
{
PropertyName = "_ScreenDistortAlphaMulti",
GuiContent = Content("相乘")
};
screenDistortAlphaMultiItem.InitTriggerByChild();
ShaderGUIFloatItem screenDistortAlphaAddItem = new ShaderGUIFloatItem(rootItem, screenAlphaBlock)
{
PropertyName = "_ScreenDistortAlphaAdd",
GuiContent = Content("偏移(相加)")
};
screenDistortAlphaAddItem.InitTriggerByChild();
new FeaturePopupItem(rootItem, this, "_DistortMode", () => Content("扭曲模式"), DistortModeNames,
property => rootItem.SyncService.ApplyToggleKeyword("_DISTORT_REFRACTION", property.floatValue > 0.5f),
keyword: "_DISTORT_REFRACTION");
TextureRelatedFoldOutItem noiseMapRelatedFoldOut = AddTextureWithRelatedFoldOut(rootItem, this, "_NoiseMap", "扭曲贴图", "_NoiseMapFoldOut", NBShaderFlags.FLAG_BIT_WRAPMODE_NOISEMAP,
isVisible: () => IsPropertyMode(rootItem, "_DistortMode", 0));
new UVModeSelectItem(rootItem, noiseMapRelatedFoldOut, "_NoiseUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_NOISE_MAP, 0, () => Content("扭曲贴图UV来源"), "_NoiseMap",
isVisible: () => IsPropertyMode(rootItem, "_DistortMode", 0));
new Vector2LineItem(rootItem, noiseMapRelatedFoldOut, "_DistortionDirection", true, () => Content("扭曲方向强度"), () => IsPropertyMode(rootItem, "_DistortMode", 0));
new CustomDataSelectItem(rootItem, noiseMapRelatedFoldOut, NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_X, 2, () => Content("扭曲方向强度X自定义曲线"), () => IsPropertyMode(rootItem, "_DistortMode", 0));
new CustomDataSelectItem(rootItem, noiseMapRelatedFoldOut, NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_NOISE_DIRECTION_Y, 2, () => Content("扭曲方向强度Y自定义曲线"), () => IsPropertyMode(rootItem, "_DistortMode", 0));
ShaderGUISliderItem noiseMapUVRotationItem = new ShaderGUISliderItem(rootItem, noiseMapRelatedFoldOut, () => IsPropertyMode(rootItem, "_DistortMode", 0))
{
PropertyName = "_NoiseMapUVRotation",
GuiContent = Content("扭曲旋转"),
Min = 0f,
Max = 360f
};
noiseMapUVRotationItem.InitTriggerByChild();
new Vector2LineItem(rootItem, noiseMapRelatedFoldOut, "_NoiseOffset", true, () => Content("扭曲偏移速度"), () => IsPropertyMode(rootItem, "_DistortMode", 0));
new ToggleItem(
rootItem,
noiseMapRelatedFoldOut,
"_DistortionBothDirection_Toggle",
() => Content("0.5为中值,双向扭曲"),
enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_NOISEMAP_NORMALIZEED_ON, enabled),
() => IsPropertyMode(rootItem, "_DistortMode", 0));
ShaderGUISliderItem refractionIorItem = new ShaderGUISliderItem(
rootItem,
this,
TierVisible(rootItem, "_DISTORT_REFRACTION", () => IsPropertyMode(rootItem, "_DistortMode", 1)))
{
PropertyName = "_RefractionIOR",
GuiContent = Content("折射率"),
Min = 0f,
Max = 5f
};
refractionIorItem.InitTriggerByChild();
new PNoiseBlendModeItem(rootItem, this, NBShaderFlags.FLAG_BIT_PNOISE_BLEND_POS_0_DISTORT, "_DistortPNoiseBlendOpacity", () => Content("扭曲程序噪波混合"),
() => rootItem.Context.ProgramNoiseEnabled == MixedBool.True);
PropertyToggleBlockItem noiseMaskBlock = ToggleBlock(
rootItem,
"_NoiseMaskBlockFoldOut",
"_noiseMaskMap_Toggle",
"扭曲遮罩",
parent: this,
keyword: "_NOISE_MASKMAP");
AddTextureWithWrap(rootItem, noiseMaskBlock, "_NoiseMaskMap", "扭曲遮罩贴图", NBShaderFlags.FLAG_BIT_WRAPMODE_NOISE_MASKMAP);
new ColorChannelSelectItem(rootItem, noiseMaskBlock, NBShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_NOISE_MASK, 0, () => Content("扭曲遮罩图通道选择"));
new UVModeSelectItem(rootItem, noiseMaskBlock, "_NoiseMaskUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_NOISE_MASK_MAP, 0, () => Content("扭曲遮罩贴图UV来源"), "_NoiseMaskMap");
InitTriggerByChild();
}
private static int GetIntProperty(NBShaderRootItem rootItem, string propertyName)
{
return rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info) && !info.Property.hasMixedValue
? Mathf.RoundToInt(info.Property.floatValue)
: 0;
}
private static bool IsPropertyGreater(NBShaderRootItem rootItem, string propertyName, float threshold)
{
return rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info) &&
!info.Property.hasMixedValue &&
info.Property.floatValue > threshold;
}
private static bool IsScreenDistortMode(NBShaderRootItem rootItem, int mode)
{
return rootItem.Context.UIEffectEnabled != MixedBool.True &&
IsPropertyMode(rootItem, ScreenDistortModePropertyName, mode);
}
private static bool HasActiveNBPostProcessRendererFeature()
{
try
{
RenderPipelineAsset pipelineAsset = GetCurrentRenderPipelineAsset();
if (pipelineAsset == null)
{
return false;
}
SerializedObject pipelineObject = new SerializedObject(pipelineAsset);
SerializedProperty rendererDataList = pipelineObject.FindProperty(RendererDataListPropertyName);
if (rendererDataList != null && rendererDataList.isArray)
{
for (int i = 0; i < rendererDataList.arraySize; i++)
{
UnityEngine.Object rendererData = rendererDataList.GetArrayElementAtIndex(i).objectReferenceValue;
if (RendererDataHasNBPostProcess(rendererData, requireActive: true))
{
return true;
}
}
return false;
}
SerializedProperty legacyRendererData = pipelineObject.FindProperty(LegacyRendererDataPropertyName);
return legacyRendererData != null && RendererDataHasNBPostProcess(legacyRendererData.objectReferenceValue, requireActive: true);
}
catch (Exception)
{
return false;
}
}
private static bool RendererDataHasNBPostProcess(UnityEngine.Object rendererData, bool requireActive)
{
if (rendererData == null)
{
return false;
}
SerializedObject rendererDataObject = new SerializedObject(rendererData);
SerializedProperty rendererFeatures = rendererDataObject.FindProperty(RendererFeaturesPropertyName);
if (rendererFeatures == null || !rendererFeatures.isArray)
{
return false;
}
for (int i = 0; i < rendererFeatures.arraySize; i++)
{
UnityEngine.Object rendererFeature = rendererFeatures.GetArrayElementAtIndex(i).objectReferenceValue;
if (IsNBPostProcessFeature(rendererFeature) &&
(!requireActive || IsRendererFeatureActive(rendererFeature)))
{
return true;
}
}
return false;
}
private static bool IsNBPostProcessFeature(UnityEngine.Object rendererFeature)
{
if (rendererFeature == null)
{
return false;
}
for (Type type = rendererFeature.GetType(); type != null; type = type.BaseType)
{
if (string.Equals(type.FullName, NBPostProcessTypeFullName, StringComparison.Ordinal) ||
string.Equals(type.Name, NBPostProcessTypeName, StringComparison.Ordinal))
{
return true;
}
}
return false;
}
private static bool IsRendererFeatureActive(UnityEngine.Object rendererFeature)
{
if (rendererFeature == null)
{
return false;
}
if (TryGetBoolProperty(rendererFeature, RendererFeatureActivePropertyName, out bool isActive))
{
return isActive;
}
try
{
SerializedObject rendererFeatureObject = new SerializedObject(rendererFeature);
SerializedProperty activeProperty = rendererFeatureObject.FindProperty(RendererFeatureActiveSerializedPropertyName);
return activeProperty != null &&
activeProperty.propertyType == SerializedPropertyType.Boolean &&
activeProperty.boolValue;
}
catch (Exception)
{
return false;
}
}
private static bool HasCameraOpaqueTextureCopyEnabled()
{
try
{
RenderPipelineAsset pipelineAsset = GetCurrentRenderPipelineAsset();
if (pipelineAsset == null)
{
return false;
}
if (TryGetBoolProperty(pipelineAsset, OpaqueTexturePropertyName, out bool supportsCameraOpaqueTexture))
{
return supportsCameraOpaqueTexture;
}
SerializedObject pipelineObject = new SerializedObject(pipelineAsset);
SerializedProperty opaqueTextureProperty = pipelineObject.FindProperty(OpaqueTextureSerializedPropertyName);
return opaqueTextureProperty != null &&
opaqueTextureProperty.propertyType == SerializedPropertyType.Boolean &&
opaqueTextureProperty.boolValue;
}
catch (Exception)
{
return false;
}
}
private static UnityEngine.Object GetRendererDataForNBPostProcessPing()
{
try
{
RenderPipelineAsset pipelineAsset = GetCurrentRenderPipelineAsset();
if (pipelineAsset == null)
{
return null;
}
SerializedObject pipelineObject = new SerializedObject(pipelineAsset);
SerializedProperty rendererDataList = pipelineObject.FindProperty(RendererDataListPropertyName);
if (rendererDataList != null && rendererDataList.isArray)
{
return GetRendererDataForNBPostProcessPing(rendererDataList);
}
SerializedProperty legacyRendererData = pipelineObject.FindProperty(LegacyRendererDataPropertyName);
return legacyRendererData != null ? legacyRendererData.objectReferenceValue : null;
}
catch (Exception)
{
return null;
}
}
private static UnityEngine.Object GetRendererDataForNBPostProcessPing(SerializedProperty rendererDataList)
{
UnityEngine.Object firstRendererData = null;
UnityEngine.Object rendererDataWithInactiveFeature = null;
for (int i = 0; i < rendererDataList.arraySize; i++)
{
UnityEngine.Object rendererData = rendererDataList.GetArrayElementAtIndex(i).objectReferenceValue;
if (rendererData == null)
{
continue;
}
if (firstRendererData == null)
{
firstRendererData = rendererData;
}
if (RendererDataHasNBPostProcess(rendererData, requireActive: true))
{
return rendererData;
}
if (rendererDataWithInactiveFeature == null &&
RendererDataHasNBPostProcess(rendererData, requireActive: false))
{
rendererDataWithInactiveFeature = rendererData;
}
}
return rendererDataWithInactiveFeature != null ? rendererDataWithInactiveFeature : firstRendererData;
}
private static RenderPipelineAsset GetCurrentRenderPipelineAsset()
{
return QualitySettings.renderPipeline != null
? QualitySettings.renderPipeline
: GraphicsSettings.currentRenderPipeline;
}
private static bool TryGetBoolProperty(UnityEngine.Object target, string propertyName, out bool value)
{
value = false;
if (target == null)
{
return false;
}
try
{
PropertyInfo propertyInfo = target.GetType().GetProperty(
propertyName,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (propertyInfo == null || propertyInfo.PropertyType != typeof(bool))
{
return false;
}
value = (bool)propertyInfo.GetValue(target, null);
return true;
}
catch (Exception)
{
return false;
}
}
private static GUIContent ButtonContent(string key, string fallback)
{
return NBShaderInspectorLocalization.MakeContent("inspector." + key + ".button", fallback);
}
private sealed class PingableHelpBoxItem : ShaderGUIItem
{
private const float HelpBoxPadding = 6f;
private const float HelpBoxButtonGap = 4f;
private const float MaxButtonWidth = 160f;
private static readonly GUIContent TempHelpContent = new GUIContent();
private readonly Func<string> _messageProvider;
private readonly MessageType _messageType;
private readonly Func<GUIContent> _buttonContentProvider;
private readonly Func<UnityEngine.Object> _targetProvider;
private readonly Func<bool> _isVisible;
public PingableHelpBoxItem(
ShaderGUIRootItem rootItem,
ShaderGUIItem parentItem,
Func<string> messageProvider,
MessageType messageType,
Func<GUIContent> buttonContentProvider,
Func<UnityEngine.Object> targetProvider,
Func<bool> isVisible) : base(rootItem, parentItem)
{
_messageProvider = messageProvider ?? (() => string.Empty);
_messageType = messageType;
_buttonContentProvider = buttonContentProvider ?? (() => GUIContent.none);
_targetProvider = targetProvider ?? (() => null);
_isVisible = isVisible;
}
public override void OnGUI()
{
if (_isVisible != null && !_isVisible())
{
return;
}
using (ParentControlDisabledScope())
{
string message = _messageProvider();
GUIContent buttonContent = _buttonContentProvider();
TempHelpContent.text = message;
float width = Mathf.Max(1f, EditorGUIUtility.currentViewWidth + GlobalRectWidthExpansion + GlobalRectXOffset);
float messageHeight = Mathf.Max(
EditorGUIUtility.singleLineHeight * 2f,
EditorStyles.helpBox.CalcHeight(TempHelpContent, width));
float buttonHeight = EditorGUIUtility.singleLineHeight;
float height = messageHeight + HelpBoxButtonGap + buttonHeight + HelpBoxPadding;
Rect rect = ApplyGlobalRectCompensation(LayoutRect(height));
EditorGUI.HelpBox(rect, message, _messageType);
float buttonWidth = Mathf.Min(
MaxButtonWidth,
Mathf.Max(90f, EditorStyles.miniButton.CalcSize(buttonContent).x + 18f));
buttonWidth = Mathf.Min(buttonWidth, Mathf.Max(0f, rect.width - HelpBoxPadding * 2f));
Rect buttonRect = new Rect(
rect.xMax - HelpBoxPadding - buttonWidth,
rect.yMax - HelpBoxPadding - buttonHeight,
buttonWidth,
buttonHeight);
UnityEngine.Object target = _targetProvider();
using (new EditorGUI.DisabledScope(target == null))
{
if (GUI.Button(buttonRect, buttonContent, EditorStyles.miniButton))
{
Selection.activeObject = target;
EditorGUIUtility.PingObject(target);
}
}
TempHelpContent.text = string.Empty;
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e4f64374c74c47478edfdd0ddb6e8355
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,35 @@
using System;
using NBShader;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
internal sealed class ParallaxFeatureItem : FeatureToggleFoldOutItem
{
public ParallaxFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(rootItem, parentItem, "_ParallaxBlockFoldOut", "_ParallaxMapping_Toggle", "遮蔽视差", keyword: "_PARALLAX_MAPPING", isVisible: () => rootItem.Context.UIEffectEnabled != MixedBool.True)
{
AddTextureWithWrap(rootItem, this, "_ParallaxMapping_Map", "视差贴图", NBShaderFlags.FLAG_BIT_WRAPMODE_PARALLAXMAPPINGMAP);
ShaderGUISliderItem parallaxMappingIntensityItem = new ShaderGUISliderItem(rootItem, this)
{
PropertyName = "_ParallaxMapping_Intensity",
GuiContent = Content("视差"),
RangePropertyName = "_ParallaxMapping_IntensityRangeVec"
};
parallaxMappingIntensityItem.InitTriggerByChild();
new VectorComponentItem(rootItem, this, "_ParallaxMapping_Vec", 0, () => Content("遮蔽视差最小层数"), true, 0f, 100f);
new VectorComponentItem(rootItem, this, "_ParallaxMapping_Vec", 1, () => Content("遮蔽视差最大层数"), true, 0f, 100f);
new HelpBoxItem(rootItem, this, () => Text("feature.parallax.layerWarning.message", "遮蔽视差层数过高将影响性能"), MessageType.Warning,
() => IsParallaxMaxLayerHigh(rootItem));
InitTriggerByChild();
}
private static bool IsParallaxMaxLayerHigh(NBShaderRootItem rootItem)
{
return rootItem.PropertyInfoDic.TryGetValue("_ParallaxMapping_Vec", out ShaderPropertyInfo info) &&
!info.Property.hasMixedValue &&
info.Property.vectorValue.y >= 20f;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d5bf38ca73454cc1916d18f40182d5ad
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
using System;
using NBShader;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
internal sealed class PortalFeatureItem : FeatureToggleFoldOutItem
{
public PortalFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(rootItem, parentItem, "_PortalBlockFoldOut", "_Portal_Toggle", "模板视差", onValueChanged: _ => rootItem.SyncService.ApplyPortalState(), isVisible: () => rootItem.Context.UIEffectEnabled != MixedBool.True)
{
new ToggleItem(rootItem, this, "_Portal_MaskToggle", () => Content("模板视差蒙版"), _ => rootItem.SyncService.ApplyPortalState());
InitTriggerByChild();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 67c4fd7f472848dfbefe5703bb834b60
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,58 @@
using System;
using NBShader;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
internal sealed class ProgramNoiseFeatureItem : FeatureToggleFoldOutItem
{
public ProgramNoiseFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(rootItem, parentItem, "_ProgramNoiseBlockFoldOut", "_ProgramNoise_Toggle", "程序化噪波", keyword: "_PROGRAM_NOISE")
{
new NBShaderKeywordToggleItem(
rootItem,
this,
"_NB_Debug_PNoise",
"NB_DEBUG_PNOISE",
() => Content("程序化噪波测试颜色"),
isVisible: null);
new UVModeSelectItem(rootItem, this, "_ProgramNoiseUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_PROGRAM_NOISE, 0, () => Content("程序噪波UV来源"), forceEnable: true);
ShaderGUIFloatItem programNoiseRotateItem = new ShaderGUIFloatItem(rootItem, this)
{
PropertyName = "_ProgramNoise_Rotate",
GuiContent = Content("程序化噪波旋转")
};
programNoiseRotateItem.InitTriggerByChild();
PropertyToggleBlockItem simpleBlock = ToggleBlock(rootItem, "_ProgramNoiseSimpleFoldOut", "_ProgramNoise_Simple_Toggle", "Perlin噪波",
parent: this, keyword: "_PROGRAM_NOISE_SIMPLE");
new Vector2LineItem(rootItem, simpleBlock, "_DissolveVoronoi_Vec", true, () => Content("噪波1缩放"));
new VectorComponentItem(rootItem, simpleBlock, "_DissolveVoronoi_Vec2", 2, () => Content("噪波1速度"), false);
new Vector2LineItem(rootItem, simpleBlock, "_DissolveVoronoi_Vec4", true, () => Content("噪波1偏移"));
new Vector2LineItem(rootItem, simpleBlock, "_DissolveVoronoi_Vec3", true, () => Content("噪波1偏移速度"));
new CustomDataSelectItem(rootItem, simpleBlock, NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_X, 2, () => Content("噪波1偏移速度X自定义曲线"));
new CustomDataSelectItem(rootItem, simpleBlock, NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE1_OFFSET_Y, 2, () => Content("噪波1偏移速度Y自定义曲线"));
PropertyToggleBlockItem voronoiBlock = ToggleBlock(rootItem, "_ProgramNoiseVoronoiFoldOut", "_ProgramNoise_Voronoi_Toggle", "Voronoi噪波",
parent: this, keyword: "_PROGRAM_NOISE_VORONOI");
new Vector2LineItem(rootItem, voronoiBlock, "_DissolveVoronoi_Vec", false, () => Content("噪波2缩放"));
new VectorComponentItem(rootItem, voronoiBlock, "_DissolveVoronoi_Vec2", 3, () => Content("噪波2速度"), false);
new Vector2LineItem(rootItem, voronoiBlock, "_DissolveVoronoi_Vec4", false, () => Content("噪波2偏移"));
new Vector2LineItem(rootItem, voronoiBlock, "_DissolveVoronoi_Vec3", false, () => Content("噪波2偏移速度"));
new CustomDataSelectItem(rootItem, voronoiBlock, NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_X, 2, () => Content("噪波2偏移速度X自定义曲线"));
new CustomDataSelectItem(rootItem, voronoiBlock, NBShaderFlags.FLAGBIT_POS_2_CUSTOMDATA_DISSOLVE_NOISE2_OFFSET_Y, 2, () => Content("噪波2偏移速度Y自定义曲线"));
new VectorComponentItem(rootItem, this, "_DissolveVoronoi_Vec2", 0, () => Content("噪波1和噪波2混合系数"), true);
new PNoiseBlendModeItem(
rootItem,
this,
NBShaderFlags.FLAG_BIT_PNOISE_BLEND_POS_0_BASE_BLEND,
"_ProgramNoiseBaseBlendOpacity",
() => Content("两种程序噪波混合"),
() => rootItem.Context.ProgramNoiseEnabled == MixedBool.True &&
rootItem.Context.IsToggleOn("_ProgramNoise_Simple_Toggle") &&
rootItem.Context.IsToggleOn("_ProgramNoise_Voronoi_Toggle"));
InitTriggerByChild();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c6a446a2f0364fb0844cb9d36bd39a27
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,37 @@
using System;
using NBShader;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
internal sealed class RampColorFeatureItem : FeatureToggleFoldOutItem
{
private static readonly string[] RampSourceNames = { "渐变", "贴图" };
private static readonly string[] BlendModeNames = { "叠加", "相乘" };
public RampColorFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(rootItem, parentItem, "_RampColorBlockFoldOut", "_RampColorToggle", "颜色映射(Ramp)", keyword: "_COLOR_RAMP")
{
Func<bool> isRampMapVisible = TierVisible(rootItem, "_COLOR_RAMP_MAP", () => IsPropertyMode(rootItem, "_RampColorSourceMode", 1));
new FeaturePopupItem(rootItem, this, "_RampColorSourceMode", () => Content("Ramp来源模式"), RampSourceNames,
_ => rootItem.SyncService.SyncMaterialState(),
keyword: "_COLOR_RAMP_MAP");
AddTextureWithWrap(rootItem, this, "_RampColorMap", "颜色映射黑白图", NBShaderFlags.FLAG_BIT_WRAPMODE_RAMP_COLOR_MAP,
isVisible: isRampMapVisible);
new TextureScaleOffsetItem(rootItem, this, "_RampColorMap", false, () => IsPropertyMode(rootItem, "_RampColorSourceMode", 0), TillingContent, OffsetContent);
new WrapModeItem(rootItem, this, NBShaderFlags.FLAG_BIT_WRAPMODE_RAMP_COLOR_MAP, () => Content("颜色映射UV Wrap"), 2,
() => IsPropertyMode(rootItem, "_RampColorSourceMode", 0));
new ColorChannelSelectItem(rootItem, this, NBShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_RAMP_COLOR_MAP, 0, () => Content("颜色映射黑白图通道选择"),
isRampMapVisible);
new UVModeSelectItem(rootItem, this, "_RampColorUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_RAMP_COLOR_MAP, 0, () => Content("颜色映射黑白图UV来源"), "_RampColorMap", true);
new Vector2LineItem(rootItem, this, "_RampColorMapOffset", true, () => Content("颜色映射贴图偏移速度"));
new VectorComponentItem(rootItem, this, "_RampColorMapOffset", 3, () => Content("颜色映射贴图旋转"), true, 0f, 360f);
AddGradient(rootItem, this, "映射颜色", "_RampColorCount", "_RampColor", "_RampColorAlpha", hdr: true);
new FeaturePopupItem(rootItem, this, "_RampColorBlendMode", () => Content("Ramp颜色混合模式"), BlendModeNames,
property => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_RAMP_COLOR_BLEND_ADD, property.floatValue > 0.5f));
new ColorItem(rootItem, this, "_RampColorBlendColor", () => Content("颜色映射叠加颜色"));
InitTriggerByChild();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 45dcb7c7a750440a99a8d5017d41fa22
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,24 @@
using System;
using NBShader;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
internal sealed class SharedUVFeatureItem : FeatureToggleFoldOutItem
{
public SharedUVFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(rootItem, parentItem, "_SharedUVBlockFoldOut", "_SharedUVToggle", "公共UV", keyword: "_SHARED_UV")
{
new UVModeSelectItem(rootItem, this, "_SharedUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_SHAREDUV, 0, () => Content("公共UV来源"), forceEnable: true);
new Vector2LineItem(rootItem, this, "_SharedUV_ST", true, () => Content("公共UV Tiling"));
new Vector2LineItem(rootItem, this, "_SharedUV_ST", false, () => Content("公共UV Offset"));
new Vector2LineItem(rootItem, this, "_SharedUV_Vec", true, () => Content("公共UV偏移速度"));
new VectorComponentItem(rootItem, this, "_SharedUV_Vec", 2, () => Content("旋转"), false);
new VectorComponentItem(rootItem, this, "_SharedUV_Vec", 3, () => Content("旋转速度"), false);
new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_X, 3, () => Content("公共UV X轴偏移自定义曲线"));
new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_SHARED_UV_OFFSET_Y, 3, () => Content("公共UV Y轴偏移自定义曲线"));
InitTriggerByChild();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dece160aaa274dd79c1e771fed834249
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,428 @@
using System;
using NBShader;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
internal sealed class VatFeatureItem : FeatureToggleFoldOutItem
{
private static readonly string[] VatModeNames = { "Houdini", "TyFlow" };
private static readonly string[] HoudiniVatSubModeNames =
{
"SoftBody (Deformation)",
"RigidBody (Pieces)",
"Dynamic Remeshing (Lookup)",
"Particle Sprites (Billboard)"
};
private static readonly string[] TyFlowVatSubModeNames =
{
"Absolute positions",
"Relative offsets",
"Skin (R)",
"Skin (PR)",
"Skin (PRSAVE)",
"Skin (PRSXYZ)"
};
public VatFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(rootItem, parentItem, "_VATBlockFoldOut", "_VAT_Toggle", "VAT顶点动画图", keyword: "_VAT", onValueChanged: rootItem.SyncService.ApplyVatEnabled)
{
new FeaturePopupItem(rootItem, this, "_VATMode", () => Content("VAT模式"), VatModeNames, _ => rootItem.SyncService.SyncMaterialState());
Func<bool> isHoudini = () => IsPropertyMode(rootItem, "_VATMode", (int)VATMode.Houdini);
Func<bool> isTyflow = () => IsPropertyMode(rootItem, "_VATMode", (int)VATMode.Tyflow);
Func<bool> hasVatFrameCustomData = () => IsVatFrameCustomDataVisible(rootItem);
ShaderGUIFloatItem floatItem;
new FeaturePopupItem(rootItem, this, "_HoudiniVATSubMode", () => Content("Houdini VAT Sub Mode"), HoudiniVatSubModeNames,
_ => rootItem.SyncService.SyncMaterialState(), isHoudini);
new HelpBoxItem(rootItem, this, () => Text("feature.vat.houdiniUnsupportedParticle.message", "该 Houdini VAT 类型需要 Mesh 多 UV 数据,不支持 ParticleSystem VertexStream 模式。"), MessageType.Warning,
() => isHoudini() && HasUnsupportedHoudiniParticleMode(rootItem));
new SectionLabelItem(rootItem, this, () => Content("Playback"), isHoudini);
new ToggleItem(rootItem, this, "_B_autoPlayback", () => Content("Auto Playback"), isVisible: isHoudini);
floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && ShouldDrawWhenFloatOff(rootItem, "_B_autoPlayback"))
{
PropertyName = "_displayFrame",
GuiContent = Content("Display Frame")
};
floatItem.InitTriggerByChild();
new VatFrameCustomDataItem(rootItem, this, () => Content("VAT Frame CustomData"), () => isHoudini() && hasVatFrameCustomData(), hasVatFrameCustomData);
floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini)
{
PropertyName = "_gameTimeAtFirstFrame",
GuiContent = Content("Game Time at First Frame")
};
floatItem.InitTriggerByChild();
floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini)
{
PropertyName = "_playbackSpeed",
GuiContent = Content("Playback Speed")
};
floatItem.InitTriggerByChild();
floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini)
{
PropertyName = "_houdiniFPS",
GuiContent = Content("Houdini FPS")
};
floatItem.InitTriggerByChild();
new ToggleItem(rootItem, this, "_B_interpolate", () => Content("Interframe Interpolation"), isVisible: isHoudini);
new ToggleItem(rootItem, this, "_animateFirstFrame", () => Content("Animate First Frame"), isVisible: () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 1));
floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini)
{
PropertyName = "_frameCount",
GuiContent = Content("Frame Count")
};
floatItem.InitTriggerByChild();
new SectionLabelItem(rootItem, this, () => Content("Bounds Metadata"), isHoudini);
floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini)
{
PropertyName = "_boundMinX",
GuiContent = Content("Bound Min X")
};
floatItem.InitTriggerByChild();
floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini)
{
PropertyName = "_boundMinY",
GuiContent = Content("Bound Min Y")
};
floatItem.InitTriggerByChild();
floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini)
{
PropertyName = "_boundMinZ",
GuiContent = Content("Bound Min Z")
};
floatItem.InitTriggerByChild();
floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini)
{
PropertyName = "_boundMaxX",
GuiContent = Content("Bound Max X")
};
floatItem.InitTriggerByChild();
floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini)
{
PropertyName = "_boundMaxY",
GuiContent = Content("Bound Max Y")
};
floatItem.InitTriggerByChild();
floatItem = new ShaderGUIFloatItem(rootItem, this, isHoudini)
{
PropertyName = "_boundMaxZ",
GuiContent = Content("Bound Max Z")
};
floatItem.InitTriggerByChild();
new SectionLabelItem(rootItem, this, () => Content("Textures"), isHoudini);
new TextureItem(rootItem, this, "_posTexture", () => Content("Position Texture"), drawScaleOffset: false, isVisible: isHoudini);
new TextureItem(rootItem, this, "_posTexture2", () => Content("Position Texture 2"), drawScaleOffset: false,
isVisible: () => isHoudini() && ShouldDrawWhenFloatOn(rootItem, "_B_LOAD_POS_TWO_TEX"));
new TextureItem(rootItem, this, "_rotTexture", () => Content("Rotation Texture"), drawScaleOffset: false,
isVisible: () => isHoudini() && ShouldDrawHoudiniRotationTexture(rootItem));
new TextureItem(rootItem, this, "_colTexture", () => Content("Color Texture"), drawScaleOffset: false,
isVisible: () => isHoudini() && ShouldDrawWhenFloatOn(rootItem, "_B_LOAD_COL_TEX"));
new TextureItem(rootItem, this, "_lookupTable", () => Content("Lookup Table"), drawScaleOffset: false,
isVisible: () => isHoudini() && (IsPropertyMode(rootItem, "_HoudiniVATSubMode", 2) || ShouldDrawWhenFloatOn(rootItem, "_B_LOAD_LOOKUP_TABLE")));
new SectionLabelItem(rootItem, this, () => Content("Scale"), () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 1, 3));
floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 1, 3))
{
PropertyName = "_globalPscaleMul",
GuiContent = Content("Global Piece Scale Multiplier")
};
floatItem.InitTriggerByChild();
new ToggleItem(rootItem, this, "_B_pscaleAreInPosA", () => Content("Piece Scales in Position Alpha"), isVisible: () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 1, 3));
new SectionLabelItem(rootItem, this, () => Content("Particle Sprite"), () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3));
floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3))
{
PropertyName = "_widthBaseScale",
GuiContent = Content("Width Base Scale")
};
floatItem.InitTriggerByChild();
floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3))
{
PropertyName = "_heightBaseScale",
GuiContent = Content("Height Base Scale")
};
floatItem.InitTriggerByChild();
new ToggleItem(rootItem, this, "_B_hideOverlappingOrigin", () => Content("Hide Overlapping Origin"), isVisible: () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3));
floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3) && ShouldDrawWhenFloatOn(rootItem, "_B_hideOverlappingOrigin"))
{
PropertyName = "_originRadius",
GuiContent = Content("Origin Effective Radius")
};
floatItem.InitTriggerByChild();
new ToggleItem(rootItem, this, "_B_CAN_SPIN", () => Content("Particles Can Spin"), isVisible: () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3));
new ToggleItem(rootItem, this, "_B_spinFromHeading", () => Content("Compute Spin from Heading"), isVisible: () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3) && ShouldDrawWhenFloatOn(rootItem, "_B_CAN_SPIN"));
floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3) && ShouldDrawWhenFloatOn(rootItem, "_B_CAN_SPIN") && ShouldDrawWhenFloatOff(rootItem, "_B_spinFromHeading"))
{
PropertyName = "_spinPhase",
GuiContent = Content("Particle Spin Phase")
};
floatItem.InitTriggerByChild();
floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3) && ShouldDrawWhenFloatOn(rootItem, "_B_CAN_SPIN"))
{
PropertyName = "_scaleByVelAmount",
GuiContent = Content("Scale by Velocity Amount")
};
floatItem.InitTriggerByChild();
floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3))
{
PropertyName = "_particleTexUScale",
GuiContent = Content("Particle Texture U Scale")
};
floatItem.InitTriggerByChild();
floatItem = new ShaderGUIFloatItem(rootItem, this, () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 3))
{
PropertyName = "_particleTexVScale",
GuiContent = Content("Particle Texture V Scale")
};
floatItem.InitTriggerByChild();
new SectionLabelItem(rootItem, this, () => Content("Flags"), isHoudini);
new ToggleItem(rootItem, this, "_B_LOAD_POS_TWO_TEX", () => Content("Positions Require Two Textures"), isVisible: isHoudini);
new ToggleItem(rootItem, this, "_B_UNLOAD_ROT_TEX", () => Content("Use Compressed Normals (no rotTex)"), isVisible: () => isHoudini() && ShouldDrawCompressedNormalsToggle(rootItem));
new ToggleItem(rootItem, this, "_B_LOAD_COL_TEX", () => Content("Load Color Texture"), isVisible: isHoudini);
new ToggleItem(rootItem, this, "_B_LOAD_LOOKUP_TABLE", () => Content("Load Lookup Table"), isVisible: () => isHoudini() && IsPropertyMode(rootItem, "_HoudiniVATSubMode", 2));
new TextureItem(rootItem, this, "_VATTex", () => Content("VAT texture"), drawScaleOffset: false, isVisible: isTyflow);
floatItem = new ShaderGUIFloatItem(rootItem, this, isTyflow)
{
PropertyName = "_ImportScale",
GuiContent = Content("ImportScale")
};
floatItem.InitTriggerByChild();
new FeaturePopupItem(rootItem, this, "_TyFlowVATSubMode", () => Content("TyFlow VAT Sub Mode"), TyFlowVatSubModeNames,
_ => rootItem.SyncService.SyncMaterialState(), isTyflow);
new HelpBoxItem(rootItem, this, () => Text("feature.vat.tyflowUnsupportedParticle.message", "该 TyFlow VAT 类型需要 Mesh 多 UV 数据,不支持 ParticleSystem VertexStream 模式。"), MessageType.Warning,
() => isTyflow() && HasUnsupportedTyflowParticleMode(rootItem));
new HelpBoxItem(rootItem, this, () => Text("feature.vat.tyflowUv2Conflict.message", "TyFlow VAT uses UV2 (TEXCOORD0.zw) as vertexIndex / vertexCount in ParticleSystem mode. Flipbook blending or Special UV (UV2) conflicts with it; VAT takes priority."), MessageType.Warning,
() => isTyflow() && !HasUnsupportedTyflowParticleMode(rootItem) && HasTyflowParticleUV2Conflict(rootItem));
new ToggleItem(rootItem, this, "_DeformingSkin", () => Content("Deforming skin"), isVisible: isTyflow);
floatItem = new ShaderGUIFloatItem(rootItem, this, isTyflow)
{
PropertyName = "_SkinBoneCount",
GuiContent = Content("Skin bone count")
};
floatItem.InitTriggerByChild();
new ToggleItem(rootItem, this, "_RGBAEncoded", () => Content("RGBA encoded"), isVisible: isTyflow);
new ToggleItem(rootItem, this, "_RGBAHalf", () => Content("RGBA half"), isVisible: isTyflow);
new ToggleItem(rootItem, this, "_LinearToGamma", () => Content("Gamma correction"), isVisible: isTyflow);
new ToggleItem(rootItem, this, "_VATIncludesNormals", () => Content("VAT includes normals"), isVisible: isTyflow);
floatItem = new ShaderGUIFloatItem(rootItem, this, isTyflow)
{
PropertyName = "_Frame",
GuiContent = Content("Frame")
};
floatItem.InitTriggerByChild();
new VatFrameCustomDataItem(rootItem, this, () => Content("VAT Frame CustomData"), () => isTyflow() && hasVatFrameCustomData(), hasVatFrameCustomData);
floatItem = new ShaderGUIFloatItem(rootItem, this, isTyflow)
{
PropertyName = "_Frames",
GuiContent = Content("Frames")
};
floatItem.InitTriggerByChild();
new ToggleItem(rootItem, this, "_FrameInterpolation", () => Content("Frame interpolation"), isVisible: isTyflow);
new ToggleItem(rootItem, this, "_Loop", () => Content("Loop"), isVisible: isTyflow);
new ToggleItem(rootItem, this, "_InterpolateLoop", () => Content("Interpolate loop"), isVisible: isTyflow);
new ToggleItem(rootItem, this, "_Autoplay", () => Content("Autoplay"), isVisible: isTyflow);
floatItem = new ShaderGUIFloatItem(rootItem, this, isTyflow)
{
PropertyName = "_AutoplaySpeed",
GuiContent = Content("AutoplaySpeed")
};
floatItem.InitTriggerByChild();
InitTriggerByChild();
}
private static bool ShouldDrawWhenFloatOn(NBShaderRootItem rootItem, string propertyName)
{
if (!rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info))
{
return false;
}
return info.Property.hasMixedValue || info.Property.floatValue > 0.5f;
}
private static bool ShouldDrawWhenFloatOff(NBShaderRootItem rootItem, string propertyName)
{
if (!rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info))
{
return false;
}
return info.Property.hasMixedValue || info.Property.floatValue <= 0.5f;
}
private static bool TryGetPropertyMode(NBShaderRootItem rootItem, string propertyName, out int mode)
{
mode = 0;
if (!rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info) ||
info.Property.hasMixedValue)
{
return false;
}
mode = Mathf.RoundToInt(info.Property.floatValue);
return true;
}
private static bool ShouldDrawHoudiniRotationTexture(NBShaderRootItem rootItem)
{
return TryGetPropertyMode(rootItem, "_HoudiniVATSubMode", out int subMode) &&
subMode != 3 &&
ShouldDrawWhenFloatOff(rootItem, "_B_UNLOAD_ROT_TEX");
}
private static bool ShouldDrawCompressedNormalsToggle(NBShaderRootItem rootItem)
{
return TryGetPropertyMode(rootItem, "_HoudiniVATSubMode", out int subMode) && subMode != 3;
}
private static bool IsVatFrameCustomDataVisible(NBShaderRootItem rootItem)
{
return IsAnyHoudiniParticleModeEnabled(rootItem) || IsAnyTyflowParticleModeEnabled(rootItem);
}
private static bool HasTyflowParticleUV2Conflict(NBShaderRootItem rootItem)
{
if (rootItem.Mats == null || rootItem.ShaderFlags == null)
{
return false;
}
int count = Mathf.Min(rootItem.Mats.Count, rootItem.ShaderFlags.Count);
for (int i = 0; i < count; i++)
{
Material mat = rootItem.Mats[i];
if (!IsTyflowParticleModeEnabled(mat) ||
!(rootItem.ShaderFlags[i] is NBShaderFlags flags))
{
continue;
}
bool flipbook = mat.IsKeywordEnabled("_FLIPBOOKBLENDING_ON");
bool specialUVUsesUV2 = flags.CheckIsUVModeOn(NBShaderFlags.UVMode.SpecialUVChannel) &&
!flags.CheckFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD2, index: 1);
if (flipbook || specialUVUsesUV2)
{
return true;
}
}
return false;
}
private static bool IsAnyHoudiniParticleModeEnabled(NBShaderRootItem rootItem)
{
if (rootItem.Mats == null)
{
return false;
}
for (int i = 0; i < rootItem.Mats.Count; i++)
{
if (IsHoudiniParticleModeEnabled(rootItem.Mats[i]))
{
return true;
}
}
return false;
}
private static bool IsAnyTyflowParticleModeEnabled(NBShaderRootItem rootItem)
{
if (rootItem.Mats == null)
{
return false;
}
for (int i = 0; i < rootItem.Mats.Count; i++)
{
if (IsTyflowParticleModeEnabled(rootItem.Mats[i]))
{
return true;
}
}
return false;
}
private static bool HasUnsupportedHoudiniParticleMode(NBShaderRootItem rootItem)
{
if (rootItem.Mats == null)
{
return false;
}
for (int i = 0; i < rootItem.Mats.Count; i++)
{
Material mat = rootItem.Mats[i];
if (IsHoudiniParticleModeEnabled(mat) &&
GetMaterialInt(mat, "_HoudiniVATSubMode", 0) == 1)
{
return true;
}
}
return false;
}
private static bool HasUnsupportedTyflowParticleMode(NBShaderRootItem rootItem)
{
if (rootItem.Mats == null)
{
return false;
}
for (int i = 0; i < rootItem.Mats.Count; i++)
{
Material mat = rootItem.Mats[i];
if (IsVatParticleMode(mat, (int)VATMode.Tyflow) &&
GetMaterialInt(mat, "_TyFlowVATSubMode", 0) >= 2)
{
return true;
}
}
return false;
}
private static bool IsHoudiniParticleModeEnabled(Material mat)
{
return IsVatParticleMode(mat, (int)VATMode.Houdini);
}
private static bool IsTyflowParticleModeEnabled(Material mat)
{
return IsVatParticleMode(mat, (int)VATMode.Tyflow) &&
(!mat.HasProperty("_TyFlowVATSubMode") || Mathf.RoundToInt(mat.GetFloat("_TyFlowVATSubMode")) <= 1);
}
private static bool IsVatParticleMode(Material mat, int vatMode)
{
if (mat == null ||
!mat.HasProperty("_VAT_Toggle") ||
!mat.HasProperty("_VATMode") ||
!mat.HasProperty("_MeshSourceMode") ||
mat.GetFloat("_VAT_Toggle") <= 0.5f ||
Mathf.RoundToInt(mat.GetFloat("_VATMode")) != vatMode)
{
return false;
}
MeshSourceMode meshSourceMode = (MeshSourceMode)Mathf.RoundToInt(mat.GetFloat("_MeshSourceMode"));
return meshSourceMode == MeshSourceMode.Particle ||
meshSourceMode == MeshSourceMode.UIParticle;
}
private static int GetMaterialInt(Material mat, string propertyName, int defaultValue)
{
return mat != null && mat.HasProperty(propertyName)
? Mathf.RoundToInt(mat.GetFloat(propertyName))
: defaultValue;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 744c08c430cd42fda37db42e777c3c84
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,62 @@
using System;
using NBShader;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
internal sealed class VertexOffsetFeatureItem : FeatureToggleFoldOutItem
{
public VertexOffsetFeatureItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(rootItem, parentItem, "_VertexOffsetBlockFoldOut", "_VertexOffset_Toggle", "顶点偏移", keyword: "_VERTEX_OFFSET")
{
new NBShaderKeywordToggleItem(
rootItem,
this,
"_NB_Debug_VertexOffset",
"NB_DEBUG_VERTEX_OFFSET",
() => Content("顶点偏移方向测试"),
isVisible: null);
AddTextureWithWrap(rootItem, this, "_VertexOffset_Map", "顶点偏移贴图", NBShaderFlags.FLAG_BIT_WRAPMODE_VERTEXOFFSETMAP);
new UVModeSelectItem(rootItem, this, "_VertexOffsetUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MAP, 0, () => Content("顶点偏移贴图UV来源"), "_VertexOffset_Map");
new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_X, 1, () => Content("顶点扰动X轴偏移自定义曲线"));
new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_VERTEX_OFFSET_Y, 1, () => Content("顶点扰动Y轴偏移自定义曲线"));
new Vector2LineItem(rootItem, this, "_VertexOffset_Vec", true, () => Content("顶点偏移动画"));
new VectorComponentItem(rootItem, this, "_VertexOffset_Vec", 2, () => Content("顶点偏移强度"), false);
new CustomDataSelectItem(rootItem, this, NBShaderFlags.FLAGBIT_POS_1_CUSTOMDATA_VERTEXOFFSET_INTENSITY, 1, () => Content("顶点扰动强度自定义曲线"));
new ToggleItem(
rootItem,
this,
"_VertexOffset_StartFromZero",
() => Content("顶点偏移从零开始"),
enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_1_VERTEXOFFSET_START_FROM_ZERO, enabled, 1));
new ToggleItem(
rootItem,
this,
"_VertexOffset_NormalDir_Toggle",
() => Content("顶点偏移使用法线方向"),
enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_VERTEX_OFFSET_NORMAL_DIR, enabled));
Func<bool> showCustomDirection = () => IsPropertyOff(rootItem, "_VertexOffset_NormalDir_Toggle");
new VectorComponentItem(rootItem, this, "_VertexOffset_CustomDir", 0, () => Content("顶点偏移本地方向X"), false, isVisible: showCustomDirection);
new VectorComponentItem(rootItem, this, "_VertexOffset_CustomDir", 1, () => Content("顶点偏移本地方向Y"), false, isVisible: showCustomDirection);
new VectorComponentItem(rootItem, this, "_VertexOffset_CustomDir", 2, () => Content("顶点偏移本地方向Z"), false, isVisible: showCustomDirection);
PropertyToggleBlockItem maskBlock = ToggleBlock(rootItem, "_VertexOffsetMaskBlockFoldOut", "_VertexOffset_Mask_Toggle", "顶点偏移遮罩",
parent: this, keyword: "_VERTEX_OFFSET_MASKMAP");
AddTextureWithWrap(rootItem, maskBlock, "_VertexOffset_MaskMap", "顶点偏移遮罩图", NBShaderFlags.FLAG_BIT_WRAPMODE_VERTEXOFFSET_MASKMAP);
new UVModeSelectItem(rootItem, maskBlock, "_VertexOffsetMaskUVModeFoldOut", NBShaderFlags.FLAG_BIT_UVMODE_POS_0_VERTEX_OFFSET_MASKMAP, 0, () => Content("顶点偏移遮罩图UV来源"), "_VertexOffset_MaskMap");
new CustomDataSelectItem(rootItem, maskBlock, NBShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_X, 3, () => Content("顶点扰动遮罩X轴偏移自定义曲线"));
new CustomDataSelectItem(rootItem, maskBlock, NBShaderFlags.FLAGBIT_POS_3_CUSTOMDATA_VERTEX_OFFSET_MASK_Y, 3, () => Content("顶点扰动遮罩Y轴偏移自定义曲线"));
new Vector2LineItem(rootItem, maskBlock, "_VertexOffset_MaskMap_Vec", true, () => Content("顶点偏移遮罩动画"));
new VectorComponentItem(rootItem, maskBlock, "_VertexOffset_MaskMap_Vec", 2, () => Content("顶点偏移遮罩强度"), true);
InitTriggerByChild();
}
private static bool IsPropertyOff(NBShaderRootItem rootItem, string propertyName)
{
return rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info) &&
!info.Property.hasMixedValue &&
info.Property.floatValue <= 0.5f;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5507463f5ee64c358b78250126100a8d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,358 @@
using NBShader;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
public enum FxLightMode
{
UnLit = 0,
BlinnPhong = 1,
HalfLambert = 2,
PBR = 3,
SixWay = 4,
UnKnownOrMixedValue = -1
}
public class LightBigBlockItem : BigBlockItem
{
private readonly NBShaderRootItem _nbRootItem;
private readonly FxLightModePopupItem _lightModeItem;
private readonly ToggleItem _specularToggleItem;
private readonly ColorItem _specularColorItem;
private readonly VectorComponentItem _specularSmoothnessItem;
private readonly VectorComponentItem _pbrMetallicItem;
private readonly VectorComponentItem _pbrSmoothnessItem;
private readonly PropertyToggleBlockItem _bumpBlock;
private readonly PropertyToggleBlockItem _matCapBlock;
private readonly TextureItem _sixWayPositiveItem;
private readonly TextureItem _sixWayNegativeItem;
private readonly ToggleItem _sixWayAbsorptionToggleItem;
private readonly VectorComponentItem _sixWayAbsorptionStrengthItem;
private readonly TextureItem _sixWayEmissionRampItem;
private readonly VectorComponentItem _sixWayEmissionPowItem;
private readonly ColorItem _sixWayEmissionColorItem;
public LightBigBlockItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(
rootItem,
parentItem,
"_LightBigBlockItemFoldOut",
() => Content("block.light", "Light", "Normal, MatCap and light mode controls"))
{
_nbRootItem = rootItem;
_lightModeItem = new FxLightModePopupItem(rootItem, this);
_specularToggleItem = new NBShaderKeywordToggleItem(
rootItem,
this,
"_BlinnPhongSpecularToggle",
"_SPECULAR_COLOR",
() => Content("light.specular.toggle", "Specular"),
isVisible: () => IsBlinnOrHalf(rootItem));
_specularColorItem = new ColorItem(
rootItem,
this,
"_SpecularColor",
() => Content("light.specular.color", "Specular Color"),
() => IsToggleOn(rootItem, "_BlinnPhongSpecularToggle") && IsBlinnOrHalf(rootItem));
_specularSmoothnessItem = new VectorComponentItem(
rootItem,
this,
"_MaterialInfo",
1,
() => Content("light.specular.smoothness", "Smoothness"),
true,
0f,
1f,
() => IsToggleOn(rootItem, "_BlinnPhongSpecularToggle") && IsBlinnOrHalf(rootItem));
_pbrMetallicItem = new VectorComponentItem(
rootItem,
this,
"_MaterialInfo",
0,
() => Content("light.pbr.metallic", "Metallic"),
true,
0f,
1f,
() => rootItem.Context.FxLightMode == FxLightMode.PBR);
_pbrSmoothnessItem = new VectorComponentItem(
rootItem,
this,
"_MaterialInfo",
1,
() => Content("light.pbr.smoothness", "Smoothness"),
true,
0f,
1f,
() => rootItem.Context.FxLightMode == FxLightMode.PBR);
_bumpBlock = new PropertyToggleBlockItem(
rootItem,
this,
"_BumpToggleFoldOut",
"_BumpMapToggle",
() => Content("light.bump.toggle", "Normal Map"),
keyword: "_NORMALMAP",
isVisible: () => rootItem.Context.FxLightMode != FxLightMode.SixWay);
new TextureItem(
rootItem,
_bumpBlock,
"_BumpTex",
() => Content("light.bump.texture", "Normal Map"),
drawScaleOffset: true);
TextureRelatedFoldOutItem bumpTexRelatedFoldOut = new TextureRelatedFoldOutItem(
rootItem,
_bumpBlock,
"_BumpTexFoldOut",
"_BumpTex",
() => Content("light.bump.related", "Normal Map Related"));
new WrapModeItem(rootItem, bumpTexRelatedFoldOut, NBShaderFlags.FLAG_BIT_WRAPMODE_BUMPTEX, () => Content("light.bump.wrap", "Normal Map Wrap"));
new UVModeSelectItem(
rootItem,
bumpTexRelatedFoldOut,
"_BumpUVModeFoldOut",
NBShaderFlags.FLAG_BIT_UVMODE_POS_0_BUMPMAP,
0,
() => Content("light.bump.uvmode", "Normal Map UV Source"),
"_BumpTex");
new ToggleItem(
rootItem,
bumpTexRelatedFoldOut,
"_BumpMapMaskMode",
() => Content("light.bump.maskMode", "Normal Map Multi Channel"),
enabled => rootItem.SyncService.ApplyToggleFlag(NBShaderFlags.FLAG_BIT_PARTICLE_NORMALMAP_MASK_MODE, enabled));
ShaderGUISliderItem bumpScaleItem = new ShaderGUISliderItem(rootItem, bumpTexRelatedFoldOut)
{
PropertyName = "_BumpScale",
GuiContent = Content("light.bump.scale", "Normal Strength"),
RangePropertyName = "BumpScaleRangeVec"
};
bumpScaleItem.InitTriggerByChild();
_matCapBlock = new PropertyToggleBlockItem(
rootItem,
this,
"_MatCapFoldOut",
"_MatCapToggle",
() => Content("light.matcap.toggle", "MatCap"),
keyword: "_MATCAP",
isVisible: () => rootItem.Context.FxLightMode != FxLightMode.SixWay);
new TextureItem(rootItem, _matCapBlock, "_MatCapTex", () => Content("light.matcap.texture", "MatCap Texture"), "_MatCapColor", false);
new VectorComponentItem(rootItem, _matCapBlock, "_MatCapInfo", 0, () => Content("light.matcap.blend", "Add/Multiply Blend"), true, 0f, 1f);
_sixWayPositiveItem = new TextureItem(
rootItem,
this,
"_RigRTBk",
() => Content("light.sixway.positive", "SixWay Positive"),
drawScaleOffset: false,
isVisible: IsSixWay);
_sixWayNegativeItem = new TextureItem(
rootItem,
this,
"_RigLBtF",
() => Content("light.sixway.negative", "SixWay Negative"),
drawScaleOffset: false,
isVisible: IsSixWay);
_sixWayAbsorptionToggleItem = new NBShaderKeywordToggleItem(
rootItem,
this,
"_SixWayColorAbsorptionToggle",
"VFX_SIX_WAY_ABSORPTION",
() => Content("light.sixway.absorption.toggle", "Light Color Absorption"),
isVisible: IsSixWay);
_sixWayAbsorptionStrengthItem = new VectorComponentItem(
rootItem,
this,
"_SixWayInfo",
0,
() => Content("light.sixway.absorption.strength", "Absorption Strength"),
true,
0f,
1f,
() => IsSixWay() && IsToggleOn(rootItem, "_SixWayColorAbsorptionToggle"));
_sixWayEmissionRampItem = new TextureItem(
rootItem,
this,
"_SixWayEmissionRamp",
() => Content("light.sixway.ramp", "SixWay Emission Ramp"),
drawScaleOffset: false,
afterDraw: SyncSixWayRampFlag,
isVisible: IsSixWay);
_sixWayEmissionPowItem = new VectorComponentItem(
rootItem,
this,
"_SixWayInfo",
1,
() => Content("light.sixway.emissionPow", "SixWay Emission Pow"),
false,
isVisible: IsSixWay);
_sixWayEmissionColorItem = new ColorItem(
rootItem,
this,
"_SixWayEmissionColor",
() => Content("light.sixway.color", "SixWay Emission Color"),
IsSixWay);
InitTriggerByChild();
}
public override void DrawBlock()
{
if (IsAnyLightModeAllowed())
{
_lightModeItem.OnGUI();
}
if (IsTierAllowed("_SPECULAR_COLOR"))
{
_specularToggleItem.OnGUI();
_specularColorItem.OnGUI();
_specularSmoothnessItem.OnGUI();
}
if (IsTierAllowed("_FX_LIGHT_MODE_PBR"))
{
_pbrMetallicItem.OnGUI();
_pbrSmoothnessItem.OnGUI();
}
if (IsTierAllowed("_NORMALMAP"))
{
_bumpBlock.OnGUI();
}
if (IsTierAllowed("_MATCAP"))
{
_matCapBlock.OnGUI();
}
if (IsTierAllowed("_FX_LIGHT_MODE_SIX_WAY"))
{
_sixWayPositiveItem.OnGUI();
_sixWayNegativeItem.OnGUI();
DrawSixWayWarning();
_sixWayEmissionRampItem.OnGUI();
_sixWayEmissionPowItem.OnGUI();
_sixWayEmissionColorItem.OnGUI();
}
if (IsTierAllowed("VFX_SIX_WAY_ABSORPTION"))
{
_sixWayAbsorptionToggleItem.OnGUI();
_sixWayAbsorptionStrengthItem.OnGUI();
}
}
private bool IsTierAllowed(string keyword)
{
return _nbRootItem.Context == null || _nbRootItem.Context.IsKeywordAllowed(keyword);
}
private bool IsAnyLightModeAllowed()
{
return _nbRootItem.Context == null ||
_nbRootItem.Context.IsAnyKeywordAllowed(
"_FX_LIGHT_MODE_UNLIT",
"_FX_LIGHT_MODE_BLINN_PHONG",
"_FX_LIGHT_MODE_HALF_LAMBERT",
"_FX_LIGHT_MODE_PBR",
"_FX_LIGHT_MODE_SIX_WAY");
}
private bool IsSixWay()
{
return _nbRootItem.Context.FxLightMode == FxLightMode.SixWay;
}
private void DrawSixWayWarning()
{
if (!IsSixWay())
{
return;
}
DrawLayoutHelpBox(
NBShaderInspectorLocalization.GetInspectorText(
"light.sixway.uvWarning.message",
"六路UV跟随主贴图UV及颜色"),
MessageType.Warning);
}
private void SyncSixWayRampFlag(MaterialProperty rampProperty)
{
if (rampProperty.hasMixedValue)
{
return;
}
_nbRootItem.SyncService.ApplyToggleFlag(
NBShaderFlags.FLAG_BIT_PARTICLE_1_SIXWAY_RAMPMAP,
rampProperty.textureValue != null,
1);
}
private static bool IsToggleOn(NBShaderRootItem rootItem, string propertyName)
{
return rootItem.Context.IsToggleOn(propertyName);
}
private static bool IsBlinnOrHalf(NBShaderRootItem rootItem)
{
return rootItem.Context.FxLightMode == FxLightMode.BlinnPhong ||
rootItem.Context.FxLightMode == FxLightMode.HalfLambert;
}
private static GUIContent Content(string key, string fallback, string tip = "")
{
return NBShaderInspectorLocalization.MakeInspectorContent(key, fallback, tip);
}
}
public class FxLightModePopupItem : ShaderGUIPopUpItem
{
private static readonly string[] LightModeOptions =
{
"Unlit",
"BlinnPhong",
"HalfLambert",
"PBR",
"SixWay"
};
private readonly NBShaderRootItem _nbRootItem;
public FxLightModePopupItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) : base(rootItem, parentItem)
{
_nbRootItem = rootItem;
PropertyName = "_FxLightMode";
GuiContent = NBShaderInspectorLocalization.MakeContent("inspector.light.mode.label", "Light Mode");
PopUpNames = NBShaderInspectorLocalization.GetInspectorOptions("light.mode", LightModeOptions);
InitTriggerByChild();
}
public override void OnGUI()
{
base.OnGUI();
}
public override void OnEndChange()
{
base.OnEndChange();
_nbRootItem.SyncService.ApplyLightMode((FxLightMode)PropertyInfo.Property.floatValue);
_nbRootItem.Context.Refresh();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3e6914407bf83004f8b2c13ccf777981
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,260 @@
using UnityEditor;
using UnityEngine;
using NBShader;
namespace NBShaderEditor
{
public class MainTexBigBlockItem : BigBlockItem
{
private readonly NBShaderRootItem _nbRootItem;
private readonly TexturePropertyGroupItem _baseMapGroupItem;
private readonly TextureRelatedFoldOutItem _baseMapRelatedFoldOutItem;
private readonly ColorLineItem _uiColorItem;
private readonly TextureScaleOffsetItem _uiMainTexScaleOffsetItem;
private readonly ColorChannelSelectItem _alphaChannelItem;
private readonly WrapModeItem _baseMapWrapModeItem;
private readonly UVModeSelectItem _uvModeItem;
private readonly CustomDataSelectItem _offsetXCustomDataItem;
private readonly CustomDataSelectItem _offsetYCustomDataItem;
private readonly Vector2LineItem _baseMapOffsetSpeedItem;
private readonly ShaderGUISliderItem _baseMapRotationItem;
private readonly ShaderGUIFloatItem _baseMapRotationSpeedItem;
private readonly ShaderGUISliderItem _texDistortionIntensityItem;
private readonly PNoiseBlendModeItem _pNoiseBlendModeItem;
private readonly HelpBoxItem _graphicMainTexHelpBox;
public MainTexBigBlockItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(
rootItem,
parentItem,
"_MainTexBigBlockItemFoldOut",
() => NBShaderInspectorLocalization.MakeContent(
"inspector.block.maintex.label",
"Main Texture",
"inspector.block.maintex.tip",
"Main texture and base color controls"))
{
_nbRootItem = rootItem;
_baseMapGroupItem = new TexturePropertyGroupItem(
rootItem,
this,
"_BaseMap",
"_BaseColor",
() => NBShaderInspectorLocalization.MakeContent(
"inspector.maintex.basemap.label",
"Main Texture"),
isVisible: () => rootItem.Context.UseGraphicMainTex == MixedBool.False,
tillingContentProvider: TillingContent,
offsetContentProvider: OffsetContent);
_baseMapRelatedFoldOutItem = new TextureRelatedFoldOutItem(
rootItem,
this,
"_BaseMapFoldOut",
"_BaseMap",
() => NBShaderInspectorLocalization.MakeContent(
"inspector.maintex.basemap.related.label",
"Main Texture Related"),
() => rootItem.Context.UseGraphicMainTex == MixedBool.False);
_graphicMainTexHelpBox = new HelpBoxItem(
rootItem,
this,
() => NBShaderInspectorLocalization.Get(
"inspector.maintex.graphic.message",
"Current mode uses Graphic texture. Only color and ST remain editable."),
MessageType.Info);
_uiColorItem = new ColorLineItem(
rootItem,
this,
"_Color",
showLabel: false,
contentProvider: () => NBShaderInspectorLocalization.MakeContent(
"inspector.maintex.uicolor.label",
"Graphic Color"),
isVisible: () => rootItem.Context.UseGraphicMainTex == MixedBool.True);
_uiMainTexScaleOffsetItem = new TextureScaleOffsetItem(
rootItem,
this,
"_UI_MainTex_ST",
isVectorProperty: true,
isVisible: () => rootItem.Context.UseGraphicMainTex == MixedBool.True,
tillingContentProvider: TillingContent,
offsetContentProvider: OffsetContent);
_alphaChannelItem = new ColorChannelSelectItem(
rootItem,
_baseMapRelatedFoldOutItem,
NBShaderFlags.FLAG_BIT_COLOR_CHANNEL_POS_0_MAINTEX_ALPHA,
3,
() => NBShaderInspectorLocalization.MakeContent(
"inspector.maintex.alphaChannel.label",
"Alpha Channel"));
_baseMapWrapModeItem = new WrapModeItem(
rootItem,
_baseMapRelatedFoldOutItem,
NBShaderFlags.FLAG_BIT_WRAPMODE_BASEMAP,
() => NBShaderInspectorLocalization.MakeContent(
"inspector.maintex.wrap.label",
"Main Texture Wrap"),
2,
() => rootItem.Context.UseGraphicMainTex == MixedBool.False);
_uvModeItem = new UVModeSelectItem(
rootItem,
_baseMapRelatedFoldOutItem,
"_MainTexUVModeFoldOut",
NBShaderFlags.FLAG_BIT_UVMODE_POS_0_MAINTEX,
0,
() => NBShaderInspectorLocalization.MakeContent(
"inspector.maintex.uvmode.label",
"Main Texture UV Source"),
forceEnable: true,
isVisible: () => rootItem.Context.MeshSourceMode != MeshSourceMode.UIEffectSprite);
_offsetXCustomDataItem = new CustomDataSelectItem(
rootItem,
_baseMapRelatedFoldOutItem,
NBShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_X,
0,
() => NBShaderInspectorLocalization.MakeContent(
"inspector.maintex.customdata.offsetx.label",
"Main Texture Offset X Custom Data"),
() => rootItem.Context.ParticleMode == MixedBool.True);
_offsetYCustomDataItem = new CustomDataSelectItem(
rootItem,
_baseMapRelatedFoldOutItem,
NBShaderFlags.FLAGBIT_POS_0_CUSTOMDATA_MAINTEX_OFFSET_Y,
0,
() => NBShaderInspectorLocalization.MakeContent(
"inspector.maintex.customdata.offsety.label",
"Main Texture Offset Y Custom Data"),
() => rootItem.Context.ParticleMode == MixedBool.True);
_baseMapOffsetSpeedItem = new Vector2LineItem(
rootItem,
_baseMapRelatedFoldOutItem,
"_BaseMapMaskMapOffset",
true,
() => NBShaderInspectorLocalization.MakeContent(
"inspector.maintex.offsetspeed.label",
"Offset Speed"),
isVisible: () => rootItem.Context.UseGraphicMainTex == MixedBool.False);
_baseMapRotationItem = new ShaderGUISliderItem(rootItem, _baseMapRelatedFoldOutItem)
{
PropertyName = "_BaseMapUVRotation",
GuiContent = NBShaderInspectorLocalization.MakeContent(
"inspector.maintex.rotation.label",
"Rotation"),
Min = 0f,
Max = 360f
};
_baseMapRotationItem.InitTriggerByChild();
_baseMapRotationSpeedItem = new ShaderGUIFloatItem(rootItem, _baseMapRelatedFoldOutItem)
{
PropertyName = "_BaseMapUVRotationSpeed",
GuiContent = NBShaderInspectorLocalization.MakeContent(
"inspector.maintex.rotationspeed.label",
"Rotation Speed")
};
_baseMapRotationSpeedItem.InitTriggerByChild();
_texDistortionIntensityItem = new ShaderGUISliderItem(rootItem, _baseMapRelatedFoldOutItem)
{
PropertyName = "_TexDistortion_intensity",
GuiContent = NBShaderInspectorLocalization.MakeContent(
"inspector.maintex.distortionIntensity.label",
"Main Texture Distortion"),
RangePropertyName = "TexDistortionintensityRangeVec"
};
_texDistortionIntensityItem.InitTriggerByChild();
_pNoiseBlendModeItem = new PNoiseBlendModeItem(
rootItem,
_baseMapRelatedFoldOutItem,
NBShaderFlags.FLAG_BIT_PNOISE_BLEND_POS_0_MAINTEX,
"_MainTexPNoiseBlendOpacity",
() => NBShaderInspectorLocalization.MakeContent(
"inspector.maintex.pnoiseBlend.label",
"Main Texture Program Noise Blend"),
() => rootItem.Context.ProgramNoiseEnabled == MixedBool.True);
InitTriggerByChild();
}
public override void DrawBlock()
{
if (_nbRootItem.Context.UseGraphicMainTex == MixedBool.Mixed)
{
DrawLayoutHelpBox(
NBShaderInspectorLocalization.GetInspectorText(
"maintex.mixedMeshSource.message",
"Mixed mesh-source modes will show the matching texture controls per material state."),
MessageType.Info);
}
_baseMapGroupItem.OnGUI();
if (_nbRootItem.Context.UseGraphicMainTex == MixedBool.True)
{
_graphicMainTexHelpBox.OnGUI();
}
_uiColorItem.OnGUI();
_uiMainTexScaleOffsetItem.OnGUI();
if (_nbRootItem.Context.UseGraphicMainTex == MixedBool.False)
{
_baseMapRelatedFoldOutItem.OnGUI();
}
else
{
DrawMainTexRelatedItems();
}
}
private void DrawMainTexRelatedItems()
{
_alphaChannelItem.OnGUI();
_baseMapWrapModeItem.OnGUI();
_uvModeItem.OnGUI();
_offsetXCustomDataItem.OnGUI();
_offsetYCustomDataItem.OnGUI();
_baseMapOffsetSpeedItem.OnGUI();
if (_nbRootItem.Context.UseGraphicMainTex == MixedBool.False)
{
_baseMapRotationItem.OnGUI();
_baseMapRotationSpeedItem.OnGUI();
}
if (_nbRootItem.Context.UseGraphicMainTex == MixedBool.False)
{
bool previousMixedValue = EditorGUI.showMixedValue;
EditorGUI.showMixedValue = _nbRootItem.Context.NoiseEnabled == MixedBool.Mixed;
using (new InheritedControlDisabledScope(_nbRootItem.Context.NoiseEnabled == MixedBool.False))
{
_texDistortionIntensityItem.OnGUI();
}
EditorGUI.showMixedValue = previousMixedValue;
}
_pNoiseBlendModeItem.OnGUI();
}
private static GUIContent TillingContent()
{
return NBShaderInspectorLocalization.MakeInspectorContent("common.tilling", "Tilling");
}
private static GUIContent OffsetContent()
{
return NBShaderInspectorLocalization.MakeInspectorContent("common.offset", "Offset");
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7ebc7f22502386443b06ac9aebc4222b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,377 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
public class ModeBigBlockItem : BigBlockItem
{
private readonly NBShaderRootItem _nbRootItem;
public ModeBigBlockItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(
rootItem,
parentItem,
"_BigBlockModeSettingFoldOut",
() => NBShaderInspectorLocalization.MakeContent(
"inspector.block.mode.label",
"模式设置",
"inspector.block.mode.tip",
"各种基础模式设置"))
{
_nbRootItem = rootItem;
_meshModePopUp = new MeshModePopUp(rootItem, this);
_transparentMode = new TransparentModePopUp(rootItem, this);
base.InitTriggerByChild();
}
private MeshModePopUp _meshModePopUp;
private TransparentModePopUp _transparentMode;
public override void DrawBlock()
{
_meshModePopUp.OnGUI();
_transparentMode.OnGUI();
}
}
public enum MeshSourceMode
{
Particle,
Mesh,
UIEffectRawImage,
UIEffectSprite,
UIEffectBaseMap,
UIParticle,
UnKnowOrMixed = -1
}
public class MeshModePopUp : ShaderGUIPopUpItem,IDisposable
{
public MeshSourceMode MeshSourceMode;
public static Dictionary<ShaderGUIRootItem,MeshModePopUp> MeshSourceModeDic = new Dictionary<ShaderGUIRootItem,MeshModePopUp>();
public MeshModePopUp(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) :
base(rootItem, parentItem: parentItem)
{
PopUpNames = NBShaderInspectorLocalization.GetInspectorOptions("mode.meshSource", MeshSourceOptions);
PropertyName = "_MeshSourceMode";
GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("mode.meshSource", "Mesh Source Mode", "Matches the current object type.");
MeshSourceModeDic[rootItem] = this;
InitTriggerByChild();
}
public MixedBool UIEffectEnabled()
{
if ((int)MeshSourceMode >= 2)
{
return MixedBool.True;
}
else if (MeshSourceMode == MeshSourceMode.UnKnowOrMixed)
{
return MixedBool.Mixed;
}
else
{
return MixedBool.False;
}
}
public override void OnGUI()
{
base.OnGUI();
if (PropertyInfo.Property.hasMixedValue)
{
MeshSourceMode = MeshSourceMode.UnKnowOrMixed;
}
else
{
MeshSourceMode = (MeshSourceMode)PropertyInfo.Property.floatValue;
}
DrawParticleSystemMismatchWarning();
}
public override void OnEndChange()
{
base.OnEndChange();
if (RootItem is NBShaderRootItem nbRootItem)
{
nbRootItem.Context.Refresh();
}
}
public void Dispose()
{
MeshSourceModeDic.Remove(RootItem);
}
private void DrawParticleSystemMismatchWarning()
{
if (!(RootItem is NBShaderRootItem nbRootItem) ||
nbRootItem.Mats == null ||
nbRootItem.Mats.Count == 0 ||
nbRootItem.Context.ParticleMode == MixedBool.True ||
!nbRootItem.IsUsedByParticleSystem)
{
return;
}
DrawLayoutHelpBox(
NBShaderInspectorLocalization.GetInspectorText(
"mode.meshSource.particleModeMismatch",
"检测到材质用在粒子系统上,和设置不匹配"),
MessageType.Error);
}
private static readonly string[] MeshSourceOptions =
{
"粒子系统",
"模型(非粒子发射)",
"2D RawImage",
"2D 精灵",
"2D 材质贴图",
"2D UIParticle"
};
}
public enum TransparentMode
{
Opaque = 0,
Transparent = 1,
CutOff = 2,
UnKnowOrMixed = -1
}
public class TransparentModePopUp : ShaderGUIPopUpItem,IDisposable
{
public TransparentMode TransparentMode;
public static Dictionary<ShaderGUIRootItem,TransparentModePopUp> TransparentModeDic =
new Dictionary<ShaderGUIRootItem, TransparentModePopUp>();
public TransparentModePopUp(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) :
base(rootItem, parentItem: parentItem)
{
PopUpNames = NBShaderInspectorLocalization.GetInspectorOptions("mode.transparent", TransparentOptions);
PropertyName = "_TransparentMode";
GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("mode.transparent", "Transparent Mode", "Controls opaque, transparent, and cutoff rendering.");
TransparentModeDic[RootItem] = this;
_cutOffSlider = new ShaderGUISliderItem(RootItem, this)
{
PropertyName = "_Cutoff",
GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("mode.cutoff", "Cutoff", "0 keeps everything, 1 clips everything.")
};
_cutOffSlider.InitTriggerByChild();
_blendPopUp = new BlendPopUp(RootItem, this);
PropertyInfo = RootItem.PropertyInfoDic[PropertyName];
TransparentMode = (TransparentMode)PropertyInfo.Property.floatValue;
InitTriggerByChild();
}
public override void OnGUI()
{
base.OnGUI();
if (PropertyInfo.Property.hasMixedValue)
{
TransparentMode = TransparentMode.UnKnowOrMixed;
}
else
{
TransparentMode = (TransparentMode)PropertyInfo.Property.floatValue;
}
}
private ShaderGUISliderItem _cutOffSlider;
private BlendPopUp _blendPopUp;
public override void DrawBlock()
{
if (TransparentMode== TransparentMode.CutOff)
{
_cutOffSlider.OnGUI();
}
if (TransparentMode == TransparentMode.Transparent)
{
_blendPopUp.OnGUI();
}
}
public override void OnEndChange()
{
TransparentMode = (TransparentMode)PropertyInfo.Property.floatValue;
switch (TransparentMode)
{
case TransparentMode.Opaque:
if (RootItem is NBShaderRootItem opaqueRootItem)
{
opaqueRootItem.SyncService.ApplyTransparentMode(TransparentMode);
}
_blendPopUp.PropertyInfo.Property.floatValue = (float)BlendMode.Opaque;
_blendPopUp.OnEndChange();
break;
case TransparentMode.Transparent:
if (RootItem is NBShaderRootItem transparentRootItem)
{
transparentRootItem.SyncService.ApplyTransparentMode(TransparentMode);
}
if (_blendPopUp.BlendMode == BlendMode.Opaque)
{
_blendPopUp.PropertyInfo.Property.floatValue = (float)BlendMode.Alpha;//如果设置错误则强制设置。
_blendPopUp.OnEndChange();
}
break;
case TransparentMode.CutOff:
if (RootItem is NBShaderRootItem cutOffRootItem)
{
cutOffRootItem.SyncService.ApplyTransparentMode(TransparentMode);
}
_blendPopUp.PropertyInfo.Property.floatValue = (float)BlendMode.Opaque;
_blendPopUp.OnEndChange();
break;
}
base.OnEndChange();
}
public void Dispose()
{
TransparentModeDic.Remove(RootItem);//回收时清掉相关引用。?会不会有时序问题
}
private static readonly string[] TransparentOptions =
{
"不透明Opaque",
"半透明Transparent",
"不透明裁剪CutOff"
};
}
public enum BlendMode
{
Alpha, // Old school alpha-blending mode, fresnel does not affect amount of transparency
Premultiply, // Physically plausible transparency mode, implemented as alpha pre-multiply
Additive,
Multiply,
Opaque,
UnKnowOrMixed = -1
}
public class BlendPopUp : ShaderGUIPopUpItem,IDisposable
{
public BlendMode BlendMode;
public static Dictionary<ShaderGUIRootItem,BlendPopUp> BlendModeDic = new Dictionary<ShaderGUIRootItem,BlendPopUp>();
public BlendPopUp(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) : base(rootItem, parentItem)
{
PropertyName = "_Blend";
PopUpNames = NBShaderInspectorLocalization.GetInspectorOptions("mode.blend", BlendOptions);
GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("mode.blend", "Blend Mode");
BlendModeDic[rootItem] = this;
_addToPreMultiplySlider = new AddToPreMultiplySlider(rootItem, this);
InitTriggerByChild();
}
public override void OnGUI()
{
base.OnGUI();
if (PropertyInfo.Property.hasMixedValue)
{
BlendMode = BlendMode.UnKnowOrMixed;
}
else
{
BlendMode = (BlendMode)PropertyInfo.Property.floatValue;
}
}
private AddToPreMultiplySlider _addToPreMultiplySlider;
public override void DrawBlock()
{
if (BlendMode == BlendMode.Additive || BlendMode == BlendMode.Premultiply)
{
_addToPreMultiplySlider.OnGUI();
}
}
public override void OnEndChange()
{
BlendMode = (BlendMode)PropertyInfo.Property.floatValue;
if (BlendMode == BlendMode.Additive)
{
_addToPreMultiplySlider.PropertyInfo.Property.floatValue = 0;
_addToPreMultiplySlider.OnEndChange();
}
if (BlendMode == BlendMode.Premultiply)
{
_addToPreMultiplySlider.PropertyInfo.Property.floatValue = 1;
_addToPreMultiplySlider.OnEndChange();
}
if (RootItem is NBShaderRootItem nbRootItem)
{
nbRootItem.SyncService.ApplyBlendMode(BlendMode);
}
base.OnEndChange();
}
public void Dispose()
{
BlendModeDic.Remove(RootItem);
}
private static readonly string[] BlendOptions =
{
"透明度混合AlphaBlend",
"预乘PreMultiply",
"叠加Additive",
"正片叠底Multiply"
};
}
public class AddToPreMultiplySlider : ShaderGUISliderItem
{
public AddToPreMultiplySlider(ShaderGUIRootItem rootItem, ShaderGUIItem parentItem) : base(rootItem, parentItem)
{
PropertyName = "_AdditiveToPreMultiplyAlphaLerp";
GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("mode.additiveToPremultiply", "Additive To Premultiply", "0 is additive, 1 is premultiply.");
base.InitTriggerByChild();
}
public override void OnGUI()
{
base.OnGUI();
}
public override void CheckIsPropertyModified(bool isCallByChild = false)
{
float defaultValue = 0;
BlendPopUp blendPopUp = BlendPopUp.BlendModeDic[RootItem];
if (blendPopUp.BlendMode == BlendMode.Premultiply)
{
defaultValue = 1;
}
HasModified = !Mathf.Approximately(defaultValue,PropertyInfo.Property.floatValue);
ParentItem?.CheckIsPropertyModified(true);
}
public override void ExecuteReset(bool isCallByParent = false)
{
float defaultValue = 0;
BlendPopUp blendPopUp = BlendPopUp.BlendModeDic[RootItem];
if (blendPopUp.BlendMode == BlendMode.Premultiply)
{
defaultValue = 1;
}
PropertyInfo.Property.floatValue = defaultValue;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ed09665b113c407dbfb8c818b74f48aa
timeCreated: 1758445745

View File

@@ -0,0 +1,220 @@
using System;
using System.Collections.Generic;
using NBShader;
using NBShaders2.Editor.FeatureLevel;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
public class NBShaderGUIContext
{
private const string FeatureTierPropertyName = "_NBShaderFeatureTier";
private readonly NBShaderRootItem _rootItem;
private HashSet<string> _currentTierAllowedKeywords;
public NBShaderGUIContext(NBShaderRootItem rootItem)
{
_rootItem = rootItem;
}
public MeshSourceMode MeshSourceMode { get; private set; } = MeshSourceMode.UnKnowOrMixed;
public TransparentMode TransparentMode { get; private set; } = TransparentMode.UnKnowOrMixed;
public MixedBool UIEffectEnabled { get; private set; } = MixedBool.Mixed;
public MixedBool UseGraphicMainTex { get; private set; } = MixedBool.Mixed;
public MixedBool ParticleMode { get; private set; } = MixedBool.Mixed;
public MixedBool NoiseEnabled { get; private set; } = MixedBool.Mixed;
public MixedBool ProgramNoiseEnabled { get; private set; } = MixedBool.Mixed;
public MixedBool VatEnabled { get; private set; } = MixedBool.Mixed;
public MixedBool FlipbookEnabled { get; private set; } = MixedBool.Mixed;
public FxLightMode FxLightMode { get; private set; } = FxLightMode.UnKnownOrMixedValue;
public NBShaderFeatureTier CurrentTier { get; private set; } = NBShaderFeatureTier.Ultra;
public bool CurrentTierMixed { get; private set; }
public bool IsKeywordAllowed(string keyword)
{
if (!NBShaderFeatureCatalog.IsManagedKeyword(keyword))
{
return true;
}
if (CurrentTierMixed)
{
return true;
}
return _currentTierAllowedKeywords != null && _currentTierAllowedKeywords.Contains(keyword);
}
public bool AreKeywordsAllowed(params string[] keywords)
{
if (keywords == null)
{
return true;
}
for (int i = 0; i < keywords.Length; i++)
{
if (!IsKeywordAllowed(keywords[i]))
{
return false;
}
}
return true;
}
public bool IsAnyKeywordAllowed(params string[] keywords)
{
if (keywords == null || keywords.Length == 0)
{
return true;
}
for (int i = 0; i < keywords.Length; i++)
{
if (IsKeywordAllowed(keywords[i]))
{
return true;
}
}
return false;
}
public bool IsAnyKeywordAllowed(string keyword0, string keyword1)
{
return IsKeywordAllowed(keyword0) || IsKeywordAllowed(keyword1);
}
public bool IsAnyKeywordAllowed(
string keyword0,
string keyword1,
string keyword2,
string keyword3,
string keyword4)
{
return IsKeywordAllowed(keyword0) ||
IsKeywordAllowed(keyword1) ||
IsKeywordAllowed(keyword2) ||
IsKeywordAllowed(keyword3) ||
IsKeywordAllowed(keyword4);
}
public static bool IsCatalogKeyword(string keyword)
{
return NBShaderFeatureCatalog.IsManagedKeyword(keyword);
}
public bool HasProperty(string propertyName)
{
return _rootItem.PropertyInfoDic.ContainsKey(propertyName);
}
public MaterialProperty GetProperty(string propertyName)
{
return _rootItem.PropertyInfoDic[propertyName].Property;
}
public void Refresh()
{
RefreshFeatureTier();
if (HasProperty("_MeshSourceMode"))
{
MaterialProperty meshSourceModeProperty = GetProperty("_MeshSourceMode");
MeshSourceMode = meshSourceModeProperty.hasMixedValue
? MeshSourceMode.UnKnowOrMixed
: (MeshSourceMode)meshSourceModeProperty.floatValue;
}
if (HasProperty("_TransparentMode"))
{
MaterialProperty transparentModeProperty = GetProperty("_TransparentMode");
TransparentMode = transparentModeProperty.hasMixedValue
? TransparentMode.UnKnowOrMixed
: (TransparentMode)transparentModeProperty.floatValue;
}
if (MeshSourceMode == MeshSourceMode.UnKnowOrMixed)
{
UIEffectEnabled = MixedBool.Mixed;
UseGraphicMainTex = MixedBool.Mixed;
ParticleMode = MixedBool.Mixed;
}
else
{
UIEffectEnabled = (int)MeshSourceMode >= 2 ? MixedBool.True : MixedBool.False;
UseGraphicMainTex = MeshSourceMode == MeshSourceMode.UIEffectRawImage || MeshSourceMode == MeshSourceMode.UIEffectSprite
? MixedBool.True
: MixedBool.False;
ParticleMode = MeshSourceMode == MeshSourceMode.Particle || MeshSourceMode == MeshSourceMode.UIParticle
? MixedBool.True
: MixedBool.False;
}
if (HasProperty("_FxLightMode"))
{
MaterialProperty lightModeProperty = GetProperty("_FxLightMode");
FxLightMode = lightModeProperty.hasMixedValue
? FxLightMode.UnKnownOrMixedValue
: (FxLightMode)lightModeProperty.floatValue;
}
NoiseEnabled = IsKeywordAllowed("_NOISEMAP") ? GetToggleState("_noisemapEnabled") : MixedBool.False;
ProgramNoiseEnabled = IsKeywordAllowed("_PROGRAM_NOISE") ? GetToggleState("_ProgramNoise_Toggle") : MixedBool.False;
VatEnabled = IsKeywordAllowed("_VAT") ? GetToggleState("_VAT_Toggle") : MixedBool.False;
FlipbookEnabled = IsKeywordAllowed("_FLIPBOOKBLENDING_ON") ? GetToggleState("_FlipbookBlending") : MixedBool.False;
}
private void RefreshFeatureTier()
{
if (!HasProperty(FeatureTierPropertyName))
{
CurrentTier = NBShaderFeatureTier.Ultra;
CurrentTierMixed = false;
_currentTierAllowedKeywords =
NBShaderFeatureLevelProjectSettings.instance.GetAllowedKeywordSetForReadOnlyUse(CurrentTier);
return;
}
MaterialProperty tierProperty = GetProperty(FeatureTierPropertyName);
CurrentTierMixed = tierProperty.hasMixedValue;
CurrentTier = CurrentTierMixed
? NBShaderFeatureTier.Ultra
: ToFeatureTier(Mathf.RoundToInt(tierProperty.floatValue));
_currentTierAllowedKeywords = CurrentTierMixed
? null
: NBShaderFeatureLevelProjectSettings.instance.GetAllowedKeywordSetForReadOnlyUse(CurrentTier);
}
private static NBShaderFeatureTier ToFeatureTier(int value)
{
return Enum.IsDefined(typeof(NBShaderFeatureTier), value) && value >= 0
? (NBShaderFeatureTier)value
: NBShaderFeatureTier.Ultra;
}
public MixedBool GetToggleState(string propertyName)
{
if (!HasProperty(propertyName))
{
return MixedBool.False;
}
MaterialProperty property = GetProperty(propertyName);
if (property.hasMixedValue)
{
return MixedBool.Mixed;
}
return property.floatValue > 0.5f ? MixedBool.True : MixedBool.False;
}
public bool IsToggleOn(string propertyName)
{
return GetToggleState(propertyName) == MixedBool.True;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fa789821f4c5470479fc50aac3322924
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,715 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using NBShader;
using NBShaders2.Editor.FeatureLevel;
namespace NBShaderEditor
{
public class NBShaderGUIToolBar
{
private const float ButtonWidth = 30f;
private const float TierButtonWidth = 105f;
private const string FeatureTierPropertyName = "_NBShaderFeatureTier";
private const string HelpUrl = "https://owejt9diz2c.feishu.cn/wiki/BHz8wHHSjiYJagk7WrmcAcconlb?from=from_copylink";
private static readonly string[] SettingsIconNames =
{
"SettingsIcon",
"d_SettingsIcon",
"Settings",
"d_Settings"
};
private readonly NBShaderRootItem _rootItem;
private readonly GUIContent _tierContent = new GUIContent();
private readonly string _tierMixedLabel;
private readonly string _tierFormat;
private readonly string _tierTooltip;
private NBShaderFeatureTier _tierContentTier;
private bool _tierContentMixed;
private bool _tierContentInitialized;
private static readonly Dictionary<string, GUIContent> IconContentCache =
new Dictionary<string, GUIContent>(StringComparer.Ordinal);
private static readonly Dictionary<string, GUIContent> TextContentCache =
new Dictionary<string, GUIContent>(StringComparer.Ordinal);
private static GUIContent s_SettingsContent;
private static string s_ToolbarContentLanguage;
private static Material copiedMaterialSnapshot;
private static Shader copiedShader;
public NBShaderGUIToolBar(NBShaderRootItem rootItem)
{
_rootItem = rootItem;
_tierMixedLabel = Label("tierMixed", "Tier: Mixed");
_tierFormat = Label("tierFormat", "Tier: {0}");
_tierTooltip = Tip("tier", "NBShader feature tier");
}
public void DrawToolbar()
{
Rect toolbarRect = ShaderGUIItem.ApplyGlobalRectCompensation(
_rootItem.GetControlRect(EditorGUIUtility.singleLineHeight));
GUI.Box(toolbarRect, GUIContent.none, EditorStyles.toolbar);
Material material = MainMaterial;
bool hasMaterial = material != null;
float buttonX = toolbarRect.x;
using (new EditorGUI.DisabledScope(!hasMaterial))
{
if (ToolbarButton(toolbarRect, ref buttonX, IconContent("Material On Icon", "ping", "跳到当前材质")))
{
EditorGUIUtility.PingObject(material);
}
if (ToolbarButton(toolbarRect, ref buttonX, IconContent("TreeEditor.Trash", "cleanUnusedTextures", "清除没有使用的贴图")))
{
CleanUnusedTextures();
}
if (ToolbarButton(toolbarRect, ref buttonX, TextContent("copy", "C", "复制材质属性")))
{
CopyMaterial(material);
}
}
using (new EditorGUI.DisabledScope(!hasMaterial || !HasCopiedMaterial()))
{
if (ToolbarButton(toolbarRect, ref buttonX, TextContent("paste", "V", "粘贴材质属性")))
{
PasteMaterial();
}
}
using (new EditorGUI.DisabledScope(!hasMaterial))
{
if (ToolbarButton(toolbarRect, ref buttonX, TextContent("specialReset", "R", "特殊重置功能")))
{
ShowResetPopupMenu();
}
if (ToolbarButton(toolbarRect, ref buttonX, IconContent("d_UnityEditor.HierarchyWindow", "collapseAll", "折叠所有控件")))
{
CollapseAll();
}
}
float rightX = toolbarRect.xMax;
rightX -= ButtonWidth;
Rect helpRect = MakeToolbarButtonRect(toolbarRect, rightX);
if (GUI.Button(helpRect, IconContent("d__Help@2x", "help", "说明文档"), EditorStyles.toolbarButton))
{
Application.OpenURL(HelpUrl);
}
rightX -= ButtonWidth;
Rect settingsRect = MakeToolbarButtonRect(toolbarRect, rightX);
if (GUI.Button(settingsRect, SettingsContent(), EditorStyles.toolbarButton))
{
OpenProjectSettings();
}
rightX -= TierButtonWidth;
Rect tierRect = MakeToolbarButtonRect(toolbarRect, rightX, TierButtonWidth);
using (new EditorGUI.DisabledScope(!hasMaterial))
{
if (GUI.Button(tierRect, TierContent(), EditorStyles.toolbarButton))
{
ShowTierPopupMenu();
}
}
}
private static bool ToolbarButton(Rect toolbarRect, ref float buttonX, GUIContent content)
{
return ToolbarButton(toolbarRect, ref buttonX, content, ButtonWidth);
}
private static bool ToolbarButton(Rect toolbarRect, ref float buttonX, GUIContent content, float width)
{
Rect buttonRect = MakeToolbarButtonRect(toolbarRect, buttonX, width);
buttonX += width;
return GUI.Button(buttonRect, content, EditorStyles.toolbarButton);
}
private static Rect MakeToolbarButtonRect(Rect toolbarRect, float x)
{
return MakeToolbarButtonRect(toolbarRect, x, ButtonWidth);
}
private static Rect MakeToolbarButtonRect(Rect toolbarRect, float x, float width)
{
return new Rect(x, toolbarRect.y, width, toolbarRect.height);
}
private static GUIContent SettingsContent()
{
EnsureToolbarContentLanguage();
if (s_SettingsContent != null)
{
return s_SettingsContent;
}
Texture image = null;
for (int i = 0; i < SettingsIconNames.Length; i++)
{
GUIContent icon = EditorGUIUtility.IconContent(SettingsIconNames[i]);
if (icon != null && icon.image != null)
{
image = icon.image;
break;
}
}
s_SettingsContent = new GUIContent(image, Tip("settings", "NBShader Project Settings"));
return s_SettingsContent;
}
private static void OpenProjectSettings()
{
SettingsService.OpenProjectSettings(NBShaderFeatureLevelSettingsProvider.SettingsPath);
}
private static bool HasCopiedMaterial()
{
return copiedMaterialSnapshot != null;
}
private static void CopyMaterial(Material material)
{
if (copiedMaterialSnapshot != null)
{
UnityEngine.Object.DestroyImmediate(copiedMaterialSnapshot);
copiedMaterialSnapshot = null;
copiedShader = null;
}
if (material == null)
{
return;
}
copiedMaterialSnapshot = new Material(material)
{
hideFlags = HideFlags.HideAndDontSave
};
copiedShader = copiedMaterialSnapshot.shader;
}
private GUIContent TierContent()
{
bool mixed = _rootItem.Context != null && _rootItem.Context.CurrentTierMixed;
NBShaderFeatureTier tier = CurrentTier;
if (!_tierContentInitialized || _tierContentMixed != mixed || _tierContentTier != tier)
{
_tierContent.text = mixed
? _tierMixedLabel
: string.Format(_tierFormat, GetTierLabel(tier));
_tierContent.tooltip = _tierTooltip;
_tierContentTier = tier;
_tierContentMixed = mixed;
_tierContentInitialized = true;
}
return _tierContent;
}
private NBShaderFeatureTier CurrentTier
{
get
{
return _rootItem.Context != null ? _rootItem.Context.CurrentTier : NBShaderFeatureTier.Ultra;
}
}
private void ShowTierPopupMenu()
{
GenericMenu menu = new GenericMenu();
AddTierMenuItem(menu, NBShaderFeatureTier.Low);
AddTierMenuItem(menu, NBShaderFeatureTier.Medium);
AddTierMenuItem(menu, NBShaderFeatureTier.High);
AddTierMenuItem(menu, NBShaderFeatureTier.Ultra);
menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
}
private void AddTierMenuItem(GenericMenu menu, NBShaderFeatureTier tier)
{
bool isChecked = (_rootItem.Context == null || !_rootItem.Context.CurrentTierMixed) && CurrentTier == tier;
menu.AddItem(new GUIContent(GetTierLabel(tier)), isChecked, () => SetFeatureTier(tier));
}
private static string GetTierLabel(NBShaderFeatureTier tier)
{
switch (tier)
{
case NBShaderFeatureTier.Low:
return Label("tierLow", "Low");
case NBShaderFeatureTier.Medium:
return Label("tierMedium", "Medium");
case NBShaderFeatureTier.High:
return Label("tierHigh", "High");
case NBShaderFeatureTier.Ultra:
return Label("tierUltra", "Ultra");
default:
return tier.ToString();
}
}
private void SetFeatureTier(NBShaderFeatureTier tier)
{
RecordAllMaterials(UndoText("setTier", "Set NBShader Feature Tier"));
if (_rootItem.PropertyInfoDic.TryGetValue(FeatureTierPropertyName, out ShaderPropertyInfo info))
{
info.Property.floatValue = (float)tier;
}
foreach (Material mat in Materials)
{
if (mat.HasProperty(FeatureTierPropertyName))
{
mat.SetFloat(FeatureTierPropertyName, (float)tier);
}
NBShaderFeatureLevelMaterialApplier.Apply(mat, tier, false, true);
}
FinishFeatureTierMutation();
}
private void ShowResetPopupMenu()
{
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent(Label("resetAll", "重置所有")), false, ResetAll);
menu.AddItem(new GUIContent(Label("resetDisabledFeatureChildren", "重置关闭功能子属性")), false, ResetDisabledFeatureChildren);
menu.AddSeparator(string.Empty);
menu.AddItem(new GUIContent(Label("resetSpecialUV", "重置特殊UV通道")), false, ResetSpecialUVChannel);
menu.AddItem(new GUIContent(Label("resetTwirl", "重置旋转扭曲")), false, ResetTwirl);
menu.AddItem(new GUIContent(Label("resetPolar", "重置极坐标")), false, ResetPolar);
menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
}
private void CleanUnusedTextures()
{
RecordAllMaterials(UndoText("cleanUnusedTextures", "清除没有使用的贴图"));
foreach (Material mat in Materials)
{
CleanUnusedTextureProperties(mat);
}
_rootItem.RequestClearUnusedTextureReferences();
MarkAllMaterialsDirty();
}
private void PasteMaterial()
{
Material material = MainMaterial;
if (material == null || !HasCopiedMaterial())
{
return;
}
Undo.RecordObject(material, UndoText("paste", "粘贴材质属性"));
if (copiedShader != null)
{
material.shader = copiedShader;
}
material.CopyPropertiesFromMaterial(copiedMaterialSnapshot);
EditorUtility.SetDirty(material);
_rootItem.IsInit = true;
_rootItem.Context?.Refresh();
_rootItem.SyncService?.SyncMaterialState();
_rootItem.Context?.Refresh();
UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
GUIUtility.ExitGUI();
}
private void ResetSpecialUVChannel()
{
RecordAllMaterials(UndoText("resetSpecialUV", "重置特殊UV通道"));
ResetSpecialUVChannelValues();
FinishMaterialMutation();
}
private void ResetTwirl()
{
RecordAllMaterials(UndoText("resetTwirl", "重置旋转扭曲"));
ResetTwirlValues();
FinishMaterialMutation();
}
private void ResetPolar()
{
RecordAllMaterials(UndoText("resetPolar", "重置极坐标"));
ResetPolarValues();
FinishMaterialMutation();
}
private void ResetAll()
{
RecordAllMaterials(UndoText("resetAll", "重置所有特殊功能"));
_rootItem.ExecuteResetAllItems();
ResetSpecialUVChannelValues();
ResetTwirlValues();
ResetPolarValues();
FinishMaterialMutation();
}
private void ResetDisabledFeatureChildren()
{
RecordAllMaterials(UndoText("resetDisabledFeatureChildren", "重置关闭功能子属性"));
foreach (ShaderGUIItem item in _rootItem.GetToolbarResetRootItems())
{
ResetDisabledFeatureChildren(item);
}
FinishMaterialMutation();
}
private static void ResetDisabledFeatureChildren(ShaderGUIItem item)
{
if (item == null)
{
return;
}
if (item is PropertyToggleBlockItem && IsExplicitlyDisabled(item))
{
ExecuteResetChildren(item);
item.CheckIsPropertyModified(true);
return;
}
for (int i = 0; i < item.ChildrenItemList.Count; i++)
{
ResetDisabledFeatureChildren(item.ChildrenItemList[i]);
}
item.CheckIsPropertyModified(true);
}
private static bool IsExplicitlyDisabled(ShaderGUIItem item)
{
MaterialProperty property = item.PropertyInfo?.Property;
return property != null &&
!property.hasMixedValue &&
property.floatValue <= 0.5f;
}
private static void ExecuteResetChildren(ShaderGUIItem item)
{
for (int i = 0; i < item.ChildrenItemList.Count; i++)
{
ExecuteResetSubtree(item.ChildrenItemList[i]);
}
}
private static void ExecuteResetSubtree(ShaderGUIItem item)
{
if (item == null)
{
return;
}
item.ExecuteReset(true);
for (int i = 0; i < item.ChildrenItemList.Count; i++)
{
ExecuteResetSubtree(item.ChildrenItemList[i]);
}
item.CheckIsPropertyModified(true);
}
private void ResetSpecialUVChannelValues()
{
float defaultValue = GetDefaultFloat("_SpecialUVChannelMode", 0f);
SetFloatProperty("_SpecialUVChannelMode", defaultValue);
bool useTexcoord1 = Mathf.RoundToInt(defaultValue) == 0;
for (int i = 0; i < _rootItem.ShaderFlags.Count; i++)
{
ShaderFlagsBase flags = _rootItem.ShaderFlags[i];
if (useTexcoord1)
{
flags.SetFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD1, index: 1);
flags.ClearFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD2, index: 1);
}
else
{
flags.ClearFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD1, index: 1);
flags.SetFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD2, index: 1);
}
}
}
private void ResetTwirlValues()
{
float enabled = GetDefaultFloat("_UTwirlEnabled", 0f);
SetFloatProperty("_UTwirlEnabled", enabled);
SetVectorProperty("_TWParameter", GetDefaultVector("_TWParameter", new Vector4(0.5f, 0.5f, 0f, 0f)));
SetFloatProperty("_TWStrength", GetDefaultFloat("_TWStrength", 1f));
ApplyFlag(NBShaderFlags.FLAG_BIT_PARTICLE_UTWIRL_ON, enabled > 0.5f, 0);
}
private void ResetPolarValues()
{
float enabled = GetDefaultFloat("_PolarCoordinatesEnabled", 0f);
SetFloatProperty("_PolarCoordinatesEnabled", enabled);
SetVectorProperty("_PCCenter", GetDefaultVector("_PCCenter", new Vector4(0.5f, 0.5f, 1f, 0f)));
ApplyFlag(NBShaderFlags.FLAG_BIT_PARTICLE_POLARCOORDINATES_ON, enabled > 0.5f, 0);
}
private void CollapseAll()
{
RecordAllMaterials(UndoText("collapseAll", "折叠所有控件"));
foreach (KeyValuePair<string, ShaderPropertyInfo> pair in _rootItem.PropertyInfoDic)
{
if (!pair.Key.EndsWith("FoldOut", StringComparison.Ordinal))
{
continue;
}
MaterialProperty property = pair.Value.Property;
ShaderPropertyType propertyType = ShaderGUIUnityCompat.GetPropertyType(property);
if (propertyType == ShaderPropertyType.Float ||
propertyType == ShaderPropertyType.Range)
{
property.floatValue = 0f;
}
}
MarkAllMaterialsDirty();
UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
}
private void CleanUnusedTextureProperties(Material mat)
{
if (mat == null || mat.shader == null)
{
return;
}
Shader shader = mat.shader;
var shaderTexProps = new HashSet<string>();
int count = shader.GetPropertyCount();
for (int i = 0; i < count; i++)
{
if (shader.GetPropertyType(i) == ShaderPropertyType.Texture)
{
shaderTexProps.Add(shader.GetPropertyName(i));
}
}
string[] texturePropertyNames = mat.GetTexturePropertyNames();
foreach (string propertyName in texturePropertyNames)
{
if (shaderTexProps.Contains(propertyName) || mat.GetTexture(propertyName) == null)
{
continue;
}
mat.SetTexture(propertyName, null);
Debug.LogFormat(
mat,
NBShaderInspectorLocalization.Get(
"inspector.toolbar.cleanUnusedTextures.log",
"清理 {0} 的无效贴图属性: {1}"),
mat.name,
propertyName);
}
}
private void FinishMaterialMutation()
{
_rootItem.Context?.Refresh();
_rootItem.SyncService?.SyncMaterialState();
_rootItem.SyncService?.NotifyKeywordsMayHaveChanged();
_rootItem.Context?.Refresh();
MarkAllMaterialsDirty();
UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
}
private void FinishFeatureTierMutation()
{
_rootItem.Context?.Refresh();
_rootItem.SyncService?.NotifyKeywordsMayHaveChanged();
_rootItem.Context?.Refresh();
MarkAllMaterialsDirty();
UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
}
private void ApplyFlag(int flagBits, bool enabled, int flagIndex)
{
for (int i = 0; i < _rootItem.ShaderFlags.Count; i++)
{
ShaderFlagsBase flags = _rootItem.ShaderFlags[i];
if (enabled)
{
flags.SetFlagBits(flagBits, index: flagIndex);
}
else
{
flags.ClearFlagBits(flagBits, index: flagIndex);
}
}
}
private float GetDefaultFloat(string propertyName, float fallback)
{
return _rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info)
? _rootItem.Shader.GetPropertyDefaultFloatValue(info.Index)
: fallback;
}
private Vector4 GetDefaultVector(string propertyName, Vector4 fallback)
{
return _rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info)
? _rootItem.Shader.GetPropertyDefaultVectorValue(info.Index)
: fallback;
}
private void SetFloatProperty(string propertyName, float value)
{
if (_rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info))
{
info.Property.floatValue = value;
}
foreach (Material mat in Materials)
{
if (mat.HasProperty(propertyName))
{
mat.SetFloat(propertyName, value);
}
}
}
private void SetVectorProperty(string propertyName, Vector4 value)
{
if (_rootItem.PropertyInfoDic.TryGetValue(propertyName, out ShaderPropertyInfo info))
{
info.Property.vectorValue = value;
}
foreach (Material mat in Materials)
{
if (mat.HasProperty(propertyName))
{
mat.SetVector(propertyName, value);
}
}
}
private void RecordAllMaterials(string undoName)
{
var objects = new List<UnityEngine.Object>();
foreach (Material mat in Materials)
{
objects.Add(mat);
}
if (objects.Count > 0)
{
Undo.RecordObjects(objects.ToArray(), undoName);
}
}
private void MarkAllMaterialsDirty()
{
foreach (Material mat in Materials)
{
EditorUtility.SetDirty(mat);
}
}
private IEnumerable<Material> Materials
{
get
{
if (_rootItem.Mats == null)
{
yield break;
}
for (int i = 0; i < _rootItem.Mats.Count; i++)
{
Material mat = _rootItem.Mats[i];
if (mat != null)
{
yield return mat;
}
}
}
}
private Material MainMaterial
{
get
{
return _rootItem.Mats != null && _rootItem.Mats.Count > 0 ? _rootItem.Mats[0] : null;
}
}
private static GUIContent IconContent(string iconName, string key, string fallbackTooltip)
{
EnsureToolbarContentLanguage();
if (IconContentCache.TryGetValue(key, out GUIContent cachedContent))
{
return cachedContent;
}
GUIContent icon = EditorGUIUtility.IconContent(iconName);
var content = new GUIContent(icon != null ? icon.image : null, Tip(key, fallbackTooltip));
IconContentCache[key] = content;
return content;
}
private static void EnsureToolbarContentLanguage()
{
string currentLanguage = NBShaderInspectorLocalization.CurrentLanguage;
if (string.Equals(s_ToolbarContentLanguage, currentLanguage, StringComparison.Ordinal))
{
return;
}
s_ToolbarContentLanguage = currentLanguage;
s_SettingsContent = null;
IconContentCache.Clear();
TextContentCache.Clear();
}
private static GUIContent TextContent(string key, string fallbackLabel, string fallbackTooltip)
{
EnsureToolbarContentLanguage();
if (TextContentCache.TryGetValue(key, out GUIContent cachedContent))
{
return cachedContent;
}
cachedContent = NBShaderInspectorLocalization.MakeInspectorContent("toolbar." + key, fallbackLabel, fallbackTooltip);
TextContentCache[key] = cachedContent;
return cachedContent;
}
private static string Label(string key, string fallback)
{
return NBShaderInspectorLocalization.Get("inspector.toolbar." + key + ".label", fallback);
}
private static string Tip(string key, string fallback)
{
return NBShaderInspectorLocalization.Get("inspector.toolbar." + key + ".tip", fallback);
}
private static string UndoText(string key, string fallback)
{
return NBShaderInspectorLocalization.Get("inspector.toolbar." + key + ".undo", fallback);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0518e5ab9884c0e4d9b2c5ba352090ff
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ce0a3556e53240939194057f6b6c7976
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 078260ce42a40b046b687b55fa82ae32
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,401 @@
using System;
using System.Collections.Generic;
using NBShader;
using UnityEditor;
using UnityEngine;
namespace NBShaderEditor
{
public class ParticleVertexStreamsItem : ShaderGUIItem
{
private readonly NBShaderRootItem _nbRootItem;
private readonly List<ParticleSystemVertexStream> _streams = new List<ParticleSystemVertexStream>();
private readonly List<string> _streamNames = new List<string>();
private readonly List<string> _warnings = new List<string>();
private readonly List<ParticleSystemVertexStream> _rendererStreams = new List<ParticleSystemVertexStream>();
private readonly List<UnityEngine.Object> _undoRenderers = new List<UnityEngine.Object>();
private WarningMessageCache _rendererWarningMessageCache;
private WarningMessageCache _trailWarningMessageCache;
public ParticleVertexStreamsItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem) : base(rootItem, parentItem)
{
_nbRootItem = rootItem;
}
public override void OnGUI()
{
if (_nbRootItem.Mats == null ||
_nbRootItem.Mats.Count != 1)
{
return;
}
Material material = _nbRootItem.Mats[0];
if (material == null)
{
return;
}
List<ParticleSystemRenderer> renderers = _nbRootItem.ParticleRenderersUsingThisMaterial;
if (renderers == null || renderers.Count == 0)
{
return;
}
NBShaderFlags flags = _nbRootItem.ShaderFlags.Count > 0
? _nbRootItem.ShaderFlags[0] as NBShaderFlags
: null;
if (_nbRootItem.Context.ParticleMode != MixedBool.True)
{
return;
}
if (flags == null)
{
return;
}
if (flags.CheckFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER, index: 1))
{
flags.ClearFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_ANIMATION_SHEET_HELPER, index: 1);
}
BuildExpectedStreams(material, flags, _streams, _streamNames);
LayoutSpace();
EditorGUI.LabelField(
ApplyGlobalRectCompensation(LayoutRect()),
NBShaderInspectorLocalization.MakeInspectorContent("vertexStreams.title", "Particle Vertex Streams"),
EditorStyles.boldLabel);
using (new EditorGUI.DisabledScope(true))
{
for (int i = 0; i < _streamNames.Count; i++)
{
EditorGUI.TextField(ApplyGlobalRectCompensation(LayoutRect()), _streamNames[i]);
}
}
DrawRendererWarnings(renderers, _streams, false);
#if UNITY_2022_3_OR_NEWER && !(UNITY_2022_3_0 || UNITY_2022_3_1 || UNITY_2022_3_2 || UNITY_2022_3_3 || UNITY_2022_3_4 || UNITY_2022_3_5 || UNITY_2022_3_6 || UNITY_2022_3_7 || UNITY_2022_3_8 || UNITY_2022_3_9 || UNITY_2022_3_10)
DrawRendererWarnings(renderers, _streams, true);
#endif
}
private static void BuildExpectedStreams(
Material material,
NBShaderFlags flags,
List<ParticleSystemVertexStream> streams,
List<string> streamNames)
{
streams.Clear();
streamNames.Clear();
AddStream(streams, streamNames, ParticleSystemVertexStream.Position, "POSITION.xyz");
bool useFlipbookBlending = material.IsKeywordEnabled("_FLIPBOOKBLENDING_ON") ||
GetFloat(material, "_FlipbookBlending") > 0.5f;
bool useSpecialUVChannel = flags.CheckIsUVModeOn(NBShaderFlags.UVMode.SpecialUVChannel);
bool useUV3ForSpecialUV = flags.CheckFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_1_USE_TEXCOORD2, index: 1);
bool customData1 = flags.CheckFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_CUSTOMDATA1_ON);
bool customData2 = flags.CheckFlagBits(NBShaderFlags.FLAG_BIT_PARTICLE_CUSTOMDATA2_ON);
bool needNormal = GetFloat(material, "_VertexOffset_NormalDir_Toggle") > 0.5f ||
GetFloat(material, "_fresnelEnabled") > 0.5f ||
GetFloat(material, "_ParallaxMapping_Toggle") > 0.5f ||
GetFloat(material, "_FxLightMode") > (float)FxLightMode.UnLit ||
GetFloat(material, "_BumpMapToggle") > 0.5f;
bool needTangent = needNormal;
if (needTangent)
{
AddStream(streams, streamNames, ParticleSystemVertexStream.Tangent, "TANGENT.xyzw");
}
if (needNormal)
{
AddStream(streams, streamNames, ParticleSystemVertexStream.Normal, "NORMAL.xyz");
}
AddStream(streams, streamNames, ParticleSystemVertexStream.Color, "COLOR.xyzw");
AddStream(streams, streamNames, ParticleSystemVertexStream.UV, "TEXCOORD0.xy");
if (useFlipbookBlending && useSpecialUVChannel)
{
AddStream(streams, streamNames, ParticleSystemVertexStream.UV2, "TEXCOORD0.zw");
}
else if (useSpecialUVChannel)
{
AddStream(streams, streamNames, useUV3ForSpecialUV ? ParticleSystemVertexStream.UV3 : ParticleSystemVertexStream.UV2, useUV3ForSpecialUV ? "TEXCOORD3.xy" : "TEXCOORD0.zw");
}
else if (useFlipbookBlending || customData1 || customData2)
{
AddStream(streams, streamNames, ParticleSystemVertexStream.UV2, "TEXCOORD0.zw");
}
bool fillSkipUV2 = false;
if (customData1 || customData2 || useFlipbookBlending)
{
AddStream(streams, streamNames, ParticleSystemVertexStream.Custom1XYZW, "TEXCOORD1.xyzw");
}
else if (useSpecialUVChannel && useUV3ForSpecialUV)
{
AddStream(streams, streamNames, ParticleSystemVertexStream.UV2, "TEXCOORD1.xy");
fillSkipUV2 = true;
}
if (customData2 || useFlipbookBlending)
{
AddStream(streams, streamNames, ParticleSystemVertexStream.Custom2XYZW, "TEXCOORD2.xyzw");
}
else if (useSpecialUVChannel && useUV3ForSpecialUV && !fillSkipUV2)
{
AddStream(streams, streamNames, ParticleSystemVertexStream.UV2, "TEXCOORD2.xy");
fillSkipUV2 = true;
}
if (useFlipbookBlending)
{
AddStream(streams, streamNames, ParticleSystemVertexStream.AnimBlend, "TEXCOORD3.x");
if (useSpecialUVChannel && useUV3ForSpecialUV)
{
AddStream(streams, streamNames, ParticleSystemVertexStream.UV3, "TEXCOORD3.yz");
}
}
else if (useSpecialUVChannel && useUV3ForSpecialUV && !fillSkipUV2)
{
AddStream(streams, streamNames, ParticleSystemVertexStream.UV2, "TEXCOORD3.xy");
}
AppendVatRequiredStreams(material, streams, streamNames);
}
private static void AppendVatRequiredStreams(Material material, List<ParticleSystemVertexStream> streams, List<string> streamNames)
{
if (GetFloat(material, "_VAT_Toggle") <= 0.5f)
{
return;
}
AddStreamUnique(streams, streamNames, ParticleSystemVertexStream.Position, "VAT POSITION.xyz");
AddStreamUnique(streams, streamNames, ParticleSystemVertexStream.Normal, "VAT NORMAL.xyz");
int vatMode = Mathf.RoundToInt(GetFloat(material, "_VATMode"));
if (vatMode == (int)VATMode.Tyflow)
{
if (IsParticleMode(material) && Mathf.RoundToInt(GetFloat(material, "_TyFlowVATSubMode")) <= 1)
{
AddStreamUnique(streams, streamNames, ParticleSystemVertexStream.UV2, "VAT TEXCOORD0.zw");
}
return;
}
int houdiniSubMode = Mathf.RoundToInt(GetFloat(material, "_HoudiniVATSubMode"));
bool isParticleMode = IsParticleMode(material);
switch (houdiniSubMode)
{
case 0:
AddHoudiniVatUV1Stream(streams, streamNames, isParticleMode);
break;
case 1:
if (isParticleMode)
{
break;
}
AddHoudiniVatUV1Stream(streams, streamNames, isParticleMode);
AddStreamUnique(streams, streamNames, ParticleSystemVertexStream.Custom2XYZW, "VAT TEXCOORD2.xyzw");
AddStreamUnique(streams, streamNames, ParticleSystemVertexStream.UV, "VAT TEXCOORD0.xy");
break;
case 2:
AddStreamUnique(streams, streamNames, ParticleSystemVertexStream.UV, "VAT TEXCOORD0.xy");
break;
case 3:
AddStreamUnique(streams, streamNames, ParticleSystemVertexStream.UV, "VAT TEXCOORD0.xy");
AddHoudiniVatUV1Stream(streams, streamNames, isParticleMode);
break;
}
}
private static void AddHoudiniVatUV1Stream(List<ParticleSystemVertexStream> streams, List<string> streamNames, bool isParticleMode)
{
AddStreamUnique(
streams,
streamNames,
isParticleMode ? ParticleSystemVertexStream.UV2 : ParticleSystemVertexStream.Custom1XYZW,
isParticleMode ? "VAT TEXCOORD0.zw" : "VAT TEXCOORD1.xyzw");
}
private static void AddStream(List<ParticleSystemVertexStream> streams, List<string> streamNames, ParticleSystemVertexStream stream, string label)
{
streams.Add(stream);
streamNames.Add(label);
}
private static void AddStreamUnique(List<ParticleSystemVertexStream> streams, List<string> streamNames, ParticleSystemVertexStream stream, string label)
{
if (streams.Contains(stream))
{
return;
}
streams.Add(stream);
streamNames.Add(label);
}
private static float GetFloat(Material material, string propertyName)
{
return material != null && material.HasProperty(propertyName) ? material.GetFloat(propertyName) : 0f;
}
private static bool IsParticleMode(Material material)
{
if (material == null || !material.HasProperty("_MeshSourceMode"))
{
return false;
}
MeshSourceMode meshSourceMode = (MeshSourceMode)Mathf.RoundToInt(material.GetFloat("_MeshSourceMode"));
return meshSourceMode == MeshSourceMode.Particle || meshSourceMode == MeshSourceMode.UIParticle;
}
private void DrawRendererWarnings(List<ParticleSystemRenderer> renderers, List<ParticleSystemVertexStream> streams, bool trail)
{
_warnings.Clear();
foreach (ParticleSystemRenderer renderer in renderers)
{
if (renderer == null)
{
continue;
}
_rendererStreams.Clear();
if (trail)
{
#if UNITY_2022_3_OR_NEWER && !(UNITY_2022_3_0 || UNITY_2022_3_1 || UNITY_2022_3_2 || UNITY_2022_3_3 || UNITY_2022_3_4 || UNITY_2022_3_5 || UNITY_2022_3_6 || UNITY_2022_3_7 || UNITY_2022_3_8 || UNITY_2022_3_9 || UNITY_2022_3_10)
renderer.GetActiveTrailVertexStreams(_rendererStreams);
#endif
}
else
{
renderer.GetActiveVertexStreams(_rendererStreams);
}
if (!StreamsEqual(_rendererStreams, streams))
{
_warnings.Add(renderer.name);
}
}
if (_warnings.Count == 0)
{
return;
}
string mismatchText = trail
? NBShaderInspectorLocalization.GetInspectorText("vertexStreams.trailMismatch", "Particle trail renderers with mismatched vertex streams:")
: NBShaderInspectorLocalization.GetInspectorText("vertexStreams.mismatch", "Particle renderers with mismatched vertex streams:");
DrawLayoutHelpBox(GetWarningMessage(trail, mismatchText), MessageType.Error);
GUIContent buttonContent = trail
? NBShaderInspectorLocalization.MakeContent("inspector.vertexStreams.applyTrail.button", "Apply Trail Vertex Streams")
: NBShaderInspectorLocalization.MakeContent("inspector.vertexStreams.apply.button", "Apply Vertex Streams");
if (GUI.Button(ApplyGlobalRectCompensation(LayoutRect()), buttonContent, EditorStyles.miniButton))
{
_undoRenderers.Clear();
for (int i = 0; i < renderers.Count; i++)
{
if (renderers[i] != null)
{
_undoRenderers.Add(renderers[i]);
}
}
Undo.RecordObjects(
_undoRenderers.ToArray(),
NBShaderInspectorLocalization.GetInspectorText("vertexStreams.apply.undo", "Apply custom vertex streams from material"));
foreach (ParticleSystemRenderer renderer in renderers)
{
if (renderer == null)
{
continue;
}
if (trail)
{
#if UNITY_2022_3_OR_NEWER && !(UNITY_2022_3_0 || UNITY_2022_3_1 || UNITY_2022_3_2 || UNITY_2022_3_3 || UNITY_2022_3_4 || UNITY_2022_3_5 || UNITY_2022_3_6 || UNITY_2022_3_7 || UNITY_2022_3_8 || UNITY_2022_3_9 || UNITY_2022_3_10)
renderer.SetActiveTrailVertexStreams(streams);
#endif
}
else
{
renderer.SetActiveVertexStreams(streams);
}
}
}
}
private static bool StreamsEqual(List<ParticleSystemVertexStream> lhs, List<ParticleSystemVertexStream> rhs)
{
if (lhs == null || rhs == null || lhs.Count != rhs.Count)
{
return false;
}
for (int i = 0; i < lhs.Count; i++)
{
if (lhs[i] != rhs[i])
{
return false;
}
}
return true;
}
private string GetWarningMessage(bool trail, string mismatchText)
{
return trail
? GetWarningMessage(ref _trailWarningMessageCache, mismatchText)
: GetWarningMessage(ref _rendererWarningMessageCache, mismatchText);
}
private string GetWarningMessage(ref WarningMessageCache cache, string mismatchText)
{
int hash = ComputeWarningsHash();
if (cache.Message != null &&
cache.Count == _warnings.Count &&
cache.Hash == hash)
{
return cache.Message;
}
cache.Count = _warnings.Count;
cache.Hash = hash;
cache.Message = mismatchText + "\n-" + string.Join("\n-", _warnings);
return cache.Message;
}
private int ComputeWarningsHash()
{
unchecked
{
int hash = 17;
for (int i = 0; i < _warnings.Count; i++)
{
hash = hash * 31 + (_warnings[i] == null ? 0 : StringComparer.Ordinal.GetHashCode(_warnings[i]));
}
return hash;
}
}
private struct WarningMessageCache
{
public int Count;
public int Hash;
public string Message;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1a9c67414c0e4a938fa58f42f8828e45
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,217 @@
using System;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
namespace NBShaderEditor
{
public class TABigBlockItem : BigBlockItem
{
private const string StencilConfigAssetPath = "Packages/com.xuanxuan.nb.fx/XuanXuanRenderUtility/Shader/StencilConfig.asset";
private readonly NBShaderRootItem _nbRootItem;
private readonly PropertyToggleBlockItem _zOffsetBlock;
private readonly PropertyToggleBlockItem _overrideZBlock;
private readonly RenderQueueItem _renderQueueItem;
private readonly ShaderGUIBitMaskItem _rgbaMaskItem;
private readonly PropertyToggleBlockItem _customStencilBlock;
private readonly BlockItem _keywordBlock;
private StencilValuesConfig _stencilValuesConfig;
private static readonly string[] RgbaMaskOptions = { "R", "G", "B", "A" };
public TABigBlockItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem)
: base(
rootItem,
parentItem,
"_TABigBlockItemFoldOut",
() => Content("block.ta", "TA Debug", "Technical artist debug and helper controls"))
{
_nbRootItem = rootItem;
_zOffsetBlock = new PropertyToggleBlockItem(
rootItem,
this,
"_ZOffsetBlockFoldOut",
"_ZOffset_Toggle",
() => Content("ta.zoffset", "Z Offset"),
onValueChanged: OnZOffsetChanged,
isVisible: () => rootItem.Context.UIEffectEnabled != MixedBool.True,
bold: true);
AddFloat(rootItem, _zOffsetBlock, "_offsetFactor", "Offset Factor");
AddFloat(rootItem, _zOffsetBlock, "_offsetUnits", "Offset Units");
_overrideZBlock = new PropertyToggleBlockItem(
rootItem,
this,
"_OverrideZBlockFoldOut",
"_OverrideZ_Toggle",
() => Content("ta.overrideZ", "Override Z"),
keyword: "_OVERRIDE_Z",
isVisible: () => rootItem.Context.UIEffectEnabled != MixedBool.True,
bold: true);
AddFloat(rootItem, _overrideZBlock, "_OverrideZValue", "Override Z Value");
_renderQueueItem = new RenderQueueItem(
rootItem,
this,
"_QueueBias",
() => Content("ta.renderQueue", "Queue Bias"),
rootItem.SyncService.SyncMaterialState);
_rgbaMaskItem = new ShaderGUIBitMaskItem(
rootItem,
this,
"_ColorMask",
() => Content("ta.property._ColorMask", "RGBA Mask"),
() => NBShaderInspectorLocalization.GetInspectorOptions("ta.colorMask", RgbaMaskOptions))
{
ValidMask = 0xF
};
_customStencilBlock = new PropertyToggleBlockItem(
rootItem,
this,
"_CustomStencilTestFoldOut",
"_CustomStencilTest",
() => Content("ta.customStencil", "Custom Stencil Test"),
onValueChanged: OnCustomStencilChanged,
bold: true);
new StencilConfigKeyItem(rootItem, _customStencilBlock, this);
AddFloat(rootItem, _customStencilBlock, "_StencilKeyIndex", "Stencil Config Index");
AddFloat(rootItem, _customStencilBlock, "_Stencil", "Stencil Value");
AddPopup(rootItem, _customStencilBlock, "_StencilComp", "Stencil Compare", Enum.GetNames(typeof(CompareFunction)));
AddPopup(rootItem, _customStencilBlock, "_StencilOp", "Stencil Operation", Enum.GetNames(typeof(StencilOp)));
AddPopup(rootItem, _customStencilBlock, "_StencilFail", "Stencil Fail", Enum.GetNames(typeof(StencilOp)));
AddPopup(rootItem, _customStencilBlock, "_StencilZFail", "Stencil ZFail", Enum.GetNames(typeof(StencilOp)));
AddFloat(rootItem, _customStencilBlock, "_StencilReadMask", "Stencil Read Mask");
AddFloat(rootItem, _customStencilBlock, "_StencilWriteMask", "Stencil Write Mask");
_keywordBlock = new BlockItem(
rootItem,
this,
"_ShaderKeywordFoldOut",
() => Content("ta.keywords", "Enabled Keywords"));
new KeywordListItem(rootItem, _keywordBlock, () => Content("ta.keywords.list", "Enabled Keywords"));
InitTriggerByChild();
}
public override void DrawBlock()
{
_zOffsetBlock.OnGUI();
_overrideZBlock.OnGUI();
_renderQueueItem.OnGUI();
_rgbaMaskItem.OnGUI();
_customStencilBlock.OnGUI();
if (_nbRootItem.Mats.Count == 1)
{
_keywordBlock.OnGUI();
}
}
private void OnZOffsetChanged(bool enabled)
{
if (enabled)
{
return;
}
SetFloat("_offsetFactor", 0f);
SetFloat("_offsetUnits", 0f);
}
private void OnCustomStencilChanged(bool enabled)
{
if (enabled)
{
return;
}
_nbRootItem.SyncService.ApplyStencilPreset("ParticleBaseDefault");
}
private void SetFloat(string propertyName, float value)
{
for (int i = 0; i < _nbRootItem.Mats.Count; i++)
{
Material mat = _nbRootItem.Mats[i];
if (mat != null && mat.HasProperty(propertyName))
{
mat.SetFloat(propertyName, value);
}
}
}
private string GetStencilKey(int index)
{
_stencilValuesConfig ??= AssetDatabase.LoadAssetAtPath<StencilValuesConfig>(StencilConfigAssetPath);
return _stencilValuesConfig != null ? _stencilValuesConfig.GetKeyByIndex(index) : string.Empty;
}
private static void AddFloat(NBShaderRootItem rootItem, ShaderGUIItem parentItem, string propertyName, string label)
{
ShaderGUIFloatItem item = new ShaderGUIFloatItem(rootItem, parentItem)
{
PropertyName = propertyName,
GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("ta.property." + propertyName, label)
};
item.InitTriggerByChild();
}
private static void AddPopup(NBShaderRootItem rootItem, ShaderGUIItem parentItem, string propertyName, string label, string[] options)
{
ShaderGUIPopUpItem item = new ShaderGUIPopUpItem(rootItem, parentItem)
{
PropertyName = propertyName,
GuiContent = NBShaderInspectorLocalization.MakeInspectorContent("ta.property." + propertyName, label),
PopUpNames = options
};
item.InitTriggerByChild();
}
private static GUIContent Content(string key, string fallback, string tip = "")
{
return NBShaderInspectorLocalization.MakeInspectorContent(key, fallback, tip);
}
private sealed class StencilConfigKeyItem : ShaderGUIItem
{
private readonly NBShaderRootItem _nbRootItem;
private readonly TABigBlockItem _owner;
public StencilConfigKeyItem(NBShaderRootItem rootItem, ShaderGUIItem parentItem, TABigBlockItem owner)
: base(rootItem, parentItem)
{
_nbRootItem = rootItem;
_owner = owner;
}
public override void OnGUI()
{
if (!_nbRootItem.PropertyInfoDic.TryGetValue("_StencilKeyIndex", out ShaderPropertyInfo info))
{
return;
}
string key = string.Empty;
bool hasMixedValue = info.Property.hasMixedValue;
if (!hasMixedValue)
{
key = _owner.GetStencilKey(Mathf.RoundToInt(info.Property.floatValue));
}
EditorGUI.showMixedValue = hasMixedValue;
using (new EditorGUI.DisabledScope(true))
{
EditorGUI.TextField(
ApplyGlobalRectCompensation(LayoutRect()),
NBShaderInspectorLocalization.GetInspectorText("ta.stencil.currentConfig", "当前Config:"),
key);
}
EditorGUI.showMixedValue = false;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 17025a3939882e0459ded7a5251b2463
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: