HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Registration

When creating new operators, you are essentially adding new entries to the operator table for a given network type. Each entry in the table is an object of class OP_Operator which basically defines everything Houdini requires in order to create nodes of the new type. This includes:

  • The internal operator name (which must be unique in the table)
  • The label, a more readable version of the internal name (for UI)
  • A class factory function which constructs nodes of this type
  • An array of PRM_Template objects defining the parameters to this operator
  • The minimum number of inputs required
  • The maximum number of inputs required
  • An array of any local variables used by the operator
  • Additional flags (eg. whether it generates new data: OP_FLAG_GENERATOR)

To create a new operator, your custom DSO needs to provide a specific entry point for registering itself. The entry point is of the form newFooOperator() where Foo is replaced with your network type (Sop, Obj, Dop, etc). For example, in the SOP_Star.C example you'll see the following:

// Example for basic SOP operator which creates geometry
void
{
op = new OP_Operator("hdk_star", // Internal name
"Star", // UI name
SOP_Star::myConstructor, // How to build the SOP
SOP_Star::myTemplateList, // My parameters
0, // Min # of sources
0, // Max # of sources
SOP_Star::myVariables, // Local variables
OP_FLAG_GENERATOR); // Generates new geo
// After addOperator(), 'table' will take ownership of 'op'
table->addOperator(op);
}

Houdini runs this function to create the new operator and adds it to the operator table. Note that the arguments to the OP_Operator constructor supply all the construction information previously mentioned. See Local Variables for how to use your own.

To create an operator which uses an unspecified number of inputs, use 0 for the minimum number of inputs, OP_MULTI_INPUT_MAX for the maximum number of inputs, and OP_FLAG_UNORDERED as the flag.

// Example for operator which uses an unspecified number of inputs
void
{
op = new OP_Operator("hdk_merge",
"HDK Merge",
SOP_HDKMerge::myConstructor,
SOP_HDKMerge::myTemplateList,
0, // Minimum 0 inputs
OP_MULTI_INPUT_MAX, // Special max inputs constant
SOP_HDKMerge::myVariables,
OP_FLAG_UNORDERED); // Do not care about input order
table->addOperator(op);
}

To categorize an operator in the TAB menu call the OP_Operator::setOpTabSubMenuPath() method on your custom operator. For example, to place the Star example under the Primitive submenu you can do the following:

// Example for categorizing the Star sample.
void
{
op = new OP_Operator("hdk_star", // Internal name
"Star", // UI name
SOP_Star::myConstructor, // How to build the SOP
SOP_Star::myTemplateList, // My parameters
0, // Min # of sources
0, // Max # of sources
SOP_Star::myVariables, // Local variables
OP_FLAG_GENERATOR); // Generates new geo
// Place the Star operator under the Primitive submenu
// in the TAB menu.
op->setOpTabSubMenuPath("Primitive");
// After addOperator(), 'table' will take ownership of 'op'
table->addOperator(op);
}

Thread Safety

By default, the created OP_Operator object will be marked as not thread-safe. This means that when OP_Node::cook() is invoked, a global lock will be acquired to ensure that the subclassed cooking will only run from a single thread.

To mark the operator as being safe to be cooked from multiple threads, call OP_Operator::setIsThreadSafe() with true before adding it to the OP_OperatorTable. Houdini currently does not perform multi-threaded cooking but may do so in the future.