Hi,
Is it possible to group last N components in grasshopper using C# ?
By group I mean ctrl+g
.
Hi,
Is it possible to group last N components in grasshopper using C# ?
By group I mean ctrl+g
.
without testing, this seems to be interesting:
maybe paired with this one:
oh, and I’d like to use the opportunity to say thank you to you Petras, your website is an amazing add with great examples of c# code. Your site saved me sooooo much time!!
Thank you!
Thank you;)
I have a small issue with this code you referenced:
List<Guid> guids = new List<Guid>();
foreach (Grasshopper.Kernel.IGH_Param param in base.Params.Input)
{
foreach (IGH_Param source in param.Sources)
{
guids.Add(source.Attributes.Parent.InstanceGuid);
}
}
I create a grasshopper component, but within this component I create some more components as input. The moment I use this option for my case Parent.InstanceGuid return null.
I create additional input components like this:
public override void AddedToDocument(GH_Document document)
{
base.AddedToDocument(document);
//Add Curve
Curve[] lines = new Curve[] {
(new Line(new Point3d(200,-200,300),new Point3d(200,-200,400))).ToNurbsCurve()
};
int[] recID = new int[] { 0 };
for (int i = 0; i < recID.Length; i++)
{
Grasshopper.Kernel.Parameters.Param_Curve ri = Params.Input[recID[i]] as Grasshopper.Kernel.Parameters.Param_Curve;
if (ri == null || ri.SourceCount > 0 || ri.PersistentDataCount > 0) return;
Attributes.PerformLayout();
int x = (int)ri.Attributes.Pivot.X - 225;
int y = (int)ri.Attributes.Pivot.Y;
IGH_Param lineParam = new Grasshopper.Kernel.Parameters.Param_Curve();
lineParam.AddVolatileData(new Grasshopper.Kernel.Data.GH_Path(0), 0, lines[i]);
lineParam.CreateAttributes();
lineParam.Attributes.Pivot = new System.Drawing.PointF(x, y);
lineParam.Attributes.ExpireLayout();
document.AddObject(lineParam, false);
ri.AddSource(lineParam);
}
//Add sliders
double[] sliderValue = new double[] { 42, 20000, 650, 40, 1, };
double[] sliderMinValue = new double[] { 1, 1000, 0, 300, 1, };
double[] sliderMaxValue = new double[] { 110, 30000, 650, 0, 20 };
int[] sliderID = new int[] { 1, 2, 3, 4, 5 };
for (int i = 0; i < sliderValue.Length; i++)
{
Grasshopper.Kernel.Parameters.Param_Number ni = Params.Input[sliderID[i]] as Grasshopper.Kernel.Parameters.Param_Number;
if (ni == null || ni.SourceCount > 0 || ni.PersistentDataCount > 0) return;
Attributes.PerformLayout();
int x = (int)ni.Attributes.Pivot.X - 250;
int y = (int)ni.Attributes.Pivot.Y - 10;
Grasshopper.Kernel.Special.GH_NumberSlider slider = new Grasshopper.Kernel.Special.GH_NumberSlider();
slider.SetInitCode(string.Format("{0}<{1}<{2}", sliderMinValue[i], sliderValue[i], sliderMaxValue[i]));
slider.CreateAttributes();
slider.Attributes.Pivot = new System.Drawing.PointF(x, y);
slider.Attributes.ExpireLayout();
document.AddObject(slider, false);
ni.AddSource(slider);
}
//Add Booleans
bool[] boolValue = new bool[] { true };
int[] boolID = new int[] { 6 };
for (int i = 0; i < boolID.Length; i++)
{
Grasshopper.Kernel.Parameters.Param_Boolean bi = Params.Input[boolID[i]] as Grasshopper.Kernel.Parameters.Param_Boolean;
if (bi == null || bi.SourceCount > 0 || bi.PersistentDataCount > 0) return;
Attributes.PerformLayout();
int x = (int)bi.Attributes.Pivot.X - 250;
int y = (int)bi.Attributes.Pivot.Y - 10;
Grasshopper.Kernel.Special.GH_BooleanToggle booleanToggle = new Grasshopper.Kernel.Special.GH_BooleanToggle();
booleanToggle.CreateAttributes();
booleanToggle.Attributes.Pivot = new PointF(x, y);
booleanToggle.Attributes.ExpireLayout();
booleanToggle.Value = boolValue[i];
document.AddObject(booleanToggle, false);
bi.AddSource(booleanToggle);
}
}
I assume that c# component runs the code to retrieve guids before all these components are created.
So the question is when do I need to call this function, so that the returned guids are not null?
Oh yes, I have seen that the code returns null for e.g. sliders. I reduced the problem to a simple slider.
I made it work (very simple, I wasn’t able to quickly rebuild your building solution) by using this code from this post from rolf:
// Checking the first Input param (at index = 0)
var param = Component.Params.Input[0];
if (param.Sources.Count < 1)
{
return; // No source was connected to inport
}
A = param.Sources[0].InstanceGuid; // Output the Guid
which will give you the correct GUID id
I guess you need to loop through them as you set the inputs yourself.
update:
here a working code that groupes all the inputs like sliders etc (not nodes though) as soon as they are connected. this is in the solveInstance:
private void RunScript(Brep B, string M, ref object A, ref object C)
{
if(B == null) return;
//get volume in metric volume
double volcm = B.GetVolume() / 1000;
//Component.Params.Input[1].Optional = true;
//populate val list
if(M == "1")
{
var input = Component.Params.Input[1].Sources[0]; //get the first thing connected to the first input of this component
var valList = input as Grasshopper.Kernel.Special.GH_ValueList;
valList.ListItems.Clear();
List <Grasshopper.Kernel.Special.GH_ValueListItem> materials = new List<Grasshopper.Kernel.Special.GH_ValueListItem>()
{
new Grasshopper.Kernel.Special.GH_ValueListItem("silver ag 999", "10.49"),
new Grasshopper.Kernel.Special.GH_ValueListItem("silver ag 925", "10.40"),
new Grasshopper.Kernel.Special.GH_ValueListItem("white gold Au750Pd130", "15.80"),
new Grasshopper.Kernel.Special.GH_ValueListItem("white gold Au750Pd150", " 15.90"),
new Grasshopper.Kernel.Special.GH_ValueListItem("white gold Au750Pd210", " 16.30"),
new Grasshopper.Kernel.Special.GH_ValueListItem("pale gold 2N Au750Ag160", " 15.60"),
new Grasshopper.Kernel.Special.GH_ValueListItem("yellow gold 3N Au750Ag125", " 15.40"),
new Grasshopper.Kernel.Special.GH_ValueListItem("rosé gold 4N Au750Ag90", "15.30"),
new Grasshopper.Kernel.Special.GH_ValueListItem("red gold 5N Au750Ag45", "15.10"),
new Grasshopper.Kernel.Special.GH_ValueListItem("most red gold 6N Au750Ag5Pt4", "15.10"),
new Grasshopper.Kernel.Special.GH_ValueListItem("platine 950", "20.40"),
new Grasshopper.Kernel.Special.GH_ValueListItem("palladium 950", "11.80")
};
valList.ListItems.AddRange(materials);
Component.Params.Output[1].VolatileData.Clear();
valList.ExpireSolution(true);
}
if(M == null) A = "please connect a item list node to M and select a material";
else
{
A = string.Format("{0}g", Math.Round(volcm * Convert.ToDouble(M), 2));
}
List<Guid> guids = new List<Guid>();
foreach(IGH_Param param in Component.Params.Input)
{
foreach(IGH_Param source in param.Sources)
{
guids.Add(source.InstanceGuid);
}
}
Grasshopper.Kernel.Special.GH_Group g = new Grasshopper.Kernel.Special.GH_Group();
g.NickName = "hhh";
g.Colour = System.Drawing.Color.FromArgb(150, 150, 0, 0);
GrasshopperDocument.AddObject(g, false, GrasshopperDocument.ObjectCount);
for(int i = 0;i < guids.Count;i++) g.AddObject(guids[i]);
g.ExpireCaches();
I might be wrong, but I think the order of objects when you iterate GrasshopperDocument.Objects
is the order of instantiation (a quick GHPython test):
So maybe you could just grab the last N objects in this list and group these. Maybe
Here’s quick go at implementing what I suggested above, seems to work okay:
what a beauty!
Hi @Petras_Vestartas, @benedict, @AndersDeleuran, maybe not related to the topic but How could a C# change only the colour of the group that belongs to, without using a group name?. I’d like to implement these lines inside my code, I’d really appreciate any help, thank you in advance!
T.
g.NickName = "hhh";
g.Colour = System.Drawing.Color.FromArgb(150, 150, 0, 0);
@Petras_Vestartas how did you make align components on the left with the inputs on the right? Did you code it?
int x = (int)ni.Attributes.Pivot.X - 250;
int y = (int)ni.Attributes.Pivot.Y - 10;
I am having a hard time to make them align. Any advice?
Exactly, and the pivot point is the alignment point
double[] sliderValue = new double[] { 42, 20000, 650, 40, 1, };
double[] sliderMinValue = new double[] { 1, 1000, 0, 300, 1, };
double[] sliderMaxValue = new double[] { 110, 30000, 650, 0, 20 };
int[] sliderID = new int[] { 1, 2, 3, 4, 5 };
for (int i = 0; i < sliderValue.Length; i++)
{
Grasshopper.Kernel.Parameters.Param_Number ni = Params.Input[sliderID[i]] as Grasshopper.Kernel.Parameters.Param_Number;
if (ni == null || ni.SourceCount > 0 || ni.PersistentDataCount > 0) return;
Attributes.PerformLayout();
int x = (int)ni.Attributes.Pivot.X - 250;
int y = (int)ni.Attributes.Pivot.Y - 10;
Grasshopper.Kernel.Special.GH_NumberSlider slider = new Grasshopper.Kernel.Special.GH_NumberSlider();
slider.SetInitCode(string.Format("{0}<{1}<{2}", sliderMinValue[i], sliderValue[i], sliderMaxValue[i]));
slider.CreateAttributes();
slider.Attributes.Pivot = new System.Drawing.PointF(x, y);
slider.Attributes.ExpireLayout();
document.AddObject(slider, false);
ni.AddSource(slider);
}
It works perfect. Thanks for the explanation!