【Photoshop】拡張機能でカスタムパネルを作成する方法[プラグイン]

eyecatch_ photoshop

Photoshopの拡張機能のカスタムパネルを試してみました。(※Photoshop CC 2014以降で作成可能です)

これで自作ツールを並べることができますし、htmlで構成されているのでcssでの見た目も調整できるので、かなりテンション上がります!

この記事の著者
CGブロガー すいみん

CGブロガー

すいみん

Suimin

プロフィール

某美大の油絵科を卒業後、大手CG映像プロダクションに入社。
その後ゲーム業界に転職。
現在は技術系のCGデザイナーをしています。 書籍:Unity デザイナーズ・バイブル
プロフィール詳細はこちら

Photoshop拡張機能でカスタムパネルを表示する方法

まずは環境構築をしてしまいましょう!

STEP.1
Bracketsのインストール
下記のURLからAdobeが開発のテキストエディタをインストール
参考 BracketsBrackets
’STEP.2′
’>Creative
Bracketsを起動して、ファイル>拡張機能マネージャー>URLからインストールから下記のURLをコピペして、インストール

参考 CC-Extension-Builder-for-BracketsGitHub

’STEP.3′
’>サンプルの拡張機能を作成’
メニューにCC Extension Builderが追加されるので、そこからNew Creative Cloud Extension>Create Extensionを実行

’STEP.4′
’>バージョンの記述の変更’

このままPhotoshop2017を立ち上げても、ウインドウ>エクステンションの中にHello Worldという名前の拡張機能が読み込まれていません。

まずは、Bracketsに表示されているmanifest.xmlを編集します。

C:Usersユーザー名AppDataRoamingAdobeCEPextensionscom.example.helloworld'CSXSmanifest.xml

<Host Name="PHXS" Version="[15.0,15.9]" />
<Host Name="PHSP" Version="[15.0,15.9]" />

<Host Name="PHSP" Version="[18.0,18.9]" />
<Host Name="PHXS" Version="[18.0,18.9]" />

に書き換えます。

※ バージョン参考

・CC2017 Version 18

・CC2015 Version 16

・CC2014 Version 15

※バージョンを[18.0,18.9]と2つ書いているのはその2つのバージョン内という意味

’STEP.5′
’>署名の設定の必要’

Photoshop2017を立ち上げてウインドウ>エクステンションの中にHello Worldという名前の拡張機能が読み込まれているのを確認します。

ただし、このまま実行しても拡張子を読み込めませんでした。正しくサインされていません。という警告がでます。

’STEP.5′
’>無署名を許可する’
レジストリを調整して無署名を許可します。

  • Win+Rからregeditを入力して、レジストリ エディターを起動
  • HKEY_CURRENT_USER/Software/Adobe/CSXS.7まで移動して、右クリックから新規>文字列値から、名前をPlayerDebugMode、値を1

参考 playerDebugModeの設定手抜きLab@DTPの現場

もう一度、Photoshop2017を立ち上げてウインドウ>エクステンションの中にHello Worldを選択すると、カスタムパネルが起動し、またボタンも機能します。

.reg作成

.reg作成してみました。

メモ帳に下記のコードをコピペして、PlayerDebugMode_on.regみたな感じで適当な命名+拡張子(reg)に変更。

実行するとレジストリに追記されます。

Windows Registry Editor Version 5.00
[HKEY_CURRENT_USERSoftwareAdobeCSXS.7]
"PlayerDebugMode"="1"

つづいて署名を作成します。

STEP.1
レジストリ調整
自分だけで、完結する場合はレジストリ調整して無署名でよいのですが。
レジストリがいじれない場合や他人に渡す場合などは、署名を作成すれば、警告がでてこなくなります。

STEP.2
CC Extensions Signing Toolkitのダウンロード
下記のURLからCC Extensions Signing Toolkitをダウンロードします。(こちらが最新のようです)

参考 Adobe-CEP/CEP-ResourcesGitHub
STEP.3
ZXPSignCmd
中身のZXPSignCmd.exeを好きな場所に保存します。

STEP.4
コマンドプロンプトの起動
Win+Rからcmdを入力して、コマンドプロンプトを起動します。

ここで、単純にZXPSignCmd.exeを入力すると、全てのコマンドが表示されます。

ZXPSignCmd -sign <inputDirectory> <outputZxp> <p12> <p12Password> [options]
options:
-tsa <timestampURL> - will attempt to timestamp the ZXP using supplied timestamp server. For example, https://timestamp.geotrust.com/tsa
ZXPSignCmd -verify <zxp>|<extensionRootDirectory> [options]
options:
-certInfo - will print out information about certificates (including timestamp and certificate revocation information)
-skipOnlineRevocationChecks - will skip online checks for certificate revocation (certificate revocation checks only happen with -certInfo flag set)
-addCerts <certificate1> <certificate2>... - will verify certificate chain and assess whether or not DER encoded certificates passed in are included
ZXPSignCmd -selfSignedCert <countryCode> <stateOrProvince> <organization> <commonName> <password> <outputPath.p12> [options]
options:
-locality <locality> -orgUnit <orgUnit> -email <email> -validityDays <validityDays> - are optional attributes for self-signed p12 certificates
```ZXPSignCmd -sign <inputDirectory> <outputZxp> <p12> <p12Password>```
STEP.5
署名を作成

ZXPSignCmd -selfSignedCert
<outputPath.p12>

[ZXPSignCmd.exeのパス] -selfSignedCert [国] [地域] [組織] [名前] [パスワード] [保存するファイル名]


C:Usersユーザー名ZXPSignCmd.exe -selfSignedCert JP Tokyo My MIN test custompanel.test

STEP.6
パッケージ化

ZXPSignCmd -sign

[ZXPSignCmd.exeのパス] -sign [Extensionのソースフォルダのパス] [保存するzxpのパス] [署名のパス] [署名のパスワード]

C:Usersユーザー名ZXPSignCmd.exe -sign "C:Usersユーザー名AppDataRoamingAdobeCEPextensionscom.example.helloworld'" custompanel.zxp custompanel.test test

custompanel.zxpが作成されます。

STEP.2
解凍
ちなみに.zxpはただのZIPファイルなので、試しに解凍してみます。

META-INFフォルダと言うものが追加されていて、その中にsignatures.xmlというファイルが署名になります。

参考 作ったらやっちゃおう!自作Adobe ExtensionのzxpへのパッケージとExManCmdによるインストール 1/2shock DTP

最後にカスタムパネルから設定した機能を実行してみましょう!

STEP.1
JSXの編集

Hello Worldのサンプルデータ
C:Usersユーザー名AppDataRoamingAdobeCEPextensionscom.example.helloworld'
から、カスタマイズしてみます。

jsx > hostscript.jsxの中身を以前、CGメソッドで作成したスクリプトを置換します。

function makeGroup(){
//顔
var layer_face = app.activeDocument.layerSets.add();
var layer_face_paint = layer_face.layerSets.add();
var layer_face_line = layer_face.layerSets.add();
layer_face.name = '顔';
layer_face_paint.name = '塗り';
layer_face_line.name = '線画';
//見本
var layer_template = app.activeDocument.layerSets.add();
layer_template.name = '見本';
}
js > main.js から先程の関数(makeGroup)を記述します。

(function () {
'use strict';
var csInterface = new CSInterface();
function init() {
themeManager.init();
$("#btn_test").click(function () {
csInterface.evalScript('makeGroup()');
});
}
init();
}());

関数がわからない時

evalFile関数を使用して、もう1スクリプト間にかまします。

function AAA() {
var external = $.evalFile("C:/Users/AAA.jsx");
}

index.htmlを編集します。今回はボタン名だけ変えてみます。

<button id="btn_test" class="topcoat-button--large hostFontSize">グループ作成</button>

あとはお好みでCSSなり画像なり入れて、パネルをカスタマイズしていきます。

###[ 簡易版]拡張機能でカスタムパネルを表示する方法

要素を最小限にして、カスタムパネルを表示させてみます。

STEP.1
下記のパスにTESTというフォルダを作成
%USERPROFILE%AppDataRoamingAdobeCEPextensions

STEP.2
フォルダを作成
階層下にCSXSというフォルダを作成

さらにCSXSの中に
manifest.xml
というファイルを作成

STEP.3
コードの書き換え
manifest.xmlの中身を下記のコードをコピペ

<?xml version="1.0" encoding="UTF-8"?>
<ExtensionManifest Version="5.0" ExtensionBundleId="com.example.test" ExtensionBundleVersion="1.0"
ExtensionBundleName="TEST" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ExtensionList>
<Extension Id="com.example.test" Version="1.0" />
</ExtensionList>
<ExecutionEnvironment>
<HostList>
<!-- Uncomment Host tags according to the apps you want your panel to support -->
<!-- Photoshop -->
<Host Name="PHSP" Version="[18.0,18.9]" />
<Host Name="PHXS" Version="[18.0,18.9]" />
</HostList>
<LocaleList>
<Locale Code="All" />
</LocaleList>
<RequiredRuntimeList>
<RequiredRuntime Name="CSXS" Version="5.0" />
</RequiredRuntimeList>
</ExecutionEnvironment>
<DispatchInfoList>
<Extension Id="com.example.test">
<DispatchInfo >
<Resources>
<MainPath>./index.html</MainPath>
<ScriptPath>./jsx/hostscript.jsx</ScriptPath>
</Resources>
<Lifecycle>
<AutoVisible>true</AutoVisible>
</Lifecycle>
<UI>
<Type>Panel</Type>
<Menu>TEST</Menu>
<Geometry>
<Size>
<Height>300</Height>
<Width>300</Width>
</Size>
<!--<MinSize>
<Height>550</Height>
<Width>400</Width>
</MinSize>
<MaxSize>
<Height>550</Height>
<Width>400</Width>
</MaxSize>-->
</Geometry>
<Icons>
<Icon Type="Normal">./icons/suimin.png</Icon>
</Icons>
</UI>
</DispatchInfo>
</Extension>
</DispatchInfoList>
</ExtensionManifest>

以上で、manifest.xmlだけでも、Photoshopを起動すると拡張機能にTESTのパネルが追加されています。

STEP.4
アイコン画像を追加
さらにiconsフォルダを作成して、その中に画像(suimin.png)を追加

STEP.5
index.htmlを作成
index.htmlを作成、中身は下記のコードに

<html>
<head>
</head>
<img src="icons/suimin.png">
</html>

パネルの中に画像が表示できました。

ちゃんとデータの役割を理解すると、カスタムパネルの作成も簡単に感じます。

拡張機能のカスタムパネルのHTML・CSSの調整方法

ここからは応用編です。CSS等を追加して見た目や機能を追加していきます。

適当にスクリプトを追加して、タブをつけて、中はアコーディオン式に展開できるように変更してみました。

JSX(hostscript.jsx)

hostscript.jsxから使う機能のスクリプトを読み込んでいるのですが、さらに外部参照にしました。

STEP.1
フォルダ作成
同階層にscriptsフォルダを作成して、使う機能(AAA.jsx)のスクリプトを置く

STEP.2
パスの追記
hostscript.jsxには#include "/c/Users/ユーザー名/AppData/Roaming/Adobe/CEP/extensions/custompanel/jsx/scripts/AAA.jsx"とだけ記述

※ 相対パスだと上手く行かなかったので、絶対パスにしています。

JavaScript(main.js)

ボタンを押した時に機能が動くような記述を追加するだけ

  $("#AAA").click(function () {
csInterface.evalScript('AAA()');
});

HTML(index.html)

STEP.1
アコーディオンを追加

最初から展開する場合は

STEP.2
タブを追加

ヘッド<head></head>間に下記のコードを追加

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
$(function() {
$(".tab li").click(function() {
var num = $(".tab li").index(this);
$(".tabContent").removeClass('active');
$(".tabContent").eq(num).addClass('active');
$(".tab li").removeClass('active');
$(this).addClass('active')
});
});
</script>

ボディ<body></body>の中の先頭に下記のコードを追加

STEP.3
タブの中身

先頭は
div class="tabContent active"></div>

残りは
<div class="tabContent"></div>
で区切る

※CSSも設定しないと上手くタブが作動しません。

CSS(styles.css)

参照しているスタイルシートはこちら
topcoat-desktop-dark.min.cssを使用。

STEP.1
ボタンのラベルを中央合わせに
div { text-align : center ; }
STEP.2
ボタンのサイズをまとめて記述
.topcoat-button--large--cta{
width: 100%;
}
.topcoat-button--large{
width: 100%;
}
STEP.2
タブ関係
ul.tab {
width: 100%;
list-style: none;
padding-left: 0;
}
ul.tab li {
float: left;
height: 30px;
font-family:inherit;
vertical-align: middle;
color:inherit;
font-size:inherit;
text-align: center;
width: 33.3%;
padding: 0 10px;
background-color: #595b5b;
color: #fff;
cursor: default;
}
ul.tab li:hover {
background-color: #539fe1;
color: #fff;
}
ul.tab li.active {
background-color: #368bdc;
color: #fff;
}
div.tabContent {
clear: both;
width: 100%;
display: none;
}
div.active {
display: block;
}
参考 TopcoatTopcoat

XML(manifest.xml)

パネル名、拡張機能名がhelloworldのままだったので、Custom Panelに変更しました。

※ Photoshopを再起動しないと変更されません。

参考 シンプルで使いやすいタブメニューを超簡単に作成する方法ふかふか交易所

拡張機能のカスタムパネルのデータを外部参照する方法

こちらも応用編です。

拡張機能のカスタムパネルの内容を更新するときに

  • hostscript.jsx
  • main.js
  • index.html

を変更して、それぞれの環境でデータを差し替えしていたのですが、手間なので外部参照してみました。

jsxの外部参照方法

#include "/C/Users/Namae/AppData/Roaming/Adobe/CEP/extensions/custompanel/jsx/hostscript.jsx"

というふうに参照先のパスを書くだけです。

参照先がさらにインクルードされていても、参照されます。

jsの外部参照方法

index.htmlに<script src="js/main.js"></script>と書かれている部分を

<script src="C:/Users/Namae/AppData/Roaming/Adobe/CEP/extensions/custompanel/js/main.js"></script>

というふうに参照先のパスを書くだけです。

htmlの外部参照方法

ここは手間取りました。

まずはinclude.js作成。

function include(filename, afterfunc) {
    include.seq = (include.seq) ? include.seq + 1 : 1;
    var id = new Date().getTime() + "-" + include.seq;
    var inc = document.createElement("iframe");
    inc.id = "inc-" + id;
    inc.src = filename;
    inc.style.display = "none";
    document.write("<span id="" + id + ""></span>");
    var incfunc = function() {
        var s = (function() {
            var suffix = (n = filename.lastIndexOf(".")) >= 0 ? filename.substring(n) : "default";
            if (suffix == ".html") return inc.contentWindow.document.body.innerHTML;
            if (suffix == ".txt") return inc.contentWindow.document.body.firstChild.innerHTML;
            if (suffix == "default") return inc.contentWindow.document.body.innerHTML;
        })();
        var span = document.getElementById(id);
        var insertBeforeHTML = function(htmlStr, refNode) {
            if (document.createRange) {
                var range = document.createRange();
                range.setStartBefore(refNode);
                refNode.parentNode.insertBefore(range.createContextualFragment(htmlStr), refNode);
            } else {
                refNode.insertAdjacentHTML('BeforeBegin', htmlStr);
            }
        };
        insertBeforeHTML(s.split(">").join(">").split("<").join("<"), span);
        document.body.removeChild(inc);
        span.parentNode.removeChild(span);
        if (afterfunc) afterfunc();
    };
    if (window.attachEvent) {
        window.attachEvent('onload',
            function() {
                document.body.appendChild(inc);
                inc.onreadystatechange = function() {
                    if (this.readyState == "complete") incfunc();
                };
            });
    } else {
        document.body.appendChild(inc);
        inc.onload = incfunc;
    }
}

あとはindex.htmlの中にインクルードするだけです。

< !doctype html >
    < html >
    < head >
    < meta charset = "utf-8" >
    < link rel = "stylesheet"
href = "css/topcoat-desktop-dark.min.css" / >
    < link id = "hostStyle"
rel = "stylesheet"
href = "css/styles.css" / >
    < script type = "text/javascript"
src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js" > < /script> < script >
    $(function() {
        $(".tab li").click(function() {
            var num = $(".tab li").index(this);
            $(".tabContent").removeClass('active');
            $(".tabContent").eq(num).addClass('active');
            $(".tab li").removeClass('active');
            $(this).addClass('active')
        });
    }); < /script> < title > < /title> < /head> < body class = "hostElt" >
    < ul class = "tab" >
    < li class = "topcoat-button--large hostFontSize active" > メニューA < /li> < li class = "topcoat-button--large hostFontSize" > メニューB < /li> < li class = "topcoat-button--large hostFontSize" > メニューC < /li> < /ul> < script type = "text/javascript"
src = "js/include.js" > < /script> < script type = "text/javascript" >
    include("C:/Users/Namae/AppData/Roaming/Adobe/CEP/extensions/custompanel/contents.html"); < /script>

※中身の参照先contents.htmlの内容はindex.hemlの後半部分

参考 静的HTMLで、インクルードを実現するためのJavaScripton the center line.

以上、すいみん(@cg_method)でした!

Adobe Creative Cloudを一番安く購入する方法

\Adobe Creative Cloudが学割(49.6%OFF!)で安い/


eyecatch-buy-adobe-creative-cloud
【Adobe Creative Cloud】最安!アドビ認定スクールから購入する方法(+講座付き)

すでに持っている方も1年分の追加可能

さらにAmazonギフト券でチャージしてAmazon Payで支払うともっとお得に!

Photoshopに関する参考記事・ツール・書籍のまとめ

Photoshopに関する記事を下記にまとめました。



photoshop-summary-article


便利な機能紹介!Photoshopに関する作り方まとめ

フォトショップのソフトウェア購入


eyecatch-buy-adobe-creative-cloud
【Adobe Creative Cloud】最安!アドビ認定スクールから購入する方法(+講座付き)

フォトショップが学べるスクール


参考
Photoshop講座ヒューマンアカデミー

フォトショップの参考書籍

すいみん

独学で勉強できてしまうPhotoshopですが、他の人の手法を見ると全然使いこなせてなかったことに気がつくこともあります