#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(); }