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)
ピンバック: GH_ParamAccess.Item or list? | ヤスダ式仕事のブログ