Bakulog

獏の夢日記的な何か。

MikuMikuMovingプラグインでC#スクリプトを走らせる

MMM弄ってた中での副産物的なネタです。

 

はじめに

MikuMikuMoving(MMM)というのはMikuMikuDanceの互換ソフトで、開発者から見た印象としては「プラグインを簡単に作れて良いソフト」です。んで、プラグインの作り方は基本的に公式wikiに載っているのですが、ここでは特に「コマンドプラグインC#スクリプトが実行できるようにする」という事をやってみます。記事中ではコマンドプラグインを作りますが、常駐プラグインへの応用も難しくないと思います。

 

 

C#スクリプト使えると何が嬉しいの?

C#スクリプト自体についてはkekyoさんの「Roslyn for Scriptingで、あなたのアプリケーションにもC#スクリプトを!」とかが大変参考になるので詳しくない場合はご覧ください。本記事ではC#スクリプトの使い方自体はスキップし、MMM上でスクリプトを使うことに注目して話を進めます。

 

MMMでスクリプトを実行したくなるケースですが、私は「ちょっとしたインターフェースのチェック」とか「デバッグの簡易化」とか、あるいは「コマンド/常駐プラグインの動作の一部だけを後から変更したい」といった場面を想定しています。たとえば標準的なコマンドプラグインを作る場合、次のような流れが基本になるかと思います。

 

  1. プラグインのDLLを作る
  2. MMMを起動
  3. プラグイン動かす
  4. 不具合ある
  5. MMMを終了
  6. DLLのソースを書き直す
  7. ビルド
  8. DLLを配置
  9. MMMを起動(=2に戻る)

 

いっぽう、もしDLLのプラグインが「スクリプトを読んで実行する」ものである場合、次のような流れでコードが書けます。

 

  1. DLLを作って配置(※「スクリプトを動かす」という汎用的なのを1回だけ用意)
  2. MMMを起動
  3. プラグイン動かす( = スクリプト実行)
  4. 不具合ある
  5. スクリプトを書き直す
  6. プラグイン動かす(=3に戻る)

 

最初の2ステップはほぼあって無いようなモンなので「書いて実行する」という非常にシンプルな手順になります。

スクリプトの規模によりますが、機能チェックで短いC#コードを動かしたい場合とか、シーンデータの一部をファイルに保存したい場合、あるいはデータを一部拾ってUDP通信などでネット越しに投げたいといったピンポイントな用途に対しては、いちいちDLLをビルドするよりもスクリプトで済ませる方がラクちんです。

 

 

スクリプトを動かすサンプルプラグインのビルドと配置

ソースはGithubに上げています。開発はVisual Studio 2015 Update 1で行っており、現時点ではMMM v1.2.7.2 x64版でのみ動作確認しています。再利用制限は特にありませんが利用は自己責任でお願いします。

 

で。このソースは(ソースを拾ってきた後でローカルPC内のDxMath.dllとMikuMikuPlugin.dllへの参照追加を行えば)そのままクラスライブラリとしてビルドできるのですが、MMMへの配置にあたってはいくつか手順を踏む必要があります。

 

まずC#スクリプトを動かすためのライブラリとしてプラグイン以外のDLLが色々必要になります。具体的にはDLLの出力ライブラリ(x64/Debug)内に吐かれるdllのうち下記「以外」のDLLを依存ライブラリとして配置しなければなりません。

  • DxMath.dll
  • MikuMikuPlugin.dll
  • プラグイン本体(RoslynScriptForMMM.dll)

コピーすべきライブラリは合計で10個くらいあるので、これを適当なフォルダ(例えば"RoslynDLLs")を作った中にコピーします。そしてライブラリの入ったフォルダを丸ごとMikuMikuMoving.exeのあるフォルダに移動します。

 

フォルダ中のDLLはそのままだとMikuMikuMoving.exeから参照できないので実行設定ファイル"MikuMikuMoving64.exe.config"を書き換えます。

<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
  
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <!-- 下の"RoslynDLLs"の所が追加部分 -->
      <probing privatePath="System\x64;RoslynDLLs;"/>
    </assemblyBinding>
  </runtime>

</configuration>

これでフォルダ内のDLLが参照できるようになります。あとはプラグイン本体(RoslynScriptForMMM.dll)をPluginsフォルダに配置したらライブラリの準備はおしまいです。

 

次にC#スクリプトを用意します。今回はシンプルな例として「メッセージボックスを表示し、シーン中のモデルがいくつあるかを表示する」という処理を行ってみます。以下がコードです。

#r "PresentationFramework"

using System.Windows;

int c = MMM.Scene.Models.Count;
MessageBox.Show($"Current Model Count is {c}");

これを"MMMPlugin.csx"という名前で保存し、MMMの実行フォルダに"Script"フォルダを用意した直下に配置します。以上で準備によって、実行フォルダからみたファイル配置はこんな感じになります。

MikuMikuMoving64.exe
MikuMikuMoving64.exe.config #書き換え
...
Plugins/
  RoslynScriptForMMM.dll #配置
  ...

RoslynDLL/ #フォルダを持ってくる
  Microsoft.(...).dll
  System.(...).dll

Script/ #フォルダを作って中にスクリプトを入れる
  MMMPlugin.csx

この状態でMMMを起動し、コマンドプラグインから"C# Script"を選んでメッセージボックスが出れば成功です。

 

 

サンプルプラグインでもうちょっと遊ぶ場合

サンプルプラグインではDLLがMMM本体からインターフェース越しに受け取るウィンドウ変数とシーン変数をスクリプトに渡すようにしています。これらの変数はそれぞれMMM.ApplicationFormMMM.Sceneという変数からアクセスできるようになっているので、基本的にコマンドプラグインで可能な事はスクリプトでもやれるハズです。

 

 

スクリプトを走らせる常駐プラグインを作る場合

プラグインの作り方に常駐プラグインのインターフェース仕様が書かれていますが、この中でも特にUpdate関数中でスクリプトを実行するようにすればOKです。

ここで注意ですが、C#スクリプトはあくまで「ビルドして」「走らせる」の2段階で構成されているので、サンプルプラグインのような「毎回スクリプトを拾ってきてビルド処理を行う」という書き方はオススメできません(サンプルプラグインではココらへんスクリプトを毎回読み込んでコンパイルしています)。常駐プラグインの場合は例えば次のような手順がオススメです。

 

 

まとめ

C#スクリプトを呼び出すMMMプラグインが作れる事を紹介しました。再ビルド不要であるというのは案外嬉しいものなので、状況に応じてうまく活用してもらえればと思います。