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

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

```jsx
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に追加される