NB_FX
This commit is contained in:
@@ -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:
|
||||
Reference in New Issue
Block a user