适用版本:UIProbe v3.8.0+ 涵盖模块:图片规范化(Image Normalizer)· 批量命名(Batch Rename)· 大红大金资源修改导入(Red/Gold Resource Importer) 最后更新:2026-06
- 模块概述
- 文件结构
- 图片规范化模块
- 3.1 数据类与枚举
- 3.2 UI 状态字段
- 3.3 核心算法层
- 3.4 目标尺寸计算逻辑
- 3.5 UI 交互流程
- 3.6 配置持久化
- 批量命名模块
- 4.1 数据类
- 4.2 UI 状态字段
- 4.3 命名规则引擎
- 4.4 冲突检测机制
- 4.5 执行与日志
- 4.6 配置持久化
- 大红大金资源修改导入模块
- 公共基础设施
- 扩展指南
- 已知限制与注意事项
三个模块共同挂载在 图片工具(Image Tools) 标签页下,通过子标签栏切换:
图片工具
├── 📐 图片规范化 ← UIProbeWindow_ImageNormalizer.cs
├── ✏️ 批量命名 ← UIProbeWindow_ImageRenamer.cs
└── 大红大金资源修改导入 ← UIProbeWindow_RedGoldImporter.cs
三个模块均以 partial class UIProbeWindow 形式实现,数据层独立于 UI 层,配置通过 UIProbeConfig 统一序列化到 config.json。
UIProbe/
├── UIProbeWindow_ImageNormalizer.cs 图片规范化 UI + 业务逻辑
├── UIProbeWindow_ImageRenamer.cs 批量命名 UI + 业务逻辑
├── UIProbeWindow_RedGoldImporter.cs 大红大金资源修改导入 UI + 业务逻辑(~1400 行)
│
└── Data/
├── ImageNormalizer.cs 图片处理算法(缩放、裁切、画布操作)
├── ImageRenameLogManager.cs 批量命名操作日志管理
├── DelimitedFileParser.cs 通用 CSV/TSV 分隔文件读写器
├── RedGoldDataTypes.cs 大红大金数据类(枚举、导入行、撤销条目等)
├── RedGoldPathHelper.cs 路径转换工具(绝对路径 ↔ Assets 相对路径)
├── RedGoldNamingState.cs 文件名自动编号分配引擎
├── RedGoldNameConverter.cs 拼音/语义命名转换器
├── RedGoldUndoManager.cs 栈式多级撤销管理器(最多 10 层)
├── RedGoldImageMatcher.cs 图片映射构建与源文件匹配
├── RedGoldPresetManager.cs 预设系统(保存/加载/删除配置)
├── ExcelFileParser.cs 零依赖 .xlsx 读取器
└── UIProbeConfig.cs 配置数据类(含图片工具模块的持久化字段)
命名空间级数据类(定义在对应 .cs 文件中,独立于 partial class):
| 类名 | 所在文件 | 用途 |
|---|---|---|
NormalizerImageItem |
ImageNormalizer UI | 单张图片的扫描结果(路径、尺寸、勾选状态) |
NormalizerSizeMode (enum) |
ImageNormalizer UI | 目标尺寸计算方式 |
NormalizerSizeGroup |
ImageNormalizer UI | 按分辨率聚合的分组 |
RenamePreviewItem |
ImageRenamer UI | 单条重命名预览(原名、新名、冲突状态) |
ImageRenameLogItem |
ImageRenameLogManager | CSV 日志条目 |
ModificationStatus (enum) |
RedGoldDataTypes | 预览行变更状态(新增/已修改/无变化/未知) |
RedGoldUndoEntry |
RedGoldDataTypes | 覆盖生成前的撤销记录,保存备份路径与表格旧值 |
RedGoldImportRow |
RedGoldDataTypes | 单行导入预览数据(名称、品质、格数、源图、输出路径、状态等) |
UnmatchedSourceInfo |
RedGoldDataTypes | 源目录中未被表格匹配到的图片信息 |
RedGoldTableData |
RedGoldDataTypes | 表格解析结果(分隔符、行数据、列索引),含 GetCell/SetCell 静态方法 |
RedGoldNamingState |
RedGoldNamingState | 文件名自动编号分配引擎,延续目录命名序号并避免重名 |
RedGoldUndoSnapshot |
RedGoldUndoManager | 单次生成操作的撤销快照(条目列表、表格路径、备份目录) |
QualityConfigEntry |
RedGoldDataTypes | 品质配置条目(关键字、路径、命名模板、拼音开关) |
RedGoldPreset |
RedGoldPresetManager | 预设数据(品质列表、格数规则、尺寸参数) |
internal class NormalizerImageItem
{
public string Path; // 完整绝对路径
public string FileName; // 文件名(含扩展名)
public bool IsSelected; // 是否被勾选(控制是否参与处理)
public int Width; // 原始宽度(扫描时读取并缓存)
public int Height; // 原始高度
public string SizeLabel; // 显示用字符串,如 "(512×512)"
}性能说明:宽高在
ScanImagesForNormalizer()中一次性读取并缓存,不在OnGUI中重复 IO,规避原版每帧LoadTexture的性能问题。
internal enum NormalizerSizeMode
{
Custom, // 固定尺寸:全局统一 W × H
Percentage, // 百分比:各图按自身原始尺寸等比缩放
LockWidth, // 锁定宽度:各图高度自动等比计算
LockHeight, // 锁定高度:各图宽度自动等比计算
}internal class NormalizerSizeGroup
{
public int Width; // 该组的原始宽度
public int Height; // 该组的原始高度
public string SizeLabel; // 显示标题,如 "512 × 512"
public List<NormalizerImageItem> Items;
public bool IsFoldout; // 折叠展开状态(仅 UI 用,不持久化)
}分组由 BuildNormalizerGroups() 按 Width_Height 键聚合,排序规则为像素总数降序(大图优先),相同像素数时按数量降序。
| 字段 | 类型 | 说明 |
|---|---|---|
normalizerSourceFolder |
string | 源文件夹路径 |
normalizerIncludeSubfolders |
bool | 是否递归子文件夹 |
normalizerSizeMode |
NormalizerSizeMode | 当前缩放方式 |
normalizerTargetWidth/Height |
int | Custom 模式目标尺寸 |
normalizerForceSquare |
bool | Custom 模式正方形锁定 |
normalizerScalePercent |
float | Percentage 模式缩放比(1~400);计算结果会向上补齐到 4 的整数倍 |
normalizerLockWidth/Height |
int | LockWidth / LockHeight 目标值 |
normalizerNoUpscale |
bool | 仅缩小,不放大 |
normalizerMaxDimension |
int | 最大边长限制(0=不限) |
normalizerResizeMode |
ResizeMode | 内容缩放模式(Expand/Fit/OriginalFit/Fill/Stretch) |
normalizerAlignment |
ContentAlignment | 对齐方式(仅 Expand 模式生效) |
normalizerOverwrite |
bool | 覆盖源文件;后缀非空时会将源文件改名为带后缀的新文件 |
normalizerNamingSuffix |
string | 输出文件名后缀;覆盖模式与生成新文件模式都会参与命名 |
normalizerImageItems |
List<NormalizerImageItem> | 扫描结果平铺列表 |
normalizerImageGroups |
List<NormalizerSizeGroup> | 按分辨率分组后的结构 |
public enum ResizeMode
{
Expand, // 扩展画布,内容不缩放
ProportionalFit, // 等比缩放至适应目标,多余区域透明
OriginalProportionalFit, // 整张原图等比缩放,保留透明空白区域
ProportionalFill, // 等比缩放至铺满,超出部分从中心裁切
Stretch, // 强制拉伸到目标尺寸
}// 规范化单张图片
Texture2D Normalize(Texture2D source, int targetWidth, int targetHeight,
ContentAlignment alignment, ResizeMode resizeMode = ResizeMode.Expand)
// 批量处理(Custom 模式使用,统一目标尺寸)
int ProcessBatch(string[] imagePaths, int targetWidth, int targetHeight,
ContentAlignment alignment, bool overwrite, string namingSuffix,
ResizeMode resizeMode, Action<int, int> progressCallback)
// 获取非透明内容最小包围矩形
RectInt GetContentBounds(Texture2D texture)| 方法 | 说明 |
|---|---|
NormalizeExpand |
按 alignment 平移内容,不缩放 |
NormalizeProportionalFit |
等比缩小/放大使内容完整显示,居中放置 |
NormalizeOriginalProportionalFit |
按整张原图等比缩放,保留原图透明空白区域 |
NormalizeProportionalFill |
等比缩放铺满,从中心裁切超出部分 |
NormalizeStretch |
内容直接拉伸到目标 |
ScaleTexture |
双线性插值缩放(以像素中心映射,边缘无色彩偏移) |
ExtractRegion |
裁切纹理的指定矩形区域 |
CreateBlankTexture |
创建全透明画布(内部已调用 Apply) |
ProportionalFit:scaledW/H上限钳位到targetWidth/Height,防止SetPixels越界ProportionalFill:scaledW/H下限保证>= targetWidth/Height,防止裁切区域不足- 所有模式:
Normalize返回 null 时由调用方降级处理
private (int w, int h) ComputeTarget(int srcW, int srcH)计算流程(按顺序应用):
1. 按 NormalizerSizeMode 计算初步输出尺寸
├── Custom → 使用 normalizerTargetWidth/Height
├── Percentage → outW = Round(srcW * percent / 100)
├── LockWidth → outW = normalizerLockWidth;outH 按比例
└── LockHeight → outH = normalizerLockHeight;outW 按比例
2. 仅缩小保护(normalizerNoUpscale)
└── 若 outW > srcW 或 outH > srcH → 还原为 srcW, srcH
3. 最大边长保护(normalizerMaxDimension > 0)
└── 若 max(outW, outH) > maxDim → 等比缩至上限
4. Percentage 模式尺寸补齐
└── 若 outW/outH 不是 4 的整数倍 → 分别向上补齐到最近的 4 的整数倍
5. 返回 (outW, outH)
注意:当 srcW <= 0(未知尺寸)时,回退到 Custom 模式的全局目标值。
用户操作 方法调用
────────────────────────────────────────────────────────
选择源文件夹 → 点击扫描 ScanImagesForNormalizer()
├── 读取所有 PNG/JPG 文件
├── LoadTexture → 缓存 Width/Height(含进度条)
├── 构建 normalizerImageItems
└── BuildNormalizerGroups()
└── 按 "W_H" 聚合,按像素数降序排列
调整缩放方式 / 参数 OnGUI 实时调用 ComputeTarget()
└── 分组标题与条目箭头实时更新
勾选/取消图片 item.IsSelected 直接修改
点击文件名 PingNormalizerAsset(item.Path)
├── 项目内 → AssetDatabase.PingObject + Selection
└── 项目外 → EditorUtility.RevealInFinder
点击"开始处理" StartNormalizerProcessing()
├── 过滤 IsSelected 条目
├── 弹出确认对话框(含尺寸描述)
└── 逐图调用 ComputeTarget + ImageNormalizer.Normalize
└── 保存到 outputPath(覆盖同名 / 覆盖并改名 / 生成新文件)
点击"去除后缀" StartNormalizerSuffixRemoval()
├── 使用 normalizerNamingSuffix 匹配已勾选文件
├── 冲突检查(目标文件 / 目标 .meta 已存在则阻止)
└── 将 xxx{suffix}.png 改回 xxx.png,并同步 .meta
配置类:ImageNormalizerConfig(位于 UIProbeConfig.cs)
[Serializable]
public class ImageNormalizerConfig
{
public string lastSourceFolder;
public bool includeSubfolders;
public int targetWidth, targetHeight;
public bool forceSquare;
public string alignment; // ContentAlignment.ToString()
public bool overwrite;
public string namingSuffix;
public string resizeMode; // ResizeMode.ToString()
// 新增字段(v3.2+)
public string sizeMode; // NormalizerSizeMode.ToString()
public float scalePercent;
public int lockWidth, lockHeight;
public bool noUpscale;
public int maxDimension;
}读写时机:ApplyImageNormalizerConfig()(OnEnable)和 CollectImageNormalizerConfig()(OnDisable),枚举字段使用 System.Enum.Parse 反序列化,解析失败时回退为默认值。
internal class RenamePreviewItem
{
public string OriginalPath; // 完整绝对路径
public string OriginalFileName; // 原始文件名(含扩展名)
public string OriginalNameNoExt; // 原始文件名(不含扩展名)
public string Extension; // 扩展名,如 ".png"
public string RuleGeneratedName; // 规则引擎生成的名称(不含扩展名)
public string FinalNameNoExt; // 最终名称(用户可手动覆盖)
public bool IsManualOverride; // true = 用户已手动编辑,规则变化时不覆盖
public bool HasConflict;
public string ConflictReason; // "列表内重复" 或 "目标已存在"
public string FinalFileName => FinalNameNoExt + Extension; // 完整新文件名
}public class ImageRenameLogItem
{
public string OriginalName; // 原始文件名
public string NewName; // 新文件名
public string OriginalPath; // 原始完整路径
public string TargetFolder; // 目标文件夹
public string Mode; // 操作模式描述
}| 字段 | 类型 | 说明 |
|---|---|---|
renamerSourceFolder |
string | 源图片文件夹 |
renamerTargetFolder |
string | 目标文件夹(非覆盖模式使用) |
renamerIncludeSubfolders |
bool | 是否递归子文件夹 |
renamerOverwriteInPlace |
bool | true=原路径覆盖删原文件;false=复制到目标路径 |
renamerPrefix |
string | 命名前缀 |
renamerKeepOriginalName |
bool | 是否保留原文件名 |
renamerEnableSequence |
bool | 是否启用序号 |
renamerSeqStart |
int | 序号起始值 |
renamerSeqStep |
int | 序号步长 |
renamerSeqDigits |
int | 序号位数(补零) |
renamerSuffix |
string | 命名后缀 |
renamerUpdateMeta |
bool | 是否同步更新 .meta 文件 |
renamePreviewList |
List<RenamePreviewItem> | 预览条目列表 |
renameConflictCount |
int | 当前冲突数量(缓存,避免每帧重算) |
private string BuildRenamerName(string originalNameNoExt, int seqValue)输出 = string.Join("_", parts) 其中 parts 按如下顺序组装:
[前缀(非空时加入)]
[原文件名(renamerKeepOriginalName=true 时加入)]
[序号(renamerEnableSequence=true 时加入,格式为 "D{digits}")]
[后缀(非空时加入)]
若 parts 为空(四项均未启用),则回退为 originalNameNoExt。
调用场景:
| 场景 | 传入 seqValue |
|---|---|
ScanRenamerImages 初始构建 |
renamerSeqStart + i * renamerSeqStep |
RegenerateRenamePreview 重新生成 |
从 renamerSeqStart 开始,每项 += renamerSeqStep |
DrawRenamerRules 示例预览 |
renamerSeqStart(固定展示第一个序号) |
检测按顺序执行,命中任一规则即标记冲突:
① 列表内重复
统计所有条目的 FinalFileName 出现次数
若 count > 1 → ConflictReason = "列表内重复"
② 与目标目录已有文件冲突
effectiveTarget = overwriteInPlace ? sourceFolder : targetFolder
若目标路径存在同名文件 AND 非文件自身(isSelf 判断)
→ ConflictReason = "目标已存在"
isSelf 判断:仅在 renamerOverwriteInPlace=true 时生效,比较绝对路径(OrdinalIgnoreCase),用于跳过"原名即目标名"的情况。
冲突数量缓存到 renameConflictCount,执行按钮 disabled 条件为 renameConflictCount > 0。
触发时机:
- 扫描完成后
- 规则参数变化时(
EditorGUI.EndChangeCheck()检测) - 用户手动编辑某行新文件名后
前置校验
└── 非覆盖模式必须填写目标路径
弹出确认对话框(含文件数、操作模式、Meta同步选项)
逐文件处理:
├── 原路径覆盖模式(renamerOverwriteInPlace=true)
│ ├── destPath != originalPath → File.Copy(src → dest, overwrite:true)
│ ├── updateMeta → 同步复制 .meta
│ ├── File.Delete(originalPath)
│ └── updateMeta → 删除原 .meta
│
└── 复制到目标路径模式(renamerOverwriteInPlace=false)
├── File.Copy(src → dest, overwrite:true)
└── updateMeta → 复制 .meta
isInsideProject → AssetDatabase.Refresh()
生成 CSV 日志(ImageRenameLogManager.GenerateLog)
清空 renamePreviewList
- 存储路径:
UIProbe/ImageRenameLogs/yyyy-MM-dd/ImageRename_HHmmss.csv - CSV 列:
原文件名, 新文件名, 原路径, 目标文件夹, 操作模式, 执行时间 - 每次执行独立一个文件(时间戳命名),避免追加覆盖
配置类:BatchRenameConfig(位于 UIProbeConfig.cs)
[Serializable]
public class BatchRenameConfig
{
public string lastSourceFolder, lastTargetFolder;
public bool includeSubfolders, overwriteInPlace;
public string prefix, suffix;
public bool keepOriginalName, enableSequence;
public int seqStart, seqStep, seqDigits;
public bool updateMeta;
}读写时机:由 ApplyBatchRenameConfig() / CollectBatchRenameConfig() 负责,被 ApplyImageNormalizerConfig / CollectImageNormalizerConfig 在图片规范化配置读写时顺带调用,无需在 UIProbeWindow.cs 的 OnEnable/OnDisable 中单独注册。
v3.5.0 重构后,原 1794 行的巨型文件拆分为 1 个 UI 层文件 + 7 个 Data 层文件:
UI 层(UIProbeWindow_RedGoldImporter.cs, ~1091 行)
├── 状态字段(路径、折叠状态、滚动位置等)
├── Draw* 方法(EditorGUI 绘制)
├── 编排方法(RedGoldLoadPreview / RedGoldGenerateAndWriteTable)
├── 读取 UI 状态的小方法(GetQualityFolder / ComputeOutputSize 等)
└── Config 持久化(Apply/Collect)
Data 层(UIProbe/Data/)
├── RedGoldDataTypes.cs 数据类 + GetCell/SetCell
├── RedGoldPathHelper.cs 路径转换(绝对 ↔ Assets 相对)
├── DelimitedFileParser.cs 通用 CSV/TSV 读写
├── RedGoldNamingState.cs 文件名自动编号引擎
├── RedGoldNameConverter.cs 拼音/语义命名转换
├── RedGoldUndoManager.cs 栈式多级撤销(最多 10 层)
└── RedGoldImageMatcher.cs 图片映射构建 + 源文件匹配
依赖关系:UI 层调用 Data 层,Data 层之间仅 RedGoldImageMatcher → RedGoldPathHelper、RedGoldUndoManager → DelimitedFileParser + RedGoldTableData 存在依赖。
| 类名 | 用途 |
|---|---|
ModificationStatus |
预览行变更状态,区分新增、已修改、无变化和未知 |
RedGoldUndoEntry |
覆盖生成前的撤销记录,保存备份文件路径与表格旧值 |
RedGoldImportRow |
单行导入预览数据,包含表格行号、名称、品质、格数、源图、输出目录、计划路径、变更状态和可编辑输出文件名 |
UnmatchedSourceInfo |
源目录中未被表格匹配到的图片信息 |
RedGoldTableData |
表格解析结果,保存分隔符、全部行数据以及关键列索引;提供 GetCell/SetCell 静态方法 |
通用分隔文件读写器,支持 RFC-4180 引号规则:
// 读取(自动识别逗号/Tab 分隔符,UTF-8 优先、系统默认编码兜底)
RedGoldTableData ReadTable(string path)
// 写回(UTF-8 无 BOM)
void WriteTable(string path, RedGoldTableData table)内部方法:ReadAllText、ChooseDelimiter、ParseDelimited、EscapeCell。
static string ToTablePath(string absolutePath) // 绝对路径 → "Assets/..." 相对路径
static string ToAbsolutePath(string path) // Assets/相对路径 → 绝对路径
static string GetDefaultOutputTablePath(string tablePath) // 生成 "{name}_导入结果{ext}" 路径
static string GetDefaultOutputTableName(string tablePath) // 同上,仅文件名
static string GetTableExtension(string tablePath) // 获取扩展名,默认 csv
static string GetExistingDirectory(string path) // 查找最近的已存在祖先目录检测目录中已有的命名模式(如 icon_001.png、icon_002.png),自动递增编号避免冲突:
RedGoldNamingState.Create(folder) // 扫描目录,检测命名模式
state.Allocate(folder, fallbackName) // 分配下一个文件名
state.ReserveFileName(fileName) // 预留文件名(防冲突)
state.ReservePreferred(folder, name) // 尝试使用首选名称,冲突时加后缀红品质资源专用命名:中文名 → T_Icon_Red_{拼音}.png
- 内置 ~60 字拼音映射表 + 8 条语义覆盖(如"铁球先生" →
TieQiuXianSheng) - 未映射的 CJK 字符输出 "X",ASCII 字符保持原样
static string BuildRedOutputFileName(string displayName) // "火锅神像" → "T_Icon_Red_HuoGuoShenXiang.png"
static string GetOutputFileNameFromIconPath(string iconPath) // 从路径提取文件名,确保 .png 扩展名// 构建文件名→路径映射,同名文件自动保留最新版本
static Dictionary<string,string> BuildImageMap(string folder, bool includeSubfolders, out List<string> duplicateWarnings)
// 三级查找:图标文件名 → 名称列 → 旧表格路径(兜底)
static string FindSourceImage(Dictionary<string,string> imageMap, string name, string iconPath)v3.5.0 从单级撤销升级为栈式多级(最多 10 层):
// 压入快照(超限自动清理最旧备份目录)
void PushSnapshot(List<RedGoldUndoEntry> entries, string tablePath, string description)
// 弹出栈顶并恢复文件和表格数据
UndoResult TryUndo(RedGoldTableData tableData, bool overrideGrid)
// UI 展示属性
bool HasUndo // 是否有可撤销操作
string CurrentDescription // 栈顶操作描述
int EntryCount // 栈顶操作涉及的文件数
int StackDepth // 当前栈深度UndoResult 包含 Success、RestoredFileCount、RestoredTableCount、Error 字段。
存储路径:{UIProbeStorage.GetMainFolderPath()}/RedGoldUndo/{yyyyMMdd_HHmmss}/
| 字段 | 类型 | 说明 |
|---|---|---|
redGoldTablePath |
string | CSV/TSV 表格路径 |
redGoldImageSourceFolder |
string | 待匹配图片源目录 |
redGoldIncludeSubfolders |
bool | 是否递归查找源图 |
redGoldNameColumn / redGoldQualityColumn |
string | 名称列与品质列列名 |
redGoldGridLongColumn / redGoldGridWideColumn / redGoldGridCountColumn |
string | 格数相关列名 |
redGoldIconPathColumn |
string | 图标路径回写列名 |
redGoldOverrideGrid |
bool | 是否统一覆盖格数 |
redGoldCellPixelSize |
int | 非正方形比例的单格像素基准 |
redGoldMaxOutputEdge |
int | 1:1 到 6:6 正方形资源的统一边长 |
redGoldRedOutputFolder / redGoldPurpleOutputFolder / redGoldGoldOutputFolder |
string | 红、紫、金品质输出目录 |
redGoldOverwriteTable / redGoldOutputTablePath |
bool / string | 表格覆盖或另存配置 |
redGoldUndoManager |
RedGoldUndoManager | 栈式多级撤销管理器实例 |
redGoldFoldReplaceable / redGoldFoldMissing / redGoldFoldUnmatched |
bool | 三个预览分组的折叠状态 |
选择表格和图片目录
↓
RedGoldLoadPreview()
├── DelimitedFileParser.ReadTable() 读取 CSV/TSV
├── RedGoldResolveColumns() 匹配表头列名
├── RedGoldImageMatcher.BuildImageMap() 建立源图文件名索引
├── RedGoldImageMatcher.FindSourceImage() 按图标文件名/名称匹配源图
├── RedGoldValidatePreviewRow() 标记缺图、格数无效等问题
├── RedGoldNamingState / RedGoldNameConverter 分配输出文件名
└── 收集未匹配源图并展示在独立预览分组
↓
RedGoldGenerateAndWriteTable()
├── 生成前备份已有输出文件,记录表格旧值
├── ImageNormalizer.Normalize() 等比适配到目标画布
├── 按品质输出到红/紫/金目录
├── RedGoldWriteBackRow() 回写图标路径和可选格数
├── DelimitedFileParser.WriteTable() 覆盖原表或另存结果表
└── redGoldUndoManager.PushSnapshot() 压入撤销栈
↓
↩ 撤销(UI 按钮,显示栈深度)
└── redGoldUndoManager.TryUndo() 恢复文件 + 表格数据 + AssetDatabase.Refresh
配置类:RedGoldResourceImporterConfig(位于 UIProbeConfig.cs)
[Serializable]
public class RedGoldResourceImporterConfig
{
public string tablePath, imageSourceFolder;
public bool includeSubfolders;
public string nameColumn, qualityColumn, gridLongColumn, gridWideColumn, gridCountColumn, iconPathColumn;
public bool overrideGrid;
public int overrideGridLong, overrideGridWide, cellPixelSize, maxOutputEdge;
public string redOutputFolder, purpleOutputFolder, goldOutputFolder;
public bool overwriteTable;
public string outputTablePath;
}读写时机:ApplyRedGoldResourceImporterConfig() / CollectRedGoldResourceImporterConfig() 由图片工具总配置读写流程统一调用,与图片规范化和批量命名保持一致。
显示入口:大红大金子标签由 ModulesVisibilityConfig.showRedGoldResourceImporter 控制,可在设置页的“功能模块显示设置”中单独隐藏;隐藏后图片工具会自动回到“图片规范化”子标签。
UIProbe/(主目录,默认在 AppData)
├── ImageRenameLogs/ 批量命名操作日志
│ └── yyyy-MM-dd/
│ └── ImageRename_HHmmss.csv
├── RedGoldUndo/ 大红大金撤销备份
│ └── yyyyMMdd_HHmmss/ 每次生成操作的旧文件备份
└── Settings/
└── config.json 所有配置的统一持久化文件
获取路径方法:
UIProbeStorage.GetImageRenameLogsPath() // 日志目录
UIProbeStorage.GetMainFolderPath() // 主目录
UIProbeStorage.GetSettingsPath() // 配置目录// 加载(OnEnable 调用)
UIProbeConfig config = UIProbeConfigManager.Load();
// 保存(OnDisable 或明确保存时调用)
UIProbeConfigManager.Save(config);使用 JsonUtility.ToJson/FromJson 序列化,所有子配置类均标注 [Serializable]。
- 在
ImageNormalizer.cs的ResizeMode枚举中添加新值 - 在
Normalize()的switch中添加对应case,实现处理方法 - 在
UIProbeWindow_ImageNormalizer.cs的resizeModeHintif-else 链中添加说明文字 - 无需修改配置类,
resizeMode已用字符串序列化(ToString/Enum.Parse)
- 在
NormalizerSizeMode枚举中添加新值 - 在
ComputeTarget()的switch中添加计算分支 - 在
DrawImageNormalizerContent()的switch中添加对应 UI 控件 - 在
StartNormalizerProcessing()的确认对话框targetSizeDesc中补充描述 - 在
UIProbeConfig.cs的ImageNormalizerConfig中无需改动(sizeMode 已用字符串持久化)
- 在
BuildRenamerName()的parts.Add(...)序列中添加新部分 - 在
UIProbeWindow_ImageRenamer.cs的DrawRenamerRules()中添加对应 UI 控件 - 在
BatchRenameConfig中添加持久化字段 - 在
ApplyBatchRenameConfig()/CollectBatchRenameConfig()中补充读写
| 限制 | 说明 |
|---|---|
| 支持格式 | 扫描仅识别 .png / .jpg;算法层通过 LoadImage 支持更多格式但未在 UI 层暴露 |
| 大文件处理 | 扫描时逐文件 LoadTexture 读取尺寸,文件数量极多时会有明显延迟(已添加进度条) |
| 透明通道 | 输出统一为 RGBA32 PNG,原始 JPG 处理后透明区域会以白色替代(EncodeToPNG 行为) |
| 项目外文件 | 处理后不会触发 AssetDatabase.Refresh,.meta 同步亦无意义,由操作者自行管理 |
| 多图批量 + 锁宽/锁高 | 不同宽高比的图输出高度/宽度各不相同,处理结果为非统一尺寸集合 |
| 限制 | 说明 |
|---|---|
| 序列号连续性 | 仅保证列表内序号连续,若中途跳过某些文件(未勾选或过滤),序号不会补偿断档 |
| 顺序依赖 | 原路径覆盖模式下,若两文件存在名称交换(A→B,B→A),两者均会被检测为冲突,需用户手动解决 |
| Meta 同步 | 仅做文件级 Copy/Delete,不调用 AssetDatabase.RenameAsset;Unity 重启或刷新后 GUID 关联可能丢失,建议 Unity 项目内使用时通过 AssetDatabase API 重命名 |
| 支持格式 | 扫描识别 .png/.jpg/.jpeg/.tga/.psd,其他格式(如 .webp)不会出现在列表 |
本文档由 UIProbe 开发团队维护,如有问题请通过 GitHub Issues 反馈。