NB_FX
This commit is contained in:
@@ -0,0 +1,881 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NBShader;
|
||||
using NBShaderEditor;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBShaders2.Editor.FeatureLevel
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public static class NBShaderFeatureLevelSettingsProvider
|
||||
{
|
||||
internal const string SettingsPath = NBFXProjectSettings.SettingsPath;
|
||||
private const float FeatureColumnWidth = 240f;
|
||||
private const float TierColumnWidth = 92f;
|
||||
private const float CostColumnWidth = 84f;
|
||||
private const float EffectColumnWidth = 280f;
|
||||
private const float DescriptionColumnWidth = 230f;
|
||||
private const float RowHeight = 22f;
|
||||
private const float HeaderHeight = 24f;
|
||||
private const float TableMinHeight = 360f;
|
||||
private const float TableMaxHeight = 640f;
|
||||
private const float TableWidth = FeatureColumnWidth + TierColumnWidth * 4f + CostColumnWidth + EffectColumnWidth + DescriptionColumnWidth;
|
||||
private const float RowIndentWidth = 14f;
|
||||
private const string FoldoutSessionPrefix = "NBShaderFeatureLevelSettingsProvider.Foldout.";
|
||||
|
||||
private sealed class RowContentCache
|
||||
{
|
||||
public GUIContent rowContent;
|
||||
public GUIContent effectContent;
|
||||
public GUIContent descriptionContent;
|
||||
}
|
||||
|
||||
private static readonly NBShaderFeatureTier[] Tiers =
|
||||
{
|
||||
NBShaderFeatureTier.Low,
|
||||
NBShaderFeatureTier.Medium,
|
||||
NBShaderFeatureTier.High,
|
||||
NBShaderFeatureTier.Ultra
|
||||
};
|
||||
|
||||
private static readonly Dictionary<string, RowContentCache> s_RowContentCache =
|
||||
new Dictionary<string, RowContentCache>(StringComparer.Ordinal);
|
||||
private static readonly Dictionary<NBShaderFeaturePerformanceCost, GUIContent> s_CostContentCache =
|
||||
new Dictionary<NBShaderFeaturePerformanceCost, GUIContent>();
|
||||
private static readonly GUIContent[] s_QualitySummaryContents = new GUIContent[Tiers.Length];
|
||||
private static readonly string[] s_QualitySummaryTexts = new string[Tiers.Length];
|
||||
private static readonly StringBuilder s_QualitySummaryBuilder = new StringBuilder(128);
|
||||
|
||||
private static Vector2 s_TableScrollPosition;
|
||||
private static string s_ContentCacheLanguage;
|
||||
private static GUIContent s_ProviderLabelContent;
|
||||
private static GUIContent s_QualityDescriptionContent;
|
||||
private static GUIContent s_NoValueContent;
|
||||
private static string s_QualityMenuTipText;
|
||||
private static int s_QualitySummaryHash;
|
||||
|
||||
static NBShaderFeatureLevelSettingsProvider()
|
||||
{
|
||||
NBFXProjectSettings.RegisterSettingsSection(
|
||||
"NBShaderFeatureLevels",
|
||||
GetProviderLabelContent,
|
||||
OnGUI,
|
||||
new[]
|
||||
{
|
||||
"NBShader",
|
||||
"Feature",
|
||||
"Tier",
|
||||
"Strip",
|
||||
"Keyword",
|
||||
"Quality",
|
||||
"Apply",
|
||||
"Material",
|
||||
"Loaded Materials",
|
||||
"Project Materials",
|
||||
"应用",
|
||||
"材质",
|
||||
"等级",
|
||||
"分级",
|
||||
"剔除"
|
||||
},
|
||||
100);
|
||||
}
|
||||
|
||||
private static void OnGUI(string searchContext)
|
||||
{
|
||||
EnsureContentCacheForCurrentLanguage();
|
||||
|
||||
var settings = NBShaderFeatureLevelProjectSettings.instance;
|
||||
settings.EnsureInitialized();
|
||||
|
||||
var changed = false;
|
||||
|
||||
EditorGUILayout.HelpBox(
|
||||
Text(
|
||||
"featureLevel.help.message",
|
||||
"Configure NBShader managed Catalog keywords and shader passes per tier, and bind Unity Quality levels. Build scripts select the build stripping tier through NBShaderFeatureLevelEditorAPI.OverrideBuildStripExplicitTier. Runtime settings assets can be updated from their own Inspector or Editor API. Catalog-external features are ignored."),
|
||||
MessageType.Info);
|
||||
|
||||
changed |= DrawFeatureLevelTable(settings);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
changed |= DrawButtons(settings);
|
||||
|
||||
if (changed)
|
||||
settings.SaveProjectSettings();
|
||||
}
|
||||
|
||||
private static bool DrawFeatureLevelTable(NBShaderFeatureLevelProjectSettings settings)
|
||||
{
|
||||
var changed = false;
|
||||
|
||||
EditorGUILayout.LabelField(
|
||||
Text("featureLevel.table.title", "Feature Level Matrix"),
|
||||
EditorStyles.boldLabel);
|
||||
|
||||
s_TableScrollPosition = EditorGUILayout.BeginScrollView(
|
||||
s_TableScrollPosition,
|
||||
true,
|
||||
true,
|
||||
GUILayout.MinHeight(TableMinHeight),
|
||||
GUILayout.MaxHeight(TableMaxHeight));
|
||||
|
||||
using (new GUILayout.VerticalScope(GUILayout.Width(TableWidth)))
|
||||
{
|
||||
DrawTableHeader();
|
||||
DrawQualityBindingRow(settings);
|
||||
DrawTableSeparator();
|
||||
changed |= DrawFeatureRows(settings);
|
||||
}
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
private static void DrawTableHeader()
|
||||
{
|
||||
using (new EditorGUILayout.HorizontalScope(EditorStyles.toolbar, GUILayout.Height(HeaderHeight)))
|
||||
{
|
||||
DrawHeaderCell(
|
||||
Content(
|
||||
"featureLevel.column.feature",
|
||||
"Config / Feature",
|
||||
"Tier settings and managed Catalog features."),
|
||||
FeatureColumnWidth);
|
||||
|
||||
for (var i = 0; i < Tiers.Length; i++)
|
||||
DrawHeaderCell(GetTierContent(Tiers[i]), TierColumnWidth);
|
||||
|
||||
DrawHeaderCell(
|
||||
Content(
|
||||
"featureLevel.column.cost",
|
||||
"Performance Cost",
|
||||
"Estimated shader cost when this feature is enabled."),
|
||||
CostColumnWidth);
|
||||
|
||||
DrawHeaderCell(
|
||||
Content(
|
||||
"featureLevel.column.effect",
|
||||
"Feature Effect",
|
||||
"Short description of what this keyword enables."),
|
||||
EffectColumnWidth);
|
||||
|
||||
DrawHeaderCell(
|
||||
Content(
|
||||
"featureLevel.column.description",
|
||||
"Raw Keyword / Note",
|
||||
"Raw shader keyword or configuration note."),
|
||||
DescriptionColumnWidth);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawHeaderCell(GUIContent content, float width)
|
||||
{
|
||||
GUILayout.Label(content, EditorStyles.toolbarButton, GUILayout.Width(width), GUILayout.Height(HeaderHeight));
|
||||
}
|
||||
|
||||
private static void DrawQualityBindingRow(NBShaderFeatureLevelProjectSettings settings)
|
||||
{
|
||||
using (new EditorGUILayout.HorizontalScope(GUILayout.Height(RowHeight)))
|
||||
{
|
||||
GUILayout.Label(
|
||||
Content(
|
||||
"featureLevel.row.quality",
|
||||
"Quality Binding",
|
||||
"Each Unity Quality Level belongs to exactly one NBShader tier."),
|
||||
GUILayout.Width(FeatureColumnWidth),
|
||||
GUILayout.Height(RowHeight));
|
||||
|
||||
for (var i = 0; i < Tiers.Length; i++)
|
||||
{
|
||||
var tier = Tiers[i];
|
||||
if (GUILayout.Button(
|
||||
GetQualitySummaryContent(settings, tier, i),
|
||||
EditorStyles.popup,
|
||||
GUILayout.Width(TierColumnWidth),
|
||||
GUILayout.Height(RowHeight)))
|
||||
{
|
||||
ShowQualityBindingMenu(settings, tier);
|
||||
}
|
||||
}
|
||||
|
||||
DrawCostPlaceholderCell();
|
||||
DrawInfoCell(
|
||||
Content(
|
||||
"featureLevel.effect.quality",
|
||||
"Bind Unity Quality Levels to NBShader tiers.",
|
||||
"Each Unity Quality Level belongs to exactly one NBShader tier."),
|
||||
EffectColumnWidth);
|
||||
DrawInfoCell(
|
||||
GetQualityDescriptionContent(),
|
||||
DescriptionColumnWidth);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool DrawFeatureRows(NBShaderFeatureLevelProjectSettings settings)
|
||||
{
|
||||
var changed = false;
|
||||
var rows = NBShaderFeatureLevelRowCatalog.Rows;
|
||||
var allowedKeywordSets = new HashSet<string>[Tiers.Length];
|
||||
var allowedPassFeatureSets = new HashSet<string>[Tiers.Length];
|
||||
for (var i = 0; i < Tiers.Length; i++)
|
||||
{
|
||||
allowedKeywordSets[i] = settings.GetAllowedKeywordSetForReadOnlyUse(Tiers[i]);
|
||||
allowedPassFeatureSets[i] = settings.GetAllowedPassFeatureSetForReadOnlyUse(Tiers[i]);
|
||||
}
|
||||
|
||||
for (var rowIndex = 0; rowIndex < rows.Length; rowIndex++)
|
||||
{
|
||||
var row = rows[rowIndex];
|
||||
if (!IsRowVisible(row))
|
||||
continue;
|
||||
|
||||
using (var rowScope = new EditorGUILayout.HorizontalScope(GUILayout.Height(RowHeight)))
|
||||
{
|
||||
DrawFeatureRowBackground(rowScope.rect, row);
|
||||
DrawFeatureNameCell(row);
|
||||
|
||||
if (row.isKeyword)
|
||||
{
|
||||
for (var tierIndex = 0; tierIndex < Tiers.Length; tierIndex++)
|
||||
{
|
||||
var tier = Tiers[tierIndex];
|
||||
var isAllowed = allowedKeywordSets[tierIndex].Contains(row.keyword);
|
||||
var newAllowed = DrawCellToggle(isAllowed, GUI.skin.toggle);
|
||||
if (newAllowed == isAllowed)
|
||||
continue;
|
||||
|
||||
Undo.RecordObject(settings, Text("featureLevel.undo.changeKeyword", "Change NBShader Feature Keyword"));
|
||||
settings.SetKeywordAllowed(tier, row.keyword, newAllowed);
|
||||
if (newAllowed)
|
||||
allowedKeywordSets[tierIndex].Add(row.keyword);
|
||||
else
|
||||
allowedKeywordSets[tierIndex].Remove(row.keyword);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else if (row.isPass)
|
||||
{
|
||||
for (var tierIndex = 0; tierIndex < Tiers.Length; tierIndex++)
|
||||
{
|
||||
var tier = Tiers[tierIndex];
|
||||
var isAllowed = allowedPassFeatureSets[tierIndex].Contains(row.passFeatureId);
|
||||
var newAllowed = DrawCellToggle(isAllowed, GUI.skin.toggle);
|
||||
if (newAllowed == isAllowed)
|
||||
continue;
|
||||
|
||||
Undo.RecordObject(settings, Text("featureLevel.undo.changePassFeature", "Change NBShader Pass Feature"));
|
||||
settings.SetPassFeatureAllowed(tier, row.passFeatureId, newAllowed);
|
||||
if (newAllowed)
|
||||
allowedPassFeatureSets[tierIndex].Add(row.passFeatureId);
|
||||
else
|
||||
allowedPassFeatureSets[tierIndex].Remove(row.passFeatureId);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawEmptyTierCells();
|
||||
}
|
||||
|
||||
DrawCostCell(row);
|
||||
DrawInfoCell(GetEffectContent(row), EffectColumnWidth);
|
||||
DrawInfoCell(
|
||||
GetDescriptionContent(row),
|
||||
DescriptionColumnWidth,
|
||||
row.isKeyword ? EditorStyles.miniLabel : EditorStyles.centeredGreyMiniLabel);
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
private static void DrawFeatureNameCell(NBShaderFeatureLevelRow row)
|
||||
{
|
||||
var rect = EditorGUILayout.GetControlRect(
|
||||
false,
|
||||
RowHeight,
|
||||
GUILayout.Width(FeatureColumnWidth),
|
||||
GUILayout.Height(RowHeight));
|
||||
|
||||
var hasChildren = NBShaderFeatureLevelRowCatalog.HasChildren(row);
|
||||
var indent = row.depth * RowIndentWidth;
|
||||
var foldoutRect = new Rect(rect.x + indent, rect.y, 14f, rect.height);
|
||||
var labelRect = new Rect(
|
||||
rect.x + indent + (hasChildren ? 15f : 18f),
|
||||
rect.y,
|
||||
Mathf.Max(0f, rect.width - indent - 18f),
|
||||
rect.height);
|
||||
|
||||
if (hasChildren)
|
||||
{
|
||||
var expanded = IsExpanded(row.key);
|
||||
var newExpanded = EditorGUI.Foldout(foldoutRect, expanded, GUIContent.none, true);
|
||||
if (newExpanded != expanded)
|
||||
SetExpanded(row.key, newExpanded);
|
||||
}
|
||||
|
||||
var style = hasChildren ? EditorStyles.boldLabel : EditorStyles.label;
|
||||
EditorGUI.LabelField(labelRect, GetRowContent(row), style);
|
||||
}
|
||||
|
||||
private static void DrawFeatureRowBackground(Rect rowRect, NBShaderFeatureLevelRow row)
|
||||
{
|
||||
if (!IsSectionRow(row) || Event.current.type != EventType.Repaint)
|
||||
return;
|
||||
|
||||
rowRect.width = TableWidth;
|
||||
EditorGUI.DrawRect(rowRect, new Color(0f, 0f, 0f, EditorGUIUtility.isProSkin ? 0.22f : 0.08f));
|
||||
}
|
||||
|
||||
private static bool IsSectionRow(NBShaderFeatureLevelRow row)
|
||||
{
|
||||
return row != null &&
|
||||
row.kind == NBShaderFeatureLevelRowKind.Group &&
|
||||
string.IsNullOrEmpty(row.parentKey);
|
||||
}
|
||||
|
||||
private static void DrawEmptyTierCells()
|
||||
{
|
||||
for (var i = 0; i < Tiers.Length; i++)
|
||||
GUILayout.Space(TierColumnWidth);
|
||||
}
|
||||
|
||||
private static void DrawCostCell(NBShaderFeatureLevelRow row)
|
||||
{
|
||||
if (row != null && (row.isKeyword || row.isPass))
|
||||
{
|
||||
DrawInfoCell(GetCostContent(row.performanceCost), CostColumnWidth, EditorStyles.centeredGreyMiniLabel);
|
||||
return;
|
||||
}
|
||||
|
||||
DrawCostPlaceholderCell();
|
||||
}
|
||||
|
||||
private static void DrawCostPlaceholderCell()
|
||||
{
|
||||
DrawInfoCell(GetNoValueContent(), CostColumnWidth, EditorStyles.centeredGreyMiniLabel);
|
||||
}
|
||||
|
||||
private static void DrawInfoCell(GUIContent content, float width, GUIStyle style = null)
|
||||
{
|
||||
GUILayout.Label(
|
||||
content,
|
||||
style ?? EditorStyles.miniLabel,
|
||||
GUILayout.Width(width),
|
||||
GUILayout.Height(RowHeight));
|
||||
}
|
||||
|
||||
private static bool DrawButtons(NBShaderFeatureLevelProjectSettings settings)
|
||||
{
|
||||
var changed = false;
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button(ButtonContent(
|
||||
"featureLevel.resetTierKeywords",
|
||||
"Reset Tier Features",
|
||||
"Reset the keyword and pass matrix to the built-in defaults.")))
|
||||
{
|
||||
Undo.RecordObject(settings, Text("featureLevel.undo.resetTierKeywords", "Reset NBShader Tier Features"));
|
||||
settings.ResetTierKeywordSetsToDefault();
|
||||
settings.ResetTierPassSetsToDefault();
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (GUILayout.Button(ButtonContent(
|
||||
"featureLevel.resetQualityMapping",
|
||||
"Reset Quality Mapping",
|
||||
"Reset Unity Quality bindings using the default quality-index rule.")))
|
||||
{
|
||||
Undo.RecordObject(settings, Text("featureLevel.undo.resetQualityMapping", "Reset NBShader Quality Mapping"));
|
||||
settings.ResetQualityMappingsToDefault();
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button(ButtonContent(
|
||||
"featureLevel.openVariantCollectionBuilder",
|
||||
"Open Variant Collection Builder",
|
||||
"Open the NBShader variant collection builder.")))
|
||||
{
|
||||
NBShaderSVCBuilderWindow.Open();
|
||||
}
|
||||
|
||||
if (GUILayout.Button(ButtonContent(
|
||||
"featureLevel.saveCurrentAsDefault",
|
||||
"Save Current Config as Default",
|
||||
"Write the current tier keyword and pass matrix into the package default LevelAsset.")))
|
||||
{
|
||||
if (!NBShaderFeatureLevelPresetLoader.SaveDefaultFeatureSets(settings.tierKeywordSets, settings.tierPassSets))
|
||||
{
|
||||
EditorUtility.DisplayDialog(
|
||||
Text("featureLevel.saveCurrentAsDefault.failedTitle", "Save Default Config Failed"),
|
||||
Text("featureLevel.saveCurrentAsDefault.failedMessage", "Could not write the package default LevelAsset."),
|
||||
Text("featureLevel.dialog.ok", "OK"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button(ButtonContent(
|
||||
"featureLevel.applyCurrentQualityTierToLoadedMaterials",
|
||||
"Apply Current Quality Tier To Loaded Materials",
|
||||
"Apply the tier bound to the current Unity Quality Level to all loaded NBShader2 materials.")))
|
||||
{
|
||||
NBShaderEditorQualityTierWatcher.ApplyCurrentQualityTierToLoadedMaterials();
|
||||
}
|
||||
|
||||
if (GUILayout.Button(ButtonContent(
|
||||
"featureLevel.applyCurrentQualityTierToProjectMaterials",
|
||||
"Apply Current Quality Tier To Project Materials",
|
||||
"Scan Assets and apply the tier bound to the current Unity Quality Level to NBShader2 material assets.")))
|
||||
{
|
||||
NBShaderEditorQualityTierWatcher.ApplyCurrentQualityTierToProjectMaterials();
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
private static void ShowQualityBindingMenu(NBShaderFeatureLevelProjectSettings settings, NBShaderFeatureTier targetTier)
|
||||
{
|
||||
var menu = new GenericMenu();
|
||||
var mappings = settings.qualityTierMappings;
|
||||
if (mappings == null || mappings.Length == 0)
|
||||
{
|
||||
menu.AddDisabledItem(new GUIContent(Text("featureLevel.quality.noLevels", "No Quality Levels")));
|
||||
menu.ShowAsContext();
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < mappings.Length; i++)
|
||||
{
|
||||
var mapping = mappings[i];
|
||||
if (mapping == null || string.IsNullOrEmpty(mapping.qualityName))
|
||||
continue;
|
||||
|
||||
var qualityName = mapping.qualityName;
|
||||
NBShaderFeatureTier currentTier;
|
||||
var isCurrentTier = settings.TryGetTierForQualityName(qualityName, out currentTier) && currentTier == targetTier;
|
||||
if (isCurrentTier)
|
||||
{
|
||||
menu.AddDisabledItem(new GUIContent("✓ " + qualityName));
|
||||
continue;
|
||||
}
|
||||
|
||||
menu.AddItem(new GUIContent(qualityName), false, () =>
|
||||
{
|
||||
Undo.RecordObject(settings, Text("featureLevel.undo.changeQualityBinding", "Change NBShader Quality Binding"));
|
||||
settings.MoveQualityToTier(qualityName, targetTier);
|
||||
settings.SaveProjectSettings();
|
||||
UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
|
||||
});
|
||||
}
|
||||
|
||||
menu.ShowAsContext();
|
||||
}
|
||||
|
||||
private static bool DrawCellToggle(bool value, GUIStyle style)
|
||||
{
|
||||
bool result;
|
||||
using (new GUILayout.HorizontalScope(GUILayout.Width(TierColumnWidth), GUILayout.Height(RowHeight)))
|
||||
{
|
||||
GUILayout.FlexibleSpace();
|
||||
result = GUILayout.Toggle(
|
||||
value,
|
||||
GUIContent.none,
|
||||
style,
|
||||
GUILayout.Width(18f),
|
||||
GUILayout.Height(RowHeight));
|
||||
GUILayout.FlexibleSpace();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void DrawTableSeparator()
|
||||
{
|
||||
var rect = EditorGUILayout.GetControlRect(false, 1f, GUILayout.Width(TableWidth));
|
||||
EditorGUI.DrawRect(rect, new Color(0f, 0f, 0f, 0.25f));
|
||||
}
|
||||
|
||||
private static bool IsRowVisible(NBShaderFeatureLevelRow row)
|
||||
{
|
||||
var parentKey = row.parentKey;
|
||||
while (!string.IsNullOrEmpty(parentKey))
|
||||
{
|
||||
if (!IsExpanded(parentKey))
|
||||
return false;
|
||||
|
||||
NBShaderFeatureLevelRow parent;
|
||||
parentKey = NBShaderFeatureLevelRowCatalog.TryGetRow(parentKey, out parent) ? parent.parentKey : null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsExpanded(string key)
|
||||
{
|
||||
return SessionState.GetBool(FoldoutSessionPrefix + key, true);
|
||||
}
|
||||
|
||||
private static void SetExpanded(string key, bool expanded)
|
||||
{
|
||||
SessionState.SetBool(FoldoutSessionPrefix + key, expanded);
|
||||
}
|
||||
|
||||
private static GUIContent GetTierContent(NBShaderFeatureTier tier)
|
||||
{
|
||||
switch (tier)
|
||||
{
|
||||
case NBShaderFeatureTier.Low:
|
||||
return NBShaderInspectorLocalization.MakeContent(
|
||||
"inspector.toolbar.tierLow.label",
|
||||
"Low",
|
||||
"inspector.toolbar.tier.tip",
|
||||
"NBShader feature tier");
|
||||
case NBShaderFeatureTier.Medium:
|
||||
return NBShaderInspectorLocalization.MakeContent(
|
||||
"inspector.toolbar.tierMedium.label",
|
||||
"Medium",
|
||||
"inspector.toolbar.tier.tip",
|
||||
"NBShader feature tier");
|
||||
case NBShaderFeatureTier.High:
|
||||
return NBShaderInspectorLocalization.MakeContent(
|
||||
"inspector.toolbar.tierHigh.label",
|
||||
"High",
|
||||
"inspector.toolbar.tier.tip",
|
||||
"NBShader feature tier");
|
||||
default:
|
||||
return NBShaderInspectorLocalization.MakeContent(
|
||||
"inspector.toolbar.tierUltra.label",
|
||||
"Ultra",
|
||||
"inspector.toolbar.tier.tip",
|
||||
"NBShader feature tier");
|
||||
}
|
||||
}
|
||||
|
||||
private static GUIContent GetRowContent(NBShaderFeatureLevelRow row)
|
||||
{
|
||||
return GetCachedRowContent(row).rowContent;
|
||||
}
|
||||
|
||||
private static GUIContent BuildRowContent(NBShaderFeatureLevelRow row)
|
||||
{
|
||||
if (row.isKeyword)
|
||||
return BuildKeywordContent(row.keyword, row.labelFallback);
|
||||
|
||||
if (row.isPass)
|
||||
return BuildPassContent(row.passFeatureId, row.labelFallback);
|
||||
|
||||
return NBShaderInspectorLocalization.MakeContent(
|
||||
"inspector.featureLevel.group." + row.key + ".label",
|
||||
row.labelFallback,
|
||||
"inspector.featureLevel.group." + row.key + ".tip",
|
||||
Text("featureLevel.group.tooltip", "Click the foldout to show or hide child rows."));
|
||||
}
|
||||
|
||||
private static GUIContent BuildKeywordContent(string keyword, string fallback)
|
||||
{
|
||||
var label = NBShaderInspectorLocalization.Get(
|
||||
"inspector.featureLevel.keyword." + keyword + ".label",
|
||||
string.IsNullOrEmpty(fallback) ? keyword : fallback);
|
||||
var tooltipFormat = Text(
|
||||
"featureLevel.keyword.tooltip",
|
||||
"Raw keyword: {0}. Unchecked in a tier strips variants using this Catalog keyword.");
|
||||
return new GUIContent(label, string.Format(tooltipFormat, keyword));
|
||||
}
|
||||
|
||||
private static GUIContent BuildPassContent(string passFeatureId, string fallback)
|
||||
{
|
||||
string passName;
|
||||
string displayName;
|
||||
if (!NBShaderFeatureLevelCatalog.TryGetManagedPassFeatureInfo(passFeatureId, out passName, out displayName))
|
||||
{
|
||||
passName = passFeatureId;
|
||||
displayName = string.IsNullOrEmpty(fallback) ? passFeatureId : fallback;
|
||||
}
|
||||
|
||||
var label = NBShaderInspectorLocalization.Get(
|
||||
"inspector.featureLevel.pass." + passFeatureId + ".label",
|
||||
string.IsNullOrEmpty(fallback) ? displayName : fallback);
|
||||
var tooltipFormat = Text(
|
||||
"featureLevel.pass.tooltip",
|
||||
"Shader pass: {0}. Unchecked in a tier strips or gates this pass when material intent requires it.");
|
||||
return new GUIContent(label, string.Format(tooltipFormat, passName));
|
||||
}
|
||||
|
||||
private static GUIContent GetCostContent(NBShaderFeaturePerformanceCost cost)
|
||||
{
|
||||
GUIContent content;
|
||||
if (s_CostContentCache.TryGetValue(cost, out content))
|
||||
return content;
|
||||
|
||||
string key;
|
||||
string fallback;
|
||||
switch (cost)
|
||||
{
|
||||
case NBShaderFeaturePerformanceCost.Low:
|
||||
key = "featureLevel.cost.low";
|
||||
fallback = "Low";
|
||||
break;
|
||||
case NBShaderFeaturePerformanceCost.Medium:
|
||||
key = "featureLevel.cost.medium";
|
||||
fallback = "Medium";
|
||||
break;
|
||||
case NBShaderFeaturePerformanceCost.High:
|
||||
key = "featureLevel.cost.high";
|
||||
fallback = "High";
|
||||
break;
|
||||
default:
|
||||
key = "featureLevel.cost.ultra";
|
||||
fallback = "Ultra";
|
||||
break;
|
||||
}
|
||||
|
||||
content = new GUIContent(
|
||||
Text(key, fallback),
|
||||
Text("featureLevel.cost.tooltip", "Estimated shader performance cost for this feature."));
|
||||
s_CostContentCache[cost] = content;
|
||||
return content;
|
||||
}
|
||||
|
||||
private static GUIContent GetEffectContent(NBShaderFeatureLevelRow row)
|
||||
{
|
||||
return GetCachedRowContent(row).effectContent;
|
||||
}
|
||||
|
||||
private static GUIContent BuildEffectContent(NBShaderFeatureLevelRow row)
|
||||
{
|
||||
if (row.isKeyword)
|
||||
{
|
||||
var effect = NBShaderInspectorLocalization.Get(
|
||||
"inspector.featureLevel.keyword." + row.keyword + ".effect",
|
||||
string.IsNullOrEmpty(row.effectFallback) ? row.keyword : row.effectFallback);
|
||||
return new GUIContent(effect, effect);
|
||||
}
|
||||
|
||||
if (row.isPass)
|
||||
{
|
||||
var effect = NBShaderInspectorLocalization.Get(
|
||||
"inspector.featureLevel.pass." + row.passFeatureId + ".effect",
|
||||
string.IsNullOrEmpty(row.effectFallback) ? row.passFeatureId : row.effectFallback);
|
||||
return new GUIContent(effect, effect);
|
||||
}
|
||||
|
||||
var groupTip = NBShaderInspectorLocalization.GetTooltip(
|
||||
"inspector.featureLevel.group." + row.key + ".label",
|
||||
"inspector.featureLevel.group." + row.key + ".tip",
|
||||
Text("featureLevel.group.tooltip", "Click the foldout to show or hide child rows."));
|
||||
return new GUIContent(groupTip, groupTip);
|
||||
}
|
||||
|
||||
private static GUIContent GetDescriptionContent(NBShaderFeatureLevelRow row)
|
||||
{
|
||||
return GetCachedRowContent(row).descriptionContent;
|
||||
}
|
||||
|
||||
private static GUIContent BuildDescriptionContent(NBShaderFeatureLevelRow row)
|
||||
{
|
||||
if (row.isKeyword)
|
||||
return new GUIContent(row.keyword, row.keyword);
|
||||
|
||||
if (row.isPass)
|
||||
{
|
||||
string passName;
|
||||
string displayName;
|
||||
if (NBShaderFeatureLevelCatalog.TryGetManagedPassFeatureInfo(row.passFeatureId, out passName, out displayName))
|
||||
return new GUIContent(passName, row.passFeatureId);
|
||||
|
||||
return new GUIContent(row.passFeatureId, row.passFeatureId);
|
||||
}
|
||||
|
||||
return new GUIContent(
|
||||
Text("featureLevel.desc.group", "Group"),
|
||||
Text("featureLevel.group.tooltip", "Click the foldout to show or hide child rows."));
|
||||
}
|
||||
|
||||
private static GUIContent GetNoValueContent()
|
||||
{
|
||||
if (s_NoValueContent != null)
|
||||
return s_NoValueContent;
|
||||
|
||||
var text = Text("featureLevel.desc.none", "—");
|
||||
s_NoValueContent = new GUIContent(text, text);
|
||||
return s_NoValueContent;
|
||||
}
|
||||
|
||||
private static GUIContent GetProviderLabelContent()
|
||||
{
|
||||
EnsureContentCacheForCurrentLanguage();
|
||||
|
||||
if (s_ProviderLabelContent == null)
|
||||
s_ProviderLabelContent = new GUIContent(Text("featureLevel.providerLabel", "NBShader Feature Levels"));
|
||||
|
||||
return s_ProviderLabelContent;
|
||||
}
|
||||
|
||||
private static GUIContent GetQualityDescriptionContent()
|
||||
{
|
||||
if (s_QualityDescriptionContent == null)
|
||||
{
|
||||
var text = Text("featureLevel.desc.quality", "Unity Quality Level");
|
||||
s_QualityDescriptionContent = new GUIContent(text, text);
|
||||
}
|
||||
|
||||
return s_QualityDescriptionContent;
|
||||
}
|
||||
|
||||
private static GUIContent GetQualitySummaryContent(
|
||||
NBShaderFeatureLevelProjectSettings settings,
|
||||
NBShaderFeatureTier tier,
|
||||
int tierIndex)
|
||||
{
|
||||
EnsureQualitySummaryCache(settings);
|
||||
|
||||
var content = s_QualitySummaryContents[tierIndex];
|
||||
if (content == null)
|
||||
{
|
||||
content = new GUIContent();
|
||||
s_QualitySummaryContents[tierIndex] = content;
|
||||
}
|
||||
|
||||
content.text = s_QualitySummaryTexts[tierIndex];
|
||||
content.tooltip = GetQualityMenuTipText();
|
||||
return content;
|
||||
}
|
||||
|
||||
private static void EnsureQualitySummaryCache(NBShaderFeatureLevelProjectSettings settings)
|
||||
{
|
||||
var mappings = settings.qualityTierMappings;
|
||||
var hash = GetQualitySummaryHash(mappings);
|
||||
if (s_QualitySummaryTexts[0] != null && s_QualitySummaryHash == hash)
|
||||
return;
|
||||
|
||||
s_QualitySummaryHash = hash;
|
||||
var noneText = Text("featureLevel.quality.none", "—");
|
||||
for (var tierIndex = 0; tierIndex < Tiers.Length; tierIndex++)
|
||||
{
|
||||
s_QualitySummaryBuilder.Length = 0;
|
||||
if (mappings != null)
|
||||
{
|
||||
var tier = Tiers[tierIndex];
|
||||
for (var i = 0; i < mappings.Length; i++)
|
||||
{
|
||||
var mapping = mappings[i];
|
||||
if (mapping == null ||
|
||||
mapping.tier != tier ||
|
||||
string.IsNullOrEmpty(mapping.qualityName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s_QualitySummaryBuilder.Length > 0)
|
||||
s_QualitySummaryBuilder.Append(", ");
|
||||
s_QualitySummaryBuilder.Append(mapping.qualityName);
|
||||
}
|
||||
}
|
||||
|
||||
s_QualitySummaryTexts[tierIndex] =
|
||||
s_QualitySummaryBuilder.Length == 0
|
||||
? noneText
|
||||
: s_QualitySummaryBuilder.ToString();
|
||||
}
|
||||
|
||||
s_QualitySummaryBuilder.Length = 0;
|
||||
}
|
||||
|
||||
private static int GetQualitySummaryHash(NBShaderQualityTierMapping[] mappings)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
var hash = 17;
|
||||
if (mappings == null)
|
||||
return hash;
|
||||
|
||||
for (var i = 0; i < mappings.Length; i++)
|
||||
{
|
||||
var mapping = mappings[i];
|
||||
hash = hash * 31 + (mapping != null ? (int)mapping.tier : -1);
|
||||
hash = hash * 31 + (mapping != null && mapping.qualityName != null
|
||||
? StringComparer.Ordinal.GetHashCode(mapping.qualityName)
|
||||
: 0);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetQualityMenuTipText()
|
||||
{
|
||||
if (s_QualityMenuTipText == null)
|
||||
{
|
||||
s_QualityMenuTipText = Text(
|
||||
"featureLevel.quality.menuTip",
|
||||
"Click to move Unity Quality levels to this NBShader tier.");
|
||||
}
|
||||
|
||||
return s_QualityMenuTipText;
|
||||
}
|
||||
|
||||
private static RowContentCache GetCachedRowContent(NBShaderFeatureLevelRow row)
|
||||
{
|
||||
RowContentCache cache;
|
||||
if (!s_RowContentCache.TryGetValue(row.key, out cache))
|
||||
{
|
||||
cache = new RowContentCache
|
||||
{
|
||||
rowContent = BuildRowContent(row),
|
||||
effectContent = BuildEffectContent(row),
|
||||
descriptionContent = BuildDescriptionContent(row)
|
||||
};
|
||||
s_RowContentCache.Add(row.key, cache);
|
||||
}
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
private static void EnsureContentCacheForCurrentLanguage()
|
||||
{
|
||||
var language = NBShaderInspectorLocalization.CurrentLanguage;
|
||||
if (string.Equals(s_ContentCacheLanguage, language, StringComparison.Ordinal))
|
||||
return;
|
||||
|
||||
s_ContentCacheLanguage = language;
|
||||
s_RowContentCache.Clear();
|
||||
s_CostContentCache.Clear();
|
||||
s_ProviderLabelContent = null;
|
||||
s_QualityDescriptionContent = null;
|
||||
s_NoValueContent = null;
|
||||
s_QualityMenuTipText = null;
|
||||
s_QualitySummaryHash = 0;
|
||||
for (var i = 0; i < s_QualitySummaryContents.Length; i++)
|
||||
{
|
||||
s_QualitySummaryContents[i] = null;
|
||||
s_QualitySummaryTexts[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static GUIContent Content(string key, string fallback, string tip = "")
|
||||
{
|
||||
return NBShaderInspectorLocalization.MakeInspectorContent(key, fallback, tip);
|
||||
}
|
||||
|
||||
private static GUIContent ButtonContent(string key, string fallback, string tip = "")
|
||||
{
|
||||
return NBShaderInspectorLocalization.MakeContent("inspector." + key + ".button", fallback, null, tip);
|
||||
}
|
||||
|
||||
private static string Text(string key, string fallback)
|
||||
{
|
||||
return NBShaderInspectorLocalization.GetInspectorText(key, fallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user