皆様こんにちは
AMDlabの秋山です。
前回に引き続きZeroTouch Nodeの第7弾です。
今回は、ZeroTouch Nodeを使用して、Dynamoノードにボタンをつけて、ユーザー操作をトリガーに動くカスタムノードを作成していきます。
今回は以下の機能を持ったノードを作ります:
・ノード上に「クリック」というボタンを配置
・ボタンを押すとメッセージが表示される。
・出力ポートから文字列(例:”ボタンをクリックしました!”)を返す
ポイントは「ModelとViewの役割を分離すること」です。この考え方はMVVMといいまして
Dynamoでは、内部ロジック(Model)とUI表示(View)を分けることが推奨されていて、分断することでメンテナンス性と拡張性が高くなります。
今回作成するC#ファイルは、2つあります。
1.ButtonNodeModel.cs
ノードのロジックや出力を定義するものです。
2.ButtonNodeView.cs
ノードの見た目やUI(ボタンなど)を定義するものです。
これに加えて、XMLファイル1つを用意します。
DynamoはZeroTouch Nodeやカスタムノードを読み込むとき、ノードのロジック部分(Model)と見た目(View)を別々に管理しているため、
「どのViewをどのModelに割り当てるか」を紐づけるファイルがXMLになります。
3.ViewExtension.xml
1.ButtonNodeModel.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
using Dynamo.Graph.Nodes; using ProtoCore.AST.AssociativeAST; using Newtonsoft.Json; using System.Collections.Generic; namespace MyLibrary.UI { [NodeName("Button Node")] [NodeDescription("ボタン付きのカスタムノード")] [IsDesignScriptCompatible] public class ButtonNodeModel : NodeModel { [JsonConstructor] public ButtonNodeModel() { } public void Trigger() { OnNodeModified(true); // ノード再評価を指示 } public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes) { var result = AstFactory.BuildStringNode("ボタンをクリックしました!"); return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), result) }; } } } |
上記のコードを簡単に解説していきます。
① クラスの宣言
1 2 3 4 |
[NodeName("Button Node")] [NodeDescription("ボタン付きのカスタムノード")] [IsDesignScriptCompatible] public class ButtonNodeModel : NodeModel |
NodeName: Dynamoのノード名
NodeDescription: ユーザーに表示される説明文
NodeModel: カスタムノードの基底クラス(ZeroTouchではなくUIカスタムノード用)
② コンストラクタ
1 2 3 4 5 6 7 |
[JsonConstructor] public ButtonNodeModel() { } public void Trigger() { OnNodeModified(true); } |
[JsonConstructor]: Dynamoがノードを再構築するときに使います
Trigger(): View側から呼び出されて再計算を促す関数(ボタンクリック時に呼びます)
③ BuildOutputAst メソッド
1 2 3 4 5 6 |
public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes) { var result = AstFactory.BuildStringNode("ボタンをクリックしました!"); var assign = AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), result); return new[] { assign }; } |
出力内容を文字列 “ボタンをクリックしました!” に固定しています。
ボタンを押すことで Trigger() → BuildOutputAst() が再実行され、この出力が更新されます。
2.ButtonNodeView.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
using System.Windows.Controls; using Dynamo.Controls; using Dynamo.Wpf; using Dynamo.ViewModels; namespace SampleButtonNode { public class ButtonNodeView : INodeViewCustomization<ButtonNodeModel> { public void CustomizeView(ButtonNodeModel model, NodeView nodeView) { var button = new Button { Content = "クリック", Margin = new System.Windows.Thickness(5) }; button.Click += (s, e) => { System.Windows.MessageBox.Show("ボタンがクリックされました!"); // model にアクションを呼び出したり、変数をセットしたりもできます }; // ノードのコントロールに追加 nodeView.inputGrid.Children.Add(button); } public void Dispose() { } } } |
① Viewクラス作成
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class ButtonNodeView : INodeViewCustomization<ButtonNodeModel> { public void CustomizeView(ButtonNodeModel model, NodeView nodeView) { var button = new Button { Content = "Click Me" }; button.Click += (s, e) => { MessageBox.Show("ボタンがクリックされました!"); model.Trigger(); }; nodeView.inputGrid.Children.Add(button); } } |
INodeViewCustomization<T> を使って、モデル(ButtonNodeModel)に対応するUIを定義します。
nodeView.inputGrid に Button を追加し、クリックイベントで model.Trigger() を実行します。
3.ViewExtension.xml
1 2 3 4 |
<Views> <ViewModelAssembly path="MyLibrary.dll" /> <ViewModel type="MyLibrary.UI.ButtonNodeModel" viewCustomizationType="MyLibrary.UI.ButtonNodeView" /> </Views> |
ViewModelAssembly: DLL名(WPF UIが含まれる)
ViewModel: ModelとViewの紐付け
このXMLファイルは extra/ フォルダに配置します。
コーディングが完了したら、Visual Studioでプロジェクトをビルドします。ビルドが成功すると、指定したプロジェクトフォルダ内の「bin\Debug」または「bin\Release」ディレクトリにDLLファイルが生成されます。今回は、「extra」フォルダを作成して、フォルダ内にXMLデータを格納します。
Dynamoを開き、[ファイル] タブから「ライブラリを読み込む」を選択し、生成したDLLファイルを選択してインポートします。
インポート後、新しいノード(カスタムノード)として「ButtonNode」が利用可能になりましたので、配置してみます。
ボタンが作成されました。
今回は、ZeroTouch Nodeを使用して、ボタン付きのノード作成を説明してきました。
この仕組みを応用することで、ファイル選択ボタンや、True or Falseのトグルボタンなど作成することができます。
次回は、第8弾で総集編ということで「スライダー付きノード」「トグルスイッチ」「複合UI」を作成するお話をしていきます。
AMDlabでは、開発に力を貸していただけるエンジニアさんを大募集しております。少しでもご興味をお持ちいただけましたら、カジュアルにお話するだけでも大丈夫ですのでお気軽にご連絡ください!
中途求人ページ: https://www.amd-lab.com/recruit-list/mid-career
カジュアル面談がエントリーフォームからできるようになりました。
採用種別を「カジュアル面談(オンライン)」にして必要事項を記載の上送信してください!
エントリーフォーム: https://www.amd-lab.com/entry
COMMENTS