Rhinoceros5 プラグイン開発 VisualStudio 2015/RhinoCommon /Python 導入&相互運用 2016.1.12 (有)咲和惟 三枝克之 今回は、Rhinoceros のプラグインを開発するために必要な SDK と、ザクザク開発がで きる Rhinoceros Python スクリプトを導入し、お互いが相互運用できるための部分を解 説します。 おそらく、Python スクリプトを利用したほうが、 プラグイン SDK のコードよりも、1/3 くら いのコーディング量で済みます。 プラグイン SDK は、GUI なども含めてより広く粒が細かいことができるものです。一方 で、Python スクリプトのほうは、より覚えることが少なく、粒が大きくオートマチックなも の、になっています。 GUI 関連は SDK を使い、後の処理は Python を使う、といったことだと、開発が効率的 に速くおこなえます。今回はその両方の部分を紹介し、各自が判断して、いいとこどり ができるような内容としています。 1 プラグイン開発の SDK 1.1 SDK の種類 Rhino5 では、3種類の SDK があります。 • 1)C++の SDK • 2)Rhino.NET plugin SDK • 3)RhinoCommon(新しい形式) (Rhino3 以前は C++SDK のみ) 現時点の Windows 版の Rhinoceros5 では、どれでもプラグイン開発に利用 できます。 1.2 Rhino.NET Plugin SDK (DotNet PluginSDK) Rhino.NET plugin SDK では、Windows のヘッダなどを利用して、型などが定 義されていたため、Windows 的な開発スタイルでした。 MAC 版では動作しません。Rhino 4/ 5 で利用ができます。残念ながら、6 以 降は利用できないかもしれない、という情報もあります。 http://wiki.mcneel.com/developer/dotnetplugins (a) 1/23 1.3 RhinoCommon RhinoCommon は、Rhino.NET PluginSDK から派生したもの。 RhinoCommon も、.NET で動くため、Rhino.NET Plugin(version 2)という記述 も以前は見られました。 http://wiki.mcneel.com/developer/rhinocommon (b) RhinoCommon では、Windows に極力依存しないようになり、Mac でも動作 するようになりましたが、一部に RhinoWindow:IWin32Window な ど、Windows 特有の型をもつメンバなどを利用するものもあります。 オンライン・ドキュメント http://4.rhino3d.com/5/rhinocommon/ 書き方や関数名、定数なども .NET SDK とは違います スクリプトエンジンの実装も Rhinoceros5 で RhinoCommon に切り替わり、 Python のスクリプトでは、「スクリプト」と「SDK」の両方を書くことも可能にな りました。 1.4 RhinoCommon を選択しよう 次期の Rhinoceros6 からは、RhinoCommon という SDK のみになる、という 情報があります。 2)で書かれたプラグインは3)の RhinoCommon の書式や API に修正する。 (a), (b)を比較すると分かりやすい) 以上から、Rhino のプラグイン開発の講習では、3)RhinoCommon を使って 学習をします。 1.5 RhinoCommon の実装 ライノセラスの System フォルダの中に RhinoCommon.dll があります。 若干の機能の修正などがはいると、バージョンが変更になります。 現時点(2016/2/1)では、 場所:C:\Program Files\Rhinoceros 5.0(64-bit)\System 更新日時 2015/8/10 ファイルバージョン 5.12.50810.13095 .NET Framework 4.0 を利用して製作されています。 Visual Studio Community Edition、PTVS のインストール (別紙 Rhinoceros 5 + VisualStudio 2015 の開発環境の構築 を 参照下 さい) 2/23 2 RhinoCommon プラグイン・プロジェクトの作成実習 2.1 テンプレートで空のプロジェクトを作成 スタートページから、新しいプロジェクトをクリック テンプレート > VisualC# > Rhinoceros >RhinoCommon Plug-In を選択 名前:RhinoTestPlugin 場所:c:\users\(ユーザー名)\documents\visual studio 2015\Projects [ ]ソリューションのディレクトリを作成 にチェックを入れる (ソリューションも名前と同じになっているはず) Ok を押す Comman class name に"TestCommand"と入力 (このコマンドをプラグインで作成する) ShowMoreTypes ボタンを押すと、他の種類のテンプレートが表示される。 General utility PlugIn で良い あとは、デフォルトのままで[Finish]ボタンを押す。 このままでも実行できるサンプルのプロジェクトが作成される。 プロジェクト内のファイルは、ソリューションエクスプローラで確認ができる。 3/23 2.2 入力した名前と、生成するファイル名 ・プロジェクトの作成で入力したプラグインの名称 =RhinoTestPlugin コマンドの名称 =TestCommand がファイルの中で利用されています。 (プロジェクト名:RhinoTestPlugin) は、そのままソリューション名に。 (プロジェクト名)+PlugIn が、プロジェクト全体のクラス プロジェクト全体のクラスでは、主にロードしたときの初期化コード コマン ド間で共通に利用する変数や定数などを記述します。 (コマンド名:TestCommand) は、そのコマンドを Rhinoceros で起動したと きの処理をするクラスの名前になります。 4/23 2.3 ソースコードの観察 public class TestCommand : Command すでにプラグインのコマンドとなるサンプルの実装があります。 Command クラスから派生した、TestCommand クラスでは、 実装するメンバ関数は1つだけ ・RunCommand( ) コマンドが発行されたときの処理を記述します。 サンプルでは、ポイントを2つ指定をして、線を引く処理をしています。 (中身については後日) そのほかの関数はそのままにしておけばよいが、リファクターでコマンドの クラス名を変えるときは、EnglishName も一緒に変更をします。 EnglishName( ) ここには Rhino のコマンドラインでのコマンド名を返します。 (クラス名と同じものがデフォルトではいっています) 5/23 2.4 コマンドを追加する さて、1つのプラグインには、複数のコマンドを実装することができます。 プラグインにコマンドを増やしてみましょう。 メニューから、プロジェクト>新しい項目の追加 EmptyRhinoCommon Command をクリックし、追加ボタンを押す。 MyCommand1.cs というファイルが作成されて、プロジェクトに追加されまし た。 MyCommand1 を HelloRhino に変更してみます。 MyCommand1 を右クリック 名前の変更 を選択 HelloRhino に変更 コメントを含める をチェック 文字列を含める をチェック (EnglishName の中身も変更される) 適用ボタンを押す 6/23 クラス名が HelloRhino に変更されました。しかし、ファイル名が MyCommand1.cs のままなので、HelloRhino.cs に変更します。 メニューから、 ファイル>名前をつけて MyCommand1.cs を保存 HelloRhino.cs を指定 プロジェクトエクスプローラのファイル名も変更になっている点に注意。 HelloRhino. RunCommand の実装 RhinoApp.WriteLine("表示したい文字列”)で、 コマンドラインに文字を表示できます。 今回は Hello.と表示して終了するコマンドにしてみます。 protected override Result RunCommand(RhinoDoc doc, RunMode mode) { // TODO: complete command. RhinoApp.WriteLine("Hello."); return Result.Success; } これで HelloRhino コマンドが完成しました。 この状態で、プラグインと、このコマンドは実行ができますので、実行をして みましょう。 7/23 2.5 実行とデバッグの方法 ソースファイルは前のものでよいのですが、デバッグのために、いくつか準 備をする項目があるので、設定をしていきます。 2.5.1 ビルドとデバッグの「構成」 64bit 版でライノを実行してデバッグをする場合、 ビルド>構成マネージャ で、アクティブソリューション構成を Debug64 にします。 初期状態ではアクティブソリューション構成が(多分)32bit 版になっている 2.5.2 プロジェクトのプロパティの設定 ビルドしたときに、64bit と 32bit の ファイルを別のフォルダに分けて作 るようにします。 ソリューションエクスプロラーの Properties をダブルクリックする 8/23 左側からビルドを選択し、構成で Debug64 を選択 出力パスの部分が bin となっているので、bin\64bit\とします (下記) 同様に、構成で Debug32 を選び 出力パスの部分に、 bin\32bit\ と入力。 これで、64bit と 32bit のプラグインファイルが別々のフォルダに出力される ようになりました。 Properties も上書き保存をします。 Properties を選んで、 ファイル>選択したファイルを上書き保存 9/23 2.5.3 ブレークポイントの設定 (F9) Visual Studio では、ソースファイルにフォーカスがあるときに F9 キーを押す と、カーソル行にブレークポイントが設定(または解除)されます。 ライノでのプラグイン開発において、Visual Studio+C#の効率がいい点は、 ブレークをかけて、ウオッチやステップ実行などをして、その場で簡単なエ ラーに気がついたら、修正して、続行して実行が可能なところです。 あらかじめ、デバッグしたい場所にブレークをかけてみます。 今回は HelloRhino の中の、 RunCommand に書いたコンソール出力にブ レークポイントを置いてみます。(上記) 後の実行時にここで止まります。 10/23 2.5.4 Rhinoceros にプラグインを登録する 最初の1回のみ、ビルドして出力される rhp ファイル(実際は DLL)を、ライノ セラスにプラグインとして登録することで、ライノセラスが起動の度に、自動 でプラグインをロードするようになります。 ライノセラス(デバッガから見ると DLL のホストアプリケーション)がプラグイ ンを認識するまで、設定したブレークポイントなども有効になっていないと思 いますが、これは後で有効になります。 Debug64 でビルドしてデバッグすると、Rhinoceros5 64bit 版が起動します。 メニューから、 ツール>オプション で、左側でプラグイン を指定する。 インストール ボタンを押す。 C:\Users\(ユーザー名)\Documents\Visual Studio 2015\Projects\(プラグ イン名)\(プラグイン名)\bin\64bit の中の、(プラグイン名).rhp ファイルを指定する。 この段階で、rhp ファイルに埋め込まれたデバッグ情報、シンボルがホストプ ロセスに結合されて、ブレークポイントが有効になります。 11/23 2.5.5 ブレークポイントで停止を確認する ライノセラスのコマンドラインで、RhinoHello と入力する。 VisualStudio が先ほど設定したブレークポイントで、ホストプロセス(ここでは Rhinoceros)の実行を一時中断して停止します。 続行 さて、このまま続行すると、Hello と表示されるはずです。 12/23 2.5.6 ブレーク停止時に、プログラムを変更する 再度 RhinoHello と入力して停止させ、その状態で、 Hello を Hello TARO. などに変更して、そのまま プログラムを続行させてみましょう。 Hello TARO と表示されます。 Visual Studio では、「単純な修正」は、プログラムを停止した状態で、修正を おこない、途中の状態から、そのまま続行することができます。 注意点: ・プログラムの変更はプログラムがブレークなどで停止しているときにしか 出来ません。 ・変更したプログラムは、続行時には保存されないので、明示的に「保存」を する必要があります。(参考 プログラムを実行時には、編集中のファイルは 全て保存されます) 変更が大きいとき、プログラムの構造を変えてしまうときなどは、続行が出 来ません。 そのときには、下記のメッセージが表示されます。 「編集」は、編集そのものをやりなおします。大幅な編集時は編集をやりな おしたくない場合が多いかもしれません。 「停止」は、プログラムを停止(途中終了)させて、最初からコンパイルする 場合に使います。 13/23 2.5.7 変数の中身を確認する HelloRhino.cs を、下記のようにプログラムを改造してみましよう。 public class RhinoHello : Command { int a = 0; static RhinoHello _instance; public RhinoHello() { _instance = this; } ///<summary>The only instance of the RhinoHello command.</summary> public static RhinoHello Instance { get { return _instance; } } public override string EnglishName { get { return "RhinoHello"; } } protected override Result RunCommand(RhinoDoc doc, RunMode mode) { // TODO: complete command. a++; //<< -------------------------------place break point here RhinoApp.WriteLine("Hello TARO. {0} times",a); return Result.Success; } } 上記の RunCommand 内の a++ のところで、ブレークポイントを置きます。 プログラムを実行してライノセラスを起動します。 ライノセラスのコマンドプロンプトで、 RhinoHello と入力します。 14/23 下のほうに、「自動変数」の部分があります。ブレークした場所(スコープ)か ら見える変数とその値が自動的に表示されます。 変数がクラスや、構造体になっている場合は、名前の部分をダブルクリック すると展開されていきます。 値は、値の部分をダブルクリックすることで、実行中でも変更をすることが可 能です。 その他の方法 クイックウオッチ メニューから デバッグ>クイックウオッチ 指定した変数を見ることができるウインドウが表示されます。自動変数が非 常に多く目的のものが探しにくい場合など。 15/23 2.5.8 ブレークの条件を設定する ブレークポイントを右クリックして、「条件」を選択することで、ブ レークポイントの場所で条件を評価して、必要なときだけ VisualStudio がブレークをかける機能があります。 例えば、変数がある数になってから、ブレークしたい、という場合 などに使えます。 (条件式は、true の場合+C#のブール演算子を使うと分かりや すい。) 2.5.9 ステップ実行 ブレークの後は、実行のほかに、1行のみ実行する「ステップ実行」が可能 です。呼び出し関数などの場所によって、次の3種類があります。 F10 ステップ・オーバー 呼び出し関数は1行として実行 F11 ステップ・イン 呼び出し関数の中まで入ってステップ実行 Shift+F11 ステップ・アウト 現在の関数を終了するまで実行 16/23 3 Python スクリプト実行 3.1 手順 外部の Python のファイルを実行するには? コマンドでは”RunPythonScript “+( ファイル名 )で可能でした。 SDK から、コマンドラインの文字列を実行可能になれば、Python のファイル も同様な方法で、実行が可能になります。 下記の3つの手順を踏まえてみましょう。 3.1.1 コマンドライン実行のためのアトリビュート RhinoCommon では、クラスにアトリビュート(属性)を付加することで、コマン ドに対して、コマンドの実行を可能にしてくれます。 逆に、アトリビュートのないクラスでは、コマンドが実行できません。 アトリビュートは、クラス定義の前に、[ ] で書くことになっています。GUID が すでに定義されているので、カンマで続けて、次の項目を付加します。 Rhino.Commands.CommandStyle(Rhino.Commands.Style.ScriptRunner 3.1.2 Python スクリプトの実行 コマンドを実行するのは、 Rhino.RhinoApp.RunScript( コマンド文字列 , エコーの有無) です。 コマンド文字列には ”RunPythonScript “+( 実行したい Python ファイル名 ) を入れます。 プラグインやライノセラスが何処に配置されてもよいように、ファイル名はフ ルパスで指定しましょう。 3.1.3 Python の実行ファイルも VisualStudio のプロジェクトに Python の実行ファイルも VisualStudio のプロジェクトに入れておけば、どこ に置いたか探さずにすみます。Python のファイルを作ったら、 Visual Studio のメニューから プロジェクト>既存の項目を追加 を選択し、ファイルの種類で *.* を選んで、Python ファイル(.py)などを指定 することができます。 17/23 3.2 Python ファイルを実行するためのサンプル 3.1 の手順の全てをふまえて、RhinoHello クラスで、Python のファイルを実 行するように、コマンドに改造してみましょう。 例) スクリプトを実行している Python モジュールのバージョンを表示。 3.2.1 Python のファイル RhinoHello.py # -*- coding: utf-8 -*import sys print "RhinoHello.py Running on " +sys.version これをドキュメント(マイドキュメント)に置きます。 Visual Studio 側のプロジェクトに、項目の追加で指定をして、プロジェクトに 追加します。 18/23 3.2.2 C#のファイル RhinoHello.cs 下線部が3.1で説明をした追加の箇所です。 using System; using Rhino; using Rhino.Commands; namespace RhinoTestPlugin { [System.Runtime.InteropServices.Guid("9f7619ab-b273-43a4-9c594df35275e690"), Rhino.Commands.CommandStyle(Rhino.Commands.Style.ScriptRunner)] public class RhinoHello : Command { int a = 0; static RhinoHello _instance; public RhinoHello() { _instance = this; } ///<summary>The only instance of the RhinoHello command.</summary> public static RhinoHello Instance { get { return _instance; } } public override string EnglishName { get { return "RhinoHello"; } } protected override Result RunCommand(RhinoDoc doc, RunMode mode) { // TODO: complete command. a++; RhinoApp.WriteLine("Hello TARO. {0} times",a); //Python Script の起動 //Folder MyDocument string ScriptFolder = System.Environment.GetFolderPath(Environment.SpecialFolder.Personal); string ScriptFilename = @"RhinoHello.py"; string ScriptFull = ScriptFolder + "\\" + ScriptFilename; string cmd = @"-RunPythonScript """ + ScriptFull + @""""; Rhino.RhinoApp.RunScript(cmd,false); return Result.Success; } 19/23 } } 上記で、実行をすると、 コマンド: RhinoHello Hello TARO. 1 times RhinoHello.py Running on 2.7.4 (IronPython 2.7.4 (2.7.0.40) on .NET 4.0.30319.42000 (64-bi t)) と表示されます。 IronPython 2.7.4 / .NET4.0 64bit で動作しています。 付加したアトリビュートは、本当に必要だったのだろうか? アトリビュート部を一度元に戻して実行してみよう。 20/23 4 C#から Rhino の PythonScript を経由せず、ドットネットでダイレクトに Python プログラムを直接実行する 通常の IronPython として、PTVS でモジュールを作って、C#のプロジェクトに 追加したい場合は、ライノを経由しない方法があります。 ソリューションエクスプローラの参照に、下記の DLL を追加してください。 (IronPython の DLL) 64bit の場合、C:\Program Files (x86)\IronPython 2.7 32bit の場合、C:\Program Files\IronPython 2.7 にある、 ・IronPython.dll ・Microsoft.Dynamic.dll ・Microsoft.Scripting.dll 64bit の場合、IronPython の DLL は x86 にあるが、64bit の C#アセンブリか ら実行可能。 下記のコードを DirectHello.py としてマイドキュメントに保存 def DirectHello(your_name): return "Direct Hello! " + your_name HelloRhino.cs の import 部に下記を追加 using IronPython.Hosting; using IronPython.Runtime; using Microsoft.Scripting.Hosting; 21/23 HelloRhino.cs のライノセラスのスクリプトを実行する部分のあとに、ダイレク ト起動の部分を追加します。 protected override Result RunCommand(RhinoDoc doc, RunMode mode) { a++; RhinoApp.WriteLine("Hello TARO. {0} times",a); //Python Script の起動 //Folder MyDocument string ScriptFolder = System.Environment.GetFolderPath(Environment.SpecialFolder.Personal); string ScriptFilename = @"RhinoHello.py"; string ScriptFull = ScriptFolder + "\\" + ScriptFilename; string cmd = @"-RunPythonScript """ + ScriptFull + @""""; Rhino.RhinoApp.RunScript(cmd,false); //ダイレクト起動 ScriptFilename = @"DirectHello.py"; ScriptFull = ScriptFolder + "\\" + ScriptFilename; ScriptRuntime py_run = Python.CreateRuntime(); dynamic myScript = py_run.UseFile(ScriptFull); dynamic ret = myScript.DirectHello("Taro"); //ダイレクト起動で実行した結果を表示 RhinoApp.WriteLine( ret ); return Result.Success; } 実行結果:(ライノセラスのウインドウ)は下記 コマンド: RhinoHello Hello TARO. 1 times Direct Hello! Taro 22/23 5 補足 5.1.1 プラグイン用のカスタム・メニューの作成 ライノセラスのメニューに追加する機能については、Rhino.net Plugin SDK では、API があったが、RhinoCommon からは削除されました。 Rhinoceros 5では、ワークスペース・エディタで、メニュー、メニューのアイテ ムが大幅にカスタマイズできるようになっているからだと思います。 カスタムメニューについては、コーディングをするのではなく、ツールバーと 同じ rui ファイルに入れておきます。 そうすることで、メニューも、ツールバーと同時にカスタマイズと配布がおこ なえるようになりました。 方法:ツール>ツールバーレイアウト (ここからは、その画面の中のメニューを使います。) ファイル>新規作成 で新しい rui ファイルを作成 下のツールバーのウインドウで、ツールバーを作成 ツール>ワークスペースエディタで追加メニューを製作可能 6 まとめ ・Visual Studio の使い方 ・Rhinoceros を拡張するプラグイン作成の手順 ・プラグインでコマンドを実装すること ・Python のファイルを実行させること(ライノセラスの Script 経由) 以上でこれらのことが出来るようになりました 後は、C#と Python の、それぞれ良いところ、ライブラリなどを学習し、 Rhinoceros を自分の「手続き的なプログラミング手法」で拡張をしていきま しょう。 おおまかには、インタラクティブな GUI は、C#が適していて、Python では、 与えられたパラメータを使って結果を導くような部分に適していると思います。 23/23
© Copyright 2024 Paperzz