Skip to content

Commit

Permalink
feat: automatically display a dialog to import TextMeshPro support
Browse files Browse the repository at this point in the history
  • Loading branch information
mob-sakai committed Dec 27, 2024
1 parent 297c343 commit 5b50979
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ internal static class MaterialRepository

#if UNITY_EDITOR
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void Clear()
public static void Clear()
{
s_Repository.Clear();
}
Expand Down
72 changes: 68 additions & 4 deletions Packages/src/Runtime/Internal/Utilities/ShaderVariantRegistry.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.Profiling;
#if UNITY_EDITOR
using System.IO;
using Object = UnityEngine.Object;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditor.PackageManager.UI;
using UnityEditorInternal;
using PackageInfo = UnityEditor.PackageManager.PackageInfo;
using Object = UnityEngine.Object;
#endif

namespace Coffee.UIEffectInternal
Expand Down Expand Up @@ -75,7 +78,7 @@ public Shader FindOptionalShader(Shader shader,
return Shader.Find(optionalShaderName);
}

// Required shader.
// The shader has
if (shader.name.Contains(requiredName))
{
_cachedOptionalShaders[id] = shader.name;
Expand Down Expand Up @@ -105,16 +108,70 @@ public Shader FindOptionalShader(Shader shader,
return optionalShader;
}

#if UNITY_EDITOR
ImportFromSample(optionalShaderName);
#endif

// Find default optional shader.
_cachedOptionalShaders[id] = defaultOptionalShaderName;
return Shader.Find(defaultOptionalShaderName);
}

#if UNITY_EDITOR
private HashSet<StringPair> _logVariants = new HashSet<StringPair>();
private readonly HashSet<StringPair> _logVariants = new HashSet<StringPair>();
private readonly Dictionary<string, string> _sampleNames = new Dictionary<string, string>();

/// <summary>
/// Import the sample containing the requested shader.
/// If choice 'Import' is selected, the sample is imported.
/// If choice 'Skip in this session' is selected, the sample is skipped in this session.
/// </summary>
public void ImportFromSample(string shaderName)
{
if (Misc.isBatchOrBuilding) return;

// Find sample name.
if (_sampleNames.TryGetValue(shaderName, out var sampleName))
{
// Find package info.
var pInfo = PackageInfo.FindForAssembly(typeof(ShaderVariantRegistry).Assembly);
if (pInfo == null) return;

// Find sample. If not found (resolvedPath == null), skip.
var sample = Sample.FindByPackage(pInfo.name, pInfo.version)
.FirstOrDefault(x => x.displayName == sampleName);
if (sample.resolvedPath == null) return;

// Import the sample if selected.
var importSelected = EditorUtility.DisplayDialog($"Import {sampleName}",
$"Import '{sampleName}' to use the shader '{shaderName}'", "Import", "Cancel");
if (importSelected)
{
EditorApplication.delayCall += () =>
{
sample.Import();
};
}
}
}

public void ClearCache()
{
_cachedOptionalShaders.Clear();
}

public void RegisterSamples((string shaderName, string sampleName)[] samples)
{
foreach (var (shaderName, sampleName) in samples)
{
_sampleNames[shaderName] = sampleName;
}
}

public void InitializeIfNeeded(Object owner, string optionalName)
{
Profiler.BeginSample("(EDITOR/COF)[ShaderVariantRegistry] InitializeIfNeeded");

// Register optional shader names by shader comment.
if (!string.IsNullOrEmpty(optionalName))
{
Expand Down Expand Up @@ -159,12 +216,16 @@ public void InitializeIfNeeded(Object owner, string optionalName)
EditorUtility.SetDirty(owner);
AssetDatabase.SaveAssets();
}

ClearCache();
Profiler.EndSample();
}

internal void RegisterVariant(Material material, string path)
{
if (!material || !material.shader || !m_Asset) return;

Profiler.BeginSample("(EDITOR/COF)[ShaderVariantRegistry] RegisterVariant");
var shaderName = material.shader.name;
var validKeywords = material.shaderKeywords
.Where(x => !Regex.IsMatch(x, "(_EDITOR|EDITOR_)"))
Expand All @@ -181,6 +242,7 @@ internal void RegisterVariant(Material material, string path)
if (m_Asset.Contains(variant))
{
m_UnregisteredVariants.Remove(pair);
Profiler.EndSample();
return;
}

Expand All @@ -199,11 +261,13 @@ internal void RegisterVariant(Material material, string path)
$"Register it in 'ProjectSettings > {path}' to use it in player.", m_Asset);
}

Profiler.EndSample();
return;
}

m_Asset.Add(variant);
m_UnregisteredVariants.Remove(pair);
Profiler.EndSample();
}
#endif
}
Expand Down
21 changes: 0 additions & 21 deletions Packages/src/Runtime/UIEffectBase.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Coffee.UIEffectInternal;
using UnityEngine;
Expand Down Expand Up @@ -215,26 +214,6 @@ public virtual void ApplyContextToMaterial()
}

#if TMP_ENABLE
#if UNITY_EDITOR
private class Postprocessor : AssetPostprocessor
{
private static void OnPostprocessAllAssets(string[] _, string[] __, string[] ___, string[] ____)
{
if (Application.isBatchMode || BuildPipeline.isBuildingPlayer) return;

foreach (var effect in Misc.FindObjectsOfType<UIEffectBase>()
.Concat(Misc.GetAllComponentsInPrefabStage<UIEffectBase>()))
{
if (!effect.isActiveAndEnabled) continue;
if (!(effect.graphic is TextMeshProUGUI tmp) || !tmp.isActiveAndEnabled) continue;
effect.SetMaterialDirty();
}

EditorApplication.QueuePlayerLoopUpdate();
}
}
#endif

#if UNITY_EDITOR
[InitializeOnLoadMethod]
#else
Expand Down
44 changes: 44 additions & 0 deletions Packages/src/Runtime/UIEffectProjectSettings.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -82,6 +83,10 @@ protected override void OnEnable()
{
base.OnEnable();
SetPreferSamplingSize();
#if UNITY_EDITOR
SetupSamplesForShaderVariantRegistry();
m_ShaderVariantRegistry.ClearCache();
#endif
}

private void SetPreferSamplingSize()
Expand Down Expand Up @@ -117,6 +122,35 @@ private void OnValidate()
SetPreferSamplingSize();
}

private void SetupSamplesForShaderVariantRegistry()
{
#if UNITY_2023_2_OR_NEWER
const string tmpSupport = "TextMeshPro Support (Unity 6)";
#else
const string tmpSupport = "TextMeshPro Support";
#endif
m_ShaderVariantRegistry.RegisterSamples(new[]
{
("Hidden/TextMeshPro/Bitmap (UIEffect)", tmpSupport),
("Hidden/TextMeshPro/Mobile/Bitmap (UIEffect)", tmpSupport),
("Hidden/TextMeshPro/Distance Field (UIEffect)", tmpSupport),
("Hidden/TextMeshPro/Mobile/Distance Field (UIEffect)", tmpSupport)
});
}

private void Refresh()
{
m_ShaderVariantRegistry.ClearCache();
MaterialRepository.Clear();
foreach (var c in Misc.FindObjectsOfType<UIEffectBase>()
.Concat(Misc.GetAllComponentsInPrefabStage<UIEffectBase>()))
{
c.SetMaterialDirty();
}

EditorApplication.QueuePlayerLoopUpdate();
}

internal static UIEffect[] LoadEditorPresets()
{
var dirs = AssetDatabase.FindAssets(k_PresetDir + " t:folder")
Expand Down Expand Up @@ -163,6 +197,16 @@ internal static string GetPresetPath(UIEffect preset)
var m = Regex.Match(assetPath, k_PresetPathPattern);
return m.Success ? m.Groups[1].Value : Path.GetFileNameWithoutExtension(assetPath);
}

private class Postprocessor : AssetPostprocessor
{
private static void OnPostprocessAllAssets(string[] _, string[] __, string[] ___, string[] ____)
{
if (Misc.isBatchOrBuilding) return;

instance.Refresh();
}
}
#endif
}
}

0 comments on commit 5b50979

Please sign in to comment.