Grasshopper

algorithmic modeling for Rhino

Is there a way to have the outputs of the component be added or removed dynamically? I want to bring in a JSON file in a specific format and then create outputs for the various variables existing in the JSON file.

Hopefully that makes sense. Thanks in advance!

Views: 1950

Replies to This Discussion

Hi Ryan,

yes, it is fairly easy to add and remove parameters from a component. There are however some things you should keep in mind:

  • It is not legal to adjust the number of inputs/outputs during a solution. Not. Ever. Naughty boy!
  • If you automatically remove parameters, then bear in mind that the user may have spend effort hooking those up. It is not polite to erase someone's work, so always be mindful of removing outputs which have a recipient count > 0.
  • When you have a component which must first go online and do something before it looks the way it is supposed to look, you will always run into issues with deserialization. Perhaps once when you open the gh file you're offline. Or maybe the server crashed. What do you do in these cases?

My recommendation is to have your component implement IGH_VariableParameterComponent and then provide a null implementation. I.e. always return False for CanInsertParameter and CanRemoveParameter. This means the user will not be able to add/remove parameters, but you do get the added benefits of the uber-smart (de)serialization that comes with IGH_VariableParameterComponent.

The next problem you'll face is to decide when to modify your component. As mentioned before, you should not do this during a solution. You have several options:

  1. Never automatically add/remove parameters, add an item into the component menu which allows users to update the component layout. Or, if you're feeling fancy, override the component attributes and provide a button on the component itself which updates the layout.
  2. During a solution, if you detect that your current outputs don't match up with your JSON object, then schedule a new solution 1 millisecond after the current one completes. Add a callback delegate to the solution schedule so you'll be informed before the next solution kicks off. In this delegate, update your component.

Let me know if you have further questions once you've decided on an approach that works for you.

--

David Rutten

david@mcneel.com

Poprad, Slovakia

It is not legal to adjust the number of inputs/outputs during a solution. Not. Ever. Naughty boy!

This made me laugh! Ok, points taken. So ultimately, I have created a dynamic Slider application that will create realtime JSON files. A grasshopper component will then read the JSON file and create outputs to be used in the script. I think the best strategy will be to have the user create an output on the component that matches the slider name. This gives the user complete control.

Edit: Actually, looking at this now. I wonder if I can do a combination of #1 above and giving the user control to add or delete them manually. I will begin looking at implementing a IGH_VariableParameterComponent interface.

Thanks!

I am searching for an implementation example of IGH_VariableParameterComponent but I am currently at a loss. I am still learning component creation on the fly so any small example would be great. 

Thanks!

- Ryan

IGH_VariableParameterComponent does two things. One, it provides a ZUI (Zooming User Interface) for manually adding and removing parameters. There are a dozen or so components in GH which allow for this, for example Merge and Sort. It provides this ZUI by asking a number of questions which you have to answer. These questions get potentially asked a lot, so make sure your implementation is spiffy. For example, let's assume that we have a component where we want the user to be able to always add inputs, and always remove inputs as well, provided there's at least one left. Outputs are not dynamic.

First of all we need to make sure that GH knows when it's ok to remove or add a parameter:

public bool CanInsertParameter(GH_ParameterSide side, int index)

{

  if (side == GH_ParameterSide.Output) return false;

  return true;

}

public bool CanRemoveParameter(GH_ParameterSide side, int index)

{

  if (side == GH_ParameterSide.Output) return false;

  if (this.Params.Input.Count < 2) return false;

  return true; 

}

Which is just the English I wrote before implemented in C# (outputs can never be added/removed, inputs can only be removed if we'll end up with at least one of em). If you don't want users to be able to do this manually, just return false for both and you will never see the ZUI.

The above methods are used to decide whether or not to draw the little plus and minus symbols on the canvas when zoomed in on a component. However when the users clicks on one of these symbols, a lot more needs to happen. When a parameter is to be added, you need to provide this parameter. Also, when a parameter is about to be deleted, you need to ok this (though ideally, if it's not ok, you shouldn't have returned true from within CanRemoveParameter).

public IGH_Param CreateParameter(GH_ParameterSide side, int index)

{

  return new Grasshopper.Kernel.Parameters.Param_GenericObject();

}

public bool DestroyParameter(GH_ParameterSide side, int index)

{

  //If you need to take additional action, now's the time.

  return true; 

}

Ok, so far so good. All our inputs are generic parameters so we just need to return a new Param_GenericObject. If you want integers, return Param_Integer instead. Note that I haven't assigned a name, nickname, access or description to this parameter. That is because I will implement one final method which will take care of all this. You could of course give the parameter a name, nickname etc. etc. depends on the kind of component you're writing.

Ultimately, there's a cleanup method which gives you last say when it comes to your parameters. This method is called when a ZUI action completes but also when the component finishes reading from a file. If you want to make sure your parameters are set up correct, this is the ideal place to do so:

public void VariableParameterMaintenance()

{

  for (int i = 0; i < Params.Input.Count; i++)

  {

    IGH_Param param = Params.Input[i];

    param.Name = string.Format("Input {0}", i);

    param.NickName = string.Format("{0}", i);

    param.Access = GH_ParamAccess.list;

    param.Optional = true;

    param.MutableNickName = false;

  }

}

Basically, I iterate over all input parameters and make sure they all have correct names, nicknames, access flags, optional flags etc. etc.

The second thing IGH_VariableParameterComponent does (bet you you've forgotten all about part 2 haven't you?) is provide a more extensive (de)serialization. Regular components rely on RegisterInputParams and RegisterOutputParams to populate the input and output lists. Then all the parameters that have been created are asked to read themselves from the gh archive. However this doesn't work with variable parameter components as it is not obvious how many parameters there are supposed to be.

If your component implements the IGH_VariableParameterComponent interface then additional information will be written to the gh files which allows the component to correctly resurrect itself from a file.

--

David Rutten

david@mcneel.com

Poprad, Slovakia

David,

Man, all I wanted was a "little" exampleFantastic explanation! This gets me where I need to be, and I am sure it will help anyone in the future with these same problems.

Thank you so much!

David,

I've been trying to implement this above code in combination with FileSystemWatcher (c#) events and am finding that the methods work for the most part but after a number of events Rhino and Grasshopper freeze up. 

I'm not sure but there might be a bug somewhere...

The freeze behavior seems to be triggered when multiple events happen at once, or very close to one another.

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