Grasshopper

algorithmic modeling for Rhino

I'm writting a C# assembly component, and I want to automatically generate a value list input. I've got it working for components that have single inputs, or if all inputs have defaults. Basically, as long as the component runs, the list gets generated (screenshot below). It's based on a process explained by James Ramsden here.

However, the list is only generated after all inputs are defined, so for components that have certain inputs without default values, the user has to set these inputs before the list gets generated. Is there any way to force the component to generate the list even before the component has been given all input values? Here is sample code for the issue; the list is only generated after input1 has been defined:

using System;
using System.Collections.Generic;
using Grasshopper.Kernel;
using Rhino.Geometry;
using System.Drawing;
namespace IntraLattice
{
public class MyComponent1 : GH_Component
{
GH_Document GrasshopperDocument;
IGH_Component Component;
public MyComponent1()
: base("MyComponent1", "Nickname",
"Description",
"Category", "Subcategory")
{
}
protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
{
pManager.AddLineParameter("Input1", "Input1", "An input", GH_ParamAccess.list);
pManager.AddIntegerParameter("Input2", "Input2", "The list selection input", GH_ParamAccess.item, 0);
}
protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
{
pManager.AddLineParameter("Output", "Output", "Dummy output", GH_ParamAccess.item);
}
protected override void SolveInstance(IGH_DataAccess DA)
{
// 0. Generate input menu list
Component = this;
GrasshopperDocument = this.OnPingDocument();
if (Component.Params.Input[1].SourceCount == 0)
TopoSelect(ref Component, ref GrasshopperDocument, 1, 11);
// 1. Retrieve/validate input
var input1 = new List<Line>();
int input2 = 0;
if (!DA.GetDataList(0, input1)) { return; }
if (!DA.GetData(1, ref input2)) { return; }
var nodes = new List<Point3d>();
var lines = new List<Line>();
// Some dummy code, that will set the output depending on the value selection list
// create first point
Point3d pt1 = new Point3d(0, 0, 0);
Point3d pt2;
// set output depending on value list selection
if (input2 == 0)
pt2 = new Point3d(5, 0, 0);
else
pt2 = new Point3d(0, 5, 0);

// create pt2
Line line = new Line(pt1, pt2);
DA.SetData(0, line);
}
/// The 'index' input represents the input index (first input is index 0)
/// The 'offset' parameter is the vertical offset of the menu, to help with positioning
/// </summary>
public static void TopoSelect(ref IGH_Component Component, ref GH_Document GrasshopperDocument, int index, float offset)
{
//instantiate new value list
var vallist = new Grasshopper.Kernel.Special.GH_ValueList();
vallist.ListMode = Grasshopper.Kernel.Special.GH_ValueListMode.Cycle;
vallist.CreateAttributes();
//customise value list position
float xCoord = (float)Component.Attributes.Pivot.X - 200;
float yCoord = (float)Component.Attributes.Pivot.Y + index * 40 - offset;
PointF cornerPt = new PointF(xCoord, yCoord);
vallist.Attributes.Pivot = cornerPt;
//populate value list with our own data
vallist.ListItems.Clear();
var items = new List<Grasshopper.Kernel.Special.GH_ValueListItem>();
items.Add(new Grasshopper.Kernel.Special.GH_ValueListItem("Choice 0", "0"));
items.Add(new Grasshopper.Kernel.Special.GH_ValueListItem("Choice 1", "1"));
vallist.ListItems.AddRange(items);
// Until now, the slider is a hypothetical object.
// This command makes it 'real' and adds it to the canvas.
GrasshopperDocument.AddObject(vallist, false);
//Connect the new slider to this component
Component.Params.Input[index].AddSource(vallist);
Component.Params.Input[index].CollectData();
}
protected override System.Drawing.Bitmap Icon
{
get
{
return null;
}
}
public override Guid ComponentGuid
{
get { return new Guid("{ebc17377-4900-4e14-b33e-0b1c66ef2ade}"); }
}
}
}

Thanks in advance

Views: 4842

Replies to This Discussion

Hi,

how about this solution?

Its a C# skript but you can easy integrate the solution in your code.

The bool "execute" may do the trick for you.

Best,

Raul

Attachments:

hi Raul,

i am actually a very beginner on scripting and i i cant make your component to work..

can you be more specific about the different steps? 

i wish to input a list of values as inputs for the value list component list names and values...

i enlight me please *

by the way...

it is better to instantiate the lists inside the if/else...

  private void RunScript(List<object> someInputs, bool execute, ref object A)
  {
    List<Point3d> myPoints;
    List<Line> myLines;

    if (!execute)
    {
      // set two dummy points and a dummy line...

      myPoints = new List<Point3d>();
      myLines = new List<Line>();
      
      myPoints.Add(new Point3d(0, 0, 0));
      myPoints.Add(new Point3d(0, 0, 10));

      myLines.Add(new Line(myPoints[0], myPoints[1]));
    }
    else
    {
      // take the values from user here...
      
      myPoints = new List<Point3d>();
      myLines = new List<Line>();
    }

    A = myLines;
  }

RSS

About

Translate

Search

Photos

  • Add Photos
  • View All

Videos

  • Add Videos
  • View All

© 2024   Created by Scott Davidson.   Powered by

Badges  |  Report an Issue  |  Terms of Service