using GH_IO.Serialization;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Parameters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Gridshell
{
#if DEBUG
public class TestComponent : GH_VariableConfigComponent
{
public TestComponent()
: base("Component with variable configs", "TEST", "Component with variable configs.", "Test", "Test")
{
string name, tag;
IGH_Param[] inputs, outputs;
name = "First configuration";
tag = "Config 1";
inputs = new IGH_Param[2]{
new Param_Number() { Name = "Variable Input A (C1)", NickName = "VIA.C1", Description = "Variable Input A for config 1", Access = GH_ParamAccess.item, Optional = true },
new Param_Number() { Name = "Variable Input B (C1)", NickName = "VIB.C1", Description = "Variable Input B for config 1", Access = GH_ParamAccess.item, Optional = true }
};
outputs = new IGH_Param[1]{
new Param_Number() { Name = "Variable Output A (C1)", NickName = "VOA.C1", Description = "Variable Output A for config 1", Access = GH_ParamAccess.item, Optional = true }
};
AddConfig(name, tag, inputs, outputs);
name = "Secong configuration";
tag = "Config 2";
inputs = new IGH_Param[1]{
new Param_Number() { Name = "Variable Input A (C2)", NickName = "VIA.C2", Description = "Variable Input A for config 2", Access = GH_ParamAccess.item, Optional = true },
};
outputs = new IGH_Param[2]{
new Param_Number() { Name = "Variable Output A (C2)", NickName = "VOA.C2", Description = "Variable Output A for config 2", Access = GH_ParamAccess.item, Optional = true },
new Param_Number() { Name = "Variable Output B (C2)", NickName = "VOB.C2", Description = "Variable Output B for config 2", Access = GH_ParamAccess.item, Optional = true }
};
AddConfig(name, tag, inputs, outputs);
}
public override Guid ComponentGuid => new Guid("{DB495206-A92D-4A31-89E5-7FC445B7D682}");
public override GH_Exposure Exposure => GH_Exposure.secondary;
protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
{
pManager.AddIntegerParameter("First Fixed Input", "FI.1", "First Fixed Input", GH_ParamAccess.item, 0);
pManager.AddIntegerParameter("Second Fixed Input", "FI.2", "Second Fixed Input", GH_ParamAccess.item, 0);
pManager[0].Optional = true;
pManager[1].Optional = true;
}
protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
{
pManager.AddIntegerParameter("First Fixed Output", "FO.1", "First Fixed Output", GH_ParamAccess.item);
}
protected override void SolveInstance(IGH_DataAccess DA)
{
// read fixed inputs
int FI1 = 0;
int FI2 = 0;
DA.GetData(0, ref FI1);
DA.GetData(1, ref FI2);
// read variable inputs
switch (ActiveConfigIndex)
{
case 0:
int VIA_C1 = 0;
int VIB_C1 = 0;
DA.GetData(FixedInputsCount + 0, ref VIA_C1);
DA.GetData(FixedInputsCount + 1, ref VIB_C1);
break;
case 1:
int VIA_C2 = 0;
DA.GetData(FixedInputsCount + 0, ref VIA_C2);
break;
}
// write to fixed output
DA.SetData(0, -1);
// write to variable outputs
switch (ActiveConfigIndex)
{
case 0:
DA.SetData(FixedOutputsCount + 0, -2);
break;
case 1:
DA.SetData(FixedOutputsCount + 0, -3);
DA.SetData(FixedOutputsCount + 1, -4);
break;
}
}
}
#endif
///
/// This is a component template to generate components with switchable Inputs/Outputs configurations.
/// Simply use the AddConfig() method in the constrcutor.
///
public abstract class GH_VariableConfigComponent : GH_Component, IGH_VariableParameterComponent
{
// variable outputs
private List ConfigList { get; set; }
protected int ConfigCount => ConfigList.Count;
protected int ActiveConfigIndex { get; private set; }
private ComponentConfig ActiveConfig => ConfigList[ActiveConfigIndex];
protected List ConfigMenuItems { get; set; }
protected int FixedInputsCount { get; private set; }
protected int FixedOutputsCount { get; private set; }
protected int ActiveConfigInputsCount => ActiveConfig.Inputs.Length;
protected int ActiveConfigOutputsCount => ActiveConfig.Outputs.Length;
public GH_VariableConfigComponent(string name, string nickname, string description, string category, string subCategory) : base(name, nickname, description, category, subCategory)
{
ConfigList = new List();
FixedInputsCount = Params.Input.Count;
FixedOutputsCount = Params.Output.Count;
SwitchConfig(ActiveConfigIndex);
}
public void AddConfig(string name, string tag, IGH_Param[] inputs, IGH_Param[] outputs)
{
var index = ConfigList.Count;
ConfigList.Add(new ComponentConfig(index, name, tag, inputs, outputs));
// this is the default configuration
if (index == 0)
{
ActiveConfigIndex = 0;
// register params for default configuration
for (int i = 0; i < ConfigList[0].Inputs.Length; i++)
Params.RegisterInputParam(ConfigList[0].Inputs[i], FixedInputsCount + i);
for (int i = 0; i < ConfigList[0].Outputs.Length; i++)
Params.RegisterOutputParam(ConfigList[0].Outputs[i], FixedOutputsCount + i);
}
}
protected override void AppendAdditionalComponentMenuItems(ToolStripDropDown menu)
{
ConfigMenuItems = new List();
for (int i = 0; i < ConfigCount; i++)
{
var itemName = ConfigList[i].Name;
var isChecked = (i == ActiveConfigIndex);
ConfigMenuItems.Add(Menu_AppendItem(menu, itemName, OnItemClick, true, isChecked));
}
menu.Items.AddRange(ConfigMenuItems.ToArray());
base.AppendAdditionalComponentMenuItems(menu);
}
private void OnItemClick(object sender, EventArgs e)
{
var clickedItem = (ToolStripItem)sender;
var clickedItemIndex = ConfigMenuItems.FindIndex(i => i == clickedItem);
SwitchConfig(clickedItemIndex);
}
private void SwitchConfig(int toConfigIndex)
{
if (toConfigIndex == ActiveConfigIndex) return;
// unregister params
for (int i = 0; i < ActiveConfig.Inputs.Length; i++)
Params.UnregisterInputParameter(ActiveConfig.Inputs[i], true);
for (int i = 0; i < ActiveConfig.Outputs.Length; i++)
Params.UnregisterOutputParameter(ActiveConfig.Outputs[i], true);
ActiveConfigIndex = toConfigIndex;
// register params
for (int i = 0; i < ActiveConfig.Inputs.Length; i++)
Params.RegisterInputParam(ActiveConfig.Inputs[i], FixedInputsCount + i);
for (int i = 0; i < ActiveConfig.Outputs.Length; i++)
Params.RegisterOutputParam(ActiveConfig.Outputs[i], FixedOutputsCount + i);
Params.OnParametersChanged();
ExpireSolution(true);
}
protected override void BeforeSolveInstance()
{
base.BeforeSolveInstance();
this.Message = ActiveConfig.Tag;
}
// IGH_VariableParameterComponent
bool IGH_VariableParameterComponent.CanInsertParameter(GH_ParameterSide side, int index) => false;
bool IGH_VariableParameterComponent.CanRemoveParameter(GH_ParameterSide side, int index) => false;
IGH_Param IGH_VariableParameterComponent.CreateParameter(GH_ParameterSide side, int index) => null;
bool IGH_VariableParameterComponent.DestroyParameter(GH_ParameterSide side, int index) => false;
void IGH_VariableParameterComponent.VariableParameterMaintenance() {
// replace default variable parameters by previously serialized ones to preserve existing wireing
for (int i = 0; i < ActiveConfig.Inputs.Length; i++)
ActiveConfig.Inputs[i] = Params.Input[FixedInputsCount + i];
for (int i = 0; i < ActiveConfig.Outputs.Length; i++)
ActiveConfig.Outputs[i] = Params.Output[FixedOutputsCount + i];
Params.OnParametersChanged();
}
// Serialization of output states
public override bool Read(GH_IReader reader)
{
ActiveConfigIndex = reader.GetInt32("ActiveConfigIndex");
return base.Read(reader);
}
public override bool Write(GH_IWriter writer)
{
writer.SetInt32("ActiveConfigIndex", ActiveConfigIndex);
return base.Write(writer);
}
private class ComponentConfig
{
public int Index { get; set; } // config index
public string Name { get; set; }
public string Tag { get; set; }
public IGH_Param[] Inputs;
public IGH_Param[] Outputs;
public ComponentConfig(int index, string name, string tag, IGH_Param[] inputs, IGH_Param[] outputs)
{
Index = index;
Name = name;
Tag = tag;
Inputs = inputs;
Outputs = outputs;
}
}
}
}