1
Help us understand the problem. What are the problem?

posted at

updated at

AECC2020のスクリプトでapp.effectsを使用して取得したエフェクト名がマルチバイトだと文字化けするのを強引に直す

※この問題はバージョン18.0(AE2021)以降で修正されました。

var v = Number(app.version.match(/^\d+\.\d/));
if (17.0 <= v && v <= 17.99) {
    //2020用
} else {
   //その他バージョン用
}...

等のようにして、バージョンを判断して振り分ける必要があります。

AECC2020でレイヤーに適用されたエフェクトの名前を取得するのは問題ないのですが、

show_effect_name.jsx
(function(){
    $.writeln(app.project.item(1).layer(1).effect(1).matchName)
    $.writeln(app.project.item(1).layer(1).effect(1).name)
})()

実行結果

ADBE Fractal Noise
フラクタルノイズ

app.effectsでエフェクト情報を取得すると問題が。

app.effects配列1にはインストールされているエフェクト情報2のオブジェクトが入っているのですが
AECC2020では、このオブジェクトの値にマルチバイト文字があると文字化けしてしまいます。

get_effect.jsx
(function() {
    var effects = app.effects; // app.effectsは毎時実行せずに一旦変数に代入すると速い
    var count = effects.length;
    for (var i = 0; i < count; i++) {
        var effect = effects[i];
        if (effect.matchName === 'ADBE Fractal Noise') {
            $.writeln(effect.toSource());
            break;
        }
    }
})()

CC2020の結果

({displayName:"テtテノテNテ^テヒテmテCテY", matchName:"ADBE Fractal Noise", category:"テmテCテYチユテOテフテCテモ", version:"17.1"})

CC2019の結果

({displayName:"フラクタルノイズ", matchName:"ADBE Fractal Noise", category:"ノイズ&グレイン", version:"16.1.3"})
キー 説明
displayName メニューにも表示される、エフェクトのデフォルト名
matchName エフェクトのユニークな名前 (ASCII文字)
category メニューのグループ名
version エフェクト作成者が付けた任意の値

これが地味に不便で、例えばプロジェクトファイル上で使用されているエフェクト一覧を表示するスクリプトを作成しようとすると、文字化けした一覧を表示してしまいます。

レイヤーのエフェクト名は文字化けしないのだから問題ないのではと思われますが、適用されたエフェクトの名前はユーザーが任意に変更できるので、エフェクトのデフォルト名は、適用されたエフェクトのmatchNameを利用して、app.effects配列のオブジェクトからdisplayNameを取得しなくてはなりません。

そもそもapp.effectsという配列自体が使いにくいので、通常そのようなスクリプトを作成するにあたっては、ユニークな値であるmatchNameをキーとした辞書をあらかじめ作成するのがよいと思います。

make_dict.jsx
(function() {
    var effects = app.effects;
    var count = effects.length;
    var effect_dict = {};
    for (var i = 0; i < count; i++) {
        var effect = effects[i];
        effect_dict[effect.matchName] = effect;
    };

    //matchNameのキーでアクセス出来る辞書を作ると便利
    $.writeln(effect_dict['ADBE Fractal Noise'].toSource());
})()

さて文字化けについてですが、どうもエンコードがおかしいみたいなので修正すればよさそうなのですが、ここはいまだES3規格のExtendScript。文字コードライブラリを使うのも書くのめんどいと思ったところ、なんとこの文字化けした文字列、バイナリで保存してsjisで読み込むと復元できるではありませんか。

どうせ辞書を作るのなら、バイナリで保存して復元して辞書を作るのも手間なので、バイナリとしてjsonを書き出してからJSON.parseすれば簡単なのでは!

ところでJSONのライブラリはどうするのかと思われますが、実はAECC2015から、AEのインストールフォルダに予め用意されているので今回はこれを利用しようと思います。

make_json.jsx
(function() {
    // AEのインストールフォルダにあるjson2.jsxを利用する
    var lib = Folder.appPackage.fsName + '/Libraries/jsx/'
    $.evalFile(new File(lib + 'json2.jsx'));

    var effects = app.effects;
    var count = effects.length;
    var effect_dict = {};

    var tmp = new File(Folder.temp.fsName + '/__effects_dict__.txt');
    tmp.encoding = 'BINARY';
    tmp.open('w');

    // jsonを作る。JSON.stringifyはstringになってしまうので使用できない
    tmp.writeln('{');
    for (var i = 0; i < count; i++) {
        var effect = effects[i];
        var key = effect.matchName;
        var data = '"' + key + '": {'
        data += '"displayName": "' + effect.displayName + '",';
        data += '"matchName": "' + effect.matchName + '",';
        data += '"category": "' + effect.category + '",';
        data += '"version": "' + effect.version + '"},';
        tmp.writeln(data);
    }
    tmp.writeln('}');

    tmp.close();
    tmp.encoding = 'sjis';
    tmp.open('r');
    var decoded_data = tmp.read();
    tmp.close();
    tmp.remove();
    effect_dict = JSON.parse(decoded_data);

    $.writeln(effect_dict['ADBE Fractal Noise'].toSource());
})()

CC2020での実行結果

({displayName:"フラクタルノイズ", matchName:"ADBE Fractal Noise", category:"ノイズ&グレイン", version:"17.1"})

辞書のキーに空白などが含まれるのですが、とりあえずは問題なく動作しているのでこれでいいかなと。心配ならFolder.encode等を使用するといいかもしれません。
あとはバージョンによって2つのコードを使い分けるようにすればいいでしょう。

現状結構速度もそこそこ速く簡単なので、これでいいかなといった感じです。もっと良い方法がある、このライブラリ使えるかも等ありましたら教えて頂けたらと思います。

ちなみにこのバグ?全然修正されないんですよね......


  1. 多分配列のように動作する関数?AEのスクリプトにあるitemメソッドがitem(n)でもitem[n]でも動作するのと似てるかも 

  2. 厳密にはインストールされているエフェクトではなく、インスタンス化する情報のよう。インストールされていないプラグインを使用したaepを読み込むと、そのエフェクトのmatchNameなどがapp.effectsに追加される 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
1
Help us understand the problem. What are the problem?