fix: 垃圾测试
This commit is contained in:
@@ -1,416 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using AibisDream.UI;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditor.AddressableAssets;
|
|
||||||
using UnityEditor.AddressableAssets.Settings;
|
|
||||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
|
||||||
using UnityEditor.Build;
|
|
||||||
using UnityEditor.Build.Reporting;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace AibisDream.EditorTools.Localization
|
|
||||||
{
|
|
||||||
internal readonly struct LocalizedObjSpriteDirectory
|
|
||||||
{
|
|
||||||
internal LocalizedObjSpriteDirectory(
|
|
||||||
string localeCode,
|
|
||||||
string folderName,
|
|
||||||
string addressRoot,
|
|
||||||
string groupName)
|
|
||||||
{
|
|
||||||
LocaleCode = localeCode;
|
|
||||||
FolderName = folderName;
|
|
||||||
AddressRoot = addressRoot;
|
|
||||||
GroupName = groupName;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal string LocaleCode { get; }
|
|
||||||
internal string FolderName { get; }
|
|
||||||
internal string AddressRoot { get; }
|
|
||||||
internal string GroupName { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public readonly struct LocalizedObjSpriteValidationIssue
|
|
||||||
{
|
|
||||||
public LocalizedObjSpriteValidationIssue(string assetPath, string message)
|
|
||||||
{
|
|
||||||
AssetPath = assetPath;
|
|
||||||
Message = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string AssetPath { get; }
|
|
||||||
public string Message { get; }
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"{AssetPath}: {Message}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Validates locale-specific Obj folders without depending on Yarn references or
|
|
||||||
/// Unity Localization asset tables. A logical image becomes localized as soon as
|
|
||||||
/// it appears in any non-Chinese locale folder.
|
|
||||||
/// </summary>
|
|
||||||
public static class LocalizedObjSpriteValidator
|
|
||||||
{
|
|
||||||
internal const string DefaultArtRoot = "Assets/RawResources/Art";
|
|
||||||
internal const string DefaultFolderName = "Obj";
|
|
||||||
internal const string DefaultGroupName = "Shared_UI";
|
|
||||||
|
|
||||||
internal static readonly LocalizedObjSpriteDirectory[] LocaleDirectories =
|
|
||||||
{
|
|
||||||
new("en", "Obj_en", "Sprite/Obj_en", "Shared_ObjEn"),
|
|
||||||
new("ja-JP", "Obj_ja-JP", "Sprite/Obj_ja-JP", "Shared_ObjJaJp"),
|
|
||||||
new("ru", "Obj_ru", "Sprite/Obj_ru", "Shared_ObjRu"),
|
|
||||||
new("es", "Obj_es", "Sprite/Obj_es", "Shared_ObjEs"),
|
|
||||||
new("pt-BR", "Obj_pt-BR", "Sprite/Obj_pt-BR", "Shared_ObjPtBr")
|
|
||||||
};
|
|
||||||
|
|
||||||
private const string ValidateMenuPath =
|
|
||||||
"Tools/AIBIS/Localization/Validate Localized Obj Sprites";
|
|
||||||
private const string ConfigureMenuPath =
|
|
||||||
"Tools/AIBIS/Localization/Configure Localized Obj Addressables";
|
|
||||||
|
|
||||||
[MenuItem(ValidateMenuPath)]
|
|
||||||
public static void ValidateFromMenu()
|
|
||||||
{
|
|
||||||
IReadOnlyList<LocalizedObjSpriteValidationIssue> issues = Validate();
|
|
||||||
LogIssues(issues);
|
|
||||||
if (issues.Count == 0)
|
|
||||||
{
|
|
||||||
Debug.Log(
|
|
||||||
"[LocalizedObjSpriteValidator] Validation passed. " +
|
|
||||||
"All detected localized Obj sprite groups and Addressables are complete.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IReadOnlyList<LocalizedObjSpriteValidationIssue> Validate(
|
|
||||||
string artRoot = DefaultArtRoot,
|
|
||||||
bool validateAddressables = true)
|
|
||||||
{
|
|
||||||
var issues = new List<LocalizedObjSpriteValidationIssue>();
|
|
||||||
if (!Directory.Exists(artRoot))
|
|
||||||
{
|
|
||||||
issues.Add(new LocalizedObjSpriteValidationIssue(
|
|
||||||
ToAssetPath(artRoot),
|
|
||||||
"Art root does not exist."));
|
|
||||||
return issues;
|
|
||||||
}
|
|
||||||
|
|
||||||
string defaultDirectory = Path.Combine(artRoot, DefaultFolderName);
|
|
||||||
ValidateDirectoryExists(
|
|
||||||
defaultDirectory,
|
|
||||||
LocalizedObjSpriteNaming.DefaultLocaleCode,
|
|
||||||
issues);
|
|
||||||
|
|
||||||
var localizedRelativePaths = new HashSet<string>(
|
|
||||||
StringComparer.OrdinalIgnoreCase);
|
|
||||||
foreach (LocalizedObjSpriteDirectory directory in LocaleDirectories)
|
|
||||||
{
|
|
||||||
string localeDirectory = Path.Combine(artRoot, directory.FolderName);
|
|
||||||
if (!ValidateDirectoryExists(localeDirectory, directory.LocaleCode, issues))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
foreach (string filePath in Directory.EnumerateFiles(
|
|
||||||
localeDirectory,
|
|
||||||
"*.png",
|
|
||||||
SearchOption.AllDirectories))
|
|
||||||
{
|
|
||||||
localizedRelativePaths.Add(GetRelativePath(localeDirectory, filePath));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (string relativePath in localizedRelativePaths.OrderBy(
|
|
||||||
path => path,
|
|
||||||
StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
ValidateRequiredFile(
|
|
||||||
Path.Combine(defaultDirectory, relativePath),
|
|
||||||
LocalizedObjSpriteNaming.DefaultLocaleCode,
|
|
||||||
issues);
|
|
||||||
|
|
||||||
foreach (LocalizedObjSpriteDirectory directory in LocaleDirectories)
|
|
||||||
{
|
|
||||||
ValidateRequiredFile(
|
|
||||||
Path.Combine(artRoot, directory.FolderName, relativePath),
|
|
||||||
directory.LocaleCode,
|
|
||||||
issues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (validateAddressables)
|
|
||||||
ValidateAddressableConfiguration(issues);
|
|
||||||
|
|
||||||
return issues;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem(ConfigureMenuPath)]
|
|
||||||
public static void ConfigureAddressables()
|
|
||||||
{
|
|
||||||
AddressableAssetSettings settings =
|
|
||||||
AddressableAssetSettingsDefaultObject.Settings;
|
|
||||||
if (settings == null)
|
|
||||||
throw new InvalidOperationException("AddressableAssetSettings does not exist.");
|
|
||||||
|
|
||||||
foreach (LocalizedObjSpriteDirectory directory in LocaleDirectories)
|
|
||||||
{
|
|
||||||
string assetPath = $"{DefaultArtRoot}/{directory.FolderName}";
|
|
||||||
EnsureAssetFolder(assetPath);
|
|
||||||
|
|
||||||
AddressableAssetGroup group = settings.FindGroup(directory.GroupName);
|
|
||||||
if (group == null)
|
|
||||||
{
|
|
||||||
group = settings.CreateGroup(
|
|
||||||
directory.GroupName,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
null,
|
|
||||||
typeof(BundledAssetGroupSchema),
|
|
||||||
typeof(ContentUpdateGroupSchema));
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigureGroup(settings, group);
|
|
||||||
|
|
||||||
string guid = AssetDatabase.AssetPathToGUID(assetPath);
|
|
||||||
AddressableAssetEntry entry =
|
|
||||||
settings.CreateOrMoveEntry(guid, group, false, false);
|
|
||||||
entry.address = directory.AddressRoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
settings.SetDirty(
|
|
||||||
AddressableAssetSettings.ModificationEvent.BatchModification,
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
true);
|
|
||||||
EditorUtility.SetDirty(settings);
|
|
||||||
AssetDatabase.SaveAssets();
|
|
||||||
AssetDatabase.Refresh();
|
|
||||||
Debug.Log(
|
|
||||||
"[LocalizedObjSpriteValidator] Localized Obj folders and " +
|
|
||||||
"Addressable groups configured.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ConfigureFromCommandLine()
|
|
||||||
{
|
|
||||||
ConfigureAddressables();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void LogIssues(
|
|
||||||
IReadOnlyList<LocalizedObjSpriteValidationIssue> issues)
|
|
||||||
{
|
|
||||||
foreach (LocalizedObjSpriteValidationIssue issue in issues)
|
|
||||||
Debug.LogError($"[LocalizedObjSpriteValidator] {issue}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ConfigureGroup(
|
|
||||||
AddressableAssetSettings settings,
|
|
||||||
AddressableAssetGroup group)
|
|
||||||
{
|
|
||||||
BundledAssetGroupSchema bundled =
|
|
||||||
group.GetSchema<BundledAssetGroupSchema>() ??
|
|
||||||
group.AddSchema<BundledAssetGroupSchema>();
|
|
||||||
bundled.BuildPath.SetVariableByName(
|
|
||||||
settings,
|
|
||||||
AddressableAssetSettings.kLocalBuildPath);
|
|
||||||
bundled.LoadPath.SetVariableByName(
|
|
||||||
settings,
|
|
||||||
AddressableAssetSettings.kLocalLoadPath);
|
|
||||||
bundled.IncludeInBuild = true;
|
|
||||||
bundled.Compression = BundledAssetGroupSchema.BundleCompressionMode.LZ4;
|
|
||||||
bundled.BundleMode = BundledAssetGroupSchema.BundlePackingMode.PackTogether;
|
|
||||||
EditorUtility.SetDirty(bundled);
|
|
||||||
|
|
||||||
ContentUpdateGroupSchema contentUpdate =
|
|
||||||
group.GetSchema<ContentUpdateGroupSchema>() ??
|
|
||||||
group.AddSchema<ContentUpdateGroupSchema>();
|
|
||||||
contentUpdate.StaticContent = false;
|
|
||||||
EditorUtility.SetDirty(contentUpdate);
|
|
||||||
EditorUtility.SetDirty(group);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ValidateAddressableConfiguration(
|
|
||||||
ICollection<LocalizedObjSpriteValidationIssue> issues)
|
|
||||||
{
|
|
||||||
AddressableAssetSettings settings =
|
|
||||||
AddressableAssetSettingsDefaultObject.Settings;
|
|
||||||
if (settings == null)
|
|
||||||
{
|
|
||||||
issues.Add(new LocalizedObjSpriteValidationIssue(
|
|
||||||
"Assets/AddressableAssetsData",
|
|
||||||
"AddressableAssetSettings does not exist."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ValidateAddressableFolder(
|
|
||||||
settings,
|
|
||||||
$"{DefaultArtRoot}/{DefaultFolderName}",
|
|
||||||
LocalizedObjSpriteNaming.DefaultAddressRoot,
|
|
||||||
DefaultGroupName,
|
|
||||||
false,
|
|
||||||
issues);
|
|
||||||
|
|
||||||
foreach (LocalizedObjSpriteDirectory directory in LocaleDirectories)
|
|
||||||
{
|
|
||||||
ValidateAddressableFolder(
|
|
||||||
settings,
|
|
||||||
$"{DefaultArtRoot}/{directory.FolderName}",
|
|
||||||
directory.AddressRoot,
|
|
||||||
directory.GroupName,
|
|
||||||
true,
|
|
||||||
issues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ValidateAddressableFolder(
|
|
||||||
AddressableAssetSettings settings,
|
|
||||||
string assetPath,
|
|
||||||
string expectedAddress,
|
|
||||||
string expectedGroup,
|
|
||||||
bool validateGroupSchema,
|
|
||||||
ICollection<LocalizedObjSpriteValidationIssue> issues)
|
|
||||||
{
|
|
||||||
string guid = AssetDatabase.AssetPathToGUID(assetPath);
|
|
||||||
AddressableAssetEntry entry = string.IsNullOrEmpty(guid)
|
|
||||||
? null
|
|
||||||
: settings.FindAssetEntry(guid);
|
|
||||||
if (entry == null)
|
|
||||||
{
|
|
||||||
issues.Add(new LocalizedObjSpriteValidationIssue(
|
|
||||||
assetPath,
|
|
||||||
"Folder is not registered as an Addressable entry."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.Equals(entry.address, expectedAddress, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
issues.Add(new LocalizedObjSpriteValidationIssue(
|
|
||||||
assetPath,
|
|
||||||
$"Address is '{entry.address}', expected '{expectedAddress}'."));
|
|
||||||
}
|
|
||||||
|
|
||||||
AddressableAssetGroup group = entry.parentGroup;
|
|
||||||
if (group == null || !string.Equals(
|
|
||||||
group.Name,
|
|
||||||
expectedGroup,
|
|
||||||
StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
issues.Add(new LocalizedObjSpriteValidationIssue(
|
|
||||||
assetPath,
|
|
||||||
$"Group is '{group?.Name ?? "<null>"}', expected '{expectedGroup}'."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!validateGroupSchema)
|
|
||||||
return;
|
|
||||||
|
|
||||||
BundledAssetGroupSchema bundled = group.GetSchema<BundledAssetGroupSchema>();
|
|
||||||
if (bundled == null ||
|
|
||||||
!bundled.IncludeInBuild ||
|
|
||||||
bundled.Compression != BundledAssetGroupSchema.BundleCompressionMode.LZ4 ||
|
|
||||||
bundled.BundleMode != BundledAssetGroupSchema.BundlePackingMode.PackTogether ||
|
|
||||||
bundled.BuildPath.GetName(settings) != AddressableAssetSettings.kLocalBuildPath ||
|
|
||||||
bundled.LoadPath.GetName(settings) != AddressableAssetSettings.kLocalLoadPath)
|
|
||||||
{
|
|
||||||
issues.Add(new LocalizedObjSpriteValidationIssue(
|
|
||||||
assetPath,
|
|
||||||
"Addressable group must use local paths, LZ4, Include In Build, and Pack Together."));
|
|
||||||
}
|
|
||||||
|
|
||||||
ContentUpdateGroupSchema contentUpdate =
|
|
||||||
group.GetSchema<ContentUpdateGroupSchema>();
|
|
||||||
if (contentUpdate == null || contentUpdate.StaticContent)
|
|
||||||
{
|
|
||||||
issues.Add(new LocalizedObjSpriteValidationIssue(
|
|
||||||
assetPath,
|
|
||||||
"Addressable group must use non-static content update settings."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool ValidateDirectoryExists(
|
|
||||||
string directoryPath,
|
|
||||||
string localeCode,
|
|
||||||
ICollection<LocalizedObjSpriteValidationIssue> issues)
|
|
||||||
{
|
|
||||||
if (Directory.Exists(directoryPath))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
issues.Add(new LocalizedObjSpriteValidationIssue(
|
|
||||||
ToAssetPath(directoryPath),
|
|
||||||
$"Missing required '{localeCode}' Obj directory."));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ValidateRequiredFile(
|
|
||||||
string filePath,
|
|
||||||
string localeCode,
|
|
||||||
ICollection<LocalizedObjSpriteValidationIssue> issues)
|
|
||||||
{
|
|
||||||
if (File.Exists(filePath))
|
|
||||||
return;
|
|
||||||
|
|
||||||
issues.Add(new LocalizedObjSpriteValidationIssue(
|
|
||||||
ToAssetPath(filePath),
|
|
||||||
$"Missing required '{localeCode}' sprite variant."));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetRelativePath(string rootPath, string filePath)
|
|
||||||
{
|
|
||||||
string normalizedRoot = Path.GetFullPath(rootPath)
|
|
||||||
.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) +
|
|
||||||
Path.DirectorySeparatorChar;
|
|
||||||
string normalizedFile = Path.GetFullPath(filePath);
|
|
||||||
return normalizedFile.Substring(normalizedRoot.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void EnsureAssetFolder(string path)
|
|
||||||
{
|
|
||||||
string[] segments = path.Split('/');
|
|
||||||
string current = segments[0];
|
|
||||||
for (int index = 1; index < segments.Length; index++)
|
|
||||||
{
|
|
||||||
string next = $"{current}/{segments[index]}";
|
|
||||||
if (!AssetDatabase.IsValidFolder(next))
|
|
||||||
AssetDatabase.CreateFolder(current, segments[index]);
|
|
||||||
current = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string ToAssetPath(string path)
|
|
||||||
{
|
|
||||||
return path.Replace('\\', '/');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class LocalizedObjSpriteBuildValidator : IPreprocessBuildWithReport
|
|
||||||
{
|
|
||||||
// Run before build preprocessors that mutate version information.
|
|
||||||
public int callbackOrder => -1000;
|
|
||||||
|
|
||||||
public void OnPreprocessBuild(BuildReport report)
|
|
||||||
{
|
|
||||||
IReadOnlyList<LocalizedObjSpriteValidationIssue> issues =
|
|
||||||
LocalizedObjSpriteValidator.Validate();
|
|
||||||
if (issues.Count == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
LocalizedObjSpriteValidator.LogIssues(issues);
|
|
||||||
string summary = string.Join(
|
|
||||||
Environment.NewLine,
|
|
||||||
issues.Take(20).Select(issue => issue.ToString()));
|
|
||||||
if (issues.Count > 20)
|
|
||||||
{
|
|
||||||
summary += Environment.NewLine +
|
|
||||||
$"... and {issues.Count - 20} more issue(s).";
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new BuildFailedException(
|
|
||||||
"Localized Obj sprite validation failed:" +
|
|
||||||
Environment.NewLine + summary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 686ca5acbb6647d4c802ecd2a8ba043d
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using AibisDream.EditorTools.Localization;
|
|
||||||
using AibisDream.UI;
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace AibisDream.SystemEditor.Tests
|
|
||||||
{
|
|
||||||
public sealed class LocalizedObjSpriteTests
|
|
||||||
{
|
|
||||||
private string temporaryRoot;
|
|
||||||
|
|
||||||
[SetUp]
|
|
||||||
public void SetUp()
|
|
||||||
{
|
|
||||||
temporaryRoot = Path.Combine(
|
|
||||||
Path.GetTempPath(),
|
|
||||||
"AibisDreamLocalizedObjSpriteTests",
|
|
||||||
Guid.NewGuid().ToString("N"));
|
|
||||||
Directory.CreateDirectory(temporaryRoot);
|
|
||||||
Directory.CreateDirectory(Path.Combine(
|
|
||||||
temporaryRoot,
|
|
||||||
LocalizedObjSpriteValidator.DefaultFolderName));
|
|
||||||
foreach (LocalizedObjSpriteDirectory directory in
|
|
||||||
LocalizedObjSpriteValidator.LocaleDirectories)
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(Path.Combine(
|
|
||||||
temporaryRoot,
|
|
||||||
directory.FolderName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[TearDown]
|
|
||||||
public void TearDown()
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(temporaryRoot) && Directory.Exists(temporaryRoot))
|
|
||||||
Directory.Delete(temporaryRoot, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCase("zh-Hans", "Sprite/Obj/病历.png")]
|
|
||||||
[TestCase("zh-CN", "Sprite/Obj/病历.png")]
|
|
||||||
[TestCase("en", "Sprite/Obj_en/病历.png")]
|
|
||||||
[TestCase("en-US", "Sprite/Obj_en/病历.png")]
|
|
||||||
[TestCase("ja-JP", "Sprite/Obj_ja-JP/病历.png")]
|
|
||||||
[TestCase("ru-RU", "Sprite/Obj_ru/病历.png")]
|
|
||||||
[TestCase("es-ES", "Sprite/Obj_es/病历.png")]
|
|
||||||
[TestCase("pt-BR", "Sprite/Obj_pt-BR/病历.png")]
|
|
||||||
public void GetKey_UsesCanonicalLocaleDirectory(
|
|
||||||
string localeCode,
|
|
||||||
string expected)
|
|
||||||
{
|
|
||||||
Assert.That(
|
|
||||||
LocalizedObjSpriteNaming.GetKey("病历.png", localeCode),
|
|
||||||
Is.EqualTo(expected));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void CandidateNames_FallBackToUnsuffixedChineseWithoutDuplicates()
|
|
||||||
{
|
|
||||||
Assert.That(
|
|
||||||
LocalizedObjSpriteNaming.GetCandidateKeys("病历.png", "en"),
|
|
||||||
Is.EqualTo(new[]
|
|
||||||
{
|
|
||||||
"Sprite/Obj_en/病历.png",
|
|
||||||
"Sprite/Obj/病历.png"
|
|
||||||
}));
|
|
||||||
Assert.That(
|
|
||||||
LocalizedObjSpriteNaming.GetCandidateKeys("病历.png", "zh-Hans"),
|
|
||||||
Is.EqualTo(new[] { "Sprite/Obj/病历.png" }));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void Validator_IgnoresUnsuffixedOnlySprites()
|
|
||||||
{
|
|
||||||
WriteSprite(
|
|
||||||
LocalizedObjSpriteValidator.DefaultFolderName,
|
|
||||||
"普通图片.png");
|
|
||||||
|
|
||||||
Assert.That(
|
|
||||||
LocalizedObjSpriteValidator.Validate(temporaryRoot, false),
|
|
||||||
Is.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void Validator_RequiresEveryVariantAfterAGroupIsDetected()
|
|
||||||
{
|
|
||||||
WriteCompleteGroup("病历");
|
|
||||||
Assert.That(
|
|
||||||
LocalizedObjSpriteValidator.Validate(temporaryRoot, false),
|
|
||||||
Is.Empty);
|
|
||||||
|
|
||||||
File.Delete(Path.Combine(temporaryRoot, "Obj_ru", "病历.png"));
|
|
||||||
var issues = LocalizedObjSpriteValidator.Validate(temporaryRoot, false);
|
|
||||||
|
|
||||||
Assert.That(issues, Has.Count.EqualTo(1));
|
|
||||||
Assert.That(issues.Single().AssetPath, Does.EndWith("Obj_ru/病历.png"));
|
|
||||||
Assert.That(issues.Single().Message, Does.Contain("'ru'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ProjectLocaleFolders_AreAddressableByConvention()
|
|
||||||
{
|
|
||||||
Assert.That(
|
|
||||||
LocalizedObjSpriteValidator.Validate(),
|
|
||||||
Is.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WriteCompleteGroup(string logicalName)
|
|
||||||
{
|
|
||||||
WriteSprite(
|
|
||||||
LocalizedObjSpriteValidator.DefaultFolderName,
|
|
||||||
$"{logicalName}.png");
|
|
||||||
foreach (LocalizedObjSpriteDirectory directory in
|
|
||||||
LocalizedObjSpriteValidator.LocaleDirectories)
|
|
||||||
{
|
|
||||||
WriteSprite(directory.FolderName, $"{logicalName}.png");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WriteSprite(string folderName, string relativePath)
|
|
||||||
{
|
|
||||||
string filePath = Path.Combine(temporaryRoot, folderName, relativePath);
|
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
|
|
||||||
File.WriteAllBytes(filePath, Array.Empty<byte>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 212d27ffec81bcb48a886db924f43e1a
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -133,7 +133,7 @@ PlayerSettings:
|
|||||||
vulkanEnableLateAcquireNextImage: 0
|
vulkanEnableLateAcquireNextImage: 0
|
||||||
vulkanEnableCommandBufferRecycling: 1
|
vulkanEnableCommandBufferRecycling: 1
|
||||||
loadStoreDebugModeEnabled: 0
|
loadStoreDebugModeEnabled: 0
|
||||||
bundleVersion: 0.6.1.16-20260731-152037
|
bundleVersion: 0.6.2.1
|
||||||
preloadedAssets:
|
preloadedAssets:
|
||||||
- {fileID: 11400000, guid: 0fb2bc2476953fc43a74f0ab8879077c, type: 2}
|
- {fileID: 11400000, guid: 0fb2bc2476953fc43a74f0ab8879077c, type: 2}
|
||||||
metroInputSource: 0
|
metroInputSource: 0
|
||||||
|
|||||||
Reference in New Issue
Block a user