リマップ編集スクリプト。AEスクリプトでのイベント処理
今回はリマップ編集.jsxの紹介と解説です。本当は1行スクリプトにしようと思ってましたが、偶然キーイベントの獲得方法が判明しいろいろやってたらリマップ編集.jsxになってしまいました^^;
リマップ編集スクリプト。
リマップ編集.jsxは、文字通りレイヤのtimeRemapを編集するパレットを実現するスクリプトです。アニメの撮影ではセルのコマ打ちをtimeRemapで行う事が多く、以下のように同じ機能のソフトが多く有ります。
- りまぴん。ねこまたやさん作。りまぴん – タイムシートを編集しま
- STS TAKEYAMA Atsushiさん作 STS_ver2.0 サポートページ
- AEIOU kanbaraさん作 配布場所
- T-Sheet Matsumi Shinichiさん作 Animeの道具箱
- AE_Remap Exceed 自作 ここ
- RemapEditor 自作 AEP Project
スクリプトで実装できるUIがかなり不自由なので、ほとんどが別アプリでコピー&ペーストやスクリプトを使って、timeRemapを編集しています。
今回キーイベントの処理がわかったので、ちょっと作ってみたのがリマップ編集.jsxです。具体的にはAEP Projectで発表したRemapEditorをスクリプトで作り直したものになります。
ダウンロード以下から行えます。
remapEdit
Windows版After EffectsCS4で動作確認しています。CS3では一応動きますが、キーイベントが獲得できないので操作はNavパレットでマウスのみです。Mac版では後で説明しますが、動作に制限が有ります。
リマップ編集スクリプトの使い方
リマップ編集.jsxは、”Scripts/ScriptUI Panels“フォルダに入れておけばフローティングパレットとして動作します。ただし、Mac版では、フローティングパレットではキーイベントの発生と同時に何故か他のパレットへフォーカスが移動してしまうのでほとんど実用になりません。
「スクリプトファイルの実行…」から実行して通常のパレットとして動かすか、Navパレットをアクティブにした状態でキー入力を行なってください。
デフォルトでは24Fps72Frameの状態で起動します。その後は値を保存してそれを復帰させます。
GETボタンで、選択したレイヤのtimeRemapの値を獲得し、セル番号としてリストに表示します。
SETボタンで、入力したセル番号を選択したレイヤに適応させます。その際の空セルの実装方法はprefで設定したものになります。
copy/cut/pasteボタンでカット&ペーストが可能です。ただしクリップボードへのコピー・貼り付けは出来ません。
簡易的にキーボードショートカットにも対応させています。
下のリストボックスの適当なフレームを選択(Shiftで数選択可能)し、数字キーを押すとリストボックスの上に押された数値が追加されていきます。
エンターキーで入力した数値をリストボックスの選択した位置へ入力します。
prefボタンで、フレームレートの変更・フレームの削除追加・総フレーム数の設定が出来ます。
Navボタンで操作を全てマウスで行う為のパレットが表示されます。Navパレットがアクティブ(フォーカス)な状態でもキー入力で操作できます。
Inpボタンでリピート対応の自動セル番号入力ダイアログが表示されます。
操作方法は自作のAE_Remap Exceedとほぼ同じにしています。
イベントとは
簡単にイベント処理と言ってますが、イベント駆動型プログラミングと言いGUIを実装する為に考えられたものになります。AEスクリプトは、フロー駆動型プログラミングが基本的となりますが、さすがにダイアログ等を作成する為に簡単なイベントが実装されています(ボタン等のコントロールのonClickイベント等)イベントに関しては細かく説明していくと本が何冊も出来てしまう分量になるので、ここでは簡単な説明と重要なことのみにします。
基本となるイベントループ(メインループ)があり、何もイベントが起きていない状態をアイドル(idle)と呼びイベントの発生を待ちます。イベントの主なものはキーイベント・マウスイベントの二つ(他にもいろいろある)
例えば、何かのキーが押された場合イベントループ内のキー検出ファンクションがメッセージを発生させます。そのメッセージ内容を判別し、それに応じたイベントハンドラ(関数)が実行されます。
なんだかよくわかりませんね^^;とりあえず、上で書いた単語を覚えておくだけでいいと思います。
Windows/McOSXだとObject志向プログラミングによって多少わかりやすい感じになります。というかイベント駆動型プログラミングを可能にする為にObject志向プログラミングが考え出されたってイメージですが。
アイドル状態ってまぁたいていの場合アプリを起動してユーサーの入力待ちになった状態であまり意識することはないです。キーイベントによりメッセージが発生って、ボタン押したらそのボタンのonCkickが実行されたって事です。メッセージ発生とは基本的に関数呼び出しのことです。
JavaScriptはイベント処理を簡単に使えるようにかなり遮蔽化してるので、JavaScriptではなく他の言語のイベントの解説を調べるのがわかりやすいです。例えば、こことかここです。
正直に言うと僕はあまりイベントの事が良くわかってないです。概念はなんとなくわかるんですが、それ以上はわかりません。まぁObject志向プログラムのおかげでわからなくても何とかなっています。いい時代になりました。
addEventListenerとイベントの獲得
AEスクリプトでイベント処理を行うときはonで始まる名称の組み込み済みのイベントハンドラを使うのが基本です。しかし、標準状態ではかなり貧弱でイベント発生時のパラメータの獲得が出来ません。そのためイベントの追加拡張が必至です。
具体的にはUI関係のオブジェクトのメソッドであるaddEventListener()を使いイベントの追加を行います。
addEventListener()
controlObj.addEventListener (eventName, handler[, capturePhase]);
windowObj.addEventListener (eventName, handler[, capturePhase]);
“JavaScript Tools Guide“のP.112とP.136に具体的な説明が有ります。
このメソッドでコントロールやウィンドウObjectにイベントを追加できます。
第1引数(eventname)で追加できるイベントは以下のものです。イベント名は文字列で指定です。
イベント名 | 解説 |
---|---|
changing | 値が変化中に発生。スライダバー等 |
change | 値が変わった |
moving | objectの位置が変化中に発生。ウィンドウ等 |
move | objectの位置が変わった。 |
resizing | objectの大きさが変化中 |
resize | objectの大きさが変わった |
show | objectが表示された |
enterKey | objectのデフォルトキーを押した? |
focus | objectがフォーカスを獲得した |
blur | objectがフォーカスを開放した |
mousedown | マウスボタンを押した |
mouseup | マウスボタンを離した |
mousemove | マウスカーソルが移動した |
mouseover | objectの上にマウスカーソルが入った |
mouseout | objectの上からマウスカーソルが出た |
keyup | キーが押された |
keydown | キーが離れた |
click | マウスボタンをクリックした |
第2引数(handler)はイベント発生時に実行されるイベントハンドラ(function object)を指定します。
呼び出されるfunction(関数)の引数には、KeyboardEvent object/MouseEvent objectが渡されます(これがミソ)
イベントハンドラーの引数(KeyboardEvent object/MouseEvent object)のプロパティを参照することで押されたキーやマウスの位置を獲得できます。
この仕組みを使いリマップ編集.jsxスクリプトはキーの獲得を実装しています。
第3引数はイベントの動作を指定するものですが、大抵の場合省略しても大丈夫です。
具体的なサンプルコードは以下のとおりです。
addEventListener()は、イベントハンドラを上書きでなく追加していきます。
on出はじまる組み込みイベントと同時利用も可能です。イベントの発生順はaddEventListener()での登録順となります。
イベントハンドラーの破棄はremoveEventListener()で行います。
KeyboardEvent objectのプロパティ
KeyboardEvent objectのプロパティのプロパティは以下のものが有ります。詳しくはJavaScript Tools Guideを(P.145)参照してください。
プロパティ名 | Object | 説明 |
---|---|---|
type | Strig | イベントの種類。keyup or keydown |
keyName | String | 押されたキーの文字 |
keyIdentifier | String | キーコード |
altKey | Boolean | altKeyが押されていたらtrue |
ctrlKey | Boolean | ctrlKeyが押されていたらtrue |
metaKey | Boolean | metaKey(command/windows)が押されていたらtrue |
shiftKey | Boolean | shiftKeyが押されていたらtrue |
keyLocation | Number | 押されたキーの位置 |
???Keyのプロパティはそのキーが単独で押されていた場合、keyNameプロパティにそのキーの文字が反映され、???Key自体はundefinedになります。
根底 objectであるUIevent objectのプロパティも同時に使う事ができます。
MouseEvent objectのプロパティ
MouseEvent objectのプロパティのプロパティは以下のものが有ります。詳しくはJavaScript Tools Guideを(P.148)参照してください。
type | Strig | イベントの種類。mousedown/mouseup/mousemove/mouseover/mouseout/click |
detail | Number | clickイベント時の動作 1:シングルクリック 2: ダブルクリック |
button | Number | 押されたマウスボタンの位置0:左 1:真ん中 2:右 |
clientX clientY | Number | 親コントロール基準のポインタの位置 |
screenX screenY | Number | スクリーン基準のポインタの位置 |
altKey ctrlKey metaKey shiftKey | Boolean | KeyboardEventと同じ |
relatedTarget | Object |
For a mouseover event, the UI element the pointer is leaving, if any. For a mouseout event, the UI element the pointer is entering, if any. Otherwise undefined. |
根底 objectであるUIevent objectのプロパティも同時に使う事ができます。
イベントの流れ
AEスクリプトのイベントは発生したコントロールだけでなくその親コントロールにも連鎖的に発生していきます。例えばWindow上にパネルがありそのパネルにボタンがあった場合、まずボタンにイベントが発生し、パネル・ウィンドウと言った順にイベントが発生していきます。
キーボードイベントの場合、フォーカスの問題があるのでWindow objectでイベントを獲得するのが確実です。
発生したメッセージが、オリジナルのイベントかどうかは。UIEvent object(KeyboardEvent/MouseEventの根底object)のプロパティから識別できます。
targetプロパティでイベントが発生したコントロールを、currentTargetプロパティで現在のコントロールが獲得でき、それを比較することで識別できます。
イベントの流れを実感する為のスクリプトを作成してみました。
eventTest.zip
アーカイブの中には2つのスクリプト(debugConsole.jsx/eventTest.jsx)が入っています。
debugConsole.jsx
イベント処理関係では、alertダイアログを使うと無限ループでハマることが多いので作ったメッセージコンソール。
eventTest.jsx
addEventListener()を使った簡単なサンプル。
メインのコードは以下のとおり。
この2つのスクリプトを実行して色々キーを押したりマウスでクリックしてみてください。コンソールには新しいイベントが上に表示されるようになっています。
上の図では”btn1″ボタンを押した場合で、ボタンから発生したイベントが、パネル・ウィンドウと次々と発生して事がわかります。
なお、親コントロールにイベントメッセージを送りたくない場合は、UIEvent objectのstopPropagation()ファンクションで停止できます。
リマップ編集.jsxでの実装
以下のコードはリマップ編集.jsxでキーイベント処理を行なっているところです。単純にif文でkeyName毎に処理を振り分けています。簡単にショートカットの処理も行なっています。
Navパレットからのイベントも処理したかったので、引数を加えて工夫しています。Navパレットから呼び出す時は以下のラッパー関数をかませることで動作を切り分けています。
キーイベントのプログラムは、コントロールのアクティブ(フォーカス)状態の確認とその処理が必至です。リマップ編集.jsxではその処理を簡単にするためにキー入力の処理の最後にコントロールのフォーカスを制御しています。
メインのパレットから呼び出された場合は、リストボックスをアクティブにして、Navパレットからの時は、まずNavパレット自身をアクティブにした後、表示されない場所に設置してあるダミーのボタンをアクティブにしてあります。これはEntボタンにフォーカスがあった場合にEnterキーを押すとメッセージが二重に発生してしまうのをふせぐ為です。
Tip. リマップ時の空セルの処理
timeRemapでセルのコマ打ちを行う場合に問題になるのが、空セルの実装です。空セルとはAE的にいうと何も表示されるものがない状態にする事で、timeRemapの値の調整だけでは難しい実装になります。
よく使われる方法は
- 不透明度を同時に操作して空セル時には0%にする。
- ブラインドエフェクトで
- timeRemapの値を無理やり大きな数値にする(レイヤのsourceがcompitem時のみ有効)
- 読み込むソースにあらかじめ何もないフレームを用意しておく
リマップ編集.jsxでは、スライダ制御エフェクトを使った方法を採用してみました。
具体的には以下の通りです。
セル番号(スライダー制御)を元にタイプリマップと不透明度をエクスプレッションでリンクさせてあります。ポイントは、スライダ制御が無駄なメモリを使ってしまう事防ぐ為にenabledをfalseにしてる事です。
余談ですが、本来空セルとは何も描かれていないセルをおくという意味で、何もおかないって意味ではありませんです。フィルム時代ではシートに空セルを意味する×印があれば、ちゃんと空セルをおいて撮影してました。
Tip. panelのりサイズ処理
フローティングパレットの大きさは通常のダイアログと同様にboundsプロパティで獲得できます。ただ、onResizeイベントが発生しないようなので、addEventListener()でresizeイベントを追加します。
リマップ編集では以下のように実装しています。
Tip. jsonを使った設定の保存
入力した値を保存しておきたかったので、JSONを使って簡単に保存してあります。データの形成・復元が手間いらずです。以下は設定保存のコードです。
$オブジェクトから設定ファイルのファイルパスを作成し、toSource()で一発でデータ作成を行なっています。
Fileオブジェクトをopenした後、closeはtry finally文でcloseさせています。finallyを使えば確実に実行されるので便利です。
次に読み込み部分のコードは以下のとおりです。
読み込んだデータはeval()で一発で復元しています。
Tip. listboxの書き換え
listboxの表示の書き換えはかなり遅く普通にやっているとイラつくのでちょっと一工夫してあります。listboxを書き換える際にvisibleプロパティをfalseに設定し画面描画を停止させ、処理が終わった後にtrueにして有ります。ただそのままだと画面がちらついてしまうので、同じ大きさのダミーのlistboxを代わりに表示させチラツキを軽減させています。まぁ空のlistboxなので表示されている文字が多少ちらついてしまいますが、無いよりマシです。
After Effects CS3やMacの場合はlistboxの表示がかなり早いのでこんな事する必要が無いのですが、Windows版CS4はちょっと困りものです(CS5以降はどうなっているかは未確認)
終わりに
1行スクリプトのつもりが、JavaScript Tools Guideを読んでいてaddEventListener()を使ったスクリプトを検証してていきなりキーイベントが拾えて勢いで今回の投稿になりました。相変わらず無計画ですな^^;次回はちゃんと1行スクリプトをやるつもりです。一応50行分位溜まったら記事として投稿します。
その後はPythonをテーマになんか書こうと予定してます。
僕自身Pythonに興味はあるけど全然触ったことが無いので内容は未定です。
新着記事 : After Effectsユーザーのための、プログラミング入門 その9 リマップ編集スクリプト。AEスクリプトでのイベント処理 http://t.co/0ZZuW3Cz
iPhone4Sの発表聞きながら、AEP Projectに投稿しました。「リマップ編集スクリプト。AEスクリプトでのイベント処理」http://t.co/ZMUpLTCO
新着記事 : After Effectsユーザーのための、プログラミング入門 その9 リマップ編集スクリプト。AEスクリプトでのイベント処理 http://t.co/0ZZuW3Cz
After Effectsユーザーのための、プログラミング入門 その9 リマップ編集スクリプト。AEスクリプトでのイベント処理 | AEP Project http://t.co/5f75hrOB
新着記事 : After Effectsユーザーのための、プログラミング入門 その9 リマップ編集スクリプト。AEスクリプトでのイベント処理 http://t.co/0ZZuW3Cz
iPhone4Sの発表聞きながら、AEP Projectに投稿しました。「リマップ編集スクリプト。AEスクリプトでのイベント処理」http://t.co/ZMUpLTCO
リマップ編集スクリプト| AEP Project – http://t.co/3hsU7vJs りまぴんのコンポをこのスクリプトで編集できるようにコンバートします http://t.co/iryCWqus #remaping
After Effectsユーザーのための、プログラミング入門 その9 リマップ編集スクリプト。AEスクリプトでのイベント処理 | AEP Project: 今回はリマップ編集.jsxの紹介と解説です。 本当は1行スクリプト… http://t.co/Zb9f3B9i
こういう柔軟さもAfterEffectsの魅力!PhotoshopCSもスクリプト制御できるけど、そのメリットが最大限生かされるのは、やっぱ動画編集だと思う。色々とメンドイからねぇ(苦笑) http://t.co/q1t7DQvY
Macで動くタイムシート系リマップスクリプトこれくらいしかないかな?http://t.co/5jBS1Yo2
「After Effectsユーザーのための、プログラミング入門 その9 リマップ編集スクリプト。AEスクリプトでのイベント処理」AEP Project http://t.co/JTG0DWp6 #CS5_jp
「After Effectsユーザーのための、プログラミング入門 その9 リマップ編集スクリプト。AEスクリプトでのイベント処理」AEP Project http://t.co/JTG0DWp6 #CS5_jp
「After Effectsユーザーのための、プログラミング入門 その9 リマップ編集スクリプト。AEスクリプトでのイベント処理」AEP Project http://t.co/JTG0DWp6 #CS5_jp
スクリプトは経験があるけれどその他の言語はさわったことがないユーザーを対象に、C#/AEのJavaScriptをメインにプログラム全般を解説する連載の第9回です。今回はリマップ編集.jsxの紹介と解説です。http://t.co/JTG0DWp6
帰ったら1からやってみよう。 RT @AdobeCS_jp スクリプトは経験があるけれどその他の言語はさわったことがないユーザーを対象に、C#/AEのJavaScriptをメインにプログラム全般を解説する連載の第9回です。http://t.co/oVQ8DvO9
帰ったら1からやってみよう。 RT @AdobeCS_jp スクリプトは経験があるけれどその他の言語はさわったことがないユーザーを対象に、C#/AEのJavaScriptをメインにプログラム全般を解説する連載の第9回です。http://t.co/oVQ8DvO9