Close

Internal Parameters


Parameters are a powerful way to hold data in TouchDesigner. “Internal Parameters” provide a simple shortcut to parameter collections within a component, from anywhere in that component. They act like "persistent local variables".

Simplest Procedure

Most simply, right-click on a network background and select Create Custom Parameters.... You pick a shortcut Name. (By default it's the Parent Shortcut name, if it exists.) When you press Apply it creates a Base COMP in your network where you can add a collection of custom parameters. You add a parameter Parname and then refer to it with an expression ipar.Name.Parname.

(This is set it up on the Common page of the parent component where the shortcut name and the path to the nodeare found in Internal Operator 1 and Internal Operator Shortcut 1.)

ipar.Name searches up in the parent components' hierarchy until it finds a component with a matching Internal OP Shortcut name.

See also Internal Operators.

Manual Proedure

Go inside any component, say /project1 of a default TouchDesigner. Create a Base Component, and name it iparEffect.

On iparEffect create a Float Custom Parameter and name it Size.

Go to the parameters of /project1, to the Common page. Name your internal shortcut by setting Internal OP Shortcut 1 to Effect.

Give the path to the new Base Component by setting Internal OP 1 to ./iparEffect.

InternalParameters.3.jpg

The base component's parameters are now easy to get and set within your component:

Go back in project1 and create a Circle SOP. In its Radius parameters put ipar.Effect.Size.

Change the Size parameter on iparEffect. The expression on the Circle SOP updates correctly.

InternalParameters.2.jpg

To set the Size parameter in a python script, create a Text DAT and in it put: ipar.Effect.Size = 1.7

On the Text DAT, turn off Viewer Active, and on the node rclick -> Run Script. The Size parameter on iparEffect will change to 1.7.

Rationale

Holding values inside a component as parameters has advantages versus holding values in tables, Constant CHOPs, Extensions or Storage, as discussed in Pros and Cons below. Internal Parameters are simple to use, and can reduce or eliminate the need to write code in extensions. And by creating parameters inside your component, they are not needlessly exposed outside. See also Internal Operators or iOPs.

Recommendation

Name your internal parameter extension something meaningful. If it's a bin of movies, make the Parent Shortcut parameter be called Bin, and the internal parameter name be also Bin.

Like any parameter, if an internal parameter is a path to an operator, you have to write, for example, op(ipar.Effect.Oppath) or ipar.Effect.Oppath.eval(). Otherwise you generally don't need .eval().

To easily see your evaluated parameters in the network, put a Parameter DAT in the Base COMP and put ./parameter1 in the Base COMP's OP Viewer parameter. The viewer will now show the Parameter DAT's table of parameters.

To see where an internal parameter comes from when it appears in a parameter expression, select the text ipar.Effect and put your cursor over the parameter label. It will reveal its path.

Discussion - Where you can Hold and Modify Data in TouchDesigner

To review, there are already several ways to hold data internally in TouchDesigner:

  • text strings located in Table DAT cells and Text DATs
  • pre-existing parameters (on Constant CHOP, Add SOP, …)
  • Custom Parameters on the outside of components
  • CHOPs, SOPs and TOPs, some which may be "locked" (and harder to modify)
  • TouchDesigner-python Storage in any Operator
  • TouchDesigner-python Extension “Properties”
  • Regular python variables in functions and scripts (these are not persistent after a script runs)
  • data held in Script CHOP, Script DAT and Script SOP that generate data
  • Dialogs -> Variables, where you can create variables and access them in python with var('VARNAME'). These are simply strings.

Pros and Cons of Internal Parameters

Benefits

  • procedural (changing the parameter causes cooking downstream reliably)
  • easily hand-editable
  • gives good visual feedback - you can see values changing live
  • you can give them easy-to-understand labels
  • their values can be python expressions dependent on other data, and they get evaluated procedurally. These custom parameters can be driven with animated expressions.
  • you can export to them with animated channels
  • there is tight control over data integrity: they have default values, minimum and maximum ranges are imposed, and menus have specific values and labels
  • it can handle multiple data types (strings, True/False booleans, integers, floats, menus, operator paths, python lists)
  • with the new Python parameter type, a parameter can also hold a python list or dictionary, where the elements are simple strings, booleans, ints and floats. (as with all custom parameters, you create Python parameters in the Component Editor under rclick -> Customize Component)
  • persistent - they are saved in a .toe or .tox as regular parameters
  • fewer syntax errors when developing
  • can be used in conjunction with extensions, sometimes replacing extensions
  • less coding, less to learn: You don't need to code python classes in a DAT to define anything.
  • are the same speed as parameters anywhere, and at least as fast as animated numbers in DAT cells.

Limitations

  • In a parameter you cannot easily represent SOP data (points, polygons, primitives, attributes), non-trivial python structures.
  • It has not been possible to manage long lists or large arrays of 1D, 2D or 3D numbers, although now there is the Python parameter type that can hold simple lists, for example.
  • An internal parameter (any parameter) uses more memory than a DAT cell but is the same as any custom parameter.
  • The syntax for parameters that are operators is: op(ipar.Effect.Operatorpath). As stated above, in the case where the parameter is not a float, integer, boolean or string, but is an operator (like the path to some node), using ipar.Effect.Operatorpath in an expression somewhere may resolve to the parameter object and not the value you intend, so you need to put op(ipar.Effect.Operatorpath). Same with a Python type parameter.