Skip to content

Instantly share code, notes, and snippets.

@rhys-vdw
Last active July 28, 2021 06:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rhys-vdw/fe97dda5193c00f75fe35e64d2acbd22 to your computer and use it in GitHub Desktop.
Save rhys-vdw/fe97dda5193c00f75fe35e64d2acbd22 to your computer and use it in GitHub Desktop.
Check for TMP materials shared between scene and GUI
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
namespace Feed.Editor {
public static class AssetUtility {
public static IEnumerable<string> AllAssetsPathsInDirectory(string directoryPath) {
var guids = AssetDatabase.FindAssets("", new [] { directoryPath });
foreach (var guid in guids) {
yield return AssetDatabase.GUIDToAssetPath(guid);
}
}
public static IEnumerable<T> LoadAllAssetsInDirectory<T>(string directoryPath) where T : Object {
var paths = AllAssetsPathsInDirectory(directoryPath);
foreach (var path in paths) {
var asset = AssetDatabase.LoadAssetAtPath<T>(path);
if (asset) yield return asset;
}
}
}
}
using Feed.Editor;
using NUnit.Framework;
using System.Collections.Generic;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEditor;
using System.Linq;
using TMPro;
namespace Feed.Tests {
public class TextMeshProBugTest {
static string[] GetAllAssetPaths<T>(string directory) where T : Object =>
AssetUtility
.LoadAllAssetsInDirectory<T>(directory)
.Select(s => AssetDatabase.GetAssetPath(s)).ToArray();
static string[] GetScenePaths() =>
GetAllAssetPaths<SceneAsset>(SceneEditorUtility.SceneDirectory);
static string[] GetPrefabPaths() =>
GetAllAssetPaths<GameObject>("Assets/_Game/Prefabs");
static List<T> FindObjectsIncludingInactive<T>() where T : Object {
var scene = EditorSceneManager.GetActiveScene();
var result = new List<T>();
var batch = new List<T>();
foreach (var root in scene.GetRootGameObjects()) {
root.GetComponentsInChildren<T>(includeInactive: true, batch);
result.AddRange(batch);
}
return result;
}
static void AuditTexts(IReadOnlyCollection<TextMeshPro> texts) {
var wrongMaterial = new List<TextMeshPro>();
var richText = new List<TextMeshPro>();
foreach (var text in texts) {
if (!text.fontSharedMaterial.name.Contains("SCENE_ONLY")) {
wrongMaterial.Add(text);
}
const FontStyles disallowedStyles = FontStyles.Bold | FontStyles.Italic;
if (text.richText || (text.fontStyle & disallowedStyles) != 0) {
richText.Add(text);
}
}
void AssertEmpty(List<TextMeshPro> ts, string complaint) {
if (ts.Count > 0) {
var items = ts.Select(t => $"- object: '{t.name}', material: '{t.fontSharedMaterial.name}'");
Assert.Fail(
$"TextMeshPro instances found with {complaint}:\n{string.Join("\n", items)}"
);
}
}
AssertEmpty(wrongMaterial, "non-scene material");
AssertEmpty(richText, "richText enabled or not regular style");
}
[TestCaseSource(nameof(GetScenePaths))]
public void CheckScene(string scenePath) {
EditorSceneManager.OpenScene(scenePath);
var sceneTexts = FindObjectsIncludingInactive<TextMeshPro>();
AuditTexts(sceneTexts);
}
[TestCaseSource(nameof(GetPrefabPaths))]
public void CheckPrefab(string path) {
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
var texts = prefab.GetComponentsInChildren<TextMeshPro>(includeInactive: true);
AuditTexts(texts);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment