とりあえず作ってみよう!
今回はオリジナルのEffectプラグインのコーディングを行い、作成手順の説明及びソースの解説をしていきます。入門用のプラグインなので超簡単なものとして、PSET.aexというのを仕事の空き時間でさくっと作ってみました。
とりあえずソースコード一式です。
PSET.zipのダウンロード
作業時間は大体15分位。機能は指定した場所に1ピクセルの点を描画するもので、Effectsプラグインとしてはもっともシンプルなものですが、入門用としてSDKのサンプルでよくある意味不明な(本当は重要で意味がある)コードをなるべく省いています。
作成準備
コーディングを始める前に以下の準備を行います。本来ならVC++の新規プロジェクトで作り始めたいのですが、僕はテンプレートの作り方を知らないので以下の手順で作成しています(もしわかる人がいたら教えてほしいなぁ)
- まず、作業用のホームフォルダを作成します。
Examplesフォルダの中に”MyPlugins”フォルダを作ります。これは今後プラグイン作成のホームとなるフォルダになります。好みの名称しても可ですが、フォルダの位置は変えないように。プロジェクトファイルは相対パスでヘッダーファイルの位置が指定されているので注意です。
- 適当なソースをコピーする。
ソースコードを最初から作るのは流石に大変なので、Effectsフォルダから適当なソースをフォルダごとコピーします。今回はSDK_Noiseフォルダを丸ごとMyPluginsへコピーしました。 - ファイルをリネーム。中身も置換する。
手作業てファイル名の”SDK_Noise”の部分を”PSET”へリネームします。
ファイルの中身もテキストエディタで同様に置換します。ソリューションファイルやプロジェクトファイルも忘れずに書き換えます。
この作業はVC++のIDEでやるよりエディタで一括置換した方が間違いが無いです。
ここではSDK_Noiseを複製しましたが、自分専用のスケルトンを用意しておいた方が効率的です。
コーディング。覚えておいた方がいいVisual Studioの機能
後は、コーディングするだけです。ここでは、覚えておいた方がいいIDEの使い方を説明します。
- 最低限の設定
「ツール」メニュー「オプション」の、「環境」 : 「スタートアップ」 で「スタートアップ時」の設定を「空の環境の表示」に。
これで起動がかなり短縮され、快適になります。
その他の設定も自分の好みに合わせて設定しておきましょう。 - 行番号を表示させる。
「ツール」メニュー「オプション」の、「テキストエディタ」 : 「C/C++」 :「 全般」で行番号をONにします。
これは特に必要ないですが、行番号を表示しておくとなんだかプログラムしてるって気分が盛り上がります。 - 選択範囲を右クリックで定義を表示。
わからない変数の型やマクロ定義や関数は、選択して右クリックして「定義へ移動」を行えば、その項目を定義した場所を表示してくれます。
ここでは、PF_Pixelを選択して、実行すると、
とAfterEffects.hの定義場所を開いてくれます。
Visual StudioにはSDKのヘルプが無いので、この機能がヘルプの代わりになります。
SDKのソースはコメント(英語)がかなりしっかりしてますの、After_Effects_SDK_Guide.pdfをほとんど見る必要はありません。というかソースにしか書いてない事が多いです。
一般的なプログラムの事ならば、F1キーでヘルプを呼び出せます。 - Ctrl + Space で入力候補を表示
関数名やメンバ名・変数名は、先頭の2・3文字を入力した後、Ctrl+Spaceで入力候補を表示させるとタイプミスを防ぐ事が出来ます。
PSET.aexの実行
コーディングが終わったら、動作確認を行います。まぁ、今回は僕のソースをダウンロードしてリビルド行うだけですけど:-)
今回のプロジェクトにはRelease構成の設定も入れてありますので、構成マネージャでReleaseをアクティブにしてからリビルドしてもかまいません。
出来たバイナリをAfter Effectsにインストールしてみましょう。
エフェクトコントロールには、上の図のように位置と色のパラメータが表示されているはずです。そして、プレビュー画面には1ピクセルの点が描画されていると思います。
ソースの解説 PSET.h
さてここからが今回のハイライト。具体的なソースの解説です。まず、PSET.h。ヘッダーファイルです。
7行目の#programaと8・9・61行目の#で始まるコマンドはヘッダーを二度読みされないようにする為のヘッダーファイルでよく使われるものです。
SDKのヘッダーをインクルードした後に、いろいろな定義を行っています。
特に重要なものは、バージョン定義とパラメータ用のenum定義された定数。これはプラグイン毎に設定します。SDKのサンプルではパラメータ定義をPF_ADD_PARAM用と読み込み用で分けて定義していますが、ここでは兼用しています。
バージョンは、PiPLリソース(重要)にも同じ数値を定義する必要があります。異なっているとAfterEffectsの起動時にエラーとなります。
通常のヘッダーファイルならば、ここに関数等のプロトタイプ宣言がありますが、今回はパスカル方式を採用して省略してあります。
同一ファイル内ならば関数等のコードがそれを呼び出している箇所より先頭にあれば宣言を省略できます。SDKでも結構多用されてますが、ソースコードが複数になる場合は、しっかり宣言しましょう。
EntryPointFunc関数のみ、cppのソースからc形式の関数を使用するために、(extern “C”)宣言しています。
PSET.cppの解説 その1 include/EntryPointFunc
PSET.cppは、プラグインのメインとなるソースです。入門用になるべくシンプルにと考えてコーディングしたら自分でもびっくりするくらい短い行数になりました(普段書いてるスクリプトの行数より少ない)まず最初にPSET.hをincludeしてます。
ソースの一番後ろにあるEntryPointFunc関数は、標準Cでいうmain関数に相当します。
Effectプラグインは必ずこの関数から実行され、引数のセレクタ(PF_Cmd)に応じたイベント(関数)を実行するように作ります。
PSET.cppは最低限のセレクタにしか対応させていませんが、普段僕の作ってるものもコレくらいです。
PF_Cmdについては、付属のドキュメントに詳しい記述があるので、目を通しておくといいと思います。
PSET.cppの解説 その2 About
セレクタPF_Cmd_ABOUTで呼び出される関数です。
エフェクトコントロールの”情報”ボタンをクリックすると呼び出されます。この関数では情報ダイアログの表示を行います。
PF_SPRINTは、ダイアログを表示するコールバック関数をマクロ定義したもので、AfterEffectCB.hで定義されています。
大文字のコマンドはほとんどマクロ定義なので注意しましょう(マニュアル見ても絶対に分からない)
右クリックして定義を見ると以下のようにになっています。
“PF_Indata *in_data”という変数があるのが前提のマクロですので注意してください。適当な関数にこのマクロをいきなり書いてもエラーです。
PF_SPRINT自体はCの標準関数のsprintfとほぼ同じ使い方ができます。結果はコンソールではなく、ダイアログが作成され内容を表示します。
PSET.cppの解説 その3 GlobalSetup
セレクタPF_Cmd_GLOBAL_SETUPで呼び出される関数です。ホスト(AfterEfefcts)が起動時にプラグインを読み込んだと時に呼び出されます。
ホスト(AfterEffects)にプラグインのバージョンと、out_flagsの値を戻して終了しています。
ホストはPiPLリソースの値と比較して違っていた場合はエラーとしてこのプラグインの読み込みを中止します。
out_flagsは、ホスト(AfterEffects)の動作を指定するもので、描画のタイミングやその他多くの設定を指定するものです。
数値は、AfterEffect.hで定義されていて、コメントでその詳細も明記されてあります(だれかout_flagsの説明を和訳してくれる人いないかなぁ?僕自身分からないところでもあります)
プラグインのバージョンout_flagsはPiPLリソースにも同じ数値を記述する必要があります。
out_flags2は最近のバージョンになってフラグの数が足りなくて拡張したものです。out_flagsと基本的に同じものです。僕はほとんど使ったことがないので、今回もPF_out_flag_NONE(つまり0)を指定してあります。
PSET.cppの解説 その4 ParamsSetup
セレクタPF_Cmd_PARAMS_SETUPで呼び出される関数です。レイヤにこのプラグインを登録した時呼び出されます。すでに登録されているプロジェクトファイルを読み込んだ時にも呼び出されます。
ホストのエフェクトコントロールパネルへの登録と初期化をここで行います。
PF_ParamDef def変数に表示させるコントロールのパラメータを入れて、コールバック関数のadd_paramでパラメータUIの登録を行います。
ここはかなり複雑なので、Util/Param_Utils.hで定義されているマクロを使えば簡単に行うことができます。
PSET.cppでは位置パラメータと色パラメータの二つを登録しています。変数defは、マクロをつかって初期化しています。
最後にパラメータの総数を通達して、この関数での処理は終わりです。
注意点としては、パラメータの登録順が、PSET.hで定義されている定数(PSET_INPUTから始まるenum定義されているもの)と順番が同じになってないとダメです。
他のパラメータUIを追加したいときは、Util/Param_Utils.hで定義された各種マクロを使えば結構簡単にインターフェースを構築できます。
逆を言えば、ここで定義されていないカスタムUIを作成するときは、かなり面倒な事になりま。プラットホーム依存が確実に発生します。
PSET.cppの解説 その5 Render
セレクタPF_Cmd_RENDERで呼び出される関数です。ここはホストが描画準備を完了し、プラグインに描画させたいときに呼び出されます。
この関数が、プラグインの描画のメインとなります。
- プラグインパラメータの獲得。
タイムラインのカレントのパラメータの数値を引数のPF_ParamDefポインタ配列から獲得します。
ここらへんはもう構造体の嵐でパッと見良く分からない感じですが、ほとんど決まりきった表記なので適当なSDKのソースからコピペで対応出来ます。
位置パラメータは固定小数値なので、今回は単純にシフトして整数値のみにしてあります。
- 画像の情報を獲得。
画像のサイズ等、描画に必要な情報を獲得します。
獲得する情報は、
- 入力画像構造体(PF_EffectWorld)
- 画像の横サイズ
- 画像の縦サイズ
- 実際の画像の横サイズ
- 入力画像データの先頭アドレス
- 出力画像データの先頭アドレス
- その他必要な情報
ここで、注意する点は、元の画像がが入った入力画像(input)と処理が終わった画像を入れる出力画像(output)と扱う画像が二つあることです。このことは後で説明します。
- 実際の描画を行う。
あとは、プラグイン独自の描画を行うだけです。
とりあえず、今回は出力画像に入力画像を単純にコピーします。専用のコールバック関数(PF_COPY)を呼び出して簡単に行っています。
次に画像に点を打つコードを記述します。
まず、パラメータのチェックを行います。指定された位置が画面内にあることを確認してから以下のコードを実行します。
outData[psetX + psetY * outWidth] = psetCol;
outDataはPF_Pixelの1次元配列で、psetX はX座標・psetYはY座標・psetColはPF_Pixelのピクセルデータの変数です。
outWIdthは出力画像の実際の横幅です。XとYの値から1次元配列のアドレス位置を計算しています。
横幅は表示サイズとデータ内でのサイズと異なる場合がほとんどなので注意してください。データ内では効率化・ハードウエアの都合等の理由でだいたい4の倍数とかに切り上げられています。
PSETPiPL.r
PSETPiPL.rは、PiPLリソースを作成するためのリソース定義ファイルです。PiPLリソースは、ホスト(AfterEffects)が起動時にプラグインの情報を得るためのデータが入っています。起動ごとににプラグインのバイナリを実行するのはかなり大変なことなので作られているものです。昔のMacではごく普通のスタイルでAfterEffectsが最初Macで開発されていた時の名残みたいなものです。そのため通常のWindowsコンパイラではPiPLリソースは作成できないのでSDKでは、専用のツールが付属しています。
ちなみにAdobe製品はすべてPiPLリソースを持っています。各製品のSDKには必ずPiPLリソースのドキュメントが付属しています。
プロジェクトでは、カスタムビルドステップでそのツールを呼び出すコマンドラインが設定されています(PSETPiPL.rを右クリックしてプロパティを表示すると確認できます)
ここではPiPLの要素で必要なもののみ説明します(その他のリソースの詳細は説明しませんし、あまり覚える必要もありません)
要素 | 説明 | 値 |
---|---|---|
Kind | プラグインの種類。 | AEEffect |
Name | プラグインのメニューに表示されるプラグイン自体の名称 | PSET |
Category | このプラグインが表示されるサブメニューの名称 | Sample AEP Project |
AE_Effect_Version | GlobalSetupで設定しているプラグインのバージョン。AfterEffects自身のバージョンではないので注意! | 524288 |
AE_Effect_Global_OutFlags | GlobalSetupで設定しているout_flagsの値 | 1024 |
AE_Effect_Global_OutFlags_2 | GlobalSetupで設定しているout_flags2の値 | 0 |
AE_Effect_Match_Name | プラグインの識別名。同じ識別名のプラグインがあった場合エラーとなる | AEP Project PSET |
AE_Effect_Version/AE_Effect_Global_OutFlags/AE_Effect_Global_OutFlags_2は、整数値を直接記入する必要があり、計算が結構面倒です。
cppのソース内ではマクロでうまく処理させてますが、ここで再計算するのが面倒なので僕は専用のアプリを作って計算させています。
◎FsAE_tools.zip
このアーカイブ内にあるAE_Utils.exeは、バージョンとout_flagsの計算を行うもので、AE_ProjectRename.exeは、ソースコードのプロジェクト名を一括リネームするものです。
どちらもかなり前に作成したものなので、機会があったら作り直すつもりです。
最後に
今回はかなりの量があって大変でした。15分で作ったプラグインの解説にまる二日かかって仕舞いました。仕事もかなり厳しい状態だったので参りました。ところどころにいきなり説明されいない単語がありますが、SDKのヘッダやサンプル・ドキュメントに載っているものなので暇があったら調べてみてください。いずれ記事として投稿するつもりですが、慣れれば簡単に見つけられるものばかりです。SDKに慣れるつもりでお願いします。
次は、C言語の記事にしようと思ってましたが、僕自身あまり言語に詳しくなくて正確なことを書くためにちょっといろいろ調べることがいっぱい出てしまいました。投稿の間隔が開くのが嫌なので、予定を変更して今回作ったPSET.aexをちょっと改造してみようと思ってます。
ということで次回は「プラグインに機能を追加してみよう!」となります。
おまけ
あまりにも簡単なプラグインなのでおまけの機能をつけてます。PSET.cppの117行から始まるコメントアウトさせてある部分を復活させてみてください。
1ピクセルでは無く、指定した位置を中心にしたクロス線の描画に変わります。
新着記事 : アニメ制作者のためのAfterEffectsプラグイン作成入門(第2回) とりあえず作ってみよう! http://bit.ly/b0dzep
忙しい時ほど、こういう誘惑に負けちゃいそうになる。早く書いてみたーい! けどガマン・・・・ RT @AEUSERS アニメ制作者のためのAfterEffectsプラグイン作成入門(第2回) http://goo.gl/nKvS
RT @AEUSERS: アニメ制作者のためのAfterEffectsプラグイン作成入門(第2回) とりあえず作ってみよう! http://bit.ly/c1SOGg
RT @AEUSERS: アニメ制作者のためのAfterEffectsプラグイン作成入門(第2回) とりあえず作ってみよう! http://bit.ly/c1SOGg
みてる RT @AEUSERS: アニメ制作者のためのAfterEffectsプラグイン作成入門(第2回) とりあえず作ってみよう! http://bit.ly/c1SOGg
みてる RT @AEUSERS: アニメ制作者のためのAfterEffectsプラグイン作成入門(第2回) とりあえず作ってみよう! http://bit.ly/c1SOGg
http://bit.ly/aB4dVq アニメ制作者のためのAfterEffectsプラグイン作成入門(第2回) とりあえず作ってみよう! | AEP Project とりあえず作ってみよう! 今回はオリジナルのEffectプラグインのコーディングを行い、作成手順の説明..
ようやく、こちらで公開されていられるサンプルをCS5.5プラグインとして改造できた…… RT @AEUSERS アニメ制作者のためのAfterEffectsプラグイン作成入門(第2回) とりあえず作ってみよう! http://t.co/8EPCXnt6 #aejp
http://t.co/Y3aQVt9M これに挑戦してるけど専門用語ばかりで意味不明すぎて死ぬ
http://t.co/Y3aQVt9M これに挑戦してるけど専門用語ばかりで理解できなくて死にそう
サンプルプロジェクトをVS2010にコンバートしてRelease(Release-MT)ビルドすると、”_ITERATOR_DEBUG_LEVEL”による警告が発生する場合があるようです。
このような状態になる原因は判明させていませんが、おそらくVSのコンバート処理によるものと推測されます。
警告なのでビルド自体は成功しますが、デバッグ版のコードが含まれるため速度が極端に低下する可能性を考慮すると解消することを検討した方がいいと思います。
この警告は、各ソースコードのプリプロセッサ定義がプロジェクトプロパティから継承されず、各ソースコード独自でプリプロセッサ定義を保有しており、”_DEBUG”が定義されているためです。その結果、使用するランタイムライブラリが異なり警告が発生します。
解決方法は各ソースコードのプロパティを開き、プリプロセッサ定義の”_DEBUG”を削除するか、”_NDEBUG”に書き換えることが必要となります。
*.vcxprojファイルをテキストエディタで直接開いて_DEBUGを検索、適宜修正を行うとした方が楽かもしれません。