Files
tools/Mac工具/Yeomai-Toolbox-CEP/jsx/scripts/1.图层工具/重命名图层.jsx
T
2026-08-20 11:58:15 +08:00

386 lines
10 KiB
React
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#target photoshop
/*
* 重命名图层 - 独立版
*
* 使用方法:
* Photoshop -> 文件 -> 脚本 -> 浏览,选择本文件。
*
* 支持规则:
* %n 正序编号:1、2、3...
* %%n 倒序编号
* %nn 两位编号:01、02、03...
* %n### 编号 + 原图层名
* %%n### 倒序编号 + 原图层名
* %n=5 从 5 开始编号
* 旧文字=>新文字 替换名称中的第一个匹配文本
*
* CEP 调用:
* 先把 CMM_RENAME_AUTO_RUN 改为 false,加载本文件后调用:
* cmm_batchName("%n###", true, true);
* 第三个参数控制是否重命名图层组,省略时默认为 true。
*/
// 独立运行时设为 true;作为 CEP 函数库加载时改为 false。
var CMM_RENAME_AUTO_RUN = true;
// suspendHistory 使用的全局参数。
var CMM_RENAME_EXPRESSION = "";
var CMM_RENAME_FILTER_SUBLAYERS = true;
var CMM_RENAME_INCLUDE_GROUPS = true;
function cmm_s2t(value) {
return stringIDToTypeID(value);
}
function cmm_c2t(value) {
return charIDToTypeID(value);
}
function cmm_getActiveLayerId() {
var ref = new ActionReference();
ref.putProperty(cmm_s2t("property"), cmm_s2t("layerID"));
ref.putEnumerated(
cmm_s2t("layer"),
cmm_s2t("ordinal"),
cmm_s2t("targetEnum")
);
return executeActionGet(ref).getInteger(cmm_s2t("layerID"));
}
function cmm_getSelectedLayerIds() {
var ids = [];
var ref = new ActionReference();
ref.putProperty(cmm_c2t("Prpr"), cmm_s2t("targetLayers"));
ref.putEnumerated(cmm_c2t("Dcmn"), cmm_c2t("Ordn"), cmm_c2t("Trgt"));
var desc = executeActionGet(ref);
// Photoshop 单选图层时,部分版本不返回 targetLayers。
if (!desc.hasKey(cmm_s2t("targetLayers"))) {
ids.push(cmm_getActiveLayerId());
return ids;
}
var list = desc.getList(cmm_s2t("targetLayers"));
var backgroundOffset = 0;
try {
if (app.activeDocument.backgroundLayer) {
backgroundOffset = -1;
}
} catch (ignoreBackgroundError) {
backgroundOffset = 0;
}
for (var i = 0; i < list.count; i += 1) {
var layerIndex = list.getReference(i).getIndex(cmm_c2t("Lyr ")) + 1;
var layerRef = new ActionReference();
layerRef.putProperty(cmm_c2t("Prpr"), cmm_c2t("LyrI"));
layerRef.putIndex(
cmm_c2t("Lyr "),
layerIndex + backgroundOffset
);
var layerDesc = executeActionGet(layerRef);
ids.push(layerDesc.getInteger(cmm_c2t("LyrI")));
}
return ids;
}
function cmm_selectLayerById(layerId, addToSelection) {
var ref = new ActionReference();
var desc = new ActionDescriptor();
ref.putIdentifier(cmm_c2t("Lyr "), layerId);
desc.putReference(cmm_c2t("null"), ref);
desc.putBoolean(cmm_c2t("MkVs"), false);
if (addToSelection) {
desc.putEnumerated(
cmm_s2t("selectionModifier"),
cmm_s2t("selectionModifierType"),
cmm_s2t("addToSelection")
);
}
executeAction(cmm_c2t("slct"), desc, DialogModes.NO);
}
function cmm_restoreLayerSelection(ids) {
if (!ids || ids.length === 0) {
return;
}
cmm_selectLayerById(ids[0], false);
for (var i = 1; i < ids.length; i += 1) {
cmm_selectLayerById(ids[i], true);
}
}
function cmm_indexOf(arr, value) {
for (var i = 0; i < arr.length; i += 1) {
if (arr[i] === value) {
return i;
}
}
return -1;
}
/*
* 根据选项排除图层组。普通图层和图层组都使用 Photoshop 图层 ID,
* 因此必须选中目标后通过 typename 判断其类型。
*/
function cmm_filterLayerGroups(ids, includeLayerGroups) {
if (includeLayerGroups) {
return ids;
}
var result = [];
for (var i = 0; i < ids.length; i += 1) {
cmm_selectLayerById(ids[i], false);
if (app.activeDocument.activeLayer.typename !== "LayerSet") {
result.push(ids[i]);
}
}
return result;
}
/*
* 如果父图层组和它的子图层同时被选中,只保留父图层组。
*/
function cmm_filterSubLayer(ids) {
var result = [];
for (var i = 0; i < ids.length; i += 1) {
cmm_selectLayerById(ids[i], false);
var parent = app.activeDocument.activeLayer.parent;
var isChildOfSelectedGroup = false;
while (parent && parent.typename !== "Document") {
if (cmm_indexOf(ids, parent.id) !== -1) {
isChildOfSelectedGroup = true;
break;
}
parent = parent.parent;
}
if (!isChildOfSelectedGroup) {
result.push(ids[i]);
}
}
return result;
}
function cmm_isBlank(value) {
return value === undefined ||
value === null ||
String(value).replace(/\s/g, "") === "";
}
/*
* 核心函数。函数名和原插件保持一致,方便 CEP 直接调用。
*/
function cmm_batchName(expression, filterSubLayers, includeLayerGroups) {
if (app.documents.length === 0) {
throw new Error("请先打开一个 Photoshop 文档");
}
if (cmm_isBlank(expression)) {
throw new Error("重命名规则不能为空");
}
var rule = String(expression);
var ids = cmm_getSelectedLayerIds();
// 为兼容原来的两个参数调用,第三个参数省略时默认包含图层组。
if (includeLayerGroups === undefined) {
includeLayerGroups = true;
} else {
includeLayerGroups = Boolean(includeLayerGroups);
}
// 先排除图层组。这样关闭“重命名图层组”时,选中的普通子图层
// 不会因为其父图层组也被选中而被过滤掉。
ids = cmm_filterLayerGroups(ids, includeLayerGroups);
if (filterSubLayers && includeLayerGroups) {
ids = cmm_filterSubLayer(ids);
}
if (ids.length === 0) {
throw new Error("当前选择中没有符合选项的可重命名图层");
}
var reverse = rule.indexOf("%%") !== -1;
if (reverse) {
rule = rule.replace("%%", "%");
}
// %n=5、%nn=5、%%n=5 均支持;默认从 1 开始。
var startNumber = 1;
var startMatch = rule.match(/n=(-?\d+)/);
if (startMatch) {
startNumber = parseInt(startMatch[1], 10);
if (isNaN(startNumber)) {
startNumber = 1;
}
rule = rule.replace("=" + startMatch[1], "");
}
try {
for (var i = 0; i < ids.length; i += 1) {
cmm_selectLayerById(ids[i], false);
var activeLayer = app.activeDocument.activeLayer;
var oldName = activeLayer.name;
var number;
if (reverse) {
number = startNumber + ids.length - 1 - i;
} else {
number = startNumber + i;
}
var newName = rule.replace("###", oldName);
if (rule.indexOf("%nn") !== -1) {
var paddedNumber = number;
if (number >= 0 && number < 10) {
paddedNumber = "0" + number;
}
newName = newName.replace("%nn", paddedNumber);
} else if (rule.indexOf("%n") !== -1) {
newName = newName.replace("%n", number);
} else if (rule.indexOf("=>") !== -1) {
var separatorIndex = rule.indexOf("=>");
var searchText = rule.substring(0, separatorIndex);
var replacementText = rule.substring(separatorIndex + 2);
if (searchText === "") {
throw new Error("替换的原文字不能为空");
}
// 与原插件一致:每个图层只替换第一个匹配项。
newName = oldName.replace(searchText, replacementText);
}
activeLayer.name = newName;
}
} finally {
cmm_restoreLayerSelection(ids);
}
return ids.length;
}
function cmm_historyRenameRunner() {
cmm_batchName(
CMM_RENAME_EXPRESSION,
CMM_RENAME_FILTER_SUBLAYERS,
CMM_RENAME_INCLUDE_GROUPS
);
}
/*
* 把整次批量重命名合并成一条 Photoshop 历史记录。
*/
function cmm_runBatchName(expression, filterSubLayers, includeLayerGroups) {
CMM_RENAME_EXPRESSION = String(expression);
CMM_RENAME_FILTER_SUBLAYERS = Boolean(filterSubLayers);
CMM_RENAME_INCLUDE_GROUPS = includeLayerGroups === undefined ?
true : Boolean(includeLayerGroups);
app.activeDocument.suspendHistory(
"重命名图层",
"cmm_historyRenameRunner()"
);
}
function cmm_showRenameDialog() {
if (app.documents.length === 0) {
alert("请先打开一个 Photoshop 文档");
return;
}
var dialog = new Window("dialog", "重命名图层");
dialog.orientation = "column";
dialog.alignChildren = "fill";
var ruleGroup = dialog.add("group");
ruleGroup.add("statictext", undefined, "规则:");
var ruleInput = ruleGroup.add("edittext", undefined, "###%%n");
ruleInput.characters = 28;
var groupCheckbox = dialog.add(
"checkbox",
undefined,
"重命名图层组"
);
groupCheckbox.value = true;
var filterCheckbox = dialog.add(
"checkbox",
undefined,
"过滤已选父图层组中的子图层"
);
filterCheckbox.value = false;
groupCheckbox.onClick = function () {
// 不重命名图层组时,所有已选普通图层都会参与重命名,
// “过滤子图层”选项不再适用。
filterCheckbox.enabled = groupCheckbox.value;
};
var helpText = dialog.add(
"statictext",
undefined,
"%n 正序 %%n 倒序 %nn 两位编号\n%n=5 从5开始编号 ### 原名称\n旧文字=>新文字 可执行替换",
{ multiline: true }
);
helpText.alignment = "left";
var buttonGroup = dialog.add("group");
buttonGroup.alignment = "right";
buttonGroup.add("button", undefined, "取消", { name: "cancel" });
buttonGroup.add("button", undefined, "确定", { name: "ok" });
ruleInput.active = true;
if (dialog.show() !== 1) {
return;
}
try {
cmm_runBatchName(
ruleInput.text,
filterCheckbox.value,
groupCheckbox.value
);
} catch (error) {
alert("重命名失败:" + error.message);
}
}
if (CMM_RENAME_AUTO_RUN) {
cmm_showRenameDialog();
}