NB_FX
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 135aa1fd916c4155b15cada119fdf3fd
|
||||
timeCreated: 1758549245
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9bfc5d4ee5b1dc64caf81212c9880723
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6f682036413e49019b4856f356996a4c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d0e463cf92ee4725b57727544bc58488
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a4e1e4d5240a4b748b50807573e22ab8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0482c5f68e7b4438bc494df4ebf47267
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 64cae13520d842939c7d27d6ffadd01d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed7051253ed04c968aa25e96aa0e5d5d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c8170a5849c4a5abf332cdf3832fa02
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 355bed04b23c4ea093ad45991f0004a4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ee140beb49b74735960d38a89bd528fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c5fe236301944650a35adc509015737c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4f64374c74c47478edfdd0ddb6e8355
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5bf38ca73454cc1916d18f40182d5ad
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67c4fd7f472848dfbefe5703bb834b60
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c6a446a2f0364fb0844cb9d36bd39a27
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45dcb7c7a750440a99a8d5017d41fa22
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dece160aaa274dd79c1e771fed834249
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 744c08c430cd42fda37db42e777c3c84
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5507463f5ee64c358b78250126100a8d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e6914407bf83004f8b2c13ccf777981
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ebc7f22502386443b06ac9aebc4222b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed09665b113c407dbfb8c818b74f48aa
|
||||
timeCreated: 1758445745
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa789821f4c5470479fc50aac3322924
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 078260ce42a40b046b687b55fa82ae32
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a9c67414c0e4a938fa58f42f8828e45
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 17025a3939882e0459ded7a5251b2463
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user