ps插件:烘焙图层样式
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
#target photoshop
|
||||
|
||||
/*
|
||||
Photoshop Bake Layer Style 1.5 (PS 2026 兼容版)
|
||||
|
||||
功能:
|
||||
1. 校验:当前是否选中了图层;
|
||||
2. 校验:当前图层是否包含可转换的图层样式;
|
||||
3. 显示确认窗口;
|
||||
4. 确认后复制当前图层作为工作副本;
|
||||
5. 隐藏原图层,将其保留为备份;
|
||||
6. 在工作副本上执行"图层 > 图层样式 > 创建图层";
|
||||
7. 若命令失败,自动回滚到脚本执行前的状态。
|
||||
*/
|
||||
|
||||
(function () {
|
||||
var DIALOG_TITLE = "创建图层样式";
|
||||
var DIALOG_MESSAGE = "是否烘焙图层样式到单独图层?";
|
||||
|
||||
if (app.documents.length === 0) {
|
||||
alert("请先打开文档并选择一个带有图层样式的图层。", DIALOG_TITLE, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// ========== 校验 1:当前是否选中了图层 ==========
|
||||
function hasSelectedLayer() {
|
||||
try {
|
||||
var ref = new ActionReference();
|
||||
ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("targetLayers"));
|
||||
ref.putEnumerated(stringIDToTypeID("document"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
|
||||
var desc = executeActionGet(ref);
|
||||
if (desc.hasKey(stringIDToTypeID("targetLayers"))) {
|
||||
var list = desc.getList(stringIDToTypeID("targetLayers"));
|
||||
return list.count > 0;
|
||||
}
|
||||
return false;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 校验 2:当前图层是否包含图层样式 ==========
|
||||
function hasLayerStyle() {
|
||||
try {
|
||||
var ref = new ActionReference();
|
||||
ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("layerEffects"));
|
||||
ref.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
|
||||
var desc = executeActionGet(ref);
|
||||
|
||||
if (!desc.hasKey(stringIDToTypeID("layerEffects"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// layerEffects 键存在不代表有样式,需检查内部是否有实际效果
|
||||
var fxDesc = desc.getObjectValue(stringIDToTypeID("layerEffects"));
|
||||
var effectKeys = [
|
||||
"dropShadow",
|
||||
"innerShadow",
|
||||
"outerGlow",
|
||||
"innerGlow",
|
||||
"bevelEmboss",
|
||||
"chromeFX",
|
||||
"solidFill",
|
||||
"gradientFill",
|
||||
"patternFill",
|
||||
"frameFX",
|
||||
"frameFXStyle"
|
||||
];
|
||||
for (var i = 0; i < effectKeys.length; i++) {
|
||||
if (fxDesc.hasKey(stringIDToTypeID(effectKeys[i]))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 执行前置校验(缺一不可) ==========
|
||||
if (!hasSelectedLayer()) {
|
||||
alert("当前未选中任何图层,请先选择一个图层后再执行。", DIALOG_TITLE, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasLayerStyle()) {
|
||||
alert("当前图层没有图层样式,无法烘焙。\n请先为图层添加样式(如投影、描边、外发光等)。", DIALOG_TITLE, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// ========== 确认对话框 ==========
|
||||
var dialog = new Window("dialog", DIALOG_TITLE);
|
||||
dialog.orientation = "column";
|
||||
dialog.alignChildren = ["fill", "center"];
|
||||
dialog.spacing = 16;
|
||||
dialog.margins = 20;
|
||||
|
||||
var message = dialog.add("statictext", undefined, DIALOG_MESSAGE);
|
||||
message.alignment = "center";
|
||||
|
||||
var buttonGroup = dialog.add("group");
|
||||
buttonGroup.orientation = "row";
|
||||
buttonGroup.alignment = "right";
|
||||
buttonGroup.spacing = 10;
|
||||
|
||||
buttonGroup.add("button", undefined, "取消", { name: "cancel" });
|
||||
var confirmButton = buttonGroup.add(
|
||||
"button",
|
||||
undefined,
|
||||
"确认",
|
||||
{ name: "ok" }
|
||||
);
|
||||
dialog.defaultElement = confirmButton;
|
||||
|
||||
dialog.center();
|
||||
|
||||
if (dialog.show() !== 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ========== 核心执行逻辑(已验证可运行) ==========
|
||||
var documentReference = app.activeDocument;
|
||||
var originalLayer = documentReference.activeLayer;
|
||||
var originalName = originalLayer.name;
|
||||
var initialHistoryState = documentReference.activeHistoryState;
|
||||
|
||||
try {
|
||||
var workingLayer = originalLayer.duplicate();
|
||||
originalLayer.visible = false;
|
||||
|
||||
workingLayer.name = originalName + "_烘焙";
|
||||
workingLayer.visible = true;
|
||||
selectLayerExclusively(documentReference, workingLayer);
|
||||
|
||||
createLayersFromLayerStyle();
|
||||
} catch (error) {
|
||||
try {
|
||||
documentReference.activeHistoryState = initialHistoryState;
|
||||
} catch (rollbackError) {
|
||||
try {
|
||||
originalLayer.visible = true;
|
||||
documentReference.activeLayer = originalLayer;
|
||||
} catch (restoreError) {
|
||||
// 保留最初的 Photoshop 错误信息。
|
||||
}
|
||||
}
|
||||
|
||||
var details = error.message;
|
||||
if (error.number !== undefined) {
|
||||
details += "\n错误编号:" + error.number;
|
||||
}
|
||||
if (error.line !== undefined) {
|
||||
details += "\n脚本行号:" + error.line;
|
||||
}
|
||||
|
||||
alert(
|
||||
"创建图层样式失败。\n\n" +
|
||||
details +
|
||||
"\n\n请确认当前图层包含可转换的图层样式。",
|
||||
DIALOG_TITLE,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
function selectLayerExclusively(documentReference, layerReference) {
|
||||
try {
|
||||
var descriptor = new ActionDescriptor();
|
||||
var reference = new ActionReference();
|
||||
reference.putIdentifier(
|
||||
stringIDToTypeID("layer"),
|
||||
layerReference.id
|
||||
);
|
||||
descriptor.putReference(
|
||||
stringIDToTypeID("null"),
|
||||
reference
|
||||
);
|
||||
descriptor.putBoolean(
|
||||
stringIDToTypeID("makeVisible"),
|
||||
false
|
||||
);
|
||||
executeAction(
|
||||
stringIDToTypeID("select"),
|
||||
descriptor,
|
||||
DialogModes.NO
|
||||
);
|
||||
} catch (selectError) {
|
||||
documentReference.activeLayer = layerReference;
|
||||
}
|
||||
}
|
||||
|
||||
function createLayersFromLayerStyle() {
|
||||
// 使用 ScriptingListener 录制的标准代码:
|
||||
// 用 Mk (Make) 命令,将当前图层的 Lefx (Layer Effects) 属性创建为新图层。
|
||||
var idMk = charIDToTypeID("Mk ");
|
||||
var desc = new ActionDescriptor();
|
||||
|
||||
var idnull = charIDToTypeID("null");
|
||||
var ref1 = new ActionReference();
|
||||
var idLyr = charIDToTypeID("Lyr ");
|
||||
ref1.putClass(idLyr);
|
||||
desc.putReference(idnull, ref1);
|
||||
|
||||
var idUsng = charIDToTypeID("Usng");
|
||||
var ref2 = new ActionReference();
|
||||
var idPrpr = charIDToTypeID("Prpr");
|
||||
var idLefx = charIDToTypeID("Lefx");
|
||||
ref2.putProperty(idPrpr, idLefx);
|
||||
var idLyr2 = charIDToTypeID("Lyr ");
|
||||
var idOrdn = charIDToTypeID("Ordn");
|
||||
var idTrgt = charIDToTypeID("Trgt");
|
||||
ref2.putEnumerated(idLyr2, idOrdn, idTrgt);
|
||||
desc.putReference(idUsng, ref2);
|
||||
|
||||
executeAction(idMk, desc, DialogModes.NO);
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user