Docs Parameters

CustomParTools

Promote parameters to a parent with binds or expressions, customize name/label/range on drop, plus extension creation, parent shortcuts, parameter clearing and IOP promotion. Also carries the pane-bar drag-drop hijack and path-cell injection, and four stock-TouchDesigner shortcuts for opening parameters and the COMP editor.

◎ Parameters Pane bar button Toolbar button

Where it appears

Read off the registry hosts in the component, so this is where the tool puts itself in a default install; every one of these can be reordered or hidden from Hub.

Shortcuts

Global: they fire anywhere in TouchDesigner. Shortcuts scoped to a single panel are a local control scheme and stay off this list.

  • Alt+\
  • Alt+X
  • Ctrl+Alt+\
  • Ctrl+Alt+Q
  • Ctrl+Alt+W
  • Shift+Alt+Q
  • Shift+Alt+W
  • Shift+Alt+X

CustomPar Tools

This button is a quick way to manipulate Custom Parameters of a parent component. It is also added for each pane!

  • Drag-and-Drop onto the icon:
    • A Parameter: Promote that Parameter to the Parent Custom Params and Bind/Reference automatically (always to the currently active/selected page).
      • Hold Ctrl to customize parameter promotion: name it, set min/max values, and tweak clamping.
        • Label and ParName for all params, and for slider-type params: min, max values, clamping tickboxes, and default value
        • Quickly jump between text fields by pressing Tab and Shift+Tab
    • A Table DAT: adds a new ParMenu and sets the table as a menu source
    • A COMP: Promote all Custom Parameters of the dragged COMP to the Parent Custom Params and Bind/Reference automatically.
  • LeftClick: Opens Parent Parameters.
  • Shift-LeftClick: Opens Selected OP Parameters.
  • RightClick: Opens Parent Component Editor.
  • Shift-RightClick: Opens Selected OP Component Editor.
  • Alt-LeftClick (Cmd+LeftClick for Mac): Runs ClearPars on the selected COMP: any parameter left in Bind mode with no valid bind master, or in Expression mode whose expression currently raises, is switched to Constant mode (dropping the dangling bind/expression), and the COMP's script errors are cleared too. Recursive into the COMP's immediate children (excluding annotations), usually useful after copying a COMP from another project
  • Ctrl+Alt+Drag an OP (Ctrl+Cmd+Drag on Mac): Promote as iop to parent
  • Ctrl+Shift+Click: Add Parent shortcut
  • Shift+Alt+LeftClick (Shift+Cmd+LeftClick for Mac): Add QuickExt to parent for a streamlined python Extension workflow. See QuickExt
  • MiddleClick: Collapses the selected nodes via QuickCollapse (if installed). Hold Ctrl or Shift to pop the naming dialog first.

QuickExt

See the extensive description of QuickExt.


CustomParCustomize

A fast way to customize parameter promotion: name it, set min/max values, and tweak clamping. Related to CustomParTools

  • Label and ParName for all params, and for slider-type params: min, max values, clamping tickboxes, and default value
  • Invoked by holding Ctrl while drag-and-dropping a parameter onto the diamond button or a parent in the path bar
  • Quickly jump between text fields by pressing Tab and Shift+Tab

When adding an extension using CustomParTools Shift+Alt+LeftClick, the created default Extension will have the following available:

  • Simplified default extension code
  • Includes ExtUtils which contains CustomParHelper and NoNode, which are also initialized in the default extension code

You can also add QuickExt to your Base COMP via the Component Editor->Extension section by long-clicking on Add and selecting QuickExt

It is important that ExtUtils stays docked to your extension code!

By leveraging [NoNode] and [CustomParHelper], TouchDesigner developers can create more efficient, organized, and maintainable extensions, ultimately leading to smoother workflow and improved project scalability.

Pro Tip: Set your IDE's Python interpreter to that of TouchDesigner's to utilize stubs/code suggestion. ExtUtils will deploy its definition automatically!

Importing

The default extension code will contain the following import statements (complicated looking at first sight) for the utility packages. You can just ignore them, but don't remove them!

Each line is a fancy import statement that avoids any conflicts when having multiple extension classes with ExtUtils attached. It finds the ExtUtils docked to your extension, or the one beside it when the dock is missing, which is what keeps a cloned component working.

  CustomParHelper: CustomParHelper = (next((d for d in me.docked if 'ExtUtils' in d.tags), None) or next((c for c in me.parent().children if 'ExtUtils' in c.tags), None)).mod('CustomParHelper').CustomParHelper # import
  NoNode: NoNode = (next((d for d in me.docked if 'ExtUtils' in d.tags), None) or next((c for c in me.parent().children if 'ExtUtils' in c.tags), None)).mod('NoNode').NoNode # import

CustomParHelper

CustomParHelper simplifies the management of custom parameters in TouchDesigner extensions, providing an intuitive interface for accessing and manipulating parameters, implementing callbacks, and handling parameter groups.

Key Features:

  • Easy parameter access as properties
  • Simplified custom parameter callbacks
  • Support for sequence parameters and blocks
  • Parameter group (parGroups) management
  • Flexible configuration for inclusion/exclusion of properties and callbacks
  • Optional public/private naming conventions
  • Declare parameters on the class and have them created

Usage examples in your extension class:

  1. Make sure ExtUtils is docked to your extension

  2. Import the CustomParHelper class:

    CustomParHelper: CustomParHelper = (next((d for d in me.docked if 'ExtUtils' in d.tags), None) or next((c for c in me.parent().children if 'ExtUtils' in c.tags), None)).mod('CustomParHelper').CustomParHelper # import
    
  3. Initialize in your extension's init method as follows:

    CustomParHelper.Init(self, ownerComp)
    

    Full signature and optional parameters:

    CustomParHelper.Init(self, ownerComp, enable_properties: bool = True, enable_callbacks: bool = True, enable_parGroups: bool = True, enable_seq: bool = True, expose_public: bool = False,
          par_properties: list[str] = ['*'], par_callbacks: list[str] = ['*'], 
          except_properties: list[str] = [], except_sequences: list[str] = [], except_callbacks: list[str] = [], except_pages: list[str] = [], 
          enable_stubs: bool = False, general_callback_enable: bool = True,
          enable_parfields: bool = True)
    

    Additional options:

    • enable_properties: If True, creates properties for custom parameters (default: True)
    • enable_callbacks: If True, creates callbacks for custom parameters (default: True)
    • enable_parGroups: If True, creates properties and methods for parGroups (default: True)
    • enable_seq: If True, creates properties and methods for sequence parameters (default: True)
    • expose_public: If True, uses capitalized property and method names (e.g., Par, Eval instead of par, eval)
    • par_properties: List of parameter names to include in property creation, by default all parameters are included
    • par_callbacks: List of parameter names to include in callback handling, by default all parameters are included
    • except_properties: List of parameter names to exclude from property creation
    • except_callbacks: List of parameter names to exclude from callback handling
    • except_pages: List of parameter pages to exclude from property and callback handling
    • except_sequences: List of sequence names to exclude from property and callback handling
    • enable_stubs: No longer does anything from here (default: False). Stub generation was removed from ExtUtils; the Stubser it carried was ~19 operators in every instance and nothing enabled it. The argument is kept so existing calls keep working. Generate stubs through VSCodeTools or QuickExt, which carry their own (thanks to AlphaMoonbase.berlin for Stubser)
    • general_callback_enable: If True, enables general callbacks that catch all parameter changes (default: True)
    • enable_parfields: If True, creates any parameters the class DECLARES before reflection runs (default: True). Harmless for a class that declares none
  4. Optionally declare your parameters in code, and they get created:

    class MyToolExt:
        def __init__(self, ownerComp):
            self.ownerComp = ownerComp
    
            self.Speed = CustomParHelper.Float(ownerComp, 'Speed', default=1.0,
                                               min=0, max=10, page='Settings',
                                               help='Playback speed multiplier.')
            self.Mode  = CustomParHelper.Menu(ownerComp, 'Mode', ['fast', 'slow'],
                                              page='Settings',
                                              help='Which way the thing runs.')
    
            if ownerComp.par.Advanced.eval():            # conditionals work
                CustomParHelper.Int(ownerComp, 'Depth', default=3,
                                    page='Settings', help='Recursion depth.')
    
            for name in ('Alpha', 'Beta'):               # so do loops
                CustomParHelper.Toggle(ownerComp, name, page='Flags',
                                       help='Flag %s.' % name)
    
            CustomParHelper.Init(self, ownerComp)
    

    Each call creates the parameter and returns it, so you can use it on the next line: self.Speed.val = 5. Declaring inside __init__ is what makes conditionals, loops and computed defaults ordinary Python, since the COMP exists by then.

    One helper per style: Float Int Str Toggle Pulse Menu StrMenu File Folder Header XYZ RGB RGBA OP COMP TOP CHOP SOP DAT MAT. The multi-member ones (XYZ, RGB, RGBA) return a ParGroup and take either one value for every member or a sequence: default=(0.2, 0.4, 0.6).

    This is additive: CustomParHelper still reflects whatever parameters it finds, so a tool that declares nothing behaves exactly as before, and you can mix declared and hand-made parameters freely. There is no base class to inherit.

    Declare before CustomParHelper.Init, so the new parameters get properties and callbacks in the same pass. A parameter added by hand after Init has no property until something refreshes it; a declared one cannot drift.

    Which page? The page keyword, page='Settings' above. It is the page NAME, created if it does not exist, and it defaults to 'Custom'.

    Every other keyword is a TouchDesigner Par member, set straight through: default, label, help, readOnly, startSection, min, max, clampMin, clampMax, normMin, normMax, menuNames, menuLabels, order. They keep TouchDesigner's own names: see Par Class for what each does and which styles honour it.

    A static alternative. If the parameter set never varies you can declare on the class body instead, and Init creates them:

    class MyToolExt:
        Speed = CustomParHelper.ParFloat(default=1.0, page='Settings',
                                         help='Playback speed multiplier.')
    
        def __init__(self, ownerComp):
            CustomParHelper.Init(self, ownerComp)
    

    It cannot do conditionals or loops and it cannot hand you the parameter, because a class body runs before there is any COMP to create one on. self.Speed still resolves to the real Par once Init has run, and raises a message explaining itself if you touch it before that. Both forms use the same code underneath, so they behave identically once the parameter exists.

    Three things worth knowing:

    • A new parameter is seeded with its default; an existing one keeps its value. The first time a declaration creates a parameter it is set to the declared default. After that, re-initializing refreshes label, help, range and menu entries and leaves the value alone, whatever you or the saved project put there.
    • A style change is applied for you. Declaring ParStr over an existing Float rebuilds the parameter and carries across its value, expression, bind expression and position on the page. The one thing that cannot survive is an export: that link belongs to the exporting CHOP and lives outside the parameter, so it is reported in the textport and you re-export it.
    • help is strongly expected but not enforced. Omitting it logs a warning and your extension keeps working. Fill it in: it is the tooltip your users get when they hover the parameter name.
  5. Access and set custom parameters as properties (if enable_properties=True (default)):

    There are two ways to access and set parameter values:

    a) Using Eval properties (recommended for simple value setting):

    • self.eval<ParamName>: Get/set the evaluated value of the parameter
      # Get value
      value = self.evalMyparam
      # Set value (always sets .val regardless of parameter mode)
      self.evalMyparam = 5
      
    • self.evalGroup<GroupName>: Get/set the evaluated value of the parameter group
      # Get values
      values = self.evalGroupXyz
      # Set values (always sets .val for each parameter)
      self.evalGroupXyz = [1, 2, 3]
      

    b) Using Par properties (for advanced parameter control):

    • self.par<ParamName>: Access/set the parameter object
      # Get parameter object for advanced operations
      self.parMyparam.expr = "op('something').par.value"
      self.parMyparam.bindExpr = "op('other').par.value"
      # Set value (only works in CONSTANT or BIND modes)
      self.parMyparam = 5  # Ignored if parameter is in EXPRESSION mode
      
    • self.parGroup<GroupName>: Access/set the parameter group object
      # Get parameter group for advanced operations
      myGroup = self.parGroupXyz
      # Set values (only works for parameters in CONSTANT or BIND modes)
      self.parGroupXyz = [1, 2, 3]  # Only affects non-expression parameters
      

    NOTE: to expose public properties, eg. self.Par instead of self.par, set expose_public=True in the Init function

  6. Implement callbacks (if enable_callbacks=True (default)): a) Parameter-specific callbacks:

    • For regular parameters:

      def onPar<Parname>(self, _par, _val, _prev):
        # _par and _prev can be omitted if not needed
      
    • For pulse parameters:

      def onPar<PulseParname>(self, _par):
        # _par can be omitted if not needed
      
    • For sequence blocks:

      def onSeq<SeqName>N(self, idx):
      
    • For sequence parameters:

      def onSeq<SeqName>N<Parname>(self, _par, idx, _val, _prev):
        # _par and _prev can be omitted if not needed
      
    • For parameter groups if enable_parGroups=True (default):

      def onParGroup<Groupname>(self, _parGroup, _val):
        # _parGroup can be omitted if not needed
      

    b) General callbacks (if general_callback_enable=True (default)): These catch all parameter changes that aren't handled by specific callbacks:

    • For value changes:

      def onValueChange(self, _par, _val, _prev):
        # Called when any parameter value changes that doesn't have a specific callback
        # _val and _prev can be omitted if not needed
      
    • For pulse parameters:

      def onPulse(self, _par):
        # Called when any pulse parameter is triggered that doesn't have a specific callback
        # _par can be omitted if not needed
      

Naming the handler yourself

Every callback above is found by its NAME. If you would rather name the method for what it does, declare which parameter it handles:

class MyToolExt:
    def __init__(self, ownerComp):
        self.ownerComp = ownerComp
        CustomParHelper.Init(self, ownerComp)     # harvests the declarations

    @CustomParHelper.onPar('Speed')
    def playbackSpeedChanged(self, _par, _val, _prev):
        ...

    @CustomParHelper.onPar('Reset')               # a Pulse parameter
    def clearEverything(self, _par):
        ...

    @CustomParHelper.onParGroup('Translate')
    def moved(self, _parGroup, _val):
        ...

Six decorators, one per callback kind: onPar (value change, or pulse for a Pulse parameter), onParGroup, onSeq(sequence, par), onSeqBlock(sequence), onAnyValueChange() and onAnyPulse() for the two general callbacks.

Init harvests them, so there is no extra call and no change to your Init signature. Signatures and arity are exactly as documented above; the decorator records which parameter the method handles and returns the method untouched, so you can still omit _val and _prev from the right.

Two things the naming convention cannot do:

  • A declaration that names a parameter you do not have is reported. With the convention a mistyped onParSpeeed is simply a method that never runs and never complains. It is logged, so one bad declaration should not stop a tool loading.
  • A collision is reported too. If the class already defines onParSpeed and something else declares @onPar('Speed'), the real method wins and the declaration is reported as ignored, so nothing silently shadows working code.

Declared and conventionally-named callbacks work side by side on the same extension; use whichever reads better per parameter.

NoNode

NoNode is a versatile utility class that centralizes the management of various types of executions and callbacks in TouchDesigner, eliminating the need for dedicated nodes.

Usage examples:

  1. Make sure ExtUtils is docked to your extension

  2. Import the NoNode class:

    NoNode: NoNode = (next((d for d in me.docked if 'ExtUtils' in d.tags), None) or next((c for c in me.parent().children if 'ExtUtils' in c.tags), None)).mod('NoNode').NoNode # import
    
  3. Initialize the NoNode system in your extension:

    NoNode.Init(enable_chopexec=True, enable_datexec=True, enable_parexec=True, enable_keyboard_shortcuts=True)
    
  4. CHOP executions:

    • Register a callback for CHOP value changes:
      NoNode.RegisterChopExec(NoNode.ChopExecType.ValueChange, chop_op, channel_name(s), self.on_value_change_function)
      # callback signature: def on_value_change_function(self, channel: Channel, sampleIndex: int, val: float, prev: float):
      # can omit parameters from the right side of the signature if not needed
      
    • Handle CHOP state changes:
      NoNode.RegisterChopExec(NoNode.ChopExecType.OffToOn, chop_op, channel_name(s), self.on_activate_function)
      # callback signature: def on_activate_function(self, channel: Channel, sampleIndex: int, val: float, prev: float):
      # can omit parameters from the right side of the signature if not needed
      
  5. DAT executions:

    • React to table changes in a DAT:
      NoNode.RegisterDatExec(NoNode.DatExecType.TableChange, dat_op, self.on_table_change_function)
      # callback signature depends on the event type, eg.: def on_table_change_function(self, dat: DAT):
      
    • Handle cell value changes:
      NoNode.RegisterDatExec(NoNode.DatExecType.CellChange, dat_op, self.on_cell_change_function)
      # callback signature depends on the event type, eg.: def on_cell_change_function(self, dat: DAT, cells: list[Cell], prev: Cell):
      
  6. Parameter executions:

    • Register a callback for parameter value changes:
      NoNode.RegisterParExec(NoNode.ParExecType.ValueChange, par_op, par_name, self.on_value_change_function)
      # callback signature depends on the event type, eg.: def on_value_change_function(self, par: Par, val: float, prev: float):
      # can omit prev, or use val only
      
    • Handle pulse parameters:
      NoNode.RegisterParExec(NoNode.ParExecType.OnPulse, par_op, par_name, self.on_pulse_function)
      # callback signature: def on_pulse_function(self,par: Par):
      # can omit par if not needed
      
  7. Keyboard shortcuts:

    • Register a keyboard shortcut:
      NoNode.RegisterKeyboardShortcut('ctrl.k', self.onKeyboardShortcut)
      # callback signature: def onKeyboardShortcut(self):
      
  8. Deregister callbacks:

    • Deregister a CHOP execution:
      NoNode.DeregisterChopExec(NoNode.ChopExecType.ValueChange, chop_op, channel_name(s))
      
    • Deregister a DAT execution:
      NoNode.DeregisterDatExec(NoNode.DatExecType.TableChange, dat_op)
      
    • Deregister a parameter execution:
      NoNode.DeregisterParExec(NoNode.ParExecType.ValueChange, par_op, par_name)
      
    • Deregister a keyboard shortcut:
      NoNode.DeregisterKeyboardShortcut('ctrl.k')
      
  9. Visual indication:

    • Operators with registered callbacks are marked with a color for easy identification
    • Customize the mark color:
      NoNode.SetMarkColor((r, g, b))
      

Declaring callbacks on the method

The Register* calls above are one way to wire a callback. The other is to declare it on the method itself and let NoNode collect them:

class MyToolExt:
    def __init__(self, ownerComp):
        self.ownerComp = ownerComp
        NoNode.Init(ownerComp, enable_chopexec=True, enable_parexec=True)
        NoNode.HarvestCallbacks(self)          # registers everything below

    @NoNode.onChopExec(NoNode.ChopExecType.ValueChange, 'null_audio', 'chan1')
    def audioMoved(self, channel, sampleIndex, val, prev):
        ...

    @NoNode.onParExec(NoNode.ParExecType.ValueChange, 'null_hk', 'Shift')
    def shiftChanged(self, par, val, prev):
        ...

    @NoNode.onKeyboardShortcut('ctrl.k')
    def quickAction(self):
        ...

@NoNode.onChopExec, @NoNode.onDatExec, @NoNode.onParExec and @NoNode.onKeyboardShortcut take the same arguments as their Register* counterparts, minus the callback itself. Signatures are unchanged; arity is still inferred, so you can still drop arguments off the right.

Targets are strings, resolved when HarvestCallbacks runs, relative to the extension's COMP. They cannot be op() calls: a class body is executed while the class is being defined, long before any COMP exists to resolve against. Omit the owner on onParExec to watch your own COMP's parameter.

What this buys over the imperative form:

  • The binding is visible at the callback itself, right where you read the handler, and the method name is free.
  • A target that does not resolve is reported. A mistyped operator or parameter name currently produces a callback that simply never fires; harvest logs it, and nothing is raised, so one bad declaration should not stop a tool from loading.
  • Re-harvesting rebuilds from scratch, so a callback deleted from the code disappears with it and there is nothing stale to deregister.

Both styles work on the same extension, and neither needs the other: NoNode.Init + HarvestCallbacks is enough on its own, with no CustomParHelper involved.

It also works alongside CustomParHelper. The two watch through separate exec DATs and do not read each other's state, so a COMP can use CustomParHelper for its parameters and decorators for its callbacks. Note that on the same parameter both fire: an onParSpeed method and an @onParExec decorator for Speed give you two callbacks, so pick one style per parameter. Use the decorator when you want the handler's name to be free of the onPar<Name> convention.

To demo all the features you can download QuickExtTest.tox and run it or just check its extension code.

TouchDesigner shortcuts

Four conveniences over TouchDesigner's own UI, by keyboard or from the command palette:

Shortcut Action
Shift+Alt+Q Open the parameter dialog for the selected operator
Ctrl+Alt+Q Open the parameter dialog for the current network's COMP
Shift+Alt+W Open the component editor for the selected operator
Ctrl+Alt+W Open the component editor for the current network's COMP

(On macOS, Alt is Option.)

They call nothing but TouchDesigner itself, so they work regardless of which other packages are installed, and each is rebindable in HotkeyManager. Keyboard and palette share one implementation: the keyboardin callbacks invoke the same promoted methods the commands do.

These arrived from the retired MY_HOTKEYS package. Their command ids are unchanged (opencurrentparameters, openparentparameters, customizecurrentcomp, customizeparentcomp) but the owning tool is now CustomParTools, so launcher history, curation and presets that referenced MY_HOTKEYS#… need re-pointing once.

QuickParCustom

Promote and customize the parameter under the cursor, without selecting anything. Its Active toggle turns the whole feature off.

Shortcut On the hovered parameter
alt+x Promote to parent (Bind). If it is already promoted, opens the promoted parameter's customization instead
shift+alt+x Same, with the promotion made as an Expression
alt+\ Customize the parameter (a custom par customizes its owner COMP; otherwise the promoted owner)
ctrl+alt+\ Toggle that parameter between Bind and Expression

All four are rebindable on the Custom page of QuickParCustom, and listed in HotkeyManager.

It was a separate package until 2026-08-24, though it always depended on this one: it drove promotion by calling this package's promoter through the FNS_CPP global, so installing it without CustomParTools gave you hotkeys that could not promote. As a child it calls its parent directly.

Path Bar mods

Dragging an operator onto one of the parents in the Path Bar, and holding Ctrl+Alt (or Ctrl+Cmd) will promote the operator as an iop (internal operator). The root / cell counts as a parent, so a shortcut can be added to the root too.

Dragging a parameter onto one of the parents in the Path Bar will promote it to that parent.

  • ‼️MiddleClicking on a parent will open its parameter window.
  • ‼️‼️Long-MiddleClicking on a parent will open its customize window.

Modules

Everything above is a separate sub-module, and the Modules page on the CustomParTools component switches each one on or off independently. All nine default to on, and the settings persist through FNS_ConfigRegistry like the rest of the tool's parameters.

Toggle Turns off
Parameter Promotion Dropping a parameter, COMP or table on the button or on the path bar
QuickExt Extension creation from the button
QuickParent Setting a parent shortcut from the button
ClearPars Alt-LeftClick parameter clearing
IOP Promoter Ctrl+Alt drop as an internal operator
Navbar Drag/Drop Drops anywhere on the pane bar
Navbar Path Cell Click MiddleClick on a path-bar parent
QuickParCustom The rollover hotkeys (bound to QuickParCustom's own Active switch)
Parameter/Editor Hotkeys The four stock-TouchDesigner shortcuts

Switching a module off withdraws whatever surface it owns, so that surface goes away with it:

  • Navbar Drag/Drop and Navbar Path Cell Click each own their own navbar registration, so turning one off unregisters that widget and it disappears from every pane bar.
  • The other five in the top group share one surface, the CustomParTools button. It leaves the navbar and the toolbar only when all five are off, since any one of them still gives the button something to do.
  • The settings registration is never withdrawn. It carries no surface, and it is what stores these toggles, so dropping it would discard the setting that asked for the drop.

Parameters

Its Registry page comes from FNS_ConfigRegistry, FNS_NavbarRegistry and FNS_ToolbarRegistry.

Custom

ControlType / defaultWhat it does
Ref/BindRefbind on / offoff How a promoted parameter is linked back to the original. On binds the two (either end can be edited and both follow); off leaves the original in expression mode pointing at the promoted one. Holding the modifier while promoting inverts this for that one action.
Promote AllPromote button Promote every custom parameter on the current page of the referenced COMP to the target COMP at once, linked according to Ref/Bind.
Params: SelectedShortcutcurrentpars textshift.alt.q Hotkey that opens the parameter dialog for the SELECTED operator. Rebindable here or in FNS_HotkeyManager.
Params: Current COMPShortcutparentpars textctrl.alt.q Hotkey that opens the parameter dialog for the COMP whose network is showing.
Editor: SelectedShortcutcurrentcomp textshift.alt.w Hotkey that opens the component editor for the SELECTED operator.
Editor: Current COMPShortcutparentcomp textctrl.alt.w Hotkey that opens the component editor for the COMP whose network is showing.

Modules

ControlType / defaultWhat it does
Parameter PromotionActiveparpromote on / offon Drop a parameter onto the CustomParTools button to promote it onto the current network COMP. The core action of the tool.
QuickExtActivequickext on / offon Create an extension on the current COMP from the button.
QuickParentActivequickparent on / offon Set a parent shortcut on the current COMP from the button.
ClearParsActiveclearpars on / offon Alt-click (Cmd on macOS) the button to clear the custom parameters of the current child.
IOP PromoterActiveioppromoter on / offon Hold the modifier while dropping an operator on the button to promote it as an Internal OP instead of promoting parameters.
Navbar Drag/DropActivehijackdragdrop on / offon Accept operator and parameter drops anywhere on the pane navigation bar. Off UNREGISTERS the widget, removing it from every bar.
Navbar Path Cell ClickActivepathcellclickinject on / offon Open parameters for the operator whose path cell you click in the pane bar. Off UNREGISTERS the widget, removing it from every bar.
QuickParCustomActivequickparcustom on / offon Rollover hotkeys for promoting and customizing the parameter under the mouse. Bound to QuickParCustom's own Active switch.
Parameter/Editor HotkeysActivetdshortcuts on / offon The four stock-TouchDesigner hotkeys on the Custom page (open parameters, open component editor). Off deactivates the keyboardins; the matching quick-launch commands stay available.

Edit this page on GitHub →