Inputを動的に追加・削除する

UnsplashのMaksim Chernishevが撮影した写真

Grasshopperのカスタムコンポーネントで、条件によってInputの数を変えたいケースってない?

IGH_VariableParameterComponent

IGH_VariableParameterComponentインターフェースを実装してごにょごにょするとできる。

   public class DynamicInputComponent : GH_Component, IGH_VariableParameterComponent
   {
       // オプションの表示フラグ
       private bool optionEnabled = false;
       private int nBaseInputs = 3;
       private int nOptions = 2;
       private int nMaxInputs =0;


       /// <summary>
       /// Initializes a new instance of the HideInputParamterComponent class.
       /// </summary>
       public DynamicInputComponent()
         : base("Dynamic Input", "DInp",
             "Description",
              "MyGHA", "Primitive")
       {
           nMaxInputs = nBaseInputs+nOptions; // Input総数

       }

       /// <summary>
       /// Registers all the input parameters for this component.
       /// </summary>
       protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
       {
           pManager.AddNumberParameter("A", "A", "A", GH_ParamAccess.item);
           pManager.AddNumberParameter("B", "B", "B", GH_ParamAccess.item);
           pManager.AddBooleanParameter("Option", "Option", "Option Status", GH_ParamAccess.item, false);
           pManager[0].Optional = true;
           pManager[1].Optional = true;
       }

       /// <summary>
       /// Registers all the output parameters for this component.
       /// </summary>
       protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
       {
         
           pManager.AddTextParameter("text","txt", "取得した値", GH_ParamAccess.item);
       }

       /// <summary>
       /// This is the method that actually does the work.
       /// </summary>
       /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
       protected override void SolveInstance(IGH_DataAccess DA)
       { 
           // 出力用
           string str = null;
           
           // Optionの取得
           DA.GetData(2, ref optionEnabled);
           str += $"option : {optionEnabled.ToString()}\n";
           DA.SetData(0, str); // Optionのステータスを出力

           // a, bを取得
           double a=0;
           if(!DA.GetData(0, ref a)) return;
           double b=0;
           if(!DA.GetData(1, ref b)) return;
           str += $"a : {a}, b : {b}\n"; // a, bの値を出力

           if(optionEnabled && Params.Input.Count == nMaxInputs)
           {
               double d1 = 0;
               if (!DA.GetData(3, ref d1) || d1 < 0)
               {
                   // エラー処理
                   AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "d1 must be bigger than or equal to 0");
                   return;
               }
               double d2 = 0;
               if(!DA.GetData(4, ref d2) || d2 < 0)
               {
                   // エラー処理
                   AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "d2 must be bigger than or equal to 0");
                   return;
               }

               str += $"D1 : {d1}, D2 : {d2}\n";
               Debug.WriteLine(str);
           }

           DA.SetData(0, str); // 出力
       }
       /// <summary>
       /// SolveInstance()の後に呼び出される処理
       /// </summary>
       protected override void AfterSolveInstance()
       {
           VariableParameterMaintenance();
           Params.OnParametersChanged();
       }
       public bool CanInsertParameter(GH_ParameterSide side, int index) { return false; }
       public bool CanRemoveParameter(GH_ParameterSide side, int index) { return false; }
       public IGH_Param CreateParameter(GH_ParameterSide side, int index)
       {
           // IGH_VariableParameterComponent の実装に関連したコード
           // 使用していない

           return new Param_Number
           {
               Name = "Dummy",
               NickName = "C",
               Description = "C",
               Access = GH_ParamAccess.item,
               Optional = true
           };
       }
       public bool DestroyParameter(GH_ParameterSide side, int index) { return true; }
       public void VariableParameterMaintenance()
       {
           if (optionEnabled)
           {
               if (Params.Input.Count > nBaseInputs) return;// すでにOption追加済みなら何もしない

               // OptionのInputを追加

               //Params.RegisterInputParam(CreateParameter(GH_ParameterSide.Input, 4));
               //Params.RegisterInputParam(CreateParameter(GH_ParameterSide.Input, 5));
               var inp4 = new Param_Number
               {
                   Name = "D1",
                   NickName = "D1",
                   Description = "D1",
                   Access = GH_ParamAccess.item,
                   Optional = true
               };
               inp4.PersistentData.Append(new GH_Number(0.0)); // 初期値
               Params.RegisterInputParam(inp4);

               var inp5 = new Param_Number
               {
                   Name = "D2",
                   NickName = "D2",
                   Description = "D2",
                   Access = GH_ParamAccess.item,
                   Optional = true
               };
               inp5.PersistentData.Append(new GH_Number(0.0)); // 初期値
               Params.RegisterInputParam(inp5);
           }
           else
           {   // OptionのInputを削除する

               if (Params.Input.Count == nBaseInputs) return; // すでにInputが削除済み、もしくは未追加なら終了
               
               // OptionのInputを削除
               Params.Input[4].Sources.Clear();
               Params.UnregisterInputParameter(Params.Input[4]);
               Params.Input[3].Sources.Clear();
               Params.UnregisterInputParameter(Params.Input[3]);
           }
       }

SolveInstance()の処理順とか少々試行錯誤したけど、概ね思ったような動きになった。

参考

Rhinoceros Forumのこちらの投稿を参考にしました。
Hide Input Parameter using Boolean

動作環境

以下の環境で動作を確認しています。

  • Windows11 Pro(64bit, 23H2)
  • Rhinoceros 8 SR6
  • Visual Studio Professional 2022(17.9.3)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です