Building a value list based on values in sc.sticky or other non-GH storage space

grasshopper
python
unhandled

#1

I’ve seen that Ladybug and Honeybee make use of the Value List as a shortcut for calling and loading templates in Grasshopper. How do I go about doing something similar, but where the values in the list are generated from a backend storage space like scriptcontext’s sticky dictionary or something similar?

For example:

The top one is the Value List as used by Honeybee/Ladybug, the lower one is how my customized Values List with theoretically look like. What I’d like to do is that the Values List can load a list of values available from an external storage space like sc.sticky, and that it will immediately change its available values if this storage space is added to or subtracted from. Is it also possible to have outputs other than integer/float values, i.e. strings?

I don’t need to stick to using Value List, the gist is that I’d like to generated a drop-down menu “component” in Grasshopper, using Python. Any hints or alternatives approaches would be much appreciated, thanks!


(Keyu Gan) #2

Is it also possible to have outputs other than integer/float values, i.e. strings?

Yes. The items in a value list are GH_ValueListItem and the value is stored as GH expressions.

it will immediately change its available values if this storage space is added to or subtracted from

You need to explicitly manipulate the value list when your underlying data changes. It is the code I used in my plugin:

public static void UpdateValueList(IEnumerable < IGH_Param > input, ICollection < KeyValuePair < string, string >> list) {
 foreach(var inputComponent in input) {
  if (!(inputComponent is GH_ValueList)) continue;
  var valuelist = (inputComponent as GH_ValueList);
  var selected = (from item in valuelist.SelectedItems select item.Expression).ToList();
  valuelist.ListItems.Clear();
  foreach(var item in list) {
   valuelist.ListItems.Add(new GH_ValueListItem(item.Key, item.Value));
  }
  foreach(var item in selected) {
   var index = valuelist.ListItems.FindIndex(v => v.Expression == item);
   if (index != -1)
    valuelist.ToggleItem(index);
  }
  valuelist.Attributes.ExpireLayout();
  valuelist.Attributes.PerformLayout();
  valuelist.ExpireSolution(false);
 }
}

#3

Thanks for the detailed response! I think I forgot to write that I’d need to work primarily in Python. Could you perhaps provide a translation?

Additionally, would I be using GH_ValueListItem inside the component code?


(Keyu Gan) #4

I think it is dangerous. If you are running your python in a ghPython component, which means your code will run during an active solution. During that, it is really a bad thing to manipulate any other component (so usually the dirty job is done in AfterSolveInstance routine, which I’m unsure if ghPython supports).

Your problem is similar to The only safe way of Updating Slider in Python

-vv- original anwer -vv-

Sorry, I’m not so familiar with Python in GH. I would say it is the same approach as you from Grasshopper.Kernel.Special import GH_ValueList, GH_ValueListItem (pseudo-code, i don’t know if it works)

First create a list of GH_ValueListItem and insert them into GH_ValueList.ListItems. The rest of code is to ensure

  1. Previous selection is not lost if the list before and after share same elements
  2. The component is correctly expired and placed, as its size may change

#5

Hmm, thanks for the explanation and the link. I’ll see what happens when I adapt your code to python.