From 44ac9ace0aa6927c79e777c6451f78abc0dba92e Mon Sep 17 00:00:00 2001
From: Ding Yuntian <1491671119@qq.com>
Date: Mon, 3 Aug 2026 04:05:31 +0800
Subject: [PATCH] =?UTF-8?q?fix:=20=E5=9E=83=E5=9C=BE=E6=B5=8B=E8=AF=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../LocalizedObjSpriteValidator.cs | 416 ------------------
.../LocalizedObjSpriteValidator.cs.meta | 11 -
.../Editor/Tests/LocalizedObjSpriteTests.cs | 128 ------
.../Tests/LocalizedObjSpriteTests.cs.meta | 11 -
ProjectSettings/ProjectSettings.asset | 2 +-
5 files changed, 1 insertion(+), 567 deletions(-)
delete mode 100644 Assets/Editor/Localization/LocalizedObjSpriteValidator.cs
delete mode 100644 Assets/Editor/Localization/LocalizedObjSpriteValidator.cs.meta
delete mode 100644 Assets/Editor/Tests/LocalizedObjSpriteTests.cs
delete mode 100644 Assets/Editor/Tests/LocalizedObjSpriteTests.cs.meta
diff --git a/Assets/Editor/Localization/LocalizedObjSpriteValidator.cs b/Assets/Editor/Localization/LocalizedObjSpriteValidator.cs
deleted file mode 100644
index 1fa5cae49..000000000
--- a/Assets/Editor/Localization/LocalizedObjSpriteValidator.cs
+++ /dev/null
@@ -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}";
- }
- }
-
- ///
- /// 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.
- ///
- 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 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 Validate(
- string artRoot = DefaultArtRoot,
- bool validateAddressables = true)
- {
- var issues = new List();
- 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(
- 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 issues)
- {
- foreach (LocalizedObjSpriteValidationIssue issue in issues)
- Debug.LogError($"[LocalizedObjSpriteValidator] {issue}");
- }
-
- private static void ConfigureGroup(
- AddressableAssetSettings settings,
- AddressableAssetGroup group)
- {
- BundledAssetGroupSchema bundled =
- group.GetSchema() ??
- group.AddSchema();
- 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() ??
- group.AddSchema();
- contentUpdate.StaticContent = false;
- EditorUtility.SetDirty(contentUpdate);
- EditorUtility.SetDirty(group);
- }
-
- private static void ValidateAddressableConfiguration(
- ICollection 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 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 ?? ""}', expected '{expectedGroup}'."));
- return;
- }
-
- if (!validateGroupSchema)
- return;
-
- BundledAssetGroupSchema bundled = group.GetSchema();
- 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();
- 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 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 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 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);
- }
- }
-}
diff --git a/Assets/Editor/Localization/LocalizedObjSpriteValidator.cs.meta b/Assets/Editor/Localization/LocalizedObjSpriteValidator.cs.meta
deleted file mode 100644
index 17fcfcaba..000000000
--- a/Assets/Editor/Localization/LocalizedObjSpriteValidator.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 686ca5acbb6647d4c802ecd2a8ba043d
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/Assets/Editor/Tests/LocalizedObjSpriteTests.cs b/Assets/Editor/Tests/LocalizedObjSpriteTests.cs
deleted file mode 100644
index 7576adb02..000000000
--- a/Assets/Editor/Tests/LocalizedObjSpriteTests.cs
+++ /dev/null
@@ -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());
- }
- }
-}
diff --git a/Assets/Editor/Tests/LocalizedObjSpriteTests.cs.meta b/Assets/Editor/Tests/LocalizedObjSpriteTests.cs.meta
deleted file mode 100644
index 2f13e56a9..000000000
--- a/Assets/Editor/Tests/LocalizedObjSpriteTests.cs.meta
+++ /dev/null
@@ -1,11 +0,0 @@
-fileFormatVersion: 2
-guid: 212d27ffec81bcb48a886db924f43e1a
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset
index 6d0087dde..31485eaca 100644
--- a/ProjectSettings/ProjectSettings.asset
+++ b/ProjectSettings/ProjectSettings.asset
@@ -133,7 +133,7 @@ PlayerSettings:
vulkanEnableLateAcquireNextImage: 0
vulkanEnableCommandBufferRecycling: 1
loadStoreDebugModeEnabled: 0
- bundleVersion: 0.6.1.16-20260731-152037
+ bundleVersion: 0.6.2.1
preloadedAssets:
- {fileID: 11400000, guid: 0fb2bc2476953fc43a74f0ab8879077c, type: 2}
metroInputSource: 0