Photoshopでリンク配置したスマートオブジェクト(.psd)のレイヤーカンプを活用して管理する場面は多く見られます。
しかし、スマートオブジェクト内のレイヤーカンプを取得する標準のAPIは用意されていません。
それでも、Photoshopの非公開内部情報にアクセスする手法を用いれば、レイヤーカンプ一覧を取得できます。
この記事では、アクティブなドキュメント内にある全スマートオブジェクトレイヤーからレイヤーカンプ一覧を取得し、ダイアログに表示するExtendScript(JSX)を紹介します。

標準APIを使わずにレイヤーカンプを取得する方法
Photoshopのほかの自動化手順は、まとめ記事で確認できます。

処理の要となるのは、executeActionGet() と ActionReference の組み合わせです。
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID("Lyr "), layer.id);
var desc = executeActionGet(ref);この処理により、レイヤーのプロパティ情報に直接アクセスできます。
取得したプロパティ内には、スマートオブジェクト専用の smartObject キーが存在し、その階層下に compsList というリスト構造が格納されています。
内部データ構造からレイヤーカンプ一覧を取得する手順
layer (ArtLayer) →
executeActionGet(ref) →
desc.getObjectValue("smartObject") →
getObjectValue("compsList") →
getList("compList") → 各カンプ情報各 comp オブジェクトには以下の情報が含まれています。
| キー名 | 意味 |
|---|---|
name | レイヤーカンプの名前 |
ID | カンプに割り当てられたID |
補足:公式ドキュメントに記載のないActionManagerの利用について
このデータ構造は、公式のDOM(Document Object Model)では取得できません。
代替手段として、ActionManager(AMコード)と呼ばれる低レベルAPIを利用し、Photoshop内部のプロパティを参照しています。
こうした記述方法は、Photoshopの操作をコード化するScripting Listenerプラグインなどで出力ログを解析して特定されています。
サンプルコード
以下のスクリプトを拡張子 .jsx のファイルとして保存し、Photoshopの[ファイル]メニューなどから実行してください。
※リンク配置だけでなく、埋め込みスマートオブジェクトにも対応しています。
#target photoshop
// 対象レイヤーを再帰的に収集
function collectAllLayers(layerCollection, result) {
for (var i = 0; i < layerCollection.length; i++) {
var layer = layerCollection[i];
if (layer.typename === "ArtLayer") {
result.push(layer);
} else if (layer.typename === "LayerSet") {
collectAllLayers(layer.layers, result);
}
}
}
// スマートオブジェクトのレイヤーカンプ一覧を取得
function getLayerCompsFromSmartObject(layer) {
var list = [];
try {
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID("Lyr "), layer.id);
var desc = executeActionGet(ref);
if (!desc.hasKey(stringIDToTypeID("smartObject"))) return [];
var soDesc = desc.getObjectValue(stringIDToTypeID("smartObject"));
if (!soDesc.hasKey(stringIDToTypeID("compsList"))) return [];
var compsList = soDesc.getObjectValue(stringIDToTypeID("compsList")).getList(stringIDToTypeID("compList"));
for (var i = 0; i < compsList.count; i++) {
var comp = compsList.getObjectValue(i);
var name = comp.getString(stringIDToTypeID("name"));
var id = comp.getInteger(stringIDToTypeID("ID"));
list.push({ name: name, id: id });
}
} catch (e) {
// 無視(対象外)
}
return list;
}
// メイン処理
function main() {
if (app.documents.length === 0) {
alert("ドキュメントが開かれていません。");
return;
}
var allLayers = [];
collectAllLayers(app.activeDocument.layers, allLayers);
var output = "スマートオブジェクトのレイヤーカンプ一覧:\n\n";
var found = false;
for (var i = 0; i < allLayers.length; i++) {
var layer = allLayers[i];
if (layer.kind === LayerKind.SMARTOBJECT) {
var comps = getLayerCompsFromSmartObject(layer);
if (comps.length > 0) {
found = true;
output += "【" + layer.name + "】\n";
for (var j = 0; j < comps.length; j++) {
output += " ・[" + comps[j].id + "] " + comps[j].name + "\n";
}
output += "\n";
}
}
}
if (!found) {
alert("レイヤーカンプ付きスマートオブジェクトは見つかりませんでした。");
} else {
alert(output);
}
}
main();
スクリプトを実行すると、レイヤーカンプを保持するスマートオブジェクトを検出し、その一覧情報をダイアログに表示します。

この記事で紹介しているコードは、GitHubのMOTOKI-LLC/cg-method-codeにもまとめています。
レイヤーを操作するスクリプトは、ほかにもあります。




