Attachments

Hipfile

jamesr_evaluatingmenuparameters.hiplc

Menu Parameters & Evaluation Results

I can never remember off the top of my head when a menu parameter is going to evaluate the token string, or an integer, or a string representation of an integer without first doing a quick little check in the Python Shell…so here’s a table that should help future James and maybe some other folks as well. Each test was done with the parameters set to use a Normal menu, with the tokens item0, item1

Parameter Typehou.Parm.eval()hou.Parm.evalAsString()hou.Parm.evalAsInt()ch()chs()kwargs["script_value"]
Ordered Menu1“item1”11“item1”“item1”
String“item1”“item1”TypeError0“item1”“item1”
Integer1“1”11“1”“1”

Cells with formatting like 0, and 1 are integer types. Cells in double quotes " are string types.

Overview

Houdini offers a few ways to both create and evaluate dropdown menu parameters.

The way you configure these menu parameters affect how they get evaluated in different contexts (hscript, Python, parameter callbacks, etc.). Let’s take a look at what that means, and come up with a quick reference table that we can use when debugging or creating new interfaces.

Menu Parameter Types

Typical dropdown menu

Typical dropdown menu

What’s a menu made of?

Houdini menus are made up of item/label pairs.

Item/Label Pairs

Item/Label Pairs

Label

Labels are the “nice names” that the user sees in the dropdown.

Using Python, you can get a list of a menu parameter’s labels with

1
2
3
hou.parm("/obj/geo1/null1/greetings").menuLabels()

('Hi', 'Hallo', 'Kia ora', 'Hej hej', 'こんにちは')

If you ever want to get the label of the currently selected menu item, try this:

1
2
3
4
parm = hou.parm("/obj/geo1/null1/greetings")
parm.menuLabels()[parm.evalAsInt()]

'Hallo'

Item (Token)

A Menu Item is the internal name used by Houdini. You can optionally specify a token for each menu item which can be used for setting and evaluating the menu as a string, and for use with disable/hide when rules.

Just because you put something as the token, doesn’t mean that’s always what you’ll get when you evaluate it (see the table above).

Using Python, you can get a list of a menu parameter’s items/tokens using:

1
2
3
hou.parm("/obj/geo1/null1/greetings").menuItems()

('hi', 'hallo', 'kiaora', 'hej', 'konnichiwa')

Ordered Menu

In general, most of the menu parameters I come across (and create) use the Ordered Menu parameter type. This parameter type creates the classic dropdown that you’ve likely seen countless times:

Typical dropdown menu

Typical dropdown menu

Typical dropdown menu settings

Typical dropdown menu settings

These can be created directly in the Type Properties / Edit Parameter Interface UI by either explicitly specifying a list of token/label pairs

Configuring and Ordered Menu parameter in the Edit Parameter Interface window

Configuring and Ordered Menu parameter in the Edit Parameter Interface window

or more dynamically through a Python parameter menu script.

An example of Python Parameter Menu Script

An example of Python Parameter Menu Script

greetings.json

greetings.json

1
2
3
4
5
6
7
8
9
{
    "greetings": [
        {"language": "english", "token": "hi", "label": "Hi"},
        {"language": "german", "token": "hallo", "label": "Hallo"},
        {"language": "te reo", "token": "kiaora", "label": "Kia ora"},
        {"language": "swedish", "token": "hej", "label": "Hej hej"},
        {"language": "japanese", "token": "konnichiwa", "label": "こんにちは"}
    ]
}

For more info on generating menus with Python:

Generating a menu from attributes

Parameter Menu Scripts

Quick Menu Script List

String or Integer Parameter with “Use Menu” Enabled

Another common place to use menus are String and Integer parameter types.

These menus are often used to help populate a field, for instance when selecting several attributes to get rid of in the Attribute Delete SOP.

Attribute Delete SOP Menu with attributes expanded

Attribute Delete SOP Menu with attributes expanded

A regular String parameter type can be made to use a menu by enabling the following toggle on the right side of the Type Properties / Edit Parameter Interface window:

Use Menu toggle

Use Menu toggle

When using the Normal option, the menu will appear just like the ordinary Ordered Menu parameter type. The other two common options are Replace and Toggle - these will add a small mini-menu to the right of the string/int parameter from which you can select and populate the string/int field. Those are the styles that are most familiar from nodes like Attribute Delete etc.

Why would I ever use the “Normal” mode if I’m using a string or int parameter? Can’t I just use an Ordered Menu?

Usually an Ordered Menu is just fine - but one advantage is explicitness. If you want to make sure your menu always returns a string when using HOM’s hou.Parm.eval(), you can create a String parameter, enable Use Menu, and keep it as Normal (Menu Only, Single Selection). Whenever someone evaluates the parameter with hou.evalParm("/obj/geo1/null1/mymenuparm"), they will get a string back which is not the case with the standard Ordered Menu type (which would need hou.Parm.evalAsString(), even if your token looks like a string).

Test Cases

For testing, I’m using the following menu parameters:

  • Ordered Menu
  • String Parameter with Normal menu enabled
  • Integer Parameter with Normal menu enabled
Menus on the Parameter Interface

Menus on the Parameter Interface

They each have different labels, but the menu items/tokens are all the same: item0, item1

The results in the tables below were gathered when the menus were changed to their second dropdown item (item1).

See the hipfile above to check it out yourself.

Menu testing interface from hipfile

Menu testing interface from hipfile

`hou.Parm.eval()`

hou.Parm.eval()

1
2
value = parm("orderedmenu").eval()
return f"{value} {type(value)}"
Parameter Typehou.Parm.eval()Type
Ordered Menu1int
Stringitem1str
Integer1int
`hou.Parm.evalAsString()`

hou.Parm.evalAsString()

1
2
value = parm("orderedmenu").evalAsString()
return f"{value} {type(value)}"
Parameter Typehou.Parm.evalAsString()Type
Ordered Menuitem1str
Stringitem1str
Integer1str
`hou.Parm.evalAsInt()`

hou.Parm.evalAsInt()

1
2
value = parm("orderedmenu").evalAsInt()
return f"{value} {type(value)}"
Parameter Typehou.Parm.evalAsInt()Type
Ordered Menu1int
StringTypeError
Integer1int
`ch()`

ch()

1
ch("orderedmenu")
Parameter Typech()Type
Ordered Menu1int
String0int
Integer1int
`chs()`

chs()

1
chs("orderedmenu")
Parameter Typechs()Type
Ordered Menuitem1str
Stringitem1str
Integer1str
`kwargs["script_value"]`

kwargs["script_value"]

1
2
value = kwargs["script_value"]
hou.ui.displayMessage(f"kwargs['script_value'] = {value}\n\n{type(value)}")
Parameter Callback (Python)

Parameter Callback (Python)

Parameter Typekwargs["script_value"]Type
Ordered Menuitem1str
Stringitem1str
Integer1str

When implementing parameter callbacks, Houdini gives us access to a Python dictionary named kwargs filled with useful info about the parameter. One of those keys is called script_value, which according to the docs is equivalent to kwargs["parm"].eval() (see above - this isn’t quite always the case, especially when it comes to int/float parameters, since it always seems to return a string).

See Also Parameter Callback Scripts

Final Thoughts

Ordered Menus and String Parameters can be set using their tokens like so:

1
hou.parm("/obj/geo1/null1/orderedmenu").set("item1")

When an integer parm using a Normal menu that has tokens is evaluated as a string, it will not return the token, but rather a string representation of the selected index.

You cannot set an integer menu parameter by its token like you can with a string parameter / ordered menu unless the token you’re trying to set it to is a string representation of a numerical value, like "1000", "42" etc.


Use Token as Value

This reply from SESI on the SideFX Forums describes well what Use Token as Value does.

When you have Use Token as Value enabled on an integer parameter with a menu (or an Ordered Menu), and your tokens are string representations of numbers like "1000" or"42", instead of evaluating to the menu index as usual, Houdini will try to use that value instead.

For instance, if our integer parameter has the following menu:

TokenLabel
item0Int Label 0
item1Int Label 1
42Forty Two

and we have Use Token as Value disabled, calls like hou.Parm.eval() and ch() will evaluate to the selected menu index 2

Use Token and Value disabled

Use Token and Value disabled

Once we turn on Use Token as Value, we get 42

Use Token as Value enabled

Use Token as Value enabled

See it in use for real on the Vellum Constraints node’s stretchstiffnessexp parameter.